文章目录

  • 长短期记忆网络(LSTM)
    • 模型定义
    • 模型特点
    • 用 LSTM 生成文本
  • 门控循环单元网络(GRU)
    • 模型定义
    • 模型特点
  • References

长短期记忆网络(LSTM)

模型定义

简单循环神经网络(S-RNN)的每一个位置的状态以递归方式计算:
h t = tanh ⁡ ( U ⋅ h t − 1 + W ⋅ x t + b ) , t = 1 , 2 , ⋯ , T \bm{h}_t = \tanh(\bm{U}\cdot \bm{h}_{t-1} +\bm{W}\cdot \bm{x}_t + \bm{b}),\quad t=1,2,\cdots,T ht​=tanh(U⋅ht−1​+W⋅xt​+b),t=1,2,⋯,T状态表示序列数据中的短距离和长距离依存关系。S-RNN 对短距离依存关系可以有效地表示和学习,而对长距离依存关系的处理能力有限,因为长距离依存关系在模型中会被逐渐“遗忘”。为了解决这个问题,LSTM 被提出,LSTM 也能解决学习中的梯度消失和梯度爆炸问题。

LSTM 的基本想法是记录并使用之前所有位置的状态,以便更好地描述短距离和长距离依存关系。它增加了一种携带信息跨越多个时间步的方法。假设有一条传送带,其运行方向平行于所处理的序列。序列中的信息可以在任意位置跳上传送带,然后被传送到更晚的时间步,并在需要时原封不动地跳回来。这实际上就是LSTM 的原理:它保存信息以便后面使用,从而防止较早期的信号在处理过程中逐渐消失。

为此导入两个机制,一个是记忆元,另一个是门控。记忆元用来记录之前位置的状态信息。门控是指用门函数来控制状态信息的使用,有三个门,包括遗忘门(forget gate)、输入门输出门

LSTM 和 GRU 又被称为门控循环神经网络。这里门是一个向量,每一维取值在 0 和 1 之间,与其他向量进行逐元素积计算,起到“软的”逻辑门电路的作用。当某一维取值是 1 的时候,门是开放的;取值是 0 的时候,门是关闭的。门依赖于所在位置,由所在位置的输入和之前位置的状态决定。

以下的循环神经网络称为长短期记忆网络。在循环网络的每一个位置上有状态和记忆元,以及输入门、遗忘门、输出门,构成一个单元。第 t t t 个位置上的单元是以当前位置的输入 x t \bm{x}_t xt​、之前位置的记忆元 c t − 1 \bm{c}_{t-1} ct−1​、之前位置的状态 h t − 1 \bm{h}_{t-1} ht−1​ 为输入,以当前位置的状态 h t \bm{h}_t ht​ 和当前位置的记忆元 c t \bm{c}_t ct​ 为输出的函数,由以下方式计算 i t = σ ( U i ⋅ h t − 1 + W i ⋅ x t + b i ) \bm{i}_t=\sigma(\bm{U}_i\cdot \bm{h}_{t-1} +\bm{W}_i\cdot \bm{x}_t + \bm{b}_i) it​=σ(Ui​⋅ht−1​+Wi​⋅xt​+bi​) f t = σ ( U f ⋅ h t − 1 + W f ⋅ x t + b f ) \bm{f}_t=\sigma(\bm{U}_f\cdot \bm{h}_{t-1} +\bm{W}_f\cdot \bm{x}_t + \bm{b}_f) ft​=σ(Uf​⋅ht−1​+Wf​⋅xt​+bf​) o t = σ ( U o ⋅ h t − 1 + W o ⋅ x t + b o ) \bm{o}_t=\sigma(\bm{U}_o\cdot \bm{h}_{t-1} +\bm{W}_o\cdot \bm{x}_t + \bm{b}_o) ot​=σ(Uo​⋅ht−1​+Wo​⋅xt​+bo​) c ~ t = tanh ⁡ ( U c ⋅ h t − 1 + W c ⋅ x t + b c ) \tilde{\bm{c}}_t =\tanh(\bm{U}_c\cdot \bm{h}_{t-1} +\bm{W}_c\cdot \bm{x}_t + \bm{b}_c) c~t​=tanh(Uc​⋅ht−1​+Wc​⋅xt​+bc​) c t = i t ⊙ c ~ t + f t ⊙ c t − 1 \bm{c}_t = \bm{i}_t \odot \tilde{\bm{c}}_t+\bm{f}_t \odot \bm{c}_{t-1} ct​=it​⊙c~t​+ft​⊙ct−1​ h t = o t ⊙ tanh ⁡ ( c t ) \bm{h}_t=\bm{o}_t\odot \tanh(\bm{c}_t) ht​=ot​⊙tanh(ct​) 这里 i t \bm{i}_t it​ 是输入门, f t \bm{f}_t ft​ 是遗忘门, o t \bm{o}_t ot​ 是输出门, c ~ t \tilde{\bm{c}}_t c~t​ 是中间结果。

LSTM 的单元结构如下图所示。内部有三个门和一个记忆元。遗忘门、输入门、输出门有相同的结构,都是以当前位置的输入 x t \bm{x}_t xt​ 和之前位置的状态 h t − 1 \bm{h}_{t-1} ht−1​ 为输入的函数。遗忘门决定忘记之前位置的哪些信息,输入门决定从之前位置传入哪些信息,输出门决定向下一个位置传出哪些信息

模型特点

LSTM 能更好地表示和学习长距离依存关系。

当输入门和遗忘门满足 i t = 1 , f t = 0 \bm{i}_t=1,\bm{f}_t=0 it​=1,ft​=0 时,当前位置的记忆元只依赖于当前位置的输入和之前位置的状态,LSTM 是 S-RNN 的近似。

当输入门和遗忘门满足 i t = 0 , f t = 1 \bm{i}_t=0,\bm{f}_t=1 it​=0,ft​=1 时,当前位置的记忆元只依赖于之前位置的记忆元,LTSM 将之前位置的记忆元复制到当前位置。

记忆元 c t \bm{c}_t ct​ 是之前所有位置的中间结果 c ~ t \tilde{\bm{c}}_t c~t​ 的线性组合,而中间结果由所在位置的输入和之前位置的状态决定。所以,当前位置的记忆元以及状态由之前位置的状态综合决定。

学习中由于位置之间的梯度传播不是通过矩阵的连乘而是通过矩阵连乘的线性组合,所以可以避免梯度消失和梯度爆炸。

用 LSTM 生成文本

用深度学习生成序列数据的通用方法,就是使用前面的标记作为输入,训练一个网络来预测序列中接下来的一个或多个标记。例如,给定输入 the cat is on the ma,训练网络来预测目标t,即下一个字符。与处理文本数据时一样,标记(token)通常是单词或字符,给定前面的标记,能够对下一个标记的概率进行建模的任何网络都叫作语言模型(language model)。语言模型能够捕捉到语言的潜在空间(latent space),即语言的统计结构。

一旦训练好了这样一个语言模型,就可以从中采样(sample,即生成新序列)。向模型中输入一个初始文本字符串[即条件数据(conditioning data)],要求模型生成下一个字符或下一个单词(甚至可以同时生成多个标记),然后将生成的输出添加到输入数据中,并多次重复这一过程。这个循环可以生成任意长度的序列,这些序列反映了模型训练数据的结构,它们与人类书写的句子几乎相同。我们将会用到一个LSTM 层,向其输入从文本语料中提取的 N 个字符组成的字符串,然后训练模型来生成第 N+1 个字符。模型的输出是对所有可能的字符做 softmax,得到下一个字符的概率分布。这个LSTM 叫作字符级的神经语言模型(character-level neural language model)。

生成文本时,如何选择下一个字符至关重要。一种简单的方法是贪婪采样(greedy sampling),就是始终选择可能性最大的下一个字符(使得到这个位置为止的单词序列的联合概率最大)。但这种方法会得到重复的、可预测的字符串,看起来不像是连贯的语言。一种更有趣的方法是做出稍显意外的选择:在采样过程中引入随机性,即从下一个字符的概率分布中进行采样。这叫作随机采样(stochastic sampling,stochasticity )。在这种情况下,根据模型结果,如果下一个字符是 e 的概率为 0.3,那么会有30% 的概率选择它。贪婪采样也可以被看作从一个概率分布中进行采样,即某个字符的概率为1,其他所有字符的概率都是0。

更小的熵(随机性)可以让生成的序列具有更加可预测的结构(因此可能看起来更真实),而更大的熵(随机性)会得到更加出人意料且更有创造性的序列。从生成式模型中进行采样时,在生成过程中探索不同的随机性大小总是好的做法。

为了在采样过程中控制随机性的大小,引入一个叫作 softmax 温度(softmax temperature)的参数,用于表示采样概率分布的熵,即表示所选择的下一个字符会有多么出人意料或多么可预测。

给定一个 temperature 值,将按照下列方法对原始概率分布(即模型的 softmax 输出)进行重新加权,计算得到一个新的概率分布。

import numpy as npdef reweight_distribution(original_distribution, temperature=0.5):distribution = np.log(original_distribution) / temperaturedistribution = np.exp(distribution)return distribution / np.sum(distribution)

本例将使用的文本数据是尼采的一些作品,他是19 世纪末期的德国哲学家,这些作品已经被翻译成英文。因此,我们要学习的语言模型将是针对于尼采的写作风格和主题的模型,而不是关于英语的通用模型。

首先下载语料,并将其转换为小写。

import keras
import numpy as nppath = keras.utils.get_file('nietzsche.txt',origin='https://s3.amazonaws.com/text-datasets/nietzsche.txt')text = open(path).read().lower()print('Corpus length:', len(text))

接下来,我们要提取长度为 maxlen 的序列(这些序列之间存在部分重叠),对它们进行 one-hot 编码,然后将其打包成形状为 (sequences, maxlen, unique_characters) 的三维 Numpy 数组。与此同时,我们还需要准备一个数组 y,其中包含对应的目标,即在每一个所提取的序列之后出现的字符(已进行 one-hot 编码)。

maxlen = 60
step = 3          # 每3 个字符采样一个新序列
sentences = []    # 保存所提取的序列
next_chars = []   # 保存目标(即下一个字符)for i in range(0, len(text) - maxlen, step):sentences.append(text[i: i + maxlen])next_chars.append(text[i + maxlen])print('Number of sequences:', len(sentences))chars = sorted(list(set(text)))  # 语料中唯一字符组成的列表
print('Unique characters:', len(chars))
char_indices = dict((char, chars.index(char)) for char in chars)# one-hot 编码
x = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.bool)
y = np.zeros((len(sentences), len(chars)), dtype=np.bool)
for i, sentence in enumerate(sentences):for t, char in enumerate(sentence):x[i, t, char_indices[char]] = 1y[i, char_indices[next_chars[i]]] = 1"""
Number of sequences: 200278
Unique characters: 57
"""

构建网络:

from keras import layersmodel = keras.models.Sequential()
model.add(layers.LSTM(128, input_shape=(maxlen, len(chars))))
model.add(layers.Dense(len(chars), activation='softmax'))optimizer = keras.optimizers.RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)

给定模型预测,采样下一个字符的函数:

def sample(preds, temperature=1.0):preds = np.asarray(preds).astype('float64')preds = np.log(preds) / temperatureexp_preds = np.exp(preds)preds = exp_preds / np.sum(exp_preds)probas = np.random.multinomial(1, preds, 1)return np.argmax(probas)

最后,下面这个循环将反复训练并生成文本。在每轮过后都使用一系列不同的温度值来生成文本。这样我们可以看到,随着模型收敛,生成的文本如何变化,以及温度对采样策略的影响。

import random
import sysfor epoch in range(1, 60):print('epoch', epoch)model.fit(x, y, batch_size=128, epochs=1)start_index = random.randint(0, len(text) - maxlen - 1)generated_text = text[start_index: start_index + maxlen]print('--- Generating with seed: "' + generated_text + '"')for temperature in [0.2, 0.5, 1.0, 1.2]:print('\n------ temperature:', temperature)sys.stdout.write(generated_text)for i in range(400):sampled = np.zeros((1, maxlen, len(chars)))for t, char in enumerate(generated_text):sampled[0, t, char_indices[char]] = 1.preds = model.predict(sampled, verbose=0)[0]next_index = sample(preds, temperature)next_char = chars[next_index]generated_text += next_chargenerated_text = generated_text[1:]sys.stdout.write(next_char)

门控循环单元网络(GRU)

模型定义

门控循环单元是对 LSTM 进行简化得到的模型,效果相当,但计算效率更高。GRU 有两个门,更新门(update gate)和重置门(reset gate),不使用记忆门。

以下的循环神经网络称为门控循环单元网络。在循环网络的每一个位置上有状态及重置门、更新门,构成一个单元。第 t t t 个位置上的单元是以当前位置的输入 x t \bm{x}_t xt​、之前位置的状态 h t − 1 \bm{h}_{t-1} ht−1​ 为输入,以当前位置的状态 h t \bm{h}_t ht​ 为输出的函数,由以下方式计算 r t = σ ( U r ⋅ h t − 1 + W r ⋅ x t + b r ) \bm{r}_t=\sigma(\bm{U}_r\cdot \bm{h}_{t-1} +\bm{W}_r\cdot \bm{x}_t + \bm{b}_r) rt​=σ(Ur​⋅ht−1​+Wr​⋅xt​+br​) z t = σ ( U z ⋅ h t − 1 + W z ⋅ x t + b z ) \bm{z}_t=\sigma(\bm{U}_z\cdot \bm{h}_{t-1} +\bm{W}_z\cdot \bm{x}_t + \bm{b}_z) zt​=σ(Uz​⋅ht−1​+Wz​⋅xt​+bz​) h ~ t = tanh ⁡ ( U h ⋅ r t ⊙ h t − 1 + W h ⋅ x t + b h ) \tilde{\bm{h}}_t =\tanh(\bm{U}_h\cdot \bm{r}_t \odot \bm{h}_{t-1}+\bm{W}_h\cdot \bm{x}_t + \bm{b}_h) h~t​=tanh(Uh​⋅rt​⊙ht−1​+Wh​⋅xt​+bh​) h t = ( 1 − z t ) ⊙ h ~ t + z t ⊙ h t − 1 \bm{h}_t = (1-\bm{z}_t) \odot \tilde{\bm{h}}_t+\bm{z}_t \odot \bm{h}_{t-1} ht​=(1−zt​)⊙h~t​+zt​⊙ht−1​

模型特点

GRU 也能很好地表示和学习长距离依存关系。更新门和重置门起着重要作用。

当更新门和重置门满足 z t = 0 , r t = 1 \bm{z}_t=0,\bm{r}_t=1 zt​=0,rt​=1 时,当前位置的状态只依赖于当前位置的输入和之前位置的状态,GRU 回退到 S-RNN。

当更新门和重置门满足 z t = 0 , r t = 0 \bm{z}_t=0,\bm{r}_t=0 zt​=0,rt​=0 时,当前位置的状态只依赖于当前位置的输入,忽视之前位置的状态。

当更新门满足 z t = 1 \bm{z}_t=1 zt​=1 时,GRU 网络将之前位置的状态复制到当前位置,忽视当前位置的输入。

状态 h t \bm{h}_t ht​ 是之前所有位置的中间结果 h ~ t \tilde{\bm{h}}_t h~t​ 的线性组合,而中间结果由所在位置的输入和之前位置的状态决定。所以,当前位置的状态由之前位置的状态综合决定。


References

[1] 《机器学习方法》,李航,清华大学出版社。
[2] 《Python 深度学习》,François Chollet.

循环神经网络(三)(常用循环神经网络,LSTM、GRU,文本生成)相关推荐

  1. pythonif循环_三. python 循环if,while,for....

    一 .if流程控制语句 if语句: 格式: if表达式: 语句 1. if语句 #练习if语句 aa=int(input("请你输入一个数是否是奇偶:"))if aa%2==0:p ...

  2. 人工智能--基于LSTM的文本生成

    学习目标: 理解文本生成的基本原理. 掌握利用LSTM生成唐诗宋词的方法. 学习内容: 利用如下代码和100首经典宋词的数据,基于LSTM生成新的词,并调整网络参数,提高生成的效果. poetry50 ...

  3. 神经网络三:浅析神经网络backpropagation算法中的代价函数和神经网络的反向传播原理、和ResNet网络的捷径链接误差传播计算

    在博客神经网络一:介绍,示例,代码中,Backpropagation Algorithm中用到了代价函数:该代价函数是否是最好的?其有没有自身的局限性?还有其他的代价函数吗,有何特点?本文将针对这些问 ...

  4. LSTM做文本生成(基于word2vec)

    数据:使用丘吉尔的人物传记作为我的学习语料 框架:Keras import os import numpy as np import nltk from keras.models import Seq ...

  5. c语言循环的三个要素是什么意思,什么是循环结构知识点详解

    循环结构是程序设计中最能发挥计算机特长的程序结构.那么你对循环结构了解多少呢?以下是由小编整理关于什么是循环结构的内容,希望大家喜欢! 循环结构的简介 循环结构可以看成是一个条件判断语句和一个向回转向 ...

  6. 深度学习之循环神经网络(11)LSTM/GRU情感分类问题实战

    深度学习之循环神经网络(11)LSTM/GRU情感分类问题实战 1. LSTM模型 2. GRU模型  前面我们介绍了情感分类问题,并利用SimpleRNN模型完成了情感分类问题的实战,在介绍完更为强 ...

  7. 循环神经网络_漫谈循环神经网络:LSTM、GRU

    知乎视频​www.zhihu.com 简单循环神经网络的局限性 循环神经网络横向结构也是借助激活函数进行传递的: 上图是循环神经网络按时间步展开,而如果一次处理的时间步过长,即从左到右的层数很深,那么 ...

  8. 循环神经网络(RNN)和LSTM初学者指南 | 入门资料

    原作 Skymind  乾明 编译  量子位 出品 | 公众号 QbitAI 最近,有一篇入门文章引发了不少关注.文章中详细介绍了循环神经网络(RNN),及其变体长短期记忆(LSTM)背后的原理. 具 ...

  9. 循环神经网络实现文本情感分类之使用LSTM完成文本情感分类

    循环神经网络实现文本情感分类之使用LSTM完成文本情感分类 1. 使用LSTM完成文本情感分类 在前面,使用了word embedding去实现了toy级别的文本情感分类,那么现在在这个模型中添加上L ...

  10. 循环神经网络系列(六)基于LSTM的唐诗生成

    1. 思路 这个示例在很多地方都出现过,对于学习理解LSTM的原理极有帮助,因此我们下面就来一步一步地弄清楚其中的奥秘所在! 对于循环神经网络来说,我们首先需要做的仍旧是找到一种将数据序列化的方法.当 ...

最新文章

  1. Spring Boot 2.x基础教程:使用Elastic Job的分片配置
  2. mysql忽略大小写配置cnetos_CentOS7下安装MYSQL8.X并设置忽略大小写
  3. C# 获取USB设备信息
  4. js字符串函数 [http://www.cnblogs.com/qfb620/archive/2011/07/28/2119799.html]
  5. java高并发下的数据安全
  6. C# 基础知识-02----强数据类型
  7. #102030:在30天内运行20 10K,庆祝Java 20年
  8. chmod命令(chmod函数)自动清除设置用户ID位和设置组ID位
  9. maven构建ssm工程
  10. GoFrame v1.6.0 发布,Go 应用开发框架
  11. WIN7英文语言包下载,安装,使用
  12. HBase二级索引的设计原理及简单设计demo
  13. 【Eigen中基本和常用函数】
  14. python SMTP发送带图片的邮件时,报TypeError: Could not guess image MIME subtype错误的解决办法
  15. PS cs6是哪一年发布的?
  16. 【paddlepaddle安装报错系列】DLL lond failed:找不到指定模块
  17. 操作成功的提示信息动态添加
  18. 陪玩MM谁是你的NO.1?Python获取陪玩MM照片颜值检测打分
  19. 搭建自己的 CDN 的乐趣和好处
  20. 【Python】Python进程池multiprocessing.Pool八个函数对比:apply、apply_async、map、map_async、imap、starmap...

热门文章

  1. 微信小程序学习——视频播放小程序
  2. windows的cmd如何进入指定目录
  3. CMake 的常用命令
  4. 安卓获取手机唯一设备号
  5. Pytorch环境详细安装教程【Win10+CUDA升级11.6+cudNN+Anaconda3虚拟环境+pycharm】
  6. 备份数据上传腾讯云COS
  7. windows远程桌面配置CUDA
  8. 元宇宙产品有哪些 元宇宙社交平台
  9. 使用VS链接SQL Server数据库制作登录界面
  10. 【知识兔】Excel自学之6:单元格和区域