深度学习3:RNN和LSTM


一、RNN

RNN是循环神经网络的缩写,是一种用于处理序列数据的神经网络。RNN具有独特的结构,可以维护先前输入的内部记忆,并使用它们来预测序列中下一个输入。这使它们特别适用于语言模型、语音识别和机器翻译等任务。RNN通常用于自然语言处理(NLP)任务,其中单词在句子中的顺序很重要并且必须被考虑进去。

二、RNN原理和使用步骤

在这里插入图片描述
RNN存在的问题如下:

  1. 梯度消失:当RNN进行反向传播时,梯度会随着时间步骤的增加而指数级衰减,这会导致网络无法学习长期依赖关系。

  2. 梯度爆炸:有时候梯度会随着时间步骤的增加而指数级增加,这会导致数值不稳定,网络无法收敛。

  3. 训练速度慢:RNN训练速度相对较慢,因为每个时间步骤都需要进行反向传播。

  4. 长序列处理困难:对于较长的序列,RNN的计算成本会变得很高,而且长期依赖关系的学习也变得更加困难。

  5. 信息遗忘:由于RNN只能通过隐藏状态传递信息,因此网络可能会忘记过去的信息,这会导致模型性能下降。

引入LSTM


三、LSTM原理

LSTM(全称为Long Short-Term Memory)是一种循环神经网络(RNN)的变体,用于处理序列数据中的长期依赖性问题。LSTM通过引入一种称为“门”的机制,可以选择性地记忆或遗忘输入数据。下面是一张LSTM的原理图:
可以看成主线剧情和支线剧情推动故事发展,有用的支线被保留了部分,没用的就不要了,但是故事本身的主线是由每一级本身的输入产生,保留着前面有用的支线剧情的影响,最后形成了特定的故事

LSTM原理图

在LSTM中,有三个门:输入门(input gate)、遗忘门(forget gate)和输出门(output gate)。其作用如下:

  • 输入门:决定有多少信息需要传递到记忆单元中。它包含一个sigmoid激活函数,它将输入数据和前一个时间步的隐藏状态作为输入,并产生介于0和1之间的输出。
  • 遗忘门:决定有多少旧的信息需要保留在记忆单元中。它包含一个sigmoid激活函数,它将输入数据和前一个时间步的隐藏状态作为输入,并产生介于0和1之间的输出。
  • 输出门:决定从记忆单元中选择多少信息来输出。它包括一个sigmoid激活函数和一个tanh激活函数。sigmoid激活函数决定保留多少输出,而tanh激活函数产生一个介于-1和1之间的向量。

除了三个门之外,LSTM还包含一个记忆单元(memory cell),用于存储序列中的信息。记忆单元受输入门、遗忘门和输出门的控制,可以选择性地存储或删除信息。这些门和记忆单元的组合使得LSTM能够捕捉序列中长期依赖性的信息。

四、LSTM的代码和相关使用

以下是LSTM结构在TensorFlow中实现MNIST数据集分类的代码:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 加载MNIST数据集
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

# 设置超参数
learning_rate = 0.001
training_steps = 10000
batch_size = 128
display_step = 100

# 设置网络参数
n_inputs = 28 # 输入层的维度
n_steps = 28 # LSTM展开的步长
n_hidden_units = 128 # 隐藏层神经元数量
n_classes = 10 # 输出层的维度

# 创建输入占位符
x = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
y = tf.placeholder(tf.float32, [None, n_classes])

# 定义LSTM单元
lstm_cell = tf.contrib.rnn.BasicLSTMCell(n_hidden_units)

# 初始化LSTM状态
init_state = lstm_cell.zero_state(batch_size, tf.float32)

# 将输入数据转换为LSTM可以处理的形式
inputs = tf.unstack(x, n_steps, 1)

# 定义网络结构
outputs, states = tf.contrib.rnn.static_rnn(lstm_cell, inputs, initial_state=init_state)

# 定义输出层
weights = tf.Variable(tf.random_normal([n_hidden_units, n_classes]))
biases = tf.Variable(tf.random_normal([n_classes]))
output = tf.matmul(outputs[-1], weights) + biases

# 定义损失函数和优化器
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=output, labels=y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)

# 定义评估模型的指标
correct_pred = tf.equal(tf.argmax(output, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

# 初始化变量
init = tf.global_variables_initializer()

# 开始训练
with tf.Session() as sess:
    sess.run(init)
    for step in range(1, training_steps + 1):
        # 获取batch数据
        batch_x, batch_y = mnist.train.next_batch(batch_size)
        batch_x = batch_x.reshape((batch_size, n_steps, n_inputs))
        # 运行优化器
        sess.run(optimizer, feed_dict={x: batch_x, y: batch_y})
        if step % display_step == 0 or step == 1:
            # 计算损失和精度
            loss_val, acc_val = sess.run([loss, accuracy], feed_dict={x: batch_x, y: batch_y})
            print("Step " + str(step) + ", Minibatch Loss= " + \
                  "{:.4f}".format(loss_val) + ", Training Accuracy= " + \
                  "{:.3f}".format(acc_val))
    print("Optimization Finished!")
    
    # 进行测试
    test_data = mnist.test.images.reshape((-1, n_steps, n_inputs))
    test_labels = mnist.test.labels
    print("Testing Accuracy:", \
        sess.run(accuracy, feed_dict={x: test_data, y: test_labels}))

这段代码定义了一个有一层LSTM和一个全连接输出层的神经网络,可以对28*28像素的手写数字图像进行分类,最终的精度可达到约97%。static_rnn和dynamic_rnn是TensorFlow中两种不同的RNN实现方式。

例子中使用的静态的rnn

static_rnn是一种静态的RNN实现方式,需要**事先定义好RNN的长度** 
在静态图中将RNN展开成固定的层数,每层都有相同的权重和偏置参数
。这种方式适用于序列长度已知、且固定不变的情况。

dynamic_rnn是一种动态的RNN实现方式,可以处理不同长度的输入序列,
不需要事先定义好序列长度,而是根据输入数据在图中动态构建计算图。
这种方式相对于static_rnn更加灵活,适用于序列长度不固定的情况。

在实际使用中,如果序列长度已知且固定,可以使用static_rnn;如果序列长度不固定,需要动态构建计算图,则应该使用dynamic_rnn。

4.1一开始会需要产生initial_state(c_state,m_state)可以看成一个是主线另一个是支线,共同推进故事

tf.nn.rnn_cell.BasicLSTMCell(state_is_tuple=True)中的这个tuple元组参数由initial_state决定

outputs,states=tf.nn.dynamic_rnn(lstm_cell,X_in,initial_state=__init_state,time_major=False)此处的time_major是指主要依赖输入的这个x_in中起到分步走的要素是否是元组的第一个要素(元组中占位是否第一)

4.2lstm cell is divided into two part(c_state,m_state)

在隐藏层中

results=tf.matmul(state[1],weight['out'])+biases['out']

state[1]指的就是m_state

4.3关于结尾处的state[1]代码中的代替写法

4.3.1基础前提:tf.transpose中perm的对维度的影响

首先我们看下perm会对tensor的shape会进行什么调整,比如我们有一个shape=[2, 3, 4],那么经过各种perm配置后转换shape结果如下

tf.transpose(x, perm=[0, 1, 2])		# shape变为[2, 3, 4]
tf.transpose(x, perm=[0, 2, 1])		# shape变为[2, 4, 3]
tf.transpose(x, perm=[1, 0, 2])		# shape变为[3, 2, 4]
tf.transpose(x, perm=[1, 2, 0])		# shape变为[3, 4, 2]
tf.transpose(x, perm=[2, 1, 0])		# shape变为[4, 3, 2]
tf.transpose(x, perm=[2, 0, 1])		# shape变为[4, 2, 3]

官网上找不到unpack的用法了,不知道是不是看的视频太老
b站莫烦中outputs=tf.unpack(tf.transpose(outputs,[1,0,2]))#让states成为最后的ouputs
所以results=tf.matmul(output[-1],weight['out'])+biases['out']
引用自链接: 知乎中关于transpose的说法

4.4数据处理过程最重要的事情是保持数据的格式

比如:在含有batchsize和图片的行列数据形成了三维数据,必须先转为2维,再进行matmulW+bias
然后在重新分离开(课程中的案例)

"""
Know more, visit my Python tutorial page: https://morvanzhou.github.io/tutorials/
My Youtube Channel: https://www.youtube.com/user/MorvanZhou

Dependencies:
tensorflow: 1.1.0
matplotlib
numpy
"""
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
import matplotlib.pyplot as plt

tf.set_random_seed(1)
np.random.seed(1)

# Hyper Parameters
BATCH_SIZE = 64
TIME_STEP = 28          # rnn time step / image height
INPUT_SIZE = 28         # rnn input size / image width
LR = 0.01               # learning rate

# data
mnist = input_data.read_data_sets('./mnist', one_hot=True)              # they has been normalized to range (0,1)


test_x = mnist.test.images[:2000]
test_y = mnist.test.labels[:2000]

# plot one example
print(mnist.train.images.shape)     # (55000, 28 * 28)
print(mnist.train.labels.shape)   # (55000, 10)
plt.imshow(mnist.train.images[0].reshape((28, 28)), cmap='gray')
plt.title('%i' % np.argmax(mnist.train.labels[0]))
plt.show()

# tensorflow placeholders
tf_x = tf.placeholder(tf.float32, [None, TIME_STEP * INPUT_SIZE])       # shape(batch, 784)
image = tf.reshape(tf_x, [-1, TIME_STEP, INPUT_SIZE])                   # (batch, height, width, channel)
tf_y = tf.placeholder(tf.int32, [None, 10])                             # input y

# RNN
rnn_cell = tf.nn.rnn_cell.LSTMCell(num_units=64)
outputs, (h_c, h_n) = tf.nn.dynamic_rnn(
    rnn_cell,                   # cell you have chosen
    image,                      # input
    initial_state=None,         # the initial hidden state
    dtype=tf.float32,           # must given if set initial_state = None
    time_major=False,           # False: (batch, time step, input); True: (time step, batch, input)
)
output = tf.layers.dense(outputs[:, -1, :], 10)              # output based on the last output step

loss = tf.losses.softmax_cross_entropy(onehot_labels=tf_y, logits=output)           # compute cost
train_op = tf.train.AdamOptimizer(LR).minimize(loss)

accuracy = tf.metrics.accuracy(          # return (acc, update_op), and create 2 local variables
    labels=tf.argmax(tf_y, axis=1), predictions=tf.argmax(output, axis=1),)[1]

sess = tf.Session()
init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer()) # the local var is for accuracy_op
sess.run(init_op)     # initialize var in graph

for step in range(1200):    # training
    b_x, b_y = mnist.train.next_batch(BATCH_SIZE)
    _, loss_ = sess.run([train_op, loss], {tf_x: b_x, tf_y: b_y})
    if step % 50 == 0:      # testing
        accuracy_ = sess.run(accuracy, {tf_x: test_x, tf_y: test_y})
        print('train loss: %.4f' % loss_, '| test accuracy: %.2f' % accuracy_)

# print 10 predictions from test data

test_output = sess.run(output, {tf_x: test_x[:10]})
pred_y = np.argmax(test_output, 1)
print(pred_y, 'prediction number')
print(np.argmax(test_y[:10], 1), 'real number')

新版本换用法
#RNN layer can take a list of cells, which will then stack them together.
#By default, keras RNN will only return the last timestep output and will not
return states. If you need whole time sequence output as well as the states,

you can set return_sequences and return_state to True.

rnn_layer = tf.keras.layers.RNN([tf.keras.layers.LSTMCell(128),
tf.keras.layers.LSTMCell(256)],
return_sequences=True,
return_state=True)
outputs, output_states = rnn_layer(inputs, states)

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值