NLP之RNN的原理讲解(python示例)

目录

代码示例

python 复制代码
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import SimpleRNNCell

# 第t时刻要训练的数据
xt = tf.Variable(np.random.randint(2, 3, size=[1, 1]), dtype=tf.float32)
print(xt)
# https://www.cnblogs.com/Renyi-Fan/p/13722276.html

cell = SimpleRNNCell(units=1, activation=None, use_bias=True, kernel_initializer='ones', recurrent_initializer='ones',
                     bias_initializer=tf.keras.initializers.Constant(value=3))
cell.build(input_shape=[None, 1])
print('variables', cell.variables)
print('config:', cell.get_config())

print(tf.nn.tanh(tf.constant([-float("inf"), 6, float("inf")])))

# 第t时刻运算
ht_1 = tf.ones([1, 1])
out, ht = cell(xt, ht_1)  # LSTM
print(out, ht[0])
print(id(out), id(ht[0]))

# 第t+1时刻运算
cell2 = SimpleRNNCell(units=1, activation=None, use_bias=True, kernel_initializer='ones',
                      recurrent_initializer=tf.keras.initializers.Constant(value=3), bias_initializer='ones')
xt2 = tf.Variable(np.random.randint(3, 4, size=[1, 1]), dtype=tf.float32)
out2, ht2 = cell2(xt2, ht)
print(out2, ht2[0])

代码解读

这段代码包含了一些使用 TensorFlow 来创建和操作循环神经网络(RNN)的基础操作。我们将一步步地解释其含义。

  1. 导入所需的库:

    python 复制代码
    import numpy as np
    import tensorflow as tf
    from tensorflow.keras.layers import SimpleRNNCell

    代码导入了NumPy库、TensorFlow库以及SimpleRNNCell,这是一个实现了简单的RNN单元操作的类。

  2. 创建训练数据:

    python 复制代码
    xt = tf.Variable(np.random.randint(2, 3, size=[1, 1]), dtype=tf.float32)
    print(xt)

    这里创建了一个1x1的张量,其值是2或3之间的随机整数。这代表了在时间t的输入数据。

  3. 定义RNN单元:

    python 复制代码
    cell = SimpleRNNCell(units=1, activation=None, use_bias=True, kernel_initializer='ones', recurrent_initializer='ones',
                      bias_initializer=tf.keras.initializers.Constant(value=3))

    使用SimpleRNNCell创建了一个RNN单元。这个单元有以下特性:

    • 只有一个神经元(units=1)。
    • 不使用激活函数(activation=None)。
    • 使用偏置,并初始化为3(bias_initializer=tf.keras.initializers.Constant(value=3))。
    • 输入权重和循环权重都初始化为1。
    • kernel_initializer='ones' :
      • 这是一个初始化器,用于初始化RNN单元的权重(也称为内核权重)。
      • 'ones'表示所有的权重都被初始化为1。
      • 换句话说,当输入数据经过RNN单元时,它会与这些权重相乘,而这些权重的初始值都是1。
    • recurrent_initializer='ones' :
      • 这是一个初始化器,用于初始化RNN单元的循环权重。
      • 在RNN中,当前时间步的隐藏状态是基于前一个时间步的隐藏状态计算的。这个计算涉及到的权重就是循环权重。
      • 'ones'表示所有的循环权重都被初始化为1。
    • bias_initializer=tf.keras.initializers.Constant(value=3) :
      • 这是一个初始化器,用于初始化RNN单元的偏置。
      • tf.keras.initializers.Constant(value=3)表示所有的偏置被初始化为常数3。
    • 简而言之,这些参数(kernel_initializer、recurrent_initializer、bias_initializer)确定了RNN单元在开始训练之前的权重和偏置的初始状态。这些初始值在训练过程中会被更新。选择合适的初始化器对于模型的收敛速度和性能至关重要,尽管在这个特定的例子中,这些权重和偏置被赋予了特定的常数值。

    cell.build(input_shape=[None, 1])这行代码是用来告诉RNN单元输入的形状,这样它就可以创建相应的权重和偏置张量。

    • 在TensorFlow和Keras中,input_shape是用来指定输入数据的维度的参数。具体到这里的input_shape=[None, 1],我们可以解读它为:
    • [None, 1]:这是一个形状列表,其中有两个维度。
    • None
      • 第一个维度通常表示批处理的大小(即在一个批次中的样本数)。在许多情况下,为了使模型更加灵活,我们可能不想在定义模型时硬编码一个固定的批处理大小。
      • 使用None作为批处理的大小意味着模型可以接受任何大小的批次。
      • 例如,你可以选择在训练时使用64的批大小,在评估或推理时使用1的批大小,或者使用其他任何数字。
    • 1
      • 第二个维度是数据的特征维度。
      • 在这里,它指的是输入数据的每个样本有1个特征。
    • 综上所述,input_shape=[None, 1]表示模型可以接受一个二维的输入,其中第一个维度是任意大小的批处理,第二个维度是1个特征。
  4. 显示RNN单元的变量和配置 :

    代码打印出RNN单元的所有变量(如权重和偏置)以及配置。

    python 复制代码
    print('variables', cell.variables)
    print('config:', cell.get_config())

    这两行代码是关于打印关于cell(这里的cell是一个SimpleRNNCell的实例)的相关信息。

    • print('variables', cell.variables):

      • cell.variables: 这是一个属性,它返回一个列表,该列表包含cell中的所有可训练变量(权重和偏置)。在RNN cell的上下文中,这通常包括核权重、递归权重以及偏置。
      • print(...): 打印变量列表,以便于你查看和调试。通常这可以帮助你理解RNN cell中的权重如何初始化(例如,这里你已经明确地设置了初始化器)。
    • print('config:', cell.get_config()):

      • cell.get_config(): 这是一个方法,它返回一个字典,该字典包含cell的配置。这通常包括其初始化时使用的参数(例如units的数量、激活函数、是否使用偏置等)。这允许你查看或者后续再次使用这些配置信息,例如,如果你想保存模型的结构并稍后再次创建它。
      • print(...): 打印配置字典,使你能够查看cell的配置。
    • 总之,这两行代码提供了关于SimpleRNNCell实例(cell)的详细信息,包括它的权重(和它们的初始值)以及它的配置。这是非常有用的,特别是当你在调试或了解你的模型结构时。

  5. 计算tanh的值:

    python 复制代码
    print(tf.nn.tanh(tf.constant([-float("inf"), 6, float("inf")])))

    这行代码计算了tanh函数在-∞、6和三个点的值。tanh是RNN和其他神经网络中常用的激活函数。

  6. 第t时刻的计算 :

    这部分代码首先定义了上一个时间步的隐藏状态ht_1,然后使用cell(xt, ht_1)调用RNN单元来获取当前时间步的输出和隐藏状态。

    python 复制代码
    ht_1 = tf.ones([1, 1])
    out, ht = cell(xt, ht_1)  # LSTM
    print(out, ht[0])
    print(id(out), id(ht[0]))
  7. 第t+1时刻的计算 :

    同样地,这部分代码定义了一个新的RNN单元cell2,然后用新的输入xt2和上一个时间步的隐藏状态ht来获取下一个时间步的输出和隐藏状态。

    python 复制代码
    cell2 = SimpleRNNCell(units=1, activation=None, use_bias=True, kernel_initializer='ones',
                          recurrent_initializer=tf.keras.initializers.Constant(value=3), bias_initializer='ones')
    xt2 = tf.Variable(np.random.randint(3, 4, size=[1, 1]), dtype=tf.float32)
    out2, ht2 = cell2(xt2, ht)
  8. 输出与隐藏状态的关系:

    python 复制代码
    print(id(out), id(ht[0]))

    这部分代码展示了在简单的RNN中,输出状态out和隐藏状态ht是相同的对象。

最后,代码的主要目的是演示如何使用SimpleRNNCell在给定的输入和隐藏状态上进行计算,并展示其结果。

知识点介绍

tf.Variable 是 TensorFlow(TF)中的一个核心概念,它用于表示在 TF 计算过程中可能会发生变化的数据。在 TF 中,计算通常是通过计算图(graph)来定义的,而 tf.Variable 允许我们将可以变化的状态添加到这些计算图中。

以下是 tf.Variable 的一些关键点:

  1. 可变性 :与 TensorFlow 的常量(tf.constant)不同,tf.Variable 表示的值是可变的。这意味着在训练过程中,可以更新、修改或赋予其新值。

  2. 用途tf.Variable 通常用于表示模型的参数,例如神经网络中的权重和偏置。

  3. 初始化 :当创建一个 tf.Variable 时,你必须为它提供一个初始值。这个初始值可以是一个固定值,也可以是其他任何 TensorFlow 计算的结果。

  4. 赋值 :使用 assignassign_add 等方法,你可以修改 tf.Variable 的值。

  5. 存储和恢复tf.Variable 的值可以被存储到磁盘并在之后恢复,这是通过 TensorFlow 的保存和恢复机制实现的,这样可以方便地保存和加载模型。

示例:

python 复制代码
import tensorflow as tf

# 创建一个初始化为1的变量
v = tf.Variable(1.0)

# 使用变量
result = v * 2.0

# 修改变量的值
v.assign(2.0)  # 现在 v 的值为 2.0

总之,tf.Variable 是 TensorFlow 中表示可变状态的主要方式,尤其是在模型训练中,它用于存储和更新模型的参数。

相关推荐
databook7 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar8 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户8356290780518 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_8 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机15 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机16 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机16 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机16 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i16 小时前
drf初步梳理
python·django
每日AI新事件16 小时前
python的异步函数
python