0
雷鋒網按:本文原載于微信公眾號DT財經(微信號:DTCaijing),作者Jacob Plaster,University of Hull。原文出處:《Artificial machine learning writer》。
英國赫爾大學的數據俠 Jacob 創造了一個 “寫手” 程序,教大家如何模仿《哈利 · 波特》的口吻寫文章。文末還附加了 GitHub 的鏈接。可以親自上手試試。今后,哪怕沒有教授帶你玩,你也可以寫模仿 J.K Rowling 的為哈利寫一段咒語啦!
我創造了個 “寫手” 程序,能模仿大師寫作風格哦
我最近在赫爾大學完成了我高級人工智能課程單元。它特別棒。
“機器學習” 特別吸引我的地方在于,這項技術的潛在應用看起來無窮無盡。當我成功克服了(人工神經)網絡工作原理的陡峭學習曲線后,我決定是時候創作些什么了。
當我瘋狂地在互聯網上搜索機器學習的奇跡時,我偶然發現了個 GitHub 上的項目,使用了時間遞歸神經網絡(recurrent neural network,RNN)來模仿莎士比亞的寫作風格。我很喜歡這個創意,也想試著創造一個不一樣的屬于我自己的版本。
(DT 君小課堂:RNN 包含輸入單元(input units)群、輸出單元(output units)群和隱藏單元(hidden units)。這些隱藏單元完成了最為有意思的工作,它們就像魔法,讓你輸入的話變得更像莎士比亞和哈利波特。訓練 RNN 存在很多相當具有挑戰性的難題,而這仍是一個非常活躍的研究領域。感興趣的童鞋,可以戳這里來看。)
我寫了一個人工機器學習 “寫手” 程序,試圖通過訓練它來模擬人格并模仿著名作家的寫作風格寫作。我們將嘗試模仿莎士比亞,J·K·羅琳和網絡上隨機的博客。
這個 “寫手” 程序將會這么來做:通過訓練數據逐步增加句量,利用 NLTK 把句子拆解轉換成詞性標注,訓練象征符號的結果,再次增加句量,然后訓練詞性標注出現的概率。
許多程序嘗試通過分析文本來預測特征出現的概率,然而并不準確。而我的這種方法總是能有好的結果。

數據分類和歸一,都是為了有一個好的模仿對象
(DT 君小課堂:接下來作者就要對數據做分類了。分類是數據挖掘領域中一項非常重要的任務。自然語言處理 NLP 中,一般的模式分類方法都可用于文本分類研究。常用的分類算法包括:決策樹分類法,樸素的貝葉斯分類算法、基于支持向量機 (SVM) 的分類器,神經網絡法,k - 最近鄰法 (k-nearest neighbor,kNN),模糊分類法等等。)
我決定使用 scikit 機器學習庫。它使用和配置起來都特別簡單。Scikit 有著龐大的社區,里面包含了大量的教程和許多可以用來訓練你的神經網絡的樣本數據集(example datasets)。我并沒有使用原有的樣本數據集,我想把無序的文本轉變成歸一化的訓練數據。我創建的這個 “寫手” 使用了多重支持向量機(SVM)的分類器,一個向量機(vector machine)用作句子結構化,多個小型向量機用于對應從詞匯表中選取單詞算法。
(DT 君小課堂:支持向量機 (SVM) 通俗來講是一種二類分類模型,其學習策略便是間隔最大化,通過尋求結構化風險最小來提高學習機泛化能力,實現經驗風險和置信范圍的最小化,從而達到在統計樣本量較少的情況下,亦能獲得良好統計規律的目的。想要深入了解,請看《理解 SVM 的三層境界》)
我目前使用的算法能有精準的結果,這使得句式結構化非常成功。這個階段中最大的障礙就是將訓練數據歸一化(normals)。
(DT 君小課堂: 歸一化,簡單的講就是由于數據單位不一致,所以需要將不同的數據進行格式化,使之在指定的范圍內,比如在 0-1 之間。歸一化是為了后面數據處理的方便,其次是保正程序運行時收斂加快。舉個栗子:一張表有兩個變量,一個是體重 kg,一個是身高 cm。假設一般情況下體重這個變量均值為 60kg,身高均值為 170cm。這兩個變量同樣是 100,對于身高來說很矮,但對于體重來說已經很大了。所以歸一化就是要解決這個問題,目的是可以用數值直接來進行比較。)
我使用了 NLTK(Natural Language Toolkit 自然語言工具包)的庫來先將訓練數據轉化成詞性標注,例如:NN(名詞),DET(限定詞),$(符號)等等。(然后再將其歸一化)
(DT 君小課堂:為什么要用 NLTK?從計算機處理的角度來看,英語或任何自然語言(口語或普通的語言)都是極不規范和不準確的,需要對它們進行整理。NLTK 還提供了一些 “詞干分析器” 類,以便進一步規范化單詞。)
利用這些標簽, 我可以對數據進行歸一化,像下面這樣:
["The","cat","jumped"]= ['DET','NN','VP]
一旦歸一化以后就像下面這樣:
['DET','NN','VP]= [0.2237823,0.82392,0.342323]
現在我只需要得到一個目標歸一化后的值(target normal),并且將它代入神經網絡中開始訓練即可。從二進制大對象(BLOB,binary large object)中讀取文本時,同時訓練推測下一個順序詞是什么。因此:
["The","cat","jumped"]["towards"]= ['DET','NN','VP]["PRP"]= [0.2237823,0.82392,0.342323][0.12121212]
接下來要做的是獲取大量 J.K Rowling《Harry Potter》的資源并且準備開始模仿她的句式結構。
努力提高詞匯量,這樣才能 “喂飽” 我的 “寫手”
詞匯無疑是本項目中最難的部分,我很清楚地知道沒有理由不使用遞歸神經網絡,預測每個字母也是更好的辦法。然而,我選擇的方法產生非常酷炫的結果。
詞匯以詞序矩陣的形式包含在訓練用的 BLOB 文件中。每個詞分解成了詞性標注接著進行歸一化。歸一化后的值和詞匯依然被備份著,因為稍后將歸一化的值轉換回單詞依然要利用此作為映射表。詞匯看起來像這樣:
[[(cat,[0.232342]),(bat,[0.2553535]),(dog,[0.345454]),(horse,[0.4544646])...]
[(run,[0.12131],(jump,0.232323),(fall,0.43443434)...]
...
1. 我們先使用小型文本 HarryPotter(small).txt(DT 君注:作者所使用的文本,請點擊 GitHub)。
這個數據集包含了 346 個訓練向量(training vectors),是一個最小的訓練集。
Input(輸入):"Harry dont look"(哈利不要看)
Output(輸出):"Harry dont look had at eleven for witches had been for eleven then with nothing had been for eleven then with nothing had been for eleven then with nothing had been for eleven"(哈利不要看,11,女巫,11,沒有事情,11,……)
Input(輸入):"Wizards sometimes do"(巫師有時候會做)
Output(輸出):"wizards sometimes do , Harry had been been , Harry had been been , Harry had been been , Harry had been been , Harry had been been , Harry had been been"(巫師有時候會做,哈利已經在,哈利已經在,哈利已經在,哈利已經在,哈利已經在,哈利已經在)
你可以看出神經網絡很努力想要學習卻缺乏訓練數據。它幾乎就陷入無限循環中了。

2. 我們接下來開始使用中型文本 HarryPotter(medium).txt。
數據集包含了 2500 個訓練向量。
Input(輸入):"Harry don't look"(哈利不要看)
Output(輸出):"Harry don't look , incredibly that a year for been parents in . followers , Harry , and Potter was been curse . Harry was up a year , Harry was been curse "(哈利不要看,難以置信地有一年父母在。花朵,哈利,波特都被詛咒。哈利長大了,哈利被詛咒)
Input(輸入):"Wizards sometimes do"(巫師有時候會做)
Output(輸出):"wizards sometimes do parents."(巫師有時候會對父母做)
現在你可以看出神經網絡的輸出,已經生成了我們預想的結果。因為增加了訓練數據,它的性能得到了大幅度提升。
3. 使用大型文本 HarryPotter(large).txt,數據集包含了 4550 個訓練向量。
Input(輸入):"Harry don't look"(哈利不要看)
Output(輸出):"Harry don't look Petunia Harry , incredibly had on the address."(哈利不要看佩妮哈利,有地址)
現在,除了一個錯誤的停頓應該在 Petunia(佩妮)與 Harry(哈利)之間,這個句子簡直完美。
不過,在這里,訓練數據的增加反而給了一個負面的結果。這是罕見的。
Output(輸出):"Wizards sometimes do the address on the address on the address."
4. 接下來,要使用另一個和哈利波特無關的大型文本 MacbookAirBlog(large).txt 了。
我隨機在一個博客上抓取了一份(與哈利波特無關的)文本。出乎意料的是這個數據集通常能產生更精確的結果。數據集中包含了 3576 個訓練向量。
Input(輸入):"Harry don't look"(哈利不要看)
Output(輸出):"Harry don't look , also of a scaling on playing . Use for Control weight goes so cable and they've of placed it . you do to want things at at 2015."(哈利不要看,比例玩起來。控制作用體重所以有線和他們放在這里。2015 年你的確需要東西。)
Input(輸入):"Wizards sometimes do"(巫師有時候會做)
Output(輸出):"Wizards sometimes do When ports a scaling the have object , also of a scaling on playing ."(當港口有貨,巫術有時候會做,比例玩起來)
句式結構是正確的,但詞匯有限。別急,10,000 以上訓練向量的數據集馬上要來了(DT 君注:具體的訓練請大家移步 GitHub)

預測和測試:“寫手” 不僅可以模仿利波特哦
當我們試著對下一個順序的詞進行預測時,程序生成了非常準確的結果。但是當大量序列開始生成后,準確率就下降了。我創建了一個測試單元用來比較生成的下一個詞與 J.K Rowling 實際創作中的詞。
我得到了下面的結果:

通過命令行,你可以看到:
python3 main.py -utss -td "Datasets/MacbookAirBlog(large).txt"
我用同樣的想法測試了詞匯表:



python3 main.py -utv -td "Datasets/MacbookAirBlog(large).txt"
如果預估超過 80% 就會被歸為 “通過(passed)”。
以上所有的結果都來自于 “未完結” 的程序,這也就是為什么它們看起來并沒有那么準確。
哈利波特的數據集就來自于電子書,當然你也可以用其他數據集。它是非常容易添加數據集,只要確保他是 BLOB 的格式。
作者注:本實驗只應用于教育,永不用于商業化。如果你想查看這個項目,你可以在 Github 上看到。
雷峰網版權文章,未經授權禁止轉載。詳情見轉載須知。