当前位置:   article > 正文

2022.12.11 第十一次周报_long short-term memory recurrent neural network ar

long short-term memory recurrent neural network architectures for large scal


前言

This week studied an article,《Long Short-Term Memory Recurrent Neural Network Architectures for Large Scale Acoustic Modeling》 ,showed that deep LSTM RNN architectures achieve state-of-the-art performance for large scale acoustic modeling. The proposed deep LSTMP RNN architecture outperforms standard LSTM networks and DNNs .In addition, I summarized some simple understandings of tensor and trained rnn model by tensorflow.
本周研究了一篇文章《Long Short-Term Memory Recurrent Neural Network Architectures for Large Scale Acoustic Modeling》,该文表明,深度LSTM RNN架构在大规模声学建模中实现了最先进的性能。所提出的深度LSTM RNN架构优于标准LSTM网络和DNN。此外,我总结了张量的一些简单理解,并通过tensorflow训练了RNN模型。


一、论文阅读《Long Short-Term Memory Recurrent Neural Network Architectures for Large Scale Acoustic Modeling》

摘要

本文是关于RNN神经网络的一篇文章,主要通过比较传统RNN,传统LSTM,深层LSTM,和双向LSTM (BLSTM),和LSTMP(加入了一层projection layer投影层)之间的处理大规模声学建模问题的效果。论文展示了深度LSTM RNN架构在大规模声学建模方面达到了最先进的性能。提出的深度LSTMP RNN架构优于标准LSTM网络和dnn,并通过解决训练大型网络所需的计算效率,更有效地利用模型参数。还首次证明了LSTM RNN模型可以使用ASGD分布式训练快速训练。

改进

四个LSTM的模型(LSTM、DLSTM、LSTMP、DLSTMP)
在这里插入图片描述
这里主要介绍两种对比,传统的LSTM和加入了一层projection layer投影层的LSTMP。

传统LSTM

LSTM在循环隐藏层中包含称为内存块的特殊单元。记忆块包含具有自我连接的记忆单元,存储网络的时间状态,此外还有特殊的乘法单元,称为门,用于控制信息流。原始架构中的每个内存块都包含一个输入门和一个输出门。输出门控制细胞激活到网络其余部分的输出流。后来,遗忘门被添加到内存块[18]中。遗忘门则解决了LSTM模型的一个弱点,即不能处理未分段为子序列的连续输入流。
各个门的公式:
在这里插入图片描述

LSTMP

LSTMP是加入了一层projection layer投影层的LSTM。因为LSTM的参数过多,所以作者提出了长短期记忆投影(LSTMP)架构,以解决学习LSTM模型的计算复杂性,循环连接现在从这个循环投影层连接到LSTM层的输入。网络输出单元连接到这个循环层。
其中在提出的LSTMP架构中,网络单元的激活方程发生了轻微的变化,将mt-1激活向量替换为rt-1
在这里插入图片描述
也是就是把上面的(5)(6)换了。

实验思路

作者选择在多核CPU而不是GPU上实现LSTM RNN架构。这个决定是基于CPU相对简单的实现复杂性、易于调试以及使用由商用硬件组成的集群的能力。对于矩阵运算,作者使用特征矩阵库。这个模板化的c++库使用向量化指令为CPU上的矩阵运算提供了高效的实现。使用SIMD指令在矩阵上实现激活函数和梯度计算,以受益于并行化。
作者使用截断时间反向传播(BPTT)学习算法来计算训练话语的短子序列的参数梯度。激活正向传播一个固定的步骤时间Tbptt。交叉熵梯度计算这个子序列,并反向传播到它的开始。为了提高计算效率,每个线程一次操作四个语句的子序列,因此矩阵乘法可以同时在四个帧上并行操作。我们使用异步随机梯度下降(ASGD)来优化网络参数,从多核机器上的多个线程异步更新参数。这有效地增加了批处理的大小,并减少了给定批处理中帧的相关性。在线程更新了参数之后,它将继续每个语句中的下一个子序列,保留LSTM状态,或者在一个语句结束时以reset状态开始新的语句。请注意,每个语句的最后子序列可以比Tbptt短,但会填充到完整的长度,尽管不会为这些填充帧生成梯度。

实验

作者评估和比较LSTM RNN架构在大词汇量语音识别任务-谷歌语音搜索任务上的性能。我们使用混合方法与LSTM rnn进行声学建模,其中神经网络估计隐马尔可夫模型(HMM)状态后视。我们用从训练数据中估计的相对状态频率的状态先验来缩放状态后验,以获得声帧似然。在估计状态频率时,我们将沉默状态计数降低了2.7倍。
作者使用混合方法[24]与LSTM rnn进行声学建模,其中神经网络估计隐马尔可夫模型(HMM)状态后视。我们用从训练数据中估计的相对状态频率的状态先验来缩放状态后验,以获得声帧似然。
在这里插入图片描述
图3比较了不同LSTM和LSTMP架构下训练集和保留集上的帧精度。LSTMP RNN架构在大量内存单元(2048个)下的过拟合问题可以清晰地看到。我们观察到LSTMP RNN结构比LSTM RNN结构收敛更快。很明显,拥有更多的层有助于泛化,但会使训练变得更难,收敛速度变慢。

在这里插入图片描述

表2显示了具有深度LSTMP RNN架构的网络性能随模型参数深度和数量的变化。我们看到,将参数数量增加到13M以上并不能提高性能。我们还可以在不影响性能的情况下大幅减少参数的数量。深度LSTMP RNN架构有两层,每层有800个单元和512个循环投影单元,大多数在48小时内收敛,并在独立测试集上给出10.9%的WER。训练该模型100小时,WER提高到10.7%,200小时提高到10.5%。相比之下,我们最好的具有85M参数的DNN模型在相同光束下给出11.3%,并且训练需要几周时间。

二、实现LSTM

这都是使用mnist数据集的,其他数据集比较难找。

初级手写实现

import tensorflow as tf
import numpy as np
sess = tf.InteractiveSession()
#载入数据
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('mnist/', one_hot=True)
#定义参数和变量
learning_rate = 0.001
batch_size = 128
n_input = 28
n_steps = 28
n_hidden = 128
n_classes = 10
 
x = tf.placeholder(tf.float32, [None, n_steps, n_input])
y = tf.placeholder(tf.float32, [None, n_classes])
 
def RNN(x, n_steps, n_input, n_hidden, n_classes):
    # Parameters:
    # 更新门: input, previous output, and bias
    ix = tf.Variable(tf.truncated_normal([n_input, n_hidden], -0.1, 0.1))
    im = tf.Variable(tf.truncated_normal([n_hidden, n_hidden], -0.1, 0.1))
    ib = tf.Variable(tf.zeros([1, n_hidden]))
    # Forget gate: input, previous output, and bias
    fx = tf.Variable(tf.truncated_normal([n_input, n_hidden], -0.1, 0.1))
    fm = tf.Variable(tf.truncated_normal([n_hidden, n_hidden], -0.1, 0.1))
    fb = tf.Variable(tf.zeros([1, n_hidden]))
    # 遗忘门: input, state, and bias
    cx = tf.Variable(tf.truncated_normal([n_input, n_hidden], -0.1, 0.1))
    cm = tf.Variable(tf.truncated_normal([n_hidden, n_hidden], -0.1, 0.1))
    cb = tf.Variable(tf.zeros([1, n_hidden]))
    # 输出门: input, previous output, and bias
    ox = tf.Variable(tf.truncated_normal([n_input, n_hidden], -0.1, 0.1))
    om = tf.Variable(tf.truncated_normal([n_hidden, n_hidden], -0.1, 0.1))
    ob = tf.Variable(tf.zeros([1, n_hidden]))
    # Classifier weights and biases
    w = tf.Variable(tf.truncated_normal([n_hidden, n_classes]))
    b = tf.Variable(tf.zeros([n_classes]))
 
    # LSTM神经元的定义
    def lstm_cell(i, o, state):
        input_gate = tf.sigmoid(tf.matmul(i, ix) + tf.matmul(o, im) + ib)
        forget_gate = tf.sigmoid(tf.matmul(i, fx) + tf.matmul(o, fm) + fb)
        update = tf.tanh(tf.matmul(i, cx) + tf.matmul(o, cm) + cb)
        state = forget_gate * state + input_gate * update
        output_gate = tf.sigmoid(tf.matmul(i, ox) +  tf.matmul(o, om) + ob)
        return output_gate * tf.tanh(state), state
    
    # Unrolled LSTM loop
    outputs = list()
    state = tf.Variable(tf.zeros([batch_size, n_hidden]))
    output = tf.Variable(tf.zeros([batch_size, n_hidden]))
    
    # x shape: (batch_size, n_steps, n_input)
    # desired shape: list of n_steps with element shape (batch_size, n_input)
    x = tf.transpose(x, [1, 0, 2])
    x = tf.reshape(x, [-1, n_input])
    x = tf.split(0, n_steps, x)
    for i in x:
        output, state = lstm_cell(i, output, state)
        outputs.append(output)
    logits =tf.matmul(outputs[-1], w) + b
    return logits
 
#使用RNN构建训练模型
pred = RNN(x, n_steps, n_input, n_hidden, n_classes)
 
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(pred, y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
 
correct_pred = tf.equal(tf.argmax(pred,1), tf.argmax(y,1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
 
# Initializing the variables
init = tf.global_variables_initializer()
 
#载入计算图
sess.run(init)
for step in range(20000):
    batch_x, batch_y = mnist.train.next_batch(batch_size)
    batch_x = batch_x.reshape((batch_size, n_steps, n_input))
    sess.run(optimizer, feed_dict={x: batch_x, y: batch_y})
 
    if step % 50 == 0:
        acc = sess.run(accuracy, feed_dict={x: batch_x, y: batch_y})
        loss = sess.run(cost, feed_dict={x: batch_x, y: batch_y})
        print "Iter " + str(step) + ", Minibatch Loss= " +               "{:.6f}".format(loss) + ", Training Accuracy= " +               "{:.5f}".format(acc)
print "Optimization Finished!"
 
#测试数据
# Calculate accuracy for 128 mnist test images
test_len = batch_size
test_data = mnist.test.images[:test_len].reshape((-1, n_steps, n_input))
test_label = mnist.test.labels[:test_len]
print "Testing Accuracy:", sess.run(accuracy, feed_dict={x: test_data, y: test_label})
  • 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
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

使用tensorflow封装函数实现

# -*- coding: utf-8 -*-
__author__ = 'liudong'
__date__ = '2018/5/2 下午4:48'
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data
from PIL import Image

config = tf.ConfigProto()
sess = tf.Session(config=config)
mnist = input_data.read_data_sets ('/path/to/MNIST_data', one_hot=True)
print(mnist.train.images.shape)

# 设置用到的参数
lr = 1e-3
# 在训练和测试的时候 想使用不同的batch_size 所以采用占位符的方式
batch_size = tf.placeholder(tf.int32, [])
# 输入数据是28维 一行 有28个像素
input_size = 28
# 时序持续时长为28  每做一次预测,需要先输入28行
timestep_size = 28
# 每个隐含层的节点数
hidden_size = 64
# LSTM的层数
layer_num = 2
# 最后输出的分类类别数量,如果是回归预测的呼声应该是1
class_num = 10
_X = tf.placeholder(tf.float32, [None, 784])
y = tf.placeholder(tf.float32, [None, class_num])
keep_prob = tf.placeholder(tf.float32)

# 定义一个LSTM结构, 把784个点的字符信息还原成28*28的图片
X = tf.reshape(_X, [-1, 28, 28])
def unit_lstm():
    # 定义一层LSTM_CELL hiddensize 会自动匹配输入的X的维度
    lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(num_units=hidden_size, forget_bias=1.0, state_is_tuple=True)
    # 添加dropout layer, 一般只设置output_keep_prob
    lstm_cell = tf.nn.rnn_cell.DropoutWrapper(cell=lstm_cell, input_keep_prob=1.0, output_keep_prob=keep_prob)
    return lstm_cell
# 调用MultiRNNCell来实现多层 LSTM
mlstm_cell = tf.nn.rnn_cell.MultiRNNCell([unit_lstm() for i in range(3)], state_is_tuple=True)

# 使用全零来初始化state
init_state = mlstm_cell.zero_state(batch_size, dtype=tf.float32)
outputs, state = tf.nn.dynamic_rnn(mlstm_cell, inputs=X, initial_state=init_state,
                                   time_major=False)
h_state = outputs[:, -1, :]

# 设置loss function 和优化器
W = tf.Variable(tf.truncated_normal([hidden_size, class_num], stddev=0.1), dtype=tf.float32)
bias = tf.Variable(tf.constant(0.1, shape=[class_num]), dtype=tf.float32)
y_pre = tf.nn.softmax(tf.matmul(h_state, W) + bias)
# 损失和评估函数
cross_entropy = -tf.reduce_mean(y * tf.log(y_pre))
train_op = tf.train.AdamOptimizer(lr).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_pre, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

# 开始训练
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for i in range(1000):
        _batch_size = 128
        batch = mnist.train.next_batch(_batch_size)
        if (i+1)%200 == 0:
            train_accuracy  = sess.run(accuracy, feed_dict={
                _X: batch[0], y: batch[1], keep_prob: 1.0, batch_size: _batch_size
            })
            print("step %d, training accuracy %g" % ((i+1), train_accuracy ))
        sess.run(train_op, feed_dict={_X: batch[0], y: batch[1], keep_prob: 0.5,
                                      batch_size: _batch_size})
images = mnist.test.images
labels = mnist.test.labels
print("test accuracy %g" % sess.run(accuracy,feed_dict={_X: images, y: labels, keep_prob: 1.0,
                                                        batch_size: mnist.test.images.shape[0]}))

current_y = mnist.train.labels[5]
current_x = mnist.train.images[5]
print(current_y)
plt.show(current_x)

# 将原始数据进行转换,变为模型能够识别
current_x.shape = [-1, 784]
current_y.shape = [-1, class_num]
current_outputs = np.array(sess.run(outputs, feed_dict={
        _X: current_x, y: current_y, keep_prob: 1.0,batch_size: 1}))
current_outputs.shape = [28, hidden_size]

# 计算模型里边的变量
h_W = sess.run(W, feed_dict={_X: current_x,y: current_y, keep_prob: 1.0,batch_size: 1})
h_bias = sess.run(bias, feed_dict={_X: current_x,y: current_y, keep_prob: 1.0,batch_size: 1})
h_bias.shape = [-1, 10]

# 识别过程
bar_index = range(class_num)
for i in range(current_outputs.shape[0]):
    plt.subplot(7, 4, i+1)
    current_h_shate = current_outputs[i, :].reshape([-1, hidden_size])
    current_formula = tf.nn.softmax(tf.matmul(current_h_shate, h_W) + h_bias)
    pro = sess.run(current_formula)
    plt.bar(bar_index, pro[0], width=0.2)
    plt.axis('off')
plt.show()
  • 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
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104

结果:
在这里插入图片描述

三、张量是什么

张量的定义

1.张量是多维数组,这个定义常见于各种人工智能软件。
2.张量是某种几何对象,不会随着坐标系的改变而改变
3.张量是向量和余向量(covector)通过张量积(tensor product)组合而成的。
4.张量是多重线性映射,即:
在这里插入图片描述
其中V表示矢量空间,V*表示对偶空间。(对偶空间:定义一个线性空间到实数的映射,这个映射叫做泛函functional
,很多这样的映射,组合成一个集合,这个集合上定义一些符合空间的约束,形成一个空间,这样的空间就是对偶空间 )

张量的表示形式

一阶张量可以理解为一个向量,二阶张量可以理解为矩阵,三阶张量可以理解成立方体,四阶张量可以理解成立方体组成的一个向量,五阶张量可以理解成立方体组成的矩阵,依次类推。
1、标量(0D张量)
仅包含一个数字的张量叫作 标量 ( scalar ,也叫标量张量、零维张量、0D 张量)。在 Numpy 中,一个 float32 或 float64 的数字就是一个标量张量(或标量数组)。例如:数字1、10、613、1242
2、向量(1D张量)
数字组成的数组叫做向量(vector)或一维张量(1D张量)。一维张量只有一个轴。
例如:一阶张量(向量):[5,10,15,30,25]
3、矩阵(2D张量)
向量组成的数组叫做矩阵(matrix)或二维张量(2D张量)。矩阵有2个轴(通常叫做行和列)。
例如:二阶张量(矩阵):([[5,10,15,30,25],[20,30,65,70,90],[7,80,95,20,30]])
第一个轴上的元素叫做行(row),第二个轴上的元素叫做列(column).
4、3D张量与更高维张量
将多个矩阵组合成一个新的数组,可以得到一个3D张量。
例如:三阶张量:([[[5,10,15,30,25],[20,30,65,70,90],[7,80,95,20,30]],[[3,1,1,0,2],[2,3,5,7,9],[7,8,5,2,3]],[[15,0,5,0,5],[0,0,5,0,0],[7,0,5,0,0]]])
将多个3D张量组合成一个数组,可以创建一个4D张量,以此类推。深度学习处理的一般是0D到4D的张量,但处理视频 数据时可能会遇到5D张量。
在这里插入图片描述在这里插入图片描述

现实世界中的数据张量

1)向量数据:2D张量,形状为(samples, features)。

2)时间序列数据或序列数据:3D张量,形状为(samples,timestamps,features)。
当时间(或序列顺序)对于数据很重要时,应该将数据存储在带有时间轴的3D张量中。每个样本可以被编码为一个向量序列(即2D张量),因此一个数据批量就被编码为一个3D张量。
在这里插入图片描述

3)图像:4D张量,形状为(samples, height,width,channels)或(samples,channels,height,width)。
图像通常具有三个维度:高度,宽度和颜色深度。虽然灰度图像(比如MNIST数字图像)只有一个颜色通道,因此可以保存在2D张量中,但按照惯例,图像张量始终是3D张量,灰度图像的彩色通道只有一维。因此,如果图像大小为 256 × 256 256\times256256×256 ,那么128张灰度图像组成的批量可以保存在一个形状为(128,256,256,1)的张量中,而128张彩色图像组成的批量则可以保存在一个形状为(128,256,256,3)的张量中。

4)视频:5D张量,形状为(samples,frames, height,width,channels)或(samples,frames,channels,height,width)。
频可以看作一系列帧, 每一帧都是一张彩色图像。由于每一帧都可以保存在一个形状为 (height, width, color_ depth) 的 3D 张量中。

四、差分推导写成RNN结构

在这里插入图片描述

总结

一般来说,当前所有机器学习系统都使用张量作为基本数据结构。张量的核心在于,它是一个数据容器,包括数字,图片,音频,视频等。它包含的数据几乎总是数值数据,因此它是数字的容器,或者说在机器学习中,应该是一切输入输出的容器。本周还用tensorflow实现了LSTM模型,和用差分公式推导了波函数。同时还在论文中学习了LSTMP模型,用于处理大规模语音问题。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/662879
推荐阅读
相关标签
  

闽ICP备14008679号