/chinese_text_generator

用循环神经网络生成中文

Primary LanguagePython

中文文本生成器

来源

主要就是拿keras的example里那个lstm_text_generation.py改的。显然这个example是 实现The Unreasonable Effectiveness of Recurrent Neural Networks那个文本生成例子。 那篇文章用的是torch使用lua,而这个例子用的是用keras使用python。

问题

中文文本生成最明显的问题是中文字符太多,如果以中文单字输入的话向量太大内存吃不消。我 直接用中文的utf8码来当做汉字的“字母”来进行编码。这么做坏处在于很容易输出不可识别的 utf8组合,要迭代很长时间才能生成乱码不那么多的文本,意思却很惨。所以我又用jieba先分了 词再,每个词间插入一个空格。如此编码出的东西就有点像拼音文字了,有74个字母的拼音文字。 每个中文字被三个字母编码,基本单位成了长度为三个字母倍数的词。

这74个字母(训练时是直接用utf8编码)如果用ASCII码显示可以显示这样的魔性拼音语言。

	In [43]: fancy('夏娜想起当时的战斗,悠二的呐喊,最后的微笑。一想起来,又觉得苦涩。在演变成目前这种局面之前,那声呐喊,那个微笑是更加的……',utf8_to_char)
	Out[43]: 'uU@uYM v4dxfh unDvHg wK5 v9IvGH zm= v3Qtk= wK5 uBAuG; zm= vM1uA? wK5 uo_w]B s13 ti1v4d xfhvNV zm= u@9 xX:uoH x<WvgZ s13 uMY vmEu@Iv9A wL_u:> xpJwX> ub1yNS tj<u:> zm= y3TuTa uBAuG; zm= y3Tti[ uo_w]B vI` vLeu;Q wK5 r1W r1W'
	
	In [45]: print utf8_to_char
	{'\x81': '2', '\x80': '1', '\x83': '4', '\x82': '3', '\x85': '6', '\x84': '5', '\x87': '8', '\x86': '7', '\x89': ':', '\x88': '9', '\x8b': '<', '\x8a': ';', '\x8d': '>', '\x8c': '=', '\x8f': '@', '\x8e': '?', '\x91': 'B', '\x90': 'A', '\x93': 'D', '\x92': 'C', '\x95': 'F', '\x94': 'E', '\x97': 'H', '\x96': 'G', '\x99': 'J', '\x98': 'I', '\x9b': 'L', '\x9a': 'K', '\x9d': 'N', '\x9c': 'M', '\x9f': 'P', '\x9e': 'O', '\xa1': 'R', '\xa0': 'Q', '\xa3': 'T', '\xa2': 'S', '\xa5': 'V', '\xa4': 'U', '\xa7': 'X', '\xa6': 'W', '\xa9': 'Z', '\xa8': 'Y', '\xab': '\\', '\xaa': '[', '\xad': '^', '\xac': ']', '\xaf': '`', '\xae': '_', '\xb1': 'b', '\xb0': 'a', '\xb3': 'd', '\xb2': 'c', '\xb5': 'f', '\xb4': 'e', '\xb7': 'h', '\xb6': 'g', '\xb9': 'j', '\xb8': 'i', '\xbb': 'l', '\xba': 'k', '\xbd': 'n', '\xbc': 'm', '\xbf': 'p', '\xbe': 'o', '\xc2': 'q', '\xe3': 's', '\xe2': 'r', '\xe5': 'u', '\xe4': 't', '\xe7': 'w', '\xe6': 'v', '\xe9': 'y', '\xe8': 'x', '\xef': 'z'}

发现如此编码算法可以迅速进入可识别字符状态,而非因为一些小错误出些令人费解的结果。

因为文本很大,所以训练方式是随机选择一段文本,然后训练5轮,再随机选择另一端这样。于是loss函数就呈现降三步升三步的趋势。。

生成

这个LSTM算法相当于在学习给定一个任意长度字符序列后,预测下一个字符是什么,LSTM算法妙处在于其 能表示内部变量,具有了学习简单程序(而非只是函数)的能力。所以所谓文本生成也要先给它一段文本 作为种子,看它不断作用自身产生最有可能的下一个字符会是什么。直到生成一个一定长度的字符序列就是 神经网络生成的文本。

开了GPU加速,训练了三个多小时后的生成文本:

	 ( 我 的 力量 。 
	 “ 就 在 吗 ? 
	 “ 就是 一种 得到 吧 。 
	 就 在 这个 事类 的 吧 。 
	 “ 对 就 在 吗 ? 
	 在 只不用 地 的 地方 。 
	 在 同心 一点 的 少女 上 , 就 在 同样 的 吧 。 
	 这个 地方 的 发出 了 出来 。 
	 “ 就 在 向着 这个 一种 得到 了 一种 意外 的 吧 , 在 细续 在 后来 。 
	 在 到底 是 一下 吧 , �

是的,这并没有什么卵用。。

使用

你需要keras,正确的配置GPU加速使训练加速10倍等。

建立配置对象(绑定的路径/文件名/都在这配置,这一步也给文本做了分词那些操作)

	em=Extern_Monitor(fname='shana_model') 
	ds=DataStream(text_path=u'灼眼的夏娜.txt')
	model=Model()

建立新模型

	model.build(ds)

载入之前的模型

	model.load(em.fname)

查看当前模型输出效果

	model.sample(ds,em)

训练模型

	model.train(ds,em)

因为懒得设多线程,中间要中断安全的方式是到外面那个command.txt文件里写上字符串pause。当轮迭代完成 就会自动问你要不要覆盖当前训练结果等,覆盖后自动退出。之前一直用ctrl+c有次卡住了ipython报废了我一上午 的迭代结果。。记得再开的时候把pause删了。

模型文件是*.json(模型结构描述)与*.h5(模型参数序列化存储)。这两个文件的名字可以在Extern_Monitor对象 里配置。

TODO

准备试试看把网络交叉训练不同的文本看看会生成什么鬼。比如夏娜和porn(之前没分词时候就训练的这个,结果不能直视。。)。