關(guān)于自然語(yǔ)言處理之One Hot模型
本文轉(zhuǎn)載自微信公眾號(hào)「python與大數(shù)據(jù)分析」,作者 一只小小鳥(niǎo)鳥(niǎo) 。轉(zhuǎn)載本文請(qǐng)聯(lián)系python與大數(shù)據(jù)分析公眾號(hào)。
最近工作實(shí)在有點(diǎn)忙,前陣子關(guān)于梯度和導(dǎo)數(shù)的事情把人折騰的夠嗆,數(shù)學(xué)學(xué)不好,搞機(jī)器學(xué)習(xí)和神經(jīng)網(wǎng)絡(luò)真是頭疼;想轉(zhuǎn)到應(yīng)用層面輕松一下,想到了自然語(yǔ)言處理,one hot模型是基礎(chǔ)也是入門(mén),看起來(lái)很簡(jiǎn)單的一個(gè)列表轉(zhuǎn)矩陣、詞典的功能,想著手工實(shí)現(xiàn)一下,結(jié)果看了一下CountVectorizer,發(fā)現(xiàn)不是那么回事兒,還是放棄了。
顧名思義,單熱表示從一個(gè)零向量開(kāi)始,如果單詞出現(xiàn)在句子或文檔中,則將向量中的相應(yīng)條目設(shè)置為 1。
對(duì)句子進(jìn)行標(biāo)記,忽略標(biāo)點(diǎn)符號(hào),并將所有的單詞都用小寫(xiě)字母表示,就會(huì)得到一個(gè)大小為 8 的詞匯表: {time, fruit, flies, like, a, an, arrow, banana} 。所以,我們可以用一個(gè)八維的單熱向量來(lái)表示每個(gè)單詞。在本書(shū)中,我們使用 1[w] 表示標(biāo)記/單詞 w 的單熱表示。
對(duì)于短語(yǔ)、句子或文檔,壓縮的單熱表示僅僅是其組成詞的邏輯或的單熱表示。短語(yǔ) like a banana 的單熱表示將是一個(gè) 3×8 矩陣,其中的列是 8 維的單熱向量。通常還會(huì)看到“折疊”或二進(jìn)制編碼,其中文本/短語(yǔ)由詞匯表長(zhǎng)度的向量表示,用 0 和 1 表示單詞的缺失或存在。like a banana 的二進(jìn)制編碼是: [0,0,0,1,1,0,0,1] 。
- from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
- import seaborn as sns
- import matplotlib.pyplot as plt
- import jieba
- import jieba.analyse
- # 單熱表示從一個(gè)零向量開(kāi)始,如果單詞出現(xiàn)在句子或文檔中,則將向量中的相應(yīng)條目設(shè)置為 1。
- # 英文的處理和展示
- corpus = ['Time flies flies like an arrow.', 'Fruit flies like a banana.']
- one_hot_vectorizer = CountVectorizer(binary=True)
- one_hot = one_hot_vectorizer.fit_transform(corpus).toarray()
- sns.heatmap(one_hot, annot=True, cbar=False, yticklabels=['Sentence 1', 'Sentence 2'])
- plt.show()
- # 中文的處理和展示
- # 獲取停用詞列表
- def get_stopwords_list(stopwordfile):
- stopwords = [line.strip() for line in open(stopwordfile, encoding='UTF-8').readlines()]
- return stopwords
- # 移除停用詞
- def movestopwords(sentence):
- stopwords = get_stopwords_list('stopwords.txt') # 這里加載停用詞的路徑
- santi_words = [x for x in sentence if len(x) > 1 and x not in stopwords]
- return santi_words
- # 語(yǔ)料
- corpus = ["小明碩士畢業(yè)于中國(guó)科學(xué)院計(jì)算所,后在日本京都大學(xué)深造。",
- "小王本科在清華大學(xué),后在南京計(jì)算所工作和深造,后在日本早稻田大學(xué)深造",
- "小李本科在清華大學(xué),碩士畢業(yè)于中國(guó)科學(xué)院計(jì)算所,博士在南京大學(xué)"]
- newcorpus = []
- for str in corpus:
- orgwordlist = jieba.lcut(str) # jieba分詞
- wordlist = movestopwords(orgwordlist) # 移除停用詞
- newword = " ".join(wordlist) # 按照語(yǔ)料庫(kù)要求進(jìn)行空格分隔
- newcorpus.append(newword) # 按照語(yǔ)料庫(kù)要求轉(zhuǎn)換成列表
- # newcorpus
- # ['小明 碩士 畢業(yè) 中國(guó)科學(xué)院 計(jì)算所 日本京都大學(xué) 深造',
- # '小王 本科 清華大學(xué) 南京 計(jì)算所 工作 深造 日本早稻田大學(xué) 深造',
- # '小李 本科 清華大學(xué) 碩士 畢業(yè) 中國(guó)科學(xué)院 計(jì)算所 博士 南京大學(xué)']
- one_hot_vectorizer = CountVectorizer(binary=True) # 創(chuàng)建詞袋數(shù)據(jù)結(jié)構(gòu)
- one_hot = one_hot_vectorizer.fit_transform(newcorpus).toarray() # 轉(zhuǎn)換語(yǔ)料,并矩陣化
- # 下面為熱詞的輸出結(jié)果
- # one_hot_vectorizer.vocabulary_
- # {'小明': 4, '碩士': 14, '畢業(yè)': 11, '中國(guó)科學(xué)院': 0, '計(jì)算所': 15, '日本京都大學(xué)': 8, '深造': 12, '小王': 6, '本科': 10, '清華大學(xué)': 13, '南京': 1, '工作': 7, '日本早稻田大學(xué)': 9, '小李': 5, '博士': 3, '南京大學(xué)': 2}
- # one_hot_vectorizer.get_feature_names()
- # ['中國(guó)科學(xué)院', '南京', '南京大學(xué)', '博士', '小明', '小李', '小王', '工作', '日本京都大學(xué)', '日本早稻田大學(xué)', '本科', '畢業(yè)', '深造', '清華大學(xué)', '碩士', '計(jì)算所']
- # one_hot
- # [[1 0 0 0 1 0 0 0 1 0 0 1 1 0 1 1]
- # [0 1 0 0 0 0 1 1 0 1 1 0 1 1 0 1]
- # [1 0 1 1 0 1 0 0 0 0 1 1 0 1 1 1]]
- sns.set_style({'font.sans-serif': ['SimHei', 'Arial']})
- sns.heatmap(one_hot, annot=True, cbar=False, xticklabels=one_hot_vectorizer.get_feature_names(),
- yticklabels=['語(yǔ)句1', '語(yǔ)句2', '語(yǔ)句3'])
- plt.show()
IDF 表示懲罰常見(jiàn)的符號(hào),并獎(jiǎng)勵(lì)向量表示中的罕見(jiàn)符號(hào)。符號(hào) w 的 IDF(w) 對(duì)語(yǔ)料庫(kù)的定義為其中 n[w] 是包含單詞 w 的文檔數(shù)量, N 是文檔總數(shù)。TF-IDF 分?jǐn)?shù)就是 TF(w) * IDF(w) 的乘積。首先,請(qǐng)注意在所有文檔(例如, n[w] = N ), IDF(w) 為 0, TF-IDF 得分為 0,完全懲罰了這一項(xiàng)。其次,如果一個(gè)術(shù)語(yǔ)很少出現(xiàn)(可能只出現(xiàn)在一個(gè)文檔中),那么 IDF 就是 log n 的最大值
- tfidf_vectorizer = TfidfVectorizer() # 創(chuàng)建詞袋數(shù)據(jù)結(jié)構(gòu)
- tfidf = tfidf_vectorizer.fit_transform(newcorpus).toarray() # 轉(zhuǎn)換語(yǔ)料,并矩陣化
- # 下面為熱詞的輸出結(jié)果
- # tfidf_vectorizer.vocabulary_
- # '小明': 4, '碩士': 14, '畢業(yè)': 11, '中國(guó)科學(xué)院': 0, '計(jì)算所': 15, '日本京都大學(xué)': 8, '深造': 12, '小王': 6, '本科': 10, '清華大學(xué)': 13, '南京': 1, '工作': 7, '日本早稻田大學(xué)': 9, '小李': 5, '博士': 3, '南京大學(xué)': 2}
- # tfidf_vectorizer.get_feature_names()
- # ['中國(guó)科學(xué)院', '南京', '南京大學(xué)', '博士', '小明', '小李', '小王', '工作', '日本京都大學(xué)', '日本早稻田大學(xué)', '本科', '畢業(yè)', '深造', '清華大學(xué)', '碩士', '計(jì)算所']
- # tfidf
- # [[0.35221512 0. 0. 0. 0.46312056 0. 0. 0. 0.46312056 0. 0. 0.35221512 0.35221512 0. 0.35221512 0.27352646]
- # [0. 0.35761701 0. 0. 0. 0. 0.35761701 0.35761701 0. 0.35761701 0.27197695 0. 0.54395391 0.27197695 0. 0.21121437]
- # [0.30443385 0. 0.40029393 0.40029393 0. 0.40029393 0. 0. 0. 0. 0.30443385 0.30443385 0. 0.30443385 0.30443385 0.23642005]]
- sns.heatmap(tfidf, annot=True, cbar=False, xticklabels=tfidf_vectorizer.get_feature_names(),
- yticklabels=['語(yǔ)句1', '語(yǔ)句2', '語(yǔ)句3'], vmin=0, vmax=1, cm