前言:出于種種原因哆料,總是不自覺(jué)把愛(ài)好和工作相互結(jié)合起來(lái)缸剪,每每感嘆于曹雪芹構(gòu)思的巧妙剧劝,語(yǔ)言的精煉,情節(jié)的感人……于是蹦出想法讥此,看機(jī)器能否讀懂“寶黛”之間的愛(ài)情。
-
數(shù)據(jù)處理
數(shù)據(jù)當(dāng)然是偉大的《紅樓夢(mèng)》本身了卒稳,下載txt文件他巨。
然后進(jìn)行編碼轉(zhuǎn)化“utf-8”。
然后進(jìn)行分詞染突,去除其中大量的空格和標(biāo)點(diǎn),然后有兩種方法進(jìn)行詞向量的構(gòu)建份企,分別是n-gram模型訓(xùn)練和word2vect
用n-gramma生成詞向量
把數(shù)據(jù)轉(zhuǎn)化為如下格式:
也就是N=2
上述操作代碼如下:
with open("紅樓夢(mèng).txt",encoding='utf-8') as f:
text = f.read()
# print(text)
temp = jieba.lcut(text)
words = []
# print(temp)
for i in temp:
#過(guò)濾掉所有的標(biāo)點(diǎn)符號(hào)
i = re.sub("[\s+\.\!\/_,$%^*(+\"\'””《》]+|[+——!甜紫,。囚霸?、~@#¥%……&*():]+", "", i)
if len(i) > 0:
words.append(i)
# print(len(words))
# print(words)
trigrams = [([words[i], words[i + 1]], words[i + 2]) for i in range(len(words) - 2)]
# 打印出前三個(gè)元素看看
print(trigrams[:3])
然后建立詞匯表
# 得到詞匯表
vocab = set(words)
print(len(vocab))
# 兩個(gè)字典拓型,一個(gè)根據(jù)單詞索引其編號(hào),一個(gè)根據(jù)編號(hào)索引單詞
#word_to_idx中的值包含兩部分岩睁,一部分為id,另一部分為單詞出現(xiàn)的次數(shù)
#word_to_idx中的每一個(gè)元素形如:{w:[id, count]},其中w為一個(gè)詞冰啃,id為該詞的編號(hào),count為該單詞在words全文中出現(xiàn)的次數(shù)
word_to_idx = {}
idx_to_word = {}
ids = 0
#對(duì)全文循環(huán)阎毅,構(gòu)件這兩個(gè)字典
for w in words:
cnt = word_to_idx.get(w, [ids, 0])
if cnt[1] == 0:
ids += 1
cnt[1] += 1
word_to_idx[w] = cnt
idx_to_word[ids] = w
然后就是模型構(gòu)建和參數(shù)訓(xùn)練,模型結(jié)構(gòu)如下:
1矿咕、輸入層:embedding層,這一層的作用是:先將輸入單詞的編號(hào)映射為一個(gè)one hot編碼的向量碳柱,形如:001000熬芜,維度為單詞表大小莲镣。 然后涎拉,embedding會(huì)通過(guò)一個(gè)線(xiàn)性的神經(jīng)網(wǎng)絡(luò)層映射到這個(gè)詞的向量表示,輸出為embedding_dim
2鼓拧、線(xiàn)性層,從embedding_dim維度到128維度钮糖,然后經(jīng)過(guò)非線(xiàn)性ReLU函數(shù)
3、線(xiàn)性層:從128維度到單詞表大小維度藐鹤,然后log softmax函數(shù),給出預(yù)測(cè)每個(gè)單詞的概率
具體代碼可見(jiàn):https://github.com/dctongsheng/n-grama-and-wordvect-Analysis-of-the-text
迭代訓(xùn)練
word2vect進(jìn)行模型訓(xùn)練
訓(xùn)練的時(shí)候需要把數(shù)據(jù)重新進(jìn)行調(diào)整娱节,變成句子進(jìn)行輸入
如下:
['因此', '大家', '議定', '每日', '輪流', '做', '晚飯', '之主'], ['天天', '宰豬', '割羊', '屠鵝', '殺鴨', '好似', '臨潼斗寶', '的', '一般', '都', '要', '賣(mài)弄', '自己', '家里', '的', '好', '廚役', '好', '烹調(diào)'],
數(shù)據(jù)處理的代碼如下:
f = open("紅樓夢(mèng).txt", encoding='utf-8')
f = f.read().split("。")
print(list(f))
lines = []
for line in f:
temp = jieba.lcut(line)
words = []
for i in temp:
#過(guò)濾掉所有的標(biāo)點(diǎn)符號(hào)
i = re.sub("[\s+\.\!\/_,$%^*(+\"\'””《》]+|[+——谴古!,\- 掰担。怒炸?带饱、~@#¥%……&*():阅羹;‘]+", "", i)
if len(i) > 0:
words.append(i)
if len(words) > 0:
lines.append(words)
print(lines)
然后輸入模型,將圖像轉(zhuǎn)化為二維空間進(jìn)行展示
model = Word2Vec(lines, size = 20, window = 2 , min_count = 0)
renwu = model.wv.most_similar('林黛玉', topn = 20)
print(renwu)
rawWordVec = []
word2ind = {}
for i, w in enumerate(model.wv.vocab):
rawWordVec.append(model[w])
word2ind[w] = i
rawWordVec = np.array(rawWordVec)
X_reduced = PCA(n_components=2).fit_transform(rawWordVec)
然后繪制圖像捏鱼,并且展示把幾個(gè)特殊人物,在圖像中展現(xiàn)出來(lái)'賈寶玉', '林黛玉', '香菱', '賈政', '晴雯', '妙玉', '襲人', '薛寶釵', '王熙鳳', '平兒', '賈母', '探春'
# 繪制所有單詞向量的二維空間投影
fig = plt.figure(figsize = (15, 10))
ax = fig.gca()
ax.set_facecolor('black')
ax.plot(X_reduced[:, 0], X_reduced[:, 1], '.', markersize = 1, alpha = 0.3, color = 'white')
# 繪制幾個(gè)特殊單詞的向量
words = ['賈寶玉', '林黛玉', '香菱', '賈政', '晴雯', '妙玉', '襲人', '薛寶釵', '王熙鳳', '平兒', '賈母', '探春']
# 設(shè)置中文字體轨淌,否則無(wú)法在圖形上顯示中文
zhfont1 = matplotlib.font_manager.FontProperties(fname='./華文仿宋.ttf', size=16)
for w in words:
if w in word2ind:
ind = word2ind[w]
xy = X_reduced[ind]
plt.plot(xy[0], xy[1], '.', alpha =1, color = 'red')
plt.text(xy[0], xy[1], w, fontproperties = zhfont1, alpha = 1, color = 'yellow')
plt.show()
展示結(jié)果如下:
可以看到寶黛釵鳳很相近看尼,幾乎都分不清了他們的名字了,然后放大之后狡忙,震驚……
結(jié)論:原來(lái)機(jī)器也“讀懂”了“寶黛”愛(ài)情。
補(bǔ)充:由于以上用的數(shù)據(jù)僅僅來(lái)自于《紅樓夢(mèng)》文本本身灾茁,如果有另外巨大的語(yǔ)料(微博、人民日?qǐng)?bào)禀挫、上海熱線(xiàn)、汽車(chē)之家等语婴,包含1366130個(gè)詞向量)訓(xùn)練出來(lái)結(jié)果如何呢?
篇幅有限直接上結(jié)果吧砰左,
以上內(nèi)容純屬個(gè)人娛樂(lè),與君共勉缠导,不喜請(qǐng)噴