深度學習 - LSTM生成文本 - 唐詩 - 文本預處理
經過LSTM 生成文本練習過後,我就想來實踐一下李宏毅老師在上課時曾說過,有研究生演示過 LSTM 生成唐詩,還蠻有趣的!!
於是上網找了一下,已經有人發布至 Github 了,我們拿來練習一下吧!!
於是上網找了一下,已經有人發布至 Github 了,我們拿來練習一下吧!!
先來看一下文本樣貌:
其中包含了 主標題"全唐詩 捲一" 與 子標題"捲1_1【帝京篇十首】李世民"
目標 : 我們要將每首詩存成list
思路 : 將標題去掉,且每首詩皆被空行包覆,所以只要逐行讀取一首詩到空格時跳到下一首詩。
如何將標題去掉!? 以下代碼練習將過程紀錄:
先將文件逐行讀取。
with open(poetry_file, "r" ,encoding="utf-8") as f:
for i in range(0, 3):
line = f.readline()
print(line,end="")
print(len(line))
全唐詩 捲一
8
1
捲1_1【帝京篇十首】李世民
17
第一行為何是8? google 了一下 “python3 編碼轉換” 使用 json 可以幫助我們了解,修改程式碼如下:
import json
with open(poetry_file, "r" ,encoding="utf-8") as f:
for i in range(0, 3):
line = f.readline()
u = json.dumps(line)
print(u)
print(line,end="")
print(len(line))
"\ufeff\u5168\u5510\u8a69 \u6372\u4e00\n"
全唐詩 捲一
8
"\n"
1
"\u3000\u3000\u63721_1\u3010\u5e1d\u4eac\u7bc7\u5341\u9996\u3011\u674e\u4e16\u6c11\n"
捲1_1【帝京篇十首】李世民
17
可以從輸出觀察到,空格" “& 換行”\n" 都算一個list的元素。
大概了解之後的第一件事,我們要去除主標題,但是主標題到底多長? 隨便找個最長的看看print出來看看
大概了解之後的第一件事,我們要去除主標題,但是主標題到底多長? 隨便找個最長的看看print出來看看
print(len("全唐詩 捲八百四十三"))
10
import json
x= u'】'
u= json.dumps(x)
print(u)
"\u3011"
子標題呢!? 我們可以看到子標題皆含有"【","】" 特殊符號,從剛剛透過 json 印出來可以知道這兩個特殊符號是 “\u3010” & “\u3011”,所以在逐行讀取時,只要找到這兩個符號,就可以跳過。
利用正則表達示來尋找"\u3010" & “\u3011” ,用以下程式碼 test 看看,逐行讀取,如果有找到特殊符號就 print : “True”。
import re
with open(poetry_file, "r" ,encoding="utf-8") as f:
for i in range(0, 5):
line = f.readline()
if re.search(u'\u3010', line):
print("True",line)
else :
print('Flase',line)
Flase 全唐詩 捲一
Flase
True 捲1_1【帝京篇十首】李世民
Flase
Flase 秦川雄帝宅,函榖壯皇居。綺殿韆尋起,離宮百雉?。
知道這些特殊符號,可以利用正則表達式 Regular expression operations來清理文本資料,也可以說利用正則表達式抓出我們要的資料,可參考regex教學。
在了解文檔內容要如何清理後,我們將文本資料建立list。
以下是清理文本的代碼,也是參考原著再修改。
以下是清理文本的代碼,也是參考原著再修改。
# *-* coding:utf-8 *-*
poetry = [] #用來存詩的list
old_line = '' #判斷該行是空行還是詩。
import re
with open(poetry_file, "r" ,encoding="utf-8") as f:
while 1:
line = f.readline()
#跳過主標題&子標題,遇到空行時重置old_line
if len(line)<2 or"全唐詩"in line or":" in line or "【"in line:
old_line = ''
#逐行詩丟進list中
elif old_line == '':
if "-" in line: #將有些詩後面會用 "--"備註詩人,將取其前面。
line = line.split("-")[0]
if "□" in line: #將有□過濾掉,這是翻譯後產生的...
line = re.sub('□',"",line)
if "?" in line:
line = line.replace("?","") #翻譯後有些"?",刪掉。
if re.search('[a-zA-Z0-9]',line): #有些詩的開頭會有英文!? 刪掉。
line = re.sub('[a-zA-Z0-9]',"",line)
poetry.append(line[0:-1]) #將該行丟進list中
old_line = line
#下一行還是同一首詩的line,加到同一個list中,表同一首詩。
else:
if "-" in line:
line = line.split("-")[0]
if "□" in line:
line = re.sub('□',"",line)
if "?" in line:
line = line.replace("?","")
if re.search('[a-zA-Z0-9]',line):
line = re.sub('[a-zA-Z0-9]',"",line)
poetry[-1] = poetry[-1]+line[0:-1]
old_line = line
if not line:
break
#最後將文章內有()註解都刪掉
i=0
for poem in poetry:
if "(" and ")" in poem:
poem = poem.split("(")[0] + poem.split(")")[1]
poetry[i] = poem
i = i + 1
#有些遺留單個誇號註解(少量),整行刪掉
final_poetry = poetry.copy()
j = 0
for poem in poetry:
if "(" in poem or ")" in poem:
final_poetry.pop(j)
j = j-1
j = j+1
看看剩下多少詩可以訓練
print('poetry :',len(poetry))
print('final_poetry :',len(final_poetry))
poetry : 48209
final_poetry : 48125
還有剩下48125 首詩,夠我們訓練模型。
最後將 final_poetry 輸出存檔。
最後將 final_poetry 輸出存檔。
pre_process_poetry_file = os.path.join(data_dir, 'pre_process_poetry.txt')
with open(pre_process_poetry_file, "w",encoding="utf-8") as w:
for i in final_poetry :
w.write(i+"\n")
呼…接下來就是將文字轉換成向量了。
沒有留言:
張貼留言