LSTM,全称为「长短期记忆」,是一种「时间递归神经网络」(RNN)。LSTM 适合于处理和预测时间序列中间隔和延迟非常长的重要事件。
通俗来讲,LSTM 非常适合用来预测与时间相关的数据,在文本处理方面更是应用广泛 (可以理解为某个词在 t 时间点出现,预测 t+1 时间点最有可能出现哪个词);往专业上讲,呃,我完全不懂。
但这不妨碍我们去使用 LSTM 去做点有趣的事情,好比你不知道电饭煲是怎么做出来的,但你总会煮饭是吧。接下来我们使用 Keras 这个强大的「电饭煲」来煮几煲好吃的饭。
自动写代码
这有点标题党,但其实还是个人工智障。比如你在写代码的时候,写下了这么一段:
1 | cpp复制代码def afunc(i): |
下一个字符很自然应该是「n」对不对。将一个个字符转化为数字序列作为输入,这些字符组成的序列的下一个字符作为输出,比如,序列长度为 3 的话,return
这个字符序列,可以转化为:
1 | xl复制代码r,e,t -> u |
然后将这些单个字符分别映射为数字:
1 | xl复制代码r -> 1 |
变成这种形式:
1 | ini复制代码x1 = [1,2,3], y1 = 4 |
这样,我们就可以用 Keras 来训练了。
我使用的是「python requests」去掉了空行和注释的代码作为训练样本。
脚本具体可以参考
https://machinelearningmastery.com/text-generation-lstm-recurrent-neural-networks-python-keras/
训练 40 个 epoch 后的成绩:
1 | apache复制代码Epoch 40/40 |
效果:
可以看到部分输出确实有点像代码的样子,但是重复的地方也比较多,这是因为过拟合了。
「GRU」是 LSTM 的一个变种,据说结构上比 LSTM 简单,参数少,比 LSTM 在过拟合方面好点:
1 | routeros复制代码model = Sequential() |
训练 20 个 epoch 的效果:
1 | apache复制代码Epoch 20/20 |
可以看到重复性方面解决得比 LSTM 要好,有时间再训练多些看下是否能得到更好的效果。
作诗机器人
其实就是把上面例子里的英文字母,换成汉字。
文本格式如下,冒号分隔诗名和诗,一行一首诗,一共一千首诗。
1 | makefile复制代码山阁晚秋:山亭秋色满,岩牖凉风度。疏兰尚染烟,残菊犹承露。古石衣新苔,新巢封古树。历览情无极,咫尺轮光暮。 |
数据处理:
1 | stylus复制代码with open('poetry.txt') as f: |
序列长度我设置为 2,即用前面两个字来预测下一个字,一共 217687 条数据。
汉字的体量比英文字母高了几个级别,共 4620 个。我们得用 word embedding 来处理,将 one-hot 编码的词,映射为低维向量表达,以降低特征维度。
1 | stylus复制代码model = Sequential() |
定义一个生成诗的函数:
1 | apache复制代码def gen_poem(seed_text): |
为了不会每次都生成一样的句子,我设置了随机从最有可能的 5 个结果里面取。
训练了 25 个 epoch 看下效果:
还不错吧!起码语句还是比较通顺的!
该诗描述了,在一个月明的夜里传来了阵阵的猿声,猿猴才不可惜眼前的这座空城呢,它发现了一面崭新的梳妆铜镜,然而它四处张望,三千里内杳无人烟,找不到镜子的主人。表达了诗人的一种孤寂虚无的情怀。( 原谅我的强行解释 … )
以下是生成的部分诗句:
- 清泉落花开,何处不见花。玉门前山水,不得无限情。
- 二月出长生,何为谁知音。礼容备乐钟,天地气调弦。
- 小荷恩重重,天涯不相见。一别有事征,云际会春花。
- 残菊还畏风,金石咸来此。礼容暗通三,天下朝斑竹。
- 悠然影曲与,云浮黄云际。风何处处在,一杯酒熟金。
训练了 75 个 epoch 的效果:
- 清泉鸣天不,一杯酒若游。此时月悬舞,一何不归去。
- 二月明月悬,何不知天涯。今宵似生长,金香玉春色。
- 小荷休征衣,天不相顾非。今宵光如可,何日更畏凉。
- 残菊杯色摇,金甲云盖极。风花落日月,云愁思君子。
- 悠然知天地,何年光彩云。君不可怜故,天涯天地无。
来个七言:
- 清泉凝愁夜长思,一何处欲待我行。君王道远烟雾里,天地来不相见无。
- 二月悬舞凤凰天,何年光如可荐严。风动四时得无声,云愁不相如此生。
- 小荷休气齐复来,金香金屋夹流水。今已枕在何须尽,金香风吹落花开。
- 残菊杯色犹倚望,云愁夜月悬舞红。今奉君之何须一,云中绣衣襟艳芳。
- 悠然身自有时人,一生百年无声至。君不可见少别有,一人行晚朝云浮。
文本情感分析
上面都是玩票的性质,接下来用 LSTM 做下比较实用的文本情感分析。
文本情感分析一般是指给出一段文本,然后给机器判断该文本表达的情绪是正面的还是负面的。
比如说:
「太喜欢这个产品了,我会推荐给朋友用。」是正面的,
「垃圾,不推荐,要求退货。」是负面的。
文本情感分析在网上做舆论分析时特别有用。
所用的语料,我爬了下京东的产品评论,url 类似下面这个例子:
1 | apache复制代码https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv3006&productId=2695276&score=1&sortType=5&page=0&pageSize=10&isShadowSku=0 |
参数 productId 为商品的 id;score=1 为一星评论 (负面),score=5 为五星评论 (正面)。
抓好后,整理成 csv 文件,如:
1 | erlang复制代码0,"很山寨!根本读不出来,换了两台电脑winXP和win10都读不出来!" |
0 表示负面;1 表示正面。差评和好评数量要均衡点。
在这个例子中,跟上面的诗词又不一样了,我们需要分词处理,否则输入序列就太长了。
数据预处理:
1 | python复制代码import pandas as pd |
训练和测试数据:
1 | stylus复制代码x_train = np.array(list(comments['w2v']))[::2] |
模型:
1 | routeros复制代码model = Sequential() |
输出只有 1 维,所以激活函数要用 sigmoid,损失函数用 binary_crossentropy。
训练:
我只用了 14255 条数据,所以训练起来非常快,准确率也达到了 96.38% 。
看下测试数据集的准确率:
1 | cli复制代码model.evaluate(x=x_test,y=y_test,verbose=0) |
也有 87.68% 的准确率,总体来说还算过得去了。
定义一个函数用来看下效果:
1 | haxe复制代码def new_data(new_comment): |
准确率还是不错的:
「他们都说好用,我就呵呵了。」 都能判断正确,神奇了哎。
本文转载自: 掘金