本篇文章5784字,读完约14分钟

雷锋。这篇文章是由magicly博客转载并经作者授权的。要阅读原文,请参阅:magicly.me/2017/04/07/rnn-lstm-generate-name/? UTM _ source = tui cool & UTM _ media = reference .

Magicly:我以前翻译过一篇关于rnn的文章,但是我从来没有看到作者写一篇关于lstm的新博客,所以我找到了其他材料来研究。本文首先介绍了lstm,然后利用lstm对金庸和古龙的名字进行训练,从而生成新的武术名称。如果你感兴趣,你也可以收集更多的名字给孩子命名。哈哈,只是为了好玩,每个人都很开心…

Rnn回顾了rnn的出现,以解决状态记忆问题。解决方法很简单。每个时间点t的隐藏状态h(t)不再简单地依赖于数据,而是还依赖于先前时间节点t-1的隐藏状态h (t-1)。可以看出,这是一个递归定义(因此递归神经网络也称为递归神经网络)。h(t-1)取决于h(t-2),h(t-2)取决于h(t-3)...所以h(t)取决于之前每个时间点的输入,这意味着H (t)记得之前的一切

用金庸、古龙群侠名称训练 LSTM 会生成多么奇葩的名字?

如果上述数字随时间扩展,可以看出rnn实际上是普通神经网络的时间堆栈。

Rnn问题:长期依赖一切似乎都是完美的,但如果h(t)依赖于h(t-1000),依赖路径很长,这将导致梯度计算时梯度的消失,并且训练时间太长,无法实际使用。下面是一个长依赖路径的示例:

1来自我的家乡[成都]。。。[这里省略了500字]。。。我们经常在那里吃火锅。。。

Lstmlong短期记忆神经网络,即lstm,由hochreiter & schmidhuber于1997年发表。它似乎解决了长期依赖的问题,近年来出现了许多改进版本。目前,它被应用于许多领域(包括机器翻译、对话机器人、语音识别、图像字幕等)。)。

在标准rnn中,重复模块只是一个非常简单的结构,如下图所示:

Lstm是一个类似的链表结构,但是它的内部结构要复杂得多:

上图中的图标具有以下含义:

lstm的核心思想是单元状态(类似于隐藏状态,一些lstm变体结合了单元状态和隐藏状态,如gru)以及三种门:输入门、遗忘门和输出门。

每一次,细胞状态作为输入被传送到下一个时间点,并且在一些线性变化之后,它继续到下一个时间点(我还没有阅读原始的论文,并且我不知道为什么在我有隐藏状态之后我需要细胞状态。幸运的是,有一个结合了这两者的改进版本,所以我暂时不讨论它)。

门的概念来自电路设计(如果我没学过,我就不敢炫耀)。在lstm中,门控制着通过门后能留下多少信息。如下图所示,sigmoid层输出值[0,1],该值决定有多少数据可以通过门。0表示没有人能通过,1表示所有人都通过。

让我们看看每个“门”都在做什么。

首先,我们必须决定需要保留多少先前的单元状态。根据h(t-1)和x(t),它计算一个数字[0,1],并确定保留多少单元状态。0表示全部丢弃,1表示全部保留。我们为什么要扔掉它?尽可能多地保留它不是更好吗?假设lstm正在生成一篇小明和小红的文章。小明在看电视,小红在厨房做饭。如果当前的主题是小明,好的,那么lstm应该输出电视相关的项目,如寻找一个遥控器和改变频道。如果话题已经转到小红身上,最好暂时忘掉电视,输出洗菜、酱油、电饭煲等等。

用金庸、古龙群侠名称训练 LSTM 会生成多么奇葩的名字?

第二步是决定输入对单元状态的影响程度。这个地方由两部分组成,一部分是计算sigmoid函数还剩多少数据,另一部分是通过tanh函数计算候选c(t)。这个地方就像主题从小明切换到小红,所以电视应该切换到厨房。

然后,我们将剩余的单元状态(在时间t-1)与新添加的单元状态相结合,以获得时间t的单元状态。

最后,我们通过tanh将单元状态压缩为[-1,1],然后将其发送到输出门([0,1]决定输出多少)。

现在有许多不同的lstm,感兴趣的人可以在这里看到。此外,lstm只是为了解决rnn的长期依赖性,其他人已经从另一个角度解决了这个问题,如koutnik等人(2014)的时钟工作rnn。

给我看看密码!我使用了安德烈·卡普西的代码,做了一些小改动。这段代码的优点是它不依赖于任何深度学习框架,只需要numpy立即运行!

"""

最小字符级普通rnn模型。作者:andrej karpathy (@karpathy)

bsd许可证

"""

将numpy作为np导入

#数据i/o

data = open( input.txt,r)。read() #应该是简单的纯文本文件

all _ name = set(data . split(" \ n "))

chars =列表(集合(数据))

data_size,vocab_size = len(数据),len(字符)

打印(数据有%d个字符,%d个唯一字符。% (data_size,vocab_size))

char_to_ix = {ch: i代表I,ch在枚举中(chars)}

ix_to_char = {i: ch for i,ch in enumerate(chars)}

#打印(char_to_ix,ix_to_char)

#超参数

hidden_size = 100 #神经元隐藏层的大小

seq_length = 25 #展开rnn的步骤数

学习率= 1e-1

#模型参数

wxh = NP . random . randn(hidden _ size,vocab_size) * 0.01 #输入至hidden

whh = np.random.randn(隐藏_大小,隐藏_大小)* 0.01 #隐藏到隐藏

为什么= np.random.randn(vocab_size,hidden_size) * 0.01 #输出隐藏

BH = NP . zero((hidden _ size,1)) #隐藏偏差

by = NP . zero((vocab _ size,1)) #输出偏置

def lossfun(输入、目标、hprev):

"""

输入、目标都是整数列表。

hprev是初始隐藏状态的hx1数组

返回损失、模型参数的梯度和最后的隐藏状态

"""

xs,hs,ys,ps = {},{},{},{}

hs[-1] = np.copy(hprev)

损耗= 0

#向前传球

对于测试范围(len(输入)):

xs[t] =

xs[t][输入[t]] = 1

hs[t] = np.tanh(np.dot(wxh,xs[t]) + np.dot(whh,

hs[t - 1]) + bh) #隐藏状态

#下一个字符的非标准化日志概率

ys[t] = np.dot(为什么,hs[t]) + by

下一个字符的概率

PS[t]= NP . exp(ys[t])/NP . sum(NP . exp(ys[t])

损失+= -np.log(ps[t][targets[t],0]) # softmax(交叉熵损失)

#反向通过:计算反向渐变

dwxh,dwhh,dwhy = np.zeros _ like(

wxh),NP . zero _ like(whh),NP . zero _ like(为什么)

dbh,dby = NP . zero _ like(BH),NP . zero _ like(by)

dhnext = np.zeros_like(hs[0])

对于反向测试(范围(len(输入))):

dy = np.copy(ps[t])

#返回y .参见

# cs231n.github.io/neural-networks-case-study/#grad如果困惑

#这里

dy[targets[t]] -= 1

dwhy += np.dot(dy,hs[t]。t)

dby += dy

dh = np.dot(why.t,dy)+dhnext # back drop进入h

dhraw = (1 - hs[t] * hs[t]) * dh #通过tanh非线性反向传播

dbh += dhraw

dwxh += np.dot(dhraw,xs[t]。t)

dwhh += np.dot(dhraw,hs[t - 1]。t)

dhnext = np.dot(whh.t,dhraw)

对于[dwxh,dwhh,dwhy,dbh,dby]中的dparam:

#剪辑以减轻爆炸梯度

np.clip(dparam,-5,5,out=dparam)

回波损耗,dwxh,dwhh,dwhy,dbh,dby,hs[len(输入)- 1]

def样本(h,seed_ix,n):

"""

从模型中采样一系列整数

h为记忆状态,seed_ix为第一步的种子字母

"""

x = NP . zero((vocab _ size,1))

x[seed_ix] = 1

ixes = []

对于范围(n)内的t:

h = np.tanh(np.dot(wxh,x) + np.dot(whh,h) + bh)

y = np.dot(为什么,h) + by

p = np.exp(y) / np.sum(np.exp(y))

ix = np.random.choice(范围(vocab_size),p=p.ravel())

x = NP . zero((vocab _ size,1))

x[ix] = 1

IX . append(IX)

返回ixes

n,p = 0,0

mwxh,mwhh,mwhy = NP . zero like(wxh),NP . zero like(whh),NP . zero like(为什么)

mbh,mby = np.zeros_like(bh),NP . zeros _ like(by)# adagrad的内存变量

smooth _ loss =-NP . log(1.0/vocab _ size)* seq _ length #迭代0时的损失

虽然正确:

#准备输入(我们在seq_length步骤中从左向右扫描

#长)

如果p + seq_length + 1 >= len(数据)或n == 0:

HP rev = NP . zeross((hidden _ size,1)) #复位rnn存储器

p = 0 #从数据开始

输入=[数据中ch的char _ to _ IX[ch ][ p:p+seq _ length]]

目标=[数据中ch的char _ to _ IX[ch ][ p+1:p+seq _ length+1]]

#不时从模型中取样

如果n % 100 == 0:

sample_ix = sample(hprev,输入[0],200)

txt =。连接(样本ix中ix的ix_to_char[ix])

打印(- \n %s \n - % (txt,)

#将seq_length字符通过网络转发并获取渐变

loss,dwxh,dwhh,dwhy,dbh,dby,hprev = lossfun(输入,目标,hprev)

平滑_损失=平滑_损失* 0.999 +损失* 0.001

如果n % 100 == 0:

打印(iter %d,损耗:%f % (n,smooth_loss)) #打印进度

#使用adagrad执行参数更新

对于param,dparam,mem in zip([wxh,whh,why,bh,by],

[dwxh,dwhh,dwhy,dbh,dby],

[mwxh、mwhh、mwhy、mbh、mby]:

mem += dparam * dparam

param += -learning_rate * dparam / \

np.sqrt(mem + 1e-8) # adagrad更新

p += seq_length #移动数据指针

n += 1 #迭代计数器

如果((平滑_损失= 20000)):

sample_ix = sample(hprev,inputs[0],2000)

txt =。连接(样本ix中ix的ix_to_char[ix])

expected _ name = set(txt . split(" \ n "))

新名称=预测名称-所有名称

打印(新名称)

打印(预测名称len: %d,新名称len: %d,\n % (len(预测名称),len(新名称)))

破裂

viewrawmin-char-rnn . py hosted with?bygithub

然后我从网上找到金庸小说的名字,做了一些预处理,每行一个名字,保存在input.txt中,然后运行代码。顾龙没有找到完整的名字,只有这份武术名单,只有100多人。

以下是基于这两个列表的训练结果,相同的名字(如段宇)都被去掉了,所以以下都是lstm的“新创造和发明”的名字。来,猜猜哪一个是金庸的,哪一个是古龙的。

{姜增铁、袁、石、郭万臣、、程、王铁之、陈毅、薛铁、哈赤、尹、钟小艳、冯一刀、鲍兰、齐,若无其事,王老营、钟、、石、李元珍、曹兰、赵桑飞西、上官红喜红、刘志宇、童怀道、周云鹤、田、冯、奚灵素、大治湖石、阮土忠、王兆能、袁正义、尚保和、常伯峰 冯一弼、曹阙、、曾铁文、顾若芝、、、崔百真、陈冠、陈仲、倪凤峰、梅原道、徐、任彤都、上官铁楚容、大建台、、盛、南、南转、石双镇、海铁山、尹和珍、司、德晓、吴若思、、田青

用金庸、古龙群侠名称训练 LSTM 会生成多么奇葩的名字?

{邀请函3,熊猫凯,鹰星,陆凯,华,薛玉洛平,南宫主,南宫九,孙夫人,景冬梅,铁急,裴都,,满,陆子无齿,连,钟,,方达,叶魂,落寞红,叶,雷。约请一郎、东楼、铁十一红、、伍伟柳老峰三、萧茂儿、东郭先锋、李顺、狄先生、孟建兴、蒋晓峰、华双楼、、邱珏、白坏刹、阎悲、冀北岩、董、陆丰、碧玉波等流颜南田、萧连景、龙步岩、董国玉、司东郭金田、薛、熊宝玉、吴、刘、、刘、东莞小雨、渐飞、陆鱼、吹王、傲骨 谢郎唐傲、铁夜帝、蒋晓峰、孙玉叶、邱任重、柴兴富、詹夫人、贾斯珀、老吴俞、铁铁铁花、杜、薛龚玥九、老郭和尚、龙冠飞、东郭鲁大、司臧、李倩、孙柏芝、南双平、王惠、纪元庆、孙瑜、东郭大路、白玉罗生、高二、董觉天、萧望尚、九、关垂学、上官晓峰、邱上官金飞、陆上龙晓天、空灵魂、衣服邀请人

用金庸、古龙群侠名称训练 LSTM 会生成多么奇葩的名字?

感兴趣的人也可以用古代诗人、诗人等的名字。训练。如果你有好的机器或时间,你可以训练更多。你训练得越多,你就越准确。

综上所述,rnn由于其记忆功能,在自然语言处理、语音、计算机视觉等诸多领域显示出巨大的优势。实际上,rnn相当于图灵。

如果训练普通神经网络是对函数的优化,那么训练递归网络就是对程序的优化。

Lstm是一种常用且实用的rnn算法,主要解决rnn的长期依赖性问题。此外,rnn一直在进行新的研究,如注意机制。又有空要介绍了。。。

referscolah.github.io/posts/2015-08-understanding-lstms/

karpathy.github.io/2015/05/21/rnn-effectiveness/

胡志/问题/29411132

gist.github/karpathy/d4dee566867f8291f086

深度学习4j/lstm雷锋网雷锋网(公开号:雷锋网)

相关文章:

谷歌大脑科学家理解lstm:一个关于“遗忘”和“记忆”的故事

老板来了:人脸识别+手机按键,老板来了你马上就知道了!

雷锋文章版权所有。严禁擅自转载。详情请参考转载说明。

来源:搜狐微门户

标题:用金庸、古龙群侠名称训练 LSTM 会生成多么奇葩的名字?

地址:http://www.shwmhw.com/shxw/60042.html