我的 AI 初体验

趁着这几天 AlphaGo 3:0 柯洁热度不减,我也玩了把人工智能.虽然纯粹是玩票性质,不过还是值得一写.简单来说,我借助 torch-rnn 实现了中文文本的机器生成.

torch-rnn 是斯坦福大学一大神开发的用于对文本进行机器学习的循环神经网络,受到了 char-rnn 的启发,并且在性能和资源消耗方面优于后者.相对而言, char-rnn 知名度要高些,在其作者的博文 The Unreasonable Effectiveness of Recurrent Neural Networks 中介绍了循环神经网络 (RNN) 的原理和基于字符的语言模型 (Character-Level Language Models) 的结构.不过这篇文章中最为有趣的部分莫过于 Fun with RNNs 一节:作者使用 char-rnn 对莎士比亚,海明威等人的文学作品进行深度学习,生成的文本不仅符合英语语法,而且在行文风格上还惊人地与原作相似;作者指出 char-rnn 更适合分析具有复杂语法与结构的文本,于是将维基百科词条的源代码(是一种标记语言)和一本代数几何教材的源代码(使用 LaTeX) 作为训练数据集,结果更加惊人,由 char-rnn 模仿维基百科词条生成的 XML 文件中标签的闭合与嵌套关系完全合乎语法,甚至还包含了格式正确的日期时间和 URL! 而机器生成的 LaTeX 代码仅含有少量语法错误,在编译后看起来就跟真正的数学论文没有差异:较为严谨的言辞,看起来"像那么一回事"的公式,颇有专业气息的图表,甚至还会写"证明略"(原文 Proof omitted)! LaTeX 即使对人类来说都不是一门易于掌握的语言.更进一步,丧心病狂的作者甚至从 GitHub 上拉取了 Linux 的全部源代码,统统喂给 char-rnn, 在几天的训练后,机器真的写出了一些非常有趣的 C 语言代码. char-rnn 仅靠对大量代码的分析就习得了 C 的语法,有清晰的缩进,懂得左大括号要和右大括号配对,甚至还为自己的代码加上了几段注释!在机器生成的代码中,出现了 0x 表示法的十六进制数字,它甚至还懂得签名为 void 的函数不需要返回值!最为有趣的是, char-rnn 会在代码头部加入一大段 GPL 许可证的声明,就像真正的 Linux 源代码一样;同样,它也会在文件头部 include 一大堆头文件,还会定义几个宏.虽然, char-rnn 似乎仅仅是重新组合了原始数据,跟打字机前无意识地乱摁键盘的猴子有几份相似,但能达到这样的水平已经是令人叹为观止了.更何况,有人把超级马里奥的关卡转换为文本形式喂给神经网络,在训练后机器真的自己设计出了一张有一定可玩性的地图.

正因为如此,我才对 char-rnn 的"升级版" torch-rnn 跃跃欲试.在这里分享一下其使用方法.

首先参考 http://torch.ch/docs/getting-started.html 在你的设备上安装 Torch. 值得一提的是 Torch 目前提供的自动化安装脚本尚未支持 Fedora 25, 所以如果你像我一样是地沟油死忠的话,可以尝试我的魔改版: https://github.com/notastudio/distro/blob/master/install-deps. 用该脚本替换官方提供的 install-deps 即可.我已经在官方仓库开了一个 pull request 了(讲真这是我第一次在 GitHub 上提交代码,好紧张).等官方仓库合并更改之后各位还是继续用原版脚本吧.

然后按照 https://github.com/jcjohnson/torch-rnn 的指引配置 torch-rnn, 照它说的一步一步来就是了.(小彩蛋:在这过程中你会安装一个叫 torch-hdf5 的包,这个包的作者正是 DeepMind) 当然,它会指引你安装 CUDA 或 OpenCL 相关的包,这一步是可选的,根据你自己的硬件而定,比如我其实是在 VPS 上跑神经网络的,(而且纯粹是玩票,所以我也不会去买专门跑 AI 的服务器),所以我就没装这些包,当然,后果就是,速度贼贼贼贼贼贼贼贼贼贼贼慢.

这一步搞定之后就已经万事俱备了.最后一件事:寻找数据集.

我最开始以为 torch-rnn 只能分析拉丁字母,所以打算写个爬虫,去各大作业辅导类网站抓取近年来各地的英语单项选择题让它去跑,看看这玩意能不能学会为高考这种水平的考试命题.原因有几个:我是高中狗;英语的单选题应该是所有学科的所有题型中在形式上最简单的了;我没想到其它有趣的数据来源;这大概可以跟什么"人工智能改造传统教育"扯上点关系,可以就此捣鼓篇文章出来在校内骗个什么奖(我校有专门为课外研究/社会实践设立的奖项,虽说马上就高三的我估计没有机会参加了)(还是名利思想在作怪)

于是我尝试了一下.我最不希望发生的事情发生了.各个网站,甚至于一个网站内部提供的题目的格式都千奇百怪,排版错乱,用于放置答案的占位符有的是下划线,有的是空格,有的是下划线加空格;标准答案有的写在题干后,有的写在整套试卷后,有的甚至要你下载整个文档才看得见答案.好吧,这些屎一样的东西根本没法当训练数据集用.

顺便说下我原本的方案.如果一道单选题是这个样子:

2. Those websites ____.
A. sleep    B. walk    C. run    D. suck
答案: D

那么我的预处理程序应该做这些事情:去掉题号,找到答案占位符,把四个选项处理成对象或其它数据结构,靠正则或其它什么方法找到正确答案的选项,得到正确答案,替换掉占位符,并用特殊格式标记出来,如:

Those websites **suck**.

当然要处理一些例外情况,比如答案是不填任何单词(选项往往是"/").然后把大量题目汇总,交由神经网络分析.其实,你应该看出来了,我把选择题转换为了填空题,这样也许会利于机器的分析.

既然让神经网络出题已经不太现实,我们就换个思路.也许 torch-rnn 可以分析中文?我先进行了一次预实验,使用了极小的数据集进行训练.事实令我非常震惊,神经网络真的产出了中文文本,虽然意思牛头不对马嘴,但断句已经比较合理,也懂得配对左引号与右引号,并且出现了少量正确的二字词语,甚至还有个"十三五"!(你可以想象我喂给它的是什么奇怪的东西)

太棒了.这样一来, torch-rnn 的"可玩性"大幅提升.我决定让它学习一些科技媒体的文章,看看它自己能不能写点科技新闻.借助 RSS, 搜集数据这一步并不算难,具体的做法是:我选定了四家个人认为质量较高的科技媒体 (36 氪,爱范儿,虎嗅, PingWest),将其 RSS 订阅源放入 Inoreader 的单独一个文件夹中,使用"获得 HTML 片段"功能导出其内容:

这样导出的文章仍然有大量无用信息.首先,去除所有配图和 HTML 标记(可使用 $('body').innerText 获取纯文本).然后,你会发现几乎所有文章中都混杂了这些让人头疼的东西:作者署名,编辑署名,责任编辑署名,记者署名,转载声明,作者的微信号,作者的微博,作者的邮箱,作者的个人介绍,这个媒体的微信号,这个媒体的微博,配图出处,原文链接,"新闻线索请投稿至: [email protected]", "下载 XX APP, 第一时间获取深度独到的商业科技资讯,连接更多创新人群与线下活动",文章发布日期,文章更新日期............

Ohhhhh! WHAT THE FUCK!

要扫清这些模式相似而内容不同的无用信息,不得不借助正则表达式的神之力量.我大概花了 20 分钟时间,编写各种奇奇怪怪乱七八糟五颜六色(真的, Sublime Text 的搜索框会高亮正则语法)的正则表达式,终于把绝大多数无用信息删光,留下来的只有标题和正文.

至于标题,我并没有做任何强调.在之前的预实验中,我给每篇文章的标题前面加了两个 > 符号,想借格式的差异提醒 torch-rnn 这部分的文本是"不一样的".但我很快意识到这并没有意义.事实上,标题与正文真的没有太大差异,反正在 torch-rnn 眼里它们都是一长串的字符序列而已.

最终,我的数据集中包含了 260 篇文章,总字数逾 61 万字,文件大小为 1.57 MB (这其实也是一个较小的数据集).分享给各位: https://mega.nz/#!JxYRBaKQ!63Ok7Es_2hzq6Sdzj-ID7h_VirAabWyhWLobvifzf3M.

然后在 torch-rnn 目录下运行:

python scripts/preprocess.py \
   --input_txt my_data.txt \
   --output_h5 my_data.h5 \
   --output_json my_data.json
th train.lua -input_h5 my_data.h5 -input_json my_data.json -gpu -1 -num_layers 3 -rnn_size 256
th sample.lua -checkpoint cv/checkpoint_10100.t7 -length 2000 -gpu -1

上述 3 行命令分别用于预处理数据,训练和取样.必须说明,这些代码适用于我的环境,但不一定适合你.建议你参考官方文档: https://github.com/jcjohnson/torch-rnn#usage.

训练的过程是非常漫长的,特别是对于我这样用 CPU 的菜鸟.目前运算仍在进行中,距离得出结果还有很长的时间(估计得跑个两周吧)(不过我还是迫不及待地来写文章了).我服务器的 CPU 是 Xeon E5v3, 双核,不过这玩意好像没有多核心优化啊, CPU 占用率稳定 50%. (大佬们都用 GPU 跑 AI, 谁 tm 给你做 CPU 的多核心优化).不过这并非缺点,起码盈余的计算性能可以保证这个网站的正常运转.(我反倒是有点担心内存占用)

好啦,祈祷 torch-rnn 别出什么幺蛾子吧.一切顺利的话,两周后我们将会看到人工智能用中文撰写的科技新闻,真令人期待呢.如果这次实验成功的话,下一步我准备让神经网络去学习各类网络玄幻小说,我本人虽然不是玄幻小说读者,不过却对 AI 写出的"爽文"很感兴趣.

以上.

Update:

请继续阅读:在上万次迭代以后, torch-rnn 神经网络看起来还不太会说中文啊

3 thoughts on “我的 AI 初体验

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注