• NLP之RNN的原理讲解(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])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    代码解读

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

    1. 导入所需的库:

      import numpy as np
      import tensorflow as tf
      from tensorflow.keras.layers import SimpleRNNCell
      
      • 1
      • 2
      • 3

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

    2. 创建训练数据:

      xt = tf.Variable(np.random.randint(2, 3, size=[1, 1]), dtype=tf.float32)
      print(xt)
      
      • 1
      • 2

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

      xt:  <tf.Variable 'Variable:0' shape=(1, 1) dtype=float32, numpy=array([[2.]], dtype=float32)>
      
      • 1
    3. 定义RNN单元:

      cell = SimpleRNNCell(units=1, activation=None, use_bias=True, kernel_initializer='ones', recurrent_initializer='ones',
                        bias_initializer=tf.keras.initializers.Constant(value=3))
      
      • 1
      • 2

      使用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单元输入的形状,这样它就可以创建相应的权重和偏置张量。

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

      print('variables', cell.variables)
      print('config:', cell.get_config())
      
      • 1
      • 2

      这两行代码是关于打印关于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)的详细信息,包括它的权重(和它们的初始值)以及它的配置。这是非常有用的,特别是当你在调试或了解你的模型结构时。

        variables:  [<tf.Variable 'kernel:0' shape=(1, 1) dtype=float32, numpy=array([[1.]], dtype=float32)>, <tf.Variable 'recurrent_kernel:0' shape=(1, 1) dtype=float32, numpy=array([[1.]], dtype=float32)>, <tf.Variable 'bias:0' shape=(1,) dtype=float32, numpy=array([3.], dtype=float32)>]
        
        config:  {'name': 'simple_rnn_cell', 'trainable': True, 'dtype': 'float32', 'units': 1, 'activation': 'linear', 'use_bias': True, 'kernel_initializer': {'class_name': 'Ones', 'config': {}}, 'recurrent_initializer': {'class_name': 'Ones', 'config': {}}, 'bias_initializer': {'class_name': 'Constant', 'config': {'value': 3}}, 'kernel_regularizer': None, 'recurrent_regularizer': None, 'bias_regularizer': None, 'kernel_constraint': None, 'recurrent_constraint': None, 'bias_constraint': None, 'dropout': 0.0, 'recurrent_dropout': 0.0}
        
        • 1
        • 2
        • 3
    5. 计算tanh的值:

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

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

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

      ht_1 = tf.ones([1, 1])
      out, ht = cell(xt, ht_1)  # LSTM
      print(out, ht[0])
      print(id(out), id(ht[0]))
      
      • 1
      • 2
      • 3
      • 4
    7. 第t+1时刻的计算:
      同样地,这部分代码定义了一个新的RNN单元cell2,然后用新的输入xt2和上一个时间步的隐藏状态ht来获取下一个时间步的输出和隐藏状态。

      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)
      
      • 1
      • 2
      • 3
      • 4
    8. 输出与隐藏状态的关系:

      print(id(out), id(ht[0]))
      
      • 1

      这部分代码展示了在简单的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 的保存和恢复机制实现的,这样可以方便地保存和加载模型。

    示例:

    import tensorflow as tf
    
    # 创建一个初始化为1的变量
    v = tf.Variable(1.0)
    
    # 使用变量
    result = v * 2.0
    
    # 修改变量的值
    v.assign(2.0)  # 现在 v 的值为 2.0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

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

  • 相关阅读:
    java--String
    你是否感受到AI就在身边?
    3D视觉基础整理 (一)
    深度学习计算 - 层和块
    Apache Shiro 1.2.4反序列化漏洞(CVE-2016-4437)
    『PyQt5-Qt Designer篇』| 08 Qt Designer中容器布局和绝对布局的使用
    vue前端 router路由hash和history模式区别
    redis集群系列四
    期末复习 c
    java毕业设计手机在线销售系统mybatis+源码+调试部署+系统+数据库+lw
  • 原文地址:https://blog.csdn.net/weixin_46713695/article/details/134072410