深度学习(三)之LSTM写诗
Python微信訂餐小程序課程視頻
https://edu.csdn.net/course/detail/36074
Python實戰量化交易理財系統
https://edu.csdn.net/course/detail/35475
目錄* 數據預處理
- 構建數據集
- 模型結構
- 生成詩
- 根據上文生成詩
- 生成藏頭詩
- 參考
機器學習業,圣賢不可求。臨戎辭蜀計,忠信盡封疆。天子咨兩相,建章應四方。自疑非俗態,誰復念鷦鷯。
國步平生不愿君,古人今在古人風。
科公既得忘機者,白首空山道姓名。
大道不應無散處,未曾進退卻還征。
環境:
- python:3.9.7
- pytorch:1.11.0
- numpy:1.21.2
代碼地址:https://github.com/xiaohuiduan/deeplearning-study/tree/main/寫詩
數據預處理
數據集文件由3部分組成:ix2word,word2ix,data:
- ix2word:id到word的映射,如{23:‘姑’},一共有8293個word。
- word2ix2:word到id的映射,如{‘姑’:23}
- data:保存了詩的數據,一共有57580首詩,每條數據由125個word構成;如果詩的長度大于125則截斷,如果詩的長度小于125,則使用""進行填充。
每條數據的構成規則為:…\dots詩詞。
在訓練的時候,不考慮填充數據,因此,將數據中的填充數據去除,去除后,部分數據顯示如下:
構建數據集
模型輸入輸出決定了數據集怎么構建,下圖是模型的輸入輸出示意圖。詩詞生成實際上是一個語言模型,我們希望Model能夠根據當前輸入x0,x1,x2…xn?1x_0,x_1,x_2\dots x_{n-1}去預測下一個狀態xnx_n。如圖中所示例子,則是希望在訓練的過程中,模型能夠根據輸入床前明月光生成床前明月光,。
因此根據“床前明月光,凝是地上霜。舉頭望明月,低頭思故鄉”,可以生成如下的X和Y(seq_len=6)。
X:床前明月光,Y:床前明月光,
X:,凝是地上霜,Y:凝是地上霜。
X:。舉頭望明月,Y:舉頭望明月,
X:,低頭思故鄉,Y:低頭思故鄉。
代碼示意圖如下所示,seq_len代表每條訓練數據的長度。
seq_len = 48 X = [] Y = []poems_data = [j for i in poems for j in i] # 將所有詩的內容變成一個一維數組for i in range(0,len(poems_data) - seq_len -1,seq_len):X.append(poems_data[i:i+seq_len])Y.append(poems_data[i+1:i+seq_len+1])模型結構
模型結構如下所示,模型一共由3部分構成,Embedding層,LSTM層和全連接層。輸入數據首先輸入Embedding層,進行word2vec,然后將Word2Vec后的數據輸入到LSTM中,最后將LSTM的輸出輸入到全連接層中得到預測結果。
模型構建代碼如下,其中在本文中embedding_dim=200,hidden_dim=1024。
import torch import torch.nn.functional as F import torch.nn as nn class PoemNet(nn.Module):def \_\_init\_\_(self, vocab\_size, embedding\_dim, hidden\_dim):"""vocab\_size:訓練集合字典大小(8293)embedding\_dim:word2vec的維度hidden\_dim:LSTM的hidden\_dim"""super(PoemNet, self).__init__()self.hidden_dim = hidden_dimself.embeddings = nn.Embedding(vocab_size, embedding_dim)self.lstm = nn.LSTM(embedding_dim, self.hidden_dim,batch_first=True)self.fc = nn.Sequential(nn.Linear(self.hidden_dim,2048),nn.ReLU(),nn.Dropout(0.25),nn.Linear(2048,4096),nn.Dropout(0.2),nn.ReLU(),nn.Linear(4096,vocab_size),)def forward(self, input,hidden=None):"""input:輸入的詩詞hidden:在生成詩詞的時候需要使用,在pytorch中,如果不指定初始狀態h\_0和C\_0,則其默認為0.pytorch的LSTM的輸出是(output,(h\_n,c\_n))。實際上,output就是h\_1,h\_2,……h\_n"""embeds = self.embeddings(input)batch_size, seq_len = input.size()if hidden is None:output, hidden = self.lstm(embeds)else:# h\_0,c\_0 = hiddenoutput, hidden = self.lstm(embeds,hidden)output = self.fc(output)output = output.reshape(batch_size * seq_len, -1)output = F.log_softmax(output,dim=1)return output,hidden優化器使用的是Adam優化器,lr=0.001,損失函數是CrossEntropyLoss。訓練次數為100個epcoh。
生成詩
因為在模型構建的過程中,使用了dropout,所以在模型使用的時候,需要將model設置為eval模式。
生成詩的邏輯圖:
根據上文生成詩
根據上圖的原理,寫出的代碼如下所示:
def generate\_poem(my\_words,max\_len=128):'''根據前文my\_words生成一首詩。max\_len表示生成詩的最大長度。'''def \_\_generate\_next(idx,hidden=None):"""根據input和hidden輸出下一個預測"""input = torch.Tensor([idx]).view(1,1).long().to(device)output,hidden = my_net(input,hidden)return output,hidden# 初始化hidden狀態output,hidden = __generate_next(word2ix[""])my_words_len = len(my_words)result = []for word in my_words:result.append(word)# 積累hidden狀態(h & c)output,hidden = __generate_next(word2ix[word],hidden)_,top_index = torch.max(output,1)word = idx2word[top_index[0].item()]result.append(word)for i in range(max_len-my_words_len):output,hidden = __generate_next(top_index[0].item(),hidden)_,top_index = torch.max(output,1)if top_index[0].item() == word2ix['']: # 如果詩詞已經預測到結尾breakword = idx2word[top_index[0].item()]result.append(word)return "".join(result)generate_poem("睡覺")睡覺寒爐火,晨鐘坐中朝。爐煙沾煖露,池月靜清砧。自有傳心法,曾無住處傳。不知塵世隔,一覺一壺秋。皎潔垂銀液,浮航入綠醪。誰知舊鄰里,相對似相親。
生成藏頭詩
生成藏頭詩的方法與根據上文生成詩的方法大同小異。
def acrostic\_poetry(my\_words):def \_\_generate\_next(idx,hidden=None):"""根據input和hidden輸出下一個預測詞"""input = torch.Tensor([idx]).view(1,1).long().to(device)output,hidden = my_net(input,hidden)return output,hiddendef \_\_generate(word,hidden):"""根據word生成一句詩(以“?!苯Y尾的話) 如根據床生成“床前明月光,凝是地上霜?!?#34;""generate_word = word2ix[word]sentence = []sentence.append(word)while generate_word != word2ix["。"]: output,hidden = __generate_next(generate_word,hidden)_,top_index = torch.max(output,1)generate_word = top_index[0].item()sentence.append(idx2word[generate_word])# 根據"。"生成下一個隱狀態。_,hidden = __generate_next(generate_word,hidden)return sentence,hidden_,hidden = __generate_next(word2ix[""])result = []for word in my_words:sentence,hidden = __generate(word,hidden)result.append("".join(sentence))print("\n".join(result))acrostic_poetry("滾去讀書")滾發初生光,三乘如太白。 去去冥冥沒,冥茫寄天海。 讀書三十年,手把棼琴策。 書罷華省郎,憂人惜凋病。
參考
- 簡單明朗的 RNN 寫詩教程 - 段小輝 - 博客園 (cnblogs.com)
- LSTM — PyTorch 1.11.0 documentation
- Embedding — PyTorch 1.11.0 documentation
總結
以上是生活随笔為你收集整理的深度学习(三)之LSTM写诗的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 理解UI线程——SWT, Android
- 下一篇: iOS 加载本地Gif图片