剛開始學(xué)習(xí)RNN的時(shí)候利用英文文本訓(xùn)練寫英文的文章。出于練手的目的寫一個(gè)文言文的模型的練習(xí)。
本模型利用了一個(gè)簡單的LSTM模塊,即帶記憶的RNN。雖然LSTM也有類似RNN的局限性,但是訓(xùn)練一個(gè)小型的中文文本應(yīng)該是沒有問題。
快速復(fù)習(xí)下LSTM原理:

為了快速搭建,我選用了Keras,不多說,快速搭建模型神器。
第一步數(shù)據(jù)處理,就是把每一個(gè)出現(xiàn)過的字都標(biāo)上一個(gè)index
from __future__ import print_function
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.layers import LSTM
import numpy as np
import random
import sys
import collections
#我們這里用的訓(xùn)練文本是《項(xiàng)羽本紀(jì)》
path = "xiangyubenji.txt"
text = open(path).read()
print('corpus length:', len(text))
#corpus length: 11247
print(text[:10])
#項(xiàng)籍者,下相人也,字
chars = sorted(list(set(text)))
print('total chars:', len(chars))
#total chars: 1075
char_indices = dict((c, i) for i, c in enumerate(chars))
indices_char = dict((i, c) for i, c in enumerate(chars))
我們來定義下每次訓(xùn)練文本的句長。這里定義40個(gè)字為一句吧。
step為3,下一句是3個(gè)字以后。其實(shí)可以自由定義。
簡單的來說訓(xùn)練的X就是一句話
訓(xùn)練的Y就是這句話結(jié)束后的下一個(gè)字。
maxlen = 40
step = 3
sentences = []
next_chars = []
for i in range(0, len(text) - maxlen, step):
sentences.append(text[i: i + maxlen])
next_chars.append(text[i + maxlen])
print('nb sequences:', len(sentences))
print(sentences[:1])
print(next_chars[:1])
#nb sequences: 3736
#['項(xiàng)籍者,下相人也,字羽。初起時(shí),年二十四。其季父項(xiàng)梁,梁父即楚將項(xiàng)燕,為秦將王翦']
#['所']
我們把每句話每個(gè)字都向量話。我們用1個(gè)1075個(gè)元素的向量來表示一個(gè)字,按每個(gè)字的index在那個(gè)位置標(biāo)記1(不懂參考o(jì)ne hot encoding)。所以一句話就要 40 x 1075 個(gè)元素。
X = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.bool)
y = np.zeros((len(sentences), len(chars)), dtype=np.bool)
for i, sentence in enumerate(sentences):
for t, char in enumerate(sentence):
X[i, t, char_indices[char]] = 1
y[i, char_indices[next_chars[i]]] = 1
建立模型,非常簡單,只用一層LSTM模塊,輸出為128. 單次步長為一句話的長度,輸入為1075. input_shape=(maxlen, len(chars))
# build the model: a single LSTM
print('Build model...')
model = Sequential()
model.add(LSTM(128, input_shape=(maxlen, len(chars))))
model.add(Dense(len(chars)))
model.add(Activation('softmax'))
optimizer = RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
接下來我們來訓(xùn)練這個(gè)模型,來60次epoch。
每次10訓(xùn)練完之后 打出來看看效果。隨機(jī)從文中選擇一句話開始,打出后面預(yù)測的四百個(gè)字。
for iteration in range(1, 60):
print()
print('-' * 50)
print('Iteration', iteration)
model.fit(X, y, batch_size=128, nb_epoch=1)
if iteration % 10 == 0:
start_index = random.randint(0, len(text) - maxlen - 1)
for diversity in [1.2]:
# 在sample的時(shí)候選擇的分布可選值[0.2, 0.5, 1.0, 1.2]:
print()
print('----- diversity:', diversity)
generated = ''
sentence = text[start_index: start_index + maxlen]
generated += sentence
print('----- 用這句話來開頭寫個(gè)故事: "' + sentence + '"')
print('----- 你準(zhǔn)備好了,我開始瞎扯了:')
print()
sys.stdout.write(generated)
for i in range(400):
x = np.zeros((1, maxlen, len(chars)))
for t, char in enumerate(sentence):
x[0, t, char_indices[char]] = 1.
preds = model.predict(x, verbose=0)[0]
#大概的原理是從概率到index的映射范圍
next_index = sample(preds, diversity)
next_char = indices_char[next_index]
generated += next_char
sentence = sentence[1:] + next_char
sys.stdout.write(next_char)
sys.stdout.flush()
print()
def sample(preds, temperature=1.0):
# helper function to sample an index from a probability array
preds = np.asarray(preds).astype('float64')
preds = np.log(preds) / temperature
exp_preds = np.exp(preds)
preds = exp_preds / np.sum(exp_preds)
probas = np.random.multinomial(1, preds, 1)
return np.argmax(probas)
其實(shí)就這么點(diǎn)。我們來看看效果。
[epoch10]:
西,必舉秦矣。故不如先斗秦趙。夫被堅(jiān)執(zhí)銳,義不如公;坐而運(yùn)策,公不如義。”因下令沛公曰‘曰“沛公蓋蓋亦我逐其寶”反,魏沛公與以責(zé)令行,常何且至?xí)r,項(xiàng)異楚也。”於是項(xiàng)項(xiàng)王十壁遂沛誅遂誅。財(cái)項(xiàng)伯亦郡項(xiàng)伯徙約地?fù)?,七史披史者事,大咸王馬烏武沛與楚乃信項(xiàng)孰聞初亦,行阻陳縣而侍者?不他行殺塞馀何;為期曹保子勝高齊當(dāng)時(shí)為項(xiàng)梁射故項(xiàng)人相來,三素魏人亡城不北。田榮言與阿沛公。項(xiàng)大破與江召益夜反有詳漢”軍淮罵馬稍哀將屠,而免立司而楚將軍,通辦得;罪漢入城勝諸,我中別可戰(zhàn)罪若兵於言當(dāng)高。沛苛如、謹(jǐn)往騎去萬耳景卮萬人武夫山將有舉,具有安廣劍國為項(xiàng)王內(nèi)并趙彭,戰(zhàn)敗滅:其糧,多二用也?!迸鎰偌刺煜孪鄧囗?xiàng)羽謂自曰當(dāng)之不敢數(shù)略誅。不使者名可知遂不為其耳。項(xiàng)羽大久漢曰:“首項(xiàng)氏與焉項(xiàng)積曰:“糧數(shù)不然。籍於是項(xiàng)王謂羊欲立國誅歲卒,項(xiàng)王引姻受右,欲為遇披從而北者於義者。今不敗從所屬於行,遂霸於田榮不免??挚謴?fù)可勝又關(guān)處,危貴籍聞。韓及然人,乃應(yīng)渡河擊東意,公就‘得噲以其臣,諸侯侯諸將六出數(shù)高。項(xiàng)梁
[epoch20]:
無西意,而北擊齊。徵兵九江王布。布稱疾不往,使將將數(shù)千人行。項(xiàng)王由此怨布也。漢之。樊噲周項(xiàng)王。
項(xiàng)約軍走引兵渡三金,亦言。城數(shù)百項(xiàng)王,都鴻萬數(shù)傷降入,復(fù)煩王其秦,遂去四北陵之。項(xiàng)王瞋之脫逐。漢王弟南數(shù)千壁遂煩,瞳三胡萬人,使人追說漢王,非從一為萬行。。項(xiàng)弟氏,闋之?dāng)?shù)上。
居數(shù)百百言,數(shù)百壁項(xiàng)羽追軍,此亦分至,漢王皆為憐侯。長嬰說為騎齊王。齊人而射數(shù)寶項(xiàng)王。項(xiàng)羽急,曰:“諾。相大杓猴乎?”曰:“心為凍信乘,聞楚皆則兵屬秦常,軍咸陽至久都也。
西時(shí),不當(dāng)成金從武侯。項(xiàng)王如史殺之,年。諸侯至范陵,走項(xiàng)王。項(xiàng)氏、魯中,聞皆走下,引兵西。漢王徇魯,項(xiàng)王。項(xiàng)羽天下彭項(xiàng)王。軍戰(zhàn)而北與西,封又。關(guān)項(xiàng)王,乃散知代王。長懷軍,項(xiàng)王。項(xiàng)羽渡沛事騎,使人追忍沛。項(xiàng)羽謂無事之,知張矣。漢王因玉力,水走。、臣江桓張馬章?”項(xiàng)氏則功之,走楚楚而立秦嘉霸矣。今者攻罪關(guān),諸將軍薛秦萬為騎城。籍俱太曹無益子意,皆復(fù)南聲行萬人,得吳南南月必人下屬與籍倍侯。諸侯吏相曰:“雖吏吏卒,使項(xiàng)王乃自合馬
[epoch30]:
帝,曰:“古之帝者地方千里,必居上游。”乃使使徙義帝長沙郴縣。趣義帝行,其群臣稍”背齊數(shù),
時(shí)時(shí),兵漢梁患年,項(xiàng)羽乃召彭越王。漢王擊秦嘉,以惡侯與齊與齊。齊,南功於項(xiàng)王曰:“曰:“起高”何能勝亡走我何棄:“城軍滎,誅非游食,封項(xiàng)羽為詩將章卒者、東安子北有前,壽金奴、漢兵四力者秦軍,項(xiàng)王乃相置漢數(shù)十、睢其以至韓用,得楚十四,故天亡至,觀破秦入,斬西。長公已、,間與韓游戰(zhàn),近令其心為地,滎又不人,封人軍中,捍內(nèi)未江,北數(shù)由陽關(guān),故立為上為長君遺為封武,嘗從古漢,可與彭戰(zhàn),可為獨(dú)將,須又不重。欣月走勝故益為翟為王王患來,初之。知者高!夫角走楚,楚楚之出,睢有所知,王曰:“,為王將,下。今歲走城漢甬,此秦戰(zhàn),破秦易。於。王聞所諾。漢於歇漢王,得殺數(shù)十,從心長史若。項(xiàng)羽乃定陶懷王,漢王乃使徙瞳漢王父亦叱、分燒,婦為常,收其怒,殺之卒上。”乃謂、與梁
當(dāng)漢王有碭成皋。長,欲漢,如公十復(fù)數(shù)侯。約欲攻立事立誅為諸君王,封令衛(wèi)為前,郎王數(shù)為沛公沛軍事而塞王?!蹦思错?xiàng)王未:“吾聞
[epoch60]:
張良出,要項(xiàng)伯。項(xiàng)伯即入見沛公。沛公奉卮酒為壽,約為婚姻,曰:“吾入關(guān),秋豪不敢;。如用之帝者,,大漢王?”乃曰:“巴、間以楚,追九軍至,騎何陽,長史若者,不敢出。公。
沛公先為封項(xiàng)王曰:“彭越左劫積,楚王急,乃城之膠無不至江陽,定陶所知。陳馀受東與韓而必公?!睗h王聽,誡漢王至,披王定陶?qǐng)?bào)項(xiàng)王。項(xiàng)王使沛公軍項(xiàng)王聞之王三年戰(zhàn)陽。項(xiàng)王乃自王為項(xiàng)王乃疑沛公。項(xiàng)羽乃召沛公曰:“吾入急,而恐,至破中,使者高行,故楚於張耳。項(xiàng)王乃相引兵四面王。項(xiàng)王渡侵,急下,盡降不別,左勿楚北,聞?dòng)鹨h王父後以來出女。項(xiàng)王乃馳行,斬睢,故八君?!表?xiàng)王即之,曰:“旦有不趣?!表?xiàng)王曰:“田角項(xiàng)羽大破曰曰:“謹(jǐn)諾楚以楚,巴得楚之楚破之。章曰:“章邯乃魏項(xiàng)王項(xiàng)王伏,置軍,無以至東定,項(xiàng)梁怒曰:“田陽為齊受天下,使人新六鞏此,王大怒。曰:“將戮力也也”,又以即其意,不應(yīng)大,與大夫俱齊。。項(xiàng)梁聞沛公左,項(xiàng)王乃疑陳留沛公與籍?dāng)匚?,使者起,?xiàng)王伏櫟芮欣,都廢;不義頭。
項(xiàng)王聞漢羽欲得與項(xiàng)羽大驚曰:“
總結(jié):可以大概看出來,越到后來學(xué)到的專用名詞越多。所以效果還是蠻好的。反正比我寫的好多了。
源碼地址:點(diǎn)我