深度學習 - LSTM生成文本 - 唐詩 - 生成唐詩
最後,我們利用訓練好的模型來生成唐詩。
以下函式def function 通通寫在class PoetryModel(object): 底下。
import 所用到的庫
import random
import os
import keras
import numpy as np
from keras.callbacks import LambdaCallback
from keras.models import Input, Model, load_model
from keras.layers import LSTM, Dropout, Dense
from keras.optimizers import Adam
from data_utils import *
from config import Config
class PoetryModel(object):
與先前練習的差不多,也是加入softmax temperature 參數,使得在不同溫度的情況下,模型產生出得文章會有不同的創造力。
這邊與先前不同的是,這裡使用np.power,是冪次函數,而先前練習的是指數函數。不過都是利用加入 temperature 參數,使得預測的文字具有創造性。
這邊與先前不同的是,這裡使用np.power,是冪次函數,而先前練習的是指數函數。不過都是利用加入 temperature 參數,使得預測的文字具有創造性。
#給定模型預測,採樣下一個字符的函數
def sample(self, preds, temperature=1.0):
'''
當temperature=1.0時,模型輸出正常
當temperature=0.5時,模型輸出比較open
當temperature=1.5時,模型輸出比較保守
在訓練的過程中可以看到temperature不同,結果也不同
就是一個概率分佈變換的問題,保守的時候概率大的值變得更大,選擇的可能性也更大
'''
preds = np.asarray(preds).astype('float64')
exp_preds = np.power(preds,1./temperature)
preds = exp_preds / np.sum(exp_preds)
pro = np.random.choice(range(len(preds)),1,p=preds)
return int(pro.squeeze())
再來,將預測文字的函數先寫好,供class內部使用。
#根據一串輸入,返回單個預測字符
def _pred(self,sentence,temperature =1):
'''因為模型是用 max_len 長度輸入訓練,預測下個字符。
所以要排除輸入一串文字小於 max_len 的情況'''
if len(sentence) < self.config.max_len:
print('in def _pred,length error ')
return
'''輸入字串向量化,丟入模型預測'''
sentence = sentence[-self.config.max_len:]
x_pred = np.zeros((1, self.config.max_len, len(self.words)))
for t, char in enumerate(sentence):
x_pred[0, t, self.word2numF(char)] = 1.
preds = self.model.predict(x_pred, verbose=0)[0]
next_index = self.sample(preds,temperature=temperature)
#輸出再由向量轉回文字
next_char = self.num2word[next_index]
return next_char
def _preds(self,sentence,length = 23,temperature =1):
'''sentence:預測輸入值;lenth:預測出的字符串長度;
供 class 內部調用,輸入max_len長度字符串,
返回length長度的預測值字符串'''
sentence = sentence[:self.config.max_len]
generate = ''
for i in range(length):
pred = self._pred(sentence,temperature)
generate += pred
sentence = sentence[1:]+pred
return generate
以上寫好後,就可以來試著生成唐詩。
先練習最基本的,如同訓練時給前六個字,預測下一個字,一直迴圈到預測整首詩。
先練習最基本的,如同訓練時給前六個字,預測下一個字,一直迴圈到預測整首詩。
'''根據給出的前max_len個字,生成詩句'''
def predict_sen(self, text,temperature =1):
'''此例中,即根據給出的第一句詩句(含逗號),來生成古詩'''
if not self.model:
return
max_len = self.config.max_len
if len(text) < max_len:
print('length should not be less than ', max_len) #排除輸入一串文字長度小於 max_len 的情況
return
sentence = text[-max_len:]
# print('the first line:',sentence)
generate = str(sentence)
generate += self._preds(sentence,length = 24-max_len,temperature=temperature)
return generate
我們試試以下練習:給三種溫度看看輸出。
for temperature in [0.5, 1, 1.5]:
poetry1 = model.predict_sen("柯批好市長,",temperature = 1.5)
print(poetry1)
柯批好市長,丹齣天杯上。齣南門荷春,將對愁華馬。
柯批好市長,新間與照想。還為碧茲陵,親國葉白上。
柯批好市長,飛坐孤何平。氣還還高得,竹時相州過。
呵,還蠻有趣的!
接著試試看隨機選一首詩的開頭,當作輸入會不會讓模型寫的詩好看一些?
接著試試看隨機選一首詩的開頭,當作輸入會不會讓模型寫的詩好看一些?
def predict_random(self,temperature = 1):
'''隨機從庫中選取一句開頭的詩句,生成五言絕句'''
if not self.model:
print('model not loaded')
return
index = random.randint(0, self.poems_num)
sentence = self.poems[index][: self.config.max_len]
generate = self.predict_sen(sentence,temperature=temperature)
return generate
for temperature in [0.5, 1, 1.5]:
poetry_Random = model.predict_random(temperature = temperature)
print(poetry_Random)
午醉醒來晚,人日何雲從。花日池東見,林同無下得。
何處鞦風至,流鍾虛日北。有月吾間人,吹臨早相連。
流品是鴛鴦,遠長夜十四。愛時來齣何,今方空石意。
原詩為:
午醉醒來晚,無人夢自驚。夕陽如有意,長傍小窗明。
何處鞦風至,蕭蕭送雁群。朝來入庭樹,孤客最先聞。
流品是鴛鴦,翻飛雲水鄉。風高離極浦,煙暝下方塘。比鷺行藏彆,穿荷羽翼香。雙雙浴輕浪,誰見在瀟湘。
午醉醒來晚,無人夢自驚。夕陽如有意,長傍小窗明。
何處鞦風至,蕭蕭送雁群。朝來入庭樹,孤客最先聞。
流品是鴛鴦,翻飛雲水鄉。風高離極浦,煙暝下方塘。比鷺行藏彆,穿荷羽翼香。雙雙浴輕浪,誰見在瀟湘。
若不知原詩為何,模型寫的以假亂真,真是難以想像。今天要是寫給外國人看,可能真的會相信呢!!
接著來玩玩藏頭詩,我們要將想藏頭的字串,逐個丟進max_len的最後一個字然後丟進模型預測下一個字,直至完整的詩句。此例為四字藏頭,如下:
'''根據給4個藏頭字,生成藏頭詩五言絕句'''
def predict_hide(self, text,temperature = 1):
if not self.model:
print('model not loaded')
return
if len(text)!=4:
print('藏頭詩的輸入必須是4個字!')
return
#選取隨機一首詩的最後(max_len-1)個字符(含句號)+給出的首個文字作為初始輸入 ex.前明月光。+text[0] (共6個字)
#此練習輸入共6個字,同訓練模型時的條件。
index = random.randint(0, self.poems_num)
sentence = self.poems[index][-self.config.max_len:-1] + text[0]
generate = str(text[0])
print('first line = ',sentence)
#給出藏頭詩後五個字(含逗號)
for i in range(5):
next_char = self._pred(sentence,temperature)
sentence = sentence[1:] + next_char
generate+= next_char
#將藏頭詩的第二個字以後加入
for i in range(3):
generate += text[i+1]
sentence = sentence[1:] + text[i+1]
#完成後面每個藏頭詩的句子
for i in range(5):
next_char = self._pred(sentence,temperature)
sentence = sentence[1:] + next_char
generate+= next_char
return generate
藏頭詩的藏頭"華碩石頭",丟進模型看看:
for temperature in [0.5, 1, 1.5]:
hide_poetry = model.predict_hide('華碩石頭', temperature = temperature)
print(hide_poetry)
first line = 意在浮花。華
華見不心故,碩道一水久。石人天關子,頭是花如鞦。
first line = 欲媚濃妝。華
華度曉可堂,碩長颱欲帝。石是青長待,頭驚齣朝相。
first line = 應在十洲。華
華清東色齊,碩王虎月顔。石山在逢歸,頭道公林共。
只給模型第一個字,完成整個詩(共24個字,含逗號、句號)
'''根據給出的首個文字,生成五言絕句'''
def predict_first(self, char,temperature =1):
if not self.model:
print('model not loaded')
return
index = random.randint(0, self.poems_num)
#選取隨機一首詩的最後max_len個字符+給出的首個文字作為初始輸入
sentence = self.poems[index][-self.config.max_len:-1] + char
generate = str(char)
# print('first line = ',sentence)
# 直接預測後面23個字符
generate += self._preds(sentence,length=23,temperature=temperature)
return generate
for temperature in [0.5, 1, 1.5]:
poetry_first = model.predict_first("中", temperature = temperature)
print(poetry_first)
中來不故君,在林中雨有。夜新月山時,聞傢誰歸空。
中平知世相,見可微得西。清城有意齣,裏正君相風。
中望微翻草,常月玉雪外。木州颱水上,林所州上願。
以上都是參考作者的編碼做練習,以下我也來利用一下 predict_first 做為內部調用,寫一個函式,把每一首詩的開頭當作藏頭,想輸入多少字,就有幾首詩:
'''每一首詩的開頭當作藏頭,想輸入多少字,就有幾首詩'''
def hide_poetry(self,text,temperature = 1,):
generate = ''
for i in text:
sen = model.predict_first(i,temperature)
generate += sen +"\n"
return generate
for temperature in [0.5, 1, 1.5]:
hide_poetry = model.hide_poetry("花好月圓")
print("temperature : %s" %temperature)
print(hide_poetry)
temperature : 0.5
花期雲曉照,鍾發上傢月。為中水城子,門願為期宿。
好今君裏蒼,樓傢復地同。群春事人多,相重山中東。
月寒空中山,且成往當一。與為君不色,中過清待外。
圓行誰陽不,國衣有山吹。華二光歸安,客夜東中春。
temperature : 1
花吳天欲水,去見今閣詩。軒惜相子得,寄聞寒高荷。
好為山滿陵,雲有香春攀。不高彆待容,知名作人殊。
月恩安帶葉,期山倚王寒。君為州上長,已長藏朝莫。
圓裏子來三,散風馀關對。君雲鞦人著,為不遲水正。
temperature : 1.5
花當未已是,中持老日門。窗不已韆在,居眾夜彆恩。
好憶天上驚,聲對朝發日。風已空來罷,樹裏煙草鳥。
月春露應清,起金閑水平。來寒起前不,晚愛前何不。
圓夜為正暮,時齣堪海池。終幾亦落思,隱颱林山白。
用AI寫詩,還蠻有趣的!! 雖然不能寫出有押韻的詩,但模型還是能寫出有模有樣的句子。
神經網絡已經可以記住逗號、句號出現在詩中的位置,且詩句都很假掰,很有詩的味道。
神經網絡已經可以記住逗號、句號出現在詩中的位置,且詩句都很假掰,很有詩的味道。
LSTM 模型的練習還有很多,可以應用面很廣,算是 NLP 領域的入門,身為初學者一定要好好練習。
沒有留言:
張貼留言