DL之CharRNN:char-rnn的简介、安装、使用方法、案例应用(生成英文文本/生成中文诗歌/生成中文小说/生成中文歌词/生成Linux代码/生成日文等)之详细攻略
目录
T2、推荐版本:基于TensorFlow框架和python代码的实现
DL之RNN:人工智能为你写英语小说短文/中文写诗/中文写歌词——基于TF利用RNN算法训练数据集(William Shakespeare的《Coriolanus》)、训练&测试过程全记录
Char-RNN的简介
Char-RNN实现了一个多层次的循环神经网络(RNN、LSTM 和 GRU),用于训练/从字符级语言模型中进行采样。换句话说,该模型以一个文本文件作为输入,训练一个循环神经网络,该网络学会预测序列中的下一个字符。即输入为字符,输出为下一个字符的概率。然后,可以使用这个RNN逐个字符生成文本,使其看起来像原始训练数据。该代码库的背景和上下文在我的博客文章中详细描述。
如果你对 Torch/Lua/神经网络还不熟悉,了解一下这个代码实际上只是我用Python/numpy写的这个100行代码的稍微高级版本可能会有所帮助。该代码库的额外内容包括:允许多层次、使用LSTM而不是普通的RNN、具有更多用于模型检查点的支持代码,并且当然更加高效,因为它使用小批量训练,并且可以在GPU上运行。
GitHub地址:https://github.com/karpathy/char-rnn
1、更新:torch-rnn
Justin Johnson(@jcjohnson)最近从头开始重新实现了char-rnn,使用了一个更加漂亮/更小/更清晰/更快的Torch代码库。它的名字是torch-rnn。它使用Adam进行优化,并在空间/时间效率上硬编码了RNN/LSTM的前向/后向传递。这也避免了在这个代码库中克隆模型时可能遇到的问题。换句话说,torch-rnn现在应该是默认的char-rnn实现,而不是这个代码库中的实现。
GitHub地址:https://github.com/jcjohnson/torch-rnn
Char-RNN的安装与实现
T1、原始版本:基于Lua语言和Torch框架的实现
1、安装
(1)、Lua编写+需要Torch
这段代码用Lua编写,需要Torch。如果你使用的是Ubuntu,在你的主目录中安装Torch可能如下所示:
$ curl -s https://raw.githubusercontent.com/torch/ezinstall/master/install-deps | bash
$ git clone https://github.com/torch/distro.git ~/torch --recursive
$ cd ~/torch;
$ ./install.sh # 并在最后输入 "yes" 以修改你的bashrc
$ source ~/.bashrc
查看Torch安装文档以获取更多详细信息。安装Torch后,我们需要使用LuaRocks获取一些其他包(LuaRocks已经随Torch安装而来)。特别是:
$ luarocks install nngraph
$ luarocks install optim
$ luarocks install nn
(2)、利用NVIDIA GPU上使用CUDA进行训练
如果你想在NVIDIA GPU上使用CUDA进行训练(这可能快15倍左右),你当然需要有GPU,并且你需要安装CUDA Toolkit。然后获取cutorch和cunn包:
$ luarocks install cutorch
$ luarocks install cunn
(3)、使用OpenCL GPU(例如ATI显卡)
如果你想使用OpenCL GPU(例如ATI显卡),你将需要安装cltorch和clnn包,然后在训练时使用选项 -opencl 1(cltorch问题):
$ luarocks install cltorch
$ luarocks install clnn
2、用法
(1)、数据
所有输入数据都存储在data/目录中。你会注意到,存储库中包含了一个示例数据集(在data/tinyshakespeare文件夹中),其中包含莎士比亚作品的一个子集。我在此页面上提供了一些其他数据集。
>> 你自己的数据:如果你想使用自己的数据,那么创建一个名为input.txt的单个文件,并将其放入data/目录中的一个文件夹中,例如data/some_folder/input.txt。第一次运行训练脚本时,它将执行一些预处理并将两个更多的便利缓存文件写入data/some_folder。
>> 数据集大小:请注意,如果你的数据太小(1MB已经被认为是非常小的),那么RNN将学习效果不佳。请记住,它必须完全从头开始学习所有内容。相反,如果你的数据很大(超过2MB左右),可以放心地增加rnn_size并训练一个更大的模型(参见下面的训练详情)。它将工作得更好。例如,对于6MB,你可以轻松地将rnn_size增加到300甚至更高。我使用这个代码训练的最大模型是rnn_size为700,num_layers为3(2是默认值)。我用这段代码训练过的最适合我的GPU。
(2)、训练
使用train.lua开始训练模型。作为健全性检查,尝试运行包含的示例数据集:
$ th train.lua -gpuid -1
请注意,这里我们将gpuid标志设置为-1,这告诉代码使用CPU进行训练,否则它将默认使用GPU 0。有许多其他标志用于各种选项。请查阅 $ th train.lua -help 以获取全面的设置。以下是另一个示例,它训练一个更大的网络,并显示如何在自己的自定义数据集上运行(这已经假定data/some_folder/input.txt存在):
$ th train.lua -data_dir data/some_folder -rnn_size 512 -num_layers 2 -dropout 0.5
Checkpoints | 当模型正在训练时,它会定期将检查点文件写入cv文件夹。这些检查点的写入频率由迭代次数控制,由eval_val_every选项指定(例如,如果这是1,则每次迭代都会写入一个检查点)。这些检查点的文件名包含一个非常重要的数字:损失。例如,一个文件名为lm_lstm_epoch0.95_2.0681.t7的检查点表示在这一点上模型处于第0.95个时代(即它几乎完成了对训练数据的一次完整遍历),并且在验证数据上的损失为2.0681。这个数字非常重要,因为它越低,检查点的工作就越好。一旦开始生成数据(下面讨论),你将希望使用报告最低验证损失的模型检查点。请注意,这可能不一定是训练结束时的最后一个检查点(由于可能的过拟合)。 |
batch_size | 另一个重要的数量要注意是batch_size(称为B)、seq_length(称为S)以及train_frac和val_frac设置。批量大小指定一次处理多少个数据流。 序列长度指定每个数据流的长度,也是梯度能够向后传播的限制。例如,如果seq_length为20,则梯度信号将永远不会向后传播超过20个时间步,并且模型可能找不到超过该长度的字符数量的依赖关系。因此,如果你的数据集中存在许多长期依赖关系,你可能需要增加这个设置。 现在,如果在运行时你的输入文本文件有N个字符,这些字符首先都会被分成大小为BxS的块。然后,这些块根据frac设置分配到三个拆分中:train/val/test。 |
seq_length | |
train_frac | 默认情况下,train_frac为0.95,val_frac为0.05,这意味着我们的数据块的95%将用于训练,5%的块将用于估计验证损失(因此是泛化损失)。如果你的数据很小,使用默认设置可能只有很少的块(例如100块)。这是不好的:在这些情况下,你可能希望减少批量大小或序列长度。 |
val_frac |
请注意,你还可以使用init_from从先前保存的检查点初始化参数。
(3)、采样
给定一个检查点文件(例如那些写入cv的文件),我们可以生成新的文本。例如:
$ th sample.lua cv/some_checkpoint.t7 -gpuid -1
确保如果你的检查点是使用GPU训练的,也要使用GPU进行采样,反之亦然。否则,代码将(目前)抱怨。与训练脚本一样,查看 $ th sample.lua -help 以获取完整的选项。一个重要的选项是(例如)-length 10000,它将生成10,000个字符(默认值= 2000)。
Temperature | 温度。一个你可能想要尝试的重要参数是-temperature,它接受范围在(0, 1](不包括0)的数字,默认值= 1。温度将在Softmax之前除以预测的对数概率,因此较低的温度将导致模型更有可能做出更可能但也更无聊和保守的预测。较高的温度会导致模型更加冒险,增加结果的多样性,但代价是更多的错误。 |
Priming | 引导。还可以使用-primetext用一些起始文本引导模型。这使用一些硬编码的字符启动RNN,为其在开始生成文本之前提供一些上下文。例如,一个有趣的primetext可能是-primetext "the meaning of life is"。 |
GPU训练 | 使用GPU进行训练但在CPU上进行采样。目前的解决方案是使用convert_gpu_cpu_checkpoint.lua脚本将GPU检查点转换为CPU检查点。在不久的将来,你将无需显式执行此操作。例如: $ th convert_gpu_cpu_checkpoint.lua cv/lm_lstm_epoch30.00_1.3950.t7 将创建一个新文件cv/lm_lstm_epoch30.00_1.3950.t7_cpu.t7,你可以在采样脚本中使用,并使用 -gpuid -1 进入CPU模式。 愉快的采样! |
(4)、提示和技巧
监控验证损失与训练损失 | 如果你对机器学习或神经网络有一些了解,要获得良好的模型可能需要一些专业知识。要追踪的最重要的数量是训练损失(在训练期间打印)和验证损失(当RNN在验证数据上运行时定期打印,通常每1000次迭代一次)。特别是: >> 如果你的训练损失远远低于验证损失,那么这意味着网络可能过拟合。解决这个问题的方法是减小网络大小,或增加dropout。例如,你可以尝试dropout为0.5等等。 >> 如果你的训练/验证损失大致相等,那么你的模型是欠拟合的。增加模型的大小(层数或每层的原始神经元数量)。 |
参数的大致数量 | 控制模型的两个最重要的参数是rnn_size和num_layers。我建议你总是使用num_layers为2/3。rnn_size可以根据你拥有的数据量进行调整。这里需要注意的两个重要数量是: >> 模型中的参数数量。这在你开始训练时会打印出来。 >> 你的数据集的大小。1MB文件大约是1百万字符。 |
注意 | 这两者应该在相同的数量级上。这有点难以确定。以下是一些例子: 我有一个100MB的数据集,正在使用默认的参数设置(目前打印150K个参数)。我的数据大小明显更大(100百万 >> 0.15百万),所以我预计会出现严重的欠拟合。我认为我可以放心地将rnn_size设置得更大一些。 我有一个10MB的数据集,并运行一个拥有1000万参数的模型。我有点紧张,正在仔细监控我的验证损失。如果它大于我的训练损失,那么我可能会尝试稍微增加一下dropout,看看是否对验证损失有帮助。 |
(5)、最佳模型策略
最佳模型策略 | 获得非常好的模型的获胜策略(如果你有计算时间)是始终错误地使网络变得更大(尽可能大,只要你能等待计算完成),然后尝试不同的dropout值(在0和1之间)。无论哪个模型在验证性能上表现最好(损失写在检查点文件名中,低即好),都应该是最终选择的模型。 在深度学习中,运行许多不同的模型以及许多不同的超参数设置是非常常见的,最终选择表现最佳的验证性能的任何检查点。 顺便说一下,训练和验证拆分的大小也是参数。确保在验证集中有足够的数据,否则验证性能将会很嘈杂,不太具有信息性。 |
T2、推荐版本:基于TensorFlow框架和python代码的实现
基于TensorFlow框架的源代码实现:https://github.com/hzy46/Char-RNN-TensorFlow
相关学习资料:https://github.com/wjj0301/Deep-Learning-21-Examples/blob/master/chapter_12/README.md
简介 | 一个基于最新版本TensorFlow的Char RNN实现。可以实现生成英文、写诗、歌词、小说、生成代码、生成日文等功能。 | ||||
环境依赖 | Python 2.7.X TensorFlow >= 1.2 | ||||
训练和测试参数 | 模型训练和模型测试脚本
| ||||
微调参数 | 模型微调参数 1、用于对模型进行微调 --lstm_size:LSTM 隐层的大小。默认为128 。 --embedding_size:embedding 空间的大小。默认为128 。该参数只再在使--use_embedding 时才会生效。 --num_layers:LSTM 的层数。默认为2 。 --max_vocab:使用的字母(汉字)的最大个数,默认为3500。程序会自动挑选出使用最多的字,并将剩下的字归为一类,并标记为<unk>。 注意:自己进行尝试的时候,需要注意的是,在train.py 运行时使用了参数,如--lstm_size 256,那么在运行sample.py 时也必须使用同样的参数,即加上--lstm_size 256,否则模型将无法正确载入。 2、运行参数微调 --log_eve_n:默认为10 ,即每隔10步会在屏幕上打出曰志。 --save_eve_n:默认为1000,即每隔1000 步会将模型保存下来。 |
1、用法:生成英文文本
训练 | python train.py \ --input_file data/shakespeare.txt \ --name shakespeare \ --num_steps 50 \ --num_seqs 32 \ --learning_rate 0.01 \ --max_steps 20000 |
生成 | python sample.py \ --converter_path model/shakespeare/converter.pkl \ --checkpoint_path model/shakespeare/ \ --max_length 1000 |
2、用法:生成中文诗歌
诗歌数据集data/poetry. txt ,该文件中存放了大量的五言唐诗。
--use_embedding:为输入数据加入一个embedding层。默认是使用独热编码而不使用embedding的,这里对汉字生成,要加入embedding层,可以获得更好的效果。
训练 | python train.py \ --use_embedding \ --input_file data/poetry.txt \ --name poetry \ --learning_rate 0.005 \ --num_steps 26 \ --num_seqs 32 \ --max_steps 10000 |
生成 | python sample.py \ --use_embedding \ --converter_path model/poetry/converter.pkl \ --checkpoint_path model/poetry/ \ --max_length 300 |
3、用法:生成中文小说
训练 | python train.py \ --use_embedding True \ --input_file data/novel.txt \ --num_steps 80 \ --name novel \ --learning_rate 0.005 \ --num_seqs 32 \ --num_layers 3 \ --embedding_size 256 \ --lstm_size 256 \ --max_steps 1000000 |
生成 | python sample.py \ --converter_path model/novel/converter.pkl \ --checkpoint_path model/novel \ --use_embedding \ --max_length 2000 \ --num_layers 3 \ --lstm_size 256 \ --embedding_size 256 |
4、用法:生成中文歌词
训练 | python train.py \ --input_file data/jay.txt \ --num_steps 20 \ --batch_size 32 \ --name jay \ --max_steps 5000 \ --learning_rate 0.01 \ --num_layers 3 \ --use_embedding |
生成 | python sample.py --converter_path model/jay/converter.pkl \ --checkpoint_path model/jay \ --max_length 500 \ --use_embedding \ --num_layers 3 \ --start_string 我知道 |
5、用法:生成Linux代码
文件data /linux.txt为Linux源码。这里使用了更大的序列长度num _steps =100。对于代码来说,依赖关系可能在较长的序列中才能体现出来,如函数的大括号等。代码同样采用单个字母或符号输入, 因此没再必要使用embedding层。
训练 | python train.py \ --input_file data/linux.txt \ --num_steps 100 \ --name linux \ --learning_rate 0.01 \ --num_seqs 32 \ --max_steps 20000 |
生成 | python sample.py \ --converter_path model/linux/converter.pkl \ --checkpoint_path model/linux \ --max_length 1000 |
6、用法:生成日文
训练 | python train.py \ --input_file data/jpn.txt \ --num_steps 20 \ --batch_size 32 \ --name jpn \ --max_steps 10000 \ --learning_rate 0.01 \ --use_embedding |
生成 | python sample.py \ --converter_path model/jpn/converter.pkl \ --checkpoint_path model/jpn \ --max_length 1000 \ --use_embedding |
Char-RNN的使用方法
更新中……