循环神经网络与LSTM网络
循环神经网络与LSTM网络
循环神经网络RNN
循环神经网络广泛地应用在序列数据上面,如自然语言,语音和其他的序列数据上。序列数据是有很强的次序关系,比如自然语言。通过深度学习关于序列数据的算法要比两年前的算法有了很大的提升。由此诞生了很多有趣的应用,比如语音识别,音乐合成,聊天机器人,机器翻译,自然语言理解和其他的一些应用。
符号说明:
上标[l]: 表示第层,例如,例如是第四层的激活元。和是层参数
上标(i):表示第i个样本,例如表示第训练样本输入
上标<t>:表示第个时间戳,例如是输入x在第的时间戳。是样本i
个时间戳
下标i:表示向量中的第项。例如表示激活元在l层中的第项
循环神经网络的基本结构如下:

简单的说明,x就是我们输入的序列数据,如果让每一个表示一个字符的话,单词hello,就会有四个输入,分别表示h,e,l,l,o。y是我们的输出数据,我们希望通过获得的下一个字符。在这个例子中是hello的第一个字符h,的下一个字符为e,因此我们希望为e。
循环神经网络的输入:(h,e,l,l,o)
循环神经网络的输出:(根据实际的输出情况)
输出正确的标签:(e,l,l,o, )
其中为隐变量记录之前的状态信息用来计算下一个,以及
图中的每个RNN-cell结构都是相同的(所有的参数也一样)。因此上图中的循环神经网络也可以表示成如下的形式

该模型有点像隐马尔可夫模型,每一个预测结果只依赖与前一个节点的信息,而与无关。
对于每一个RNN-cell的内容如下:


这是基本的RNN单元,通过当前的输入和(之前的隐藏状态包含了过去的信息)进行计算获得预测的下一个字符以及来给下一层RNN单元计算。
代价函数的计算

要对整个前向传播中产生的预测结果y都要用来计算代价代价函数。代价函数可以使用上次提到的交叉熵来计算。将预测结果与输出的正确标签做交叉熵。
由于给出了RNN-cell的结果因此循环神经网络可以进行前向传播了。由于现在的深度学习框架比如tensorflow等很方便,只要定义好前向传播的过程,以及代价函数,框架就会帮你进行反向传播计算。
如果不用tensorflow框架进行神经网络搭建这里还是给出了循环神经网络的反向传播计算公式(注:如果求导过于复杂可以通过Calculus软件进行求导的计算,该软件会给出具体的求导过程)

对于训练好的模型进行采样

还是以上面的例子为例,在采样的过程中用户输入第一个字符='h',循环神经网络根据'h'预测'h'的下一个字符最大概率为'e',把预测的字符'e'作为下一个输入以此循环递归。关于何时结束,我们可以指定定长的字符生成后结束。注意:在大样本的训练中,为了保证结果的多样性,我们一般不直接选择预测最大的字符作为下一个输入字符,而是在预测的结果序列进行概率采样,或者随机采样。
LSTM(长短时记忆网络)
上文中已经提到了可以对序列模型进行训练,以及采样。但是由于循环神经网络层数过多,存在梯度消失的问题。该问题直接导致的效果如下。假设有下面两个句子用来训练
"The cat, which already ate……,was full"
"The cats, which already ate……,were full"
逗号表示由很多个单词。
我们需要学习当出现cat的时候需要使用was,当出现cats的时候需要使用were。由于梯度消失的问题,理论上循环神经网络是无法学习这种具有长时间依赖关系的词性变化。由此引入了LSTM(长短时记忆网络)。
LSTM的整体结构和RNN很像都是循环递归的,只是将RNN-cell替换成LSTM-cell。LSTM-cell的表示如下


:Forget gate(忘记门),在这个例子中让我们假设每次的输入都是一个单词,我们希望LSTM保持语法结构,例如主语是单数还是复数。如果主语从单数变为复数,我们需要找到一种方法来避免之前存储的关于单数和复数的状态。在LSTM中,Forget gate让我们做这件事情。

上面式子的计算结果在0到1之间。Forget gate向量会和之前cell的状态相乘,如果值为0(或者接近0)那么它意味着LSTM应该移除之前的状态信息(例如,主语是单数),如果是1,那么应该保持该信息。
:Update gate(更新门),一旦我们忘记了主语是单数,我们需要一种方式来说更新它来反应新的主语是复数。下面是更新门的表达式:

更新门会和相乘,来计算
为了计算新的主语,我们需要创建一个新的向量可以用来增加先前的cell状态。表达式如下:

最后信息的cell状态如下:

:Outputs gate(输出门),用来控制输出结果

将每一个LSTM-cell连接起来就构成了LSTM的前向传播了

在tensorflow中根据该网络结构就可以构造出前向传播的算法,进行计算了。下面会给出LSTM的代码。
如果不用tensorflow进行计算,这里简单的给出LSTM的反向传播公式:
gate derivatives

Parameter derivatives

previous hidden state, previous memory state, and input


#导入相应的包
from __future__ import print_function
import os
import numpy as np
import random
import string
import tensorflow as tf
import zipfile
from six.moves import range
from six.moves.urllib.request import urlretrieve #读取莎士比亚的文本文件
path = "./shakespeare" #文件夹目录
files= os.listdir(path) #得到文件夹下的所有文件名称
text =""
for file in files: #遍历文件夹
if not os.path.isdir(file): #判断是否是文件夹,不是文件夹才打开
f = open(path+"/"+file,'r'); #打开文件
iter_f = iter(f); #创建迭代器
str = ""
for line in iter_f: #遍历文件,一行行遍历,读取文本
str = str + line
text+=str #每个文件的文本存到list中 print('Data size %d' % len(text)) #将莎士比亚文本中出现的所有字符做成字典并编号
vocab = set(text) vocab_to_int = {c: i for i, c in enumerate(vocab)}
int_to_vocab = dict(enumerate(vocab)) #构造测试集和训练集
valid_size = 1000
valid_text = text[:valid_size]
train_text = text[valid_size:]
train_size = len(train_text)
print(train_size, train_text[:64])
print(valid_size, valid_text[:64]) vocabulary_size =len(set(text)) batch_size = 64
num_unrollings = 10 #训练用的Batch生成器
class BatchGenerator(object):
def __init__(self, text, batch_size, num_unrollings):
self._text = text
self._text_size = len(text)
self._batch_size = batch_size
self._num_unrollings = num_unrollings
segment = self._text_size // batch_size
self._cursor = [offset * segment for offset in range(batch_size)]
self._last_batch = self._next_batch() def _next_batch(self):
"""Generate a single batch from the current cursor position in the data."""
batch = np.zeros(shape=(self._batch_size, vocabulary_size), dtype=np.float)
for b in range(self._batch_size):
#batch[b, char2id(self._text[self._cursor[b]])] = 1.0
batch[b, vocab_to_int[self._text[self._cursor[b]]]] = 1.0
self._cursor[b] = (self._cursor[b] + 1) % self._text_size
return batch def next(self):
"""Generate the next array of batches from the data. The array consists of
the last batch of the previous array, followed by num_unrollings new ones.
"""
batches = [self._last_batch]
for step in range(self._num_unrollings):
batches.append(self._next_batch())
self._last_batch = batches[-1]
return batches #将概率分布转化为1-hot形式
def characters(probabilities):
"""Turn a 1-hot encoding or a probability distribution over the possible
characters back into its (most likely) character representation."""
#return [id2char(c) for c in np.argmax(probabilities, 1)]
temp=np.argmax(probabilities,1)
return [int_to_vocab[c] for c in np.argmax(probabilities, 1)] #将batches转化成字符串
def batches2string(batches):
"""Convert a sequence of batches back into their (most likely) string
representation."""
s = [''] * batches[0].shape[0]
for b in batches:
s = [''.join(x) for x in zip(s, characters(b))]
return s train_batches = BatchGenerator(train_text, batch_size, num_unrollings)
valid_batches = BatchGenerator(valid_text, 1, 1) print(batches2string(train_batches.next()))
print(batches2string(train_batches.next()))
print(batches2string(valid_batches.next()))
print(batches2string(valid_batches.next())) def logprob(predictions, labels):
"""Log-probability of the true labels in a predicted batch."""
predictions[predictions < 1e-10] = 1e-10
return np.sum(np.multiply(labels, -np.log(predictions))) / labels.shape[0] #采样相关的函数,用于字符的生成
def sample_distribution(distribution):
"""Sample one element from a distribution assumed to be an array of normalized
probabilities.
"""
r = random.uniform(0, 1)
s = 0
for i in range(len(distribution)):
s += distribution[i]
if s >= r:
return i
return len(distribution) - 1 def sample(prediction):
"""Turn a (column) prediction into 1-hot encoded samples."""
p = np.zeros(shape=[1, vocabulary_size], dtype=np.float)
p[0, sample_distribution(prediction[0])] = 1.0
return p def random_distribution():
"""Generate a random column of probabilities."""
b = np.random.uniform(0.0, 1.0, size=[1, vocabulary_size])
tmp=np.sum(b,1)
tmp1=np.sum(b,1)[:None]
return b/np.sum(b, 1)[:,None] num_nodes = 64
#构造LSTM
graph = tf.Graph()
with graph.as_default():
# Parameters:
# Input gate: input, previous output, and bias.
ix = tf.Variable(tf.truncated_normal([vocabulary_size, num_nodes], -0.1, 0.1))
im = tf.Variable(tf.truncated_normal([num_nodes, num_nodes], -0.1, 0.1))
ib = tf.Variable(tf.zeros([1, num_nodes]))
# Forget gate: input, previous output, and bias.
fx = tf.Variable(tf.truncated_normal([vocabulary_size, num_nodes], -0.1, 0.1))
fm = tf.Variable(tf.truncated_normal([num_nodes, num_nodes], -0.1, 0.1))
fb = tf.Variable(tf.zeros([1, num_nodes]))
# Memory cell: input, state and bias.
cx = tf.Variable(tf.truncated_normal([vocabulary_size, num_nodes], -0.1, 0.1))
cm = tf.Variable(tf.truncated_normal([num_nodes, num_nodes], -0.1, 0.1))
cb = tf.Variable(tf.zeros([1, num_nodes]))
# Output gate: input, previous output, and bias.
ox = tf.Variable(tf.truncated_normal([vocabulary_size, num_nodes], -0.1, 0.1))
om = tf.Variable(tf.truncated_normal([num_nodes, num_nodes], -0.1, 0.1))
ob = tf.Variable(tf.zeros([1, num_nodes]))
# Variables saving state across unrollings.
saved_output = tf.Variable(tf.zeros([batch_size, num_nodes]), trainable=False)
saved_state = tf.Variable(tf.zeros([batch_size, num_nodes]), trainable=False)
# Classifier weights and biases.
w = tf.Variable(tf.truncated_normal([num_nodes, vocabulary_size], -0.1, 0.1))
b = tf.Variable(tf.zeros([vocabulary_size])) # Definition of the cell computation.
def lstm_cell(i, o, state):
"""Create a LSTM cell. See e.g.: http://arxiv.org/pdf/1402.1128v1.pdf
Note that in this formulation, we omit the various connections between the
previous state and the gates."""
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.matmul(i, cx) + tf.matmul(o, cm) + cb
state = forget_gate * state + input_gate * tf.tanh(update)
output_gate = tf.sigmoid(tf.matmul(i, ox) + tf.matmul(o, om) + ob)
return output_gate * tf.tanh(state), state # Input data.
train_data = list()
for _ in range(num_unrollings + 1):
train_data.append(
tf.placeholder(tf.float32, shape=[batch_size, vocabulary_size]))
train_inputs = train_data[:num_unrollings]
train_labels = train_data[1:] # labels are inputs shifted by one time step. # Unrolled LSTM loop.
outputs = list()
output = saved_output
state = saved_state
for i in train_inputs:
output, state = lstm_cell(i, output, state)
outputs.append(output) # State saving across unrollings.
with tf.control_dependencies([saved_output.assign(output),
saved_state.assign(state)]):
# Classifier.
# The Classifier will only run after saved_output and saved_state were assigned.
logits = tf.nn.xw_plus_b(tf.concat(outputs, 0), w, b)
loss = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(
logits=logits, labels=tf.concat(train_labels, 0))) # Optimizer.
global_step = tf.Variable(0)
learning_rate = tf.train.exponential_decay(
10.0, global_step, 5000, 0.1, staircase=True)
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
gradients, v = zip(*optimizer.compute_gradients(loss))
gradients, _ = tf.clip_by_global_norm(gradients, 1.25)
optimizer = optimizer.apply_gradients(
zip(gradients, v), global_step=global_step) # Predictions.
train_prediction = tf.nn.softmax(logits) # Sampling and validation eval: batch 1, no unrolling.
sample_input = tf.placeholder(tf.float32, shape=[1, vocabulary_size])
saved_sample_output = tf.Variable(tf.zeros([1, num_nodes]))
saved_sample_state = tf.Variable(tf.zeros([1, num_nodes]))
reset_sample_state = tf.group(
saved_sample_output.assign(tf.zeros([1, num_nodes])),
saved_sample_state.assign(tf.zeros([1, num_nodes])))
sample_output, sample_state = lstm_cell(
sample_input, saved_sample_output, saved_sample_state)
with tf.control_dependencies([saved_sample_output.assign(sample_output),
saved_sample_state.assign(sample_state)]):
sample_prediction = tf.nn.softmax(tf.nn.xw_plus_b(sample_output, w, b))
saver = tf.train.Saver() num_steps = 37001
summary_frequency = 100 #saver = tf.train.Saver(var_list=[ib])
with tf.Session(graph=graph) as session:
tf.global_variables_initializer().run()
print('Initialized')
mean_loss = 0
for step in range(num_steps):
batches = train_batches.next()
feed_dict = dict()
# Add training data from batches to corresponding train_data position in the feed_dict
for i in range(num_unrollings + 1):
feed_dict[train_data[i]] = batches[i]
# Train the model
_, l, predictions, lr = session.run(
[optimizer, loss, train_prediction, learning_rate], feed_dict=feed_dict)
mean_loss += l if step % summary_frequency == 0:
if step > 0:
mean_loss = mean_loss / summary_frequency
# The mean loss is an estimate of the loss over the last few batches.
print(
'Average loss at step %d: %f learning rate: %f' % (step, mean_loss, lr))
mean_loss = 0
labels = np.concatenate(list(batches)[1:])
print('Minibatch perplexity: %.2f' % float(
np.exp(logprob(predictions, labels))))
if step % (summary_frequency * 10) == 0:
# Generate some samples.
print('=' * 80)
for _ in range(5):
feed = sample(random_distribution())
tmp=characters(feed)
sentence = characters(feed)[0]
reset_sample_state.run()
for _ in range(1379):
prediction = sample_prediction.eval({sample_input: feed})
feed = sample(prediction)
#feed = np.zeros(shape=[1, vocabulary_size], dtype=np.float)
#feed[0, vocab_to_int[characters(prediction)[0]]] = 1.0
sentence += characters(prediction)[0]
print(sentence)
# Measure validation set perplexity.
reset_sample_state.run()
valid_logprob = 0
for _ in range(valid_size):
b = valid_batches.next()
predictions = sample_prediction.eval({sample_input: b[0]})
valid_logprob = valid_logprob + logprob(predictions, b[1])
print('Validation set perplexity: %.2f' % float(np.exp(
valid_logprob / valid_size)))
实验结果:
在阿里云中的服务器中跑1h的结果为
Iivind to sh te no sh bnt if tete t segsunsed mrovd of teauty sormw And ttmdi n,
Aut teatme
Tr whene tn toer tone tf tftwaas srmtoundsng miser and to e stnce whrks anl the r sfer s aar thoarered
Tnd tore toaet oned
Th thol'nte miye thle theu h the seert
And stael soar,
Then trewgd then sirt thauld ttyle oegg, trwroun hhe weaath
Ahve tou sere nles thet ts teailesTour noy th mtye Autt ther ihere ore tavh trr h st tavh tyes
And tese,tove a dot su g,sart,
可以看出来它已经学会了部分单词,以及分段了
在阿里云中的服务器中跑3h的结果为:
L
Thosethet tn the sime tirte orove , Ao tolb tn the srlt shen t antrtn,
wo myst n st
Aut tune eye ds tocjenedtitl be tot ing mh trne
7
To ivesi soi teat uent temieeksand tvteem,oolrh oeintitn the sear frel d snd mfe
Tided itml r tnpge taovang snuie tor trrg r ios morld ty Ay ledd, o sii e thi ift tfrerlewe aow that toar f beathed wea
Tnd tincle silh tuape the saerher of atne tor mhes ht
Thet teve sn tour siic m'hle teseishne tn ty hlay ahat tldyn t coture tor my sene,
它已经初步知道可以给段落打标签了,如上面出现的7
[Tā yǐjīng chūbù zhīdào kěyǐ gěi duànluò dǎ biāoqiānle, rú shàngmiàn chūxiàn de]
It has initially known that it can label paragraphs, as shown above.
循环神经网络与LSTM网络的更多相关文章
- 循环神经网络之LSTM和GRU
看了一些LSTM的博客,都推荐看colah写的博客<Understanding LSTM Networks> 来学习LSTM,我也找来看了,写得还是比较好懂的,它把LSTM的工作流程从输入 ...
- 循环神经网络(LSTM和GRU)(1)
循环神经网络的简单实现: import tensorflow as tf x=[1,2] state=[0.0,0.0] w_cell_state=np.array([[0.1,0.2],[0.3,0 ...
- 【神经网络】LSTM 网络
Long Short Term 网络—— 一般就叫做 LSTM ——是一种 RNN 特殊的类型,可以学习长期依赖信息.LSTM 由Hochreiter & Schmidhuber (199 ...
- 循环神经网络(LSTM和GRU)(2)
1.tf.nn.dynamic_rnn()函数 参考:http://www.360doc.com/content/17/0321/10/10408243_638692495.shtml 参考:http ...
- 通过keras例子理解LSTM 循环神经网络(RNN)
博文的翻译和实践: Understanding Stateful LSTM Recurrent Neural Networks in Python with Keras 正文 一个强大而流行的循环神经 ...
- 十 | 门控循环神经网络LSTM与GRU(附python演练)
欢迎大家关注我们的网站和系列教程:http://panchuang.net/ ,学习更多的机器学习.深度学习的知识! 目录: 门控循环神经网络简介 长短期记忆网络(LSTM) 门控制循环单元(GRU) ...
- Recurrent Neural Network系列1--RNN(循环神经网络)概述
作者:zhbzz2007 出处:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明.谢谢! 本文翻译自 RECURRENT NEURAL NETWORKS T ...
- Recurrent Neural Networks(RNN) 循环神经网络初探
1. 针对机器学习/深度神经网络“记忆能力”的讨论 0x1:数据规律的本质是能代表此类数据的通用模式 - 数据挖掘的本质是在进行模式提取 数据的本质是存储信息的介质,而模式(pattern)是信息的一 ...
- 【学习笔记】循环神经网络(RNN)
前言 多方寻找视频于博客.学习笔记,依然不能完全熟悉RNN,因此决定还是回到书本(<神经网络与深度学习>第六章),一点点把啃下来,因为这一章对于整个NLP学习十分重要,我想打好基础. 当然 ...
随机推荐
- oracle删除数据库表空间
步骤一: 删除user drop user ×× cascade 说明: 删除了user,只是删除了该user下的schema objects,是不会删除相应的tablespace的. 步骤二: 删 ...
- Android笔记--Bitmap
Android | Bitmap解析 Android中Bitmap是对图像的一种抽象.通过他可以对相应的图像进行剪裁,旋转,压缩,缩放等操作.这里循序渐进的一步步了解Bitmap的相关内容. 先了解B ...
- Actionbar Demo
源码下载:http://download.csdn.net/detail/bx276626237/8874119
- C#语言基础 Main 函数中变量 整型
在我们每次上网或者用电脑的时候,请输入你的xxx 或者你的名字(年龄/身高/学校/籍贯)是 在这里我们就要学到一些变量,就是不确定的东西 string a: //赋予变量 a ="内容& ...
- vijos 1034 家族(水题日常)
描述 若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系. 规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚.如果x,y是亲戚 ...
- spring (由Rod Johnson创建的一个开源框架)
你可能正在想“Spring不过是另外一个的framework”.当已经有许多开放源代码(和专有)J2EEframework时,我们为什么还需要Spring Framework? Spring是独特的, ...
- Ubuntu 16.04下Java环境安装与配置
首先下载linux下的安装包 登陆网址https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.h ...
- 树形dp——Tree2cycle
一.问题描述(题目链接) 给你一棵树,删除或添加一条边的费用都是1,问使它变成一个环的最小费用. 二.解题思路 回溯法,然后回溯的时候的当前节点度数>2(如果是成环的话肯定就是2或者小于2)就把 ...
- 屏蔽系统的Ctrl+c/x/v操作
实现效果: 知识运用: KeyEventArgs类的Control, public bool Control {get;} //获取一个值 该值指示是否曾按下Ctrl键 KeyCode和Handled ...
- 数据库_8_SQL基本操作——数据操作
SQL基本操作——数据操作 一.新增数据(两种方案) 方案1: 给全表字段插入数据,不需要指定字段列表,要求数据的值出现的顺序必须与表中设计的字段出现的顺序一致,凡是非数值数据,都需要使用引号(建议是 ...