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)的基础操作。我们将一步步地解释其含义。
导入所需的库:
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import SimpleRNNCell
代码导入了NumPy库、TensorFlow库以及SimpleRNNCell,这是一个实现了简单的RNN单元操作的类。
创建训练数据:
xt = tf.Variable(np.random.randint(2, 3, size=[1, 1]), dtype=tf.float32)
print(xt)
这里创建了一个1x1的张量,其值是2或3之间的随机整数。这代表了在时间t的输入数据。
xt: <tf.Variable 'Variable:0' shape=(1, 1) dtype=float32, numpy=array([[2.]], dtype=float32)>
定义RNN单元:
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)。bias_initializer=tf.keras.initializers.Constant(value=3))。kernel_initializer='ones':
'ones'表示所有的权重都被初始化为1。recurrent_initializer='ones':
'ones'表示所有的循环权重都被初始化为1。bias_initializer=tf.keras.initializers.Constant(value=3):
tf.keras.initializers.Constant(value=3)表示所有的偏置被初始化为常数3。cell.build(input_shape=[None, 1])这行代码是用来告诉RNN单元输入的形状,这样它就可以创建相应的权重和偏置张量。
cell.build(input_shape=[None, 1])
input_shape是用来指定输入数据的维度的参数。具体到这里的input_shape=[None, 1],我们可以解读它为:[None, 1]:这是一个形状列表,其中有两个维度。None:
None作为批处理的大小意味着模型可以接受任何大小的批次。1:
input_shape=[None, 1]表示模型可以接受一个二维的输入,其中第一个维度是任意大小的批处理,第二个维度是1个特征。显示RNN单元的变量和配置:
代码打印出RNN单元的所有变量(如权重和偏置)以及配置。
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)的详细信息,包括它的权重(和它们的初始值)以及它的配置。这是非常有用的,特别是当你在调试或了解你的模型结构时。
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}
计算tanh的值:
print(tf.nn.tanh(tf.constant([-float("inf"), 6, float("inf")])))
这行代码计算了tanh函数在-∞、6和∞三个点的值。tanh是RNN和其他神经网络中常用的激活函数。
第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]))
第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)
输出与隐藏状态的关系:
print(id(out), id(ht[0]))
这部分代码展示了在简单的RNN中,输出状态out和隐藏状态ht是相同的对象。
最后,代码的主要目的是演示如何使用SimpleRNNCell在给定的输入和隐藏状态上进行计算,并展示其结果。
tf.Variable 是 TensorFlow(TF)中的一个核心概念,它用于表示在 TF 计算过程中可能会发生变化的数据。在 TF 中,计算通常是通过计算图(graph)来定义的,而 tf.Variable 允许我们将可以变化的状态添加到这些计算图中。
以下是 tf.Variable 的一些关键点:
可变性:与 TensorFlow 的常量(tf.constant)不同,tf.Variable 表示的值是可变的。这意味着在训练过程中,可以更新、修改或赋予其新值。
用途:tf.Variable 通常用于表示模型的参数,例如神经网络中的权重和偏置。
初始化:当创建一个 tf.Variable 时,你必须为它提供一个初始值。这个初始值可以是一个固定值,也可以是其他任何 TensorFlow 计算的结果。
赋值:使用 assign、assign_add 等方法,你可以修改 tf.Variable 的值。
存储和恢复:tf.Variable 的值可以被存储到磁盘并在之后恢复,这是通过 TensorFlow 的保存和恢复机制实现的,这样可以方便地保存和加载模型。
示例:
import tensorflow as tf
# 创建一个初始化为1的变量
v = tf.Variable(1.0)
# 使用变量
result = v * 2.0
# 修改变量的值
v.assign(2.0) # 现在 v 的值为 2.0
总之,tf.Variable 是 TensorFlow 中表示可变状态的主要方式,尤其是在模型训练中,它用于存储和更新模型的参数。