NLP入門(一)詞袋模型及句子相似度

??本文作為筆者NLP入門系列文章第一篇映挂,以后我們就要步入NLP時代绵载。
??本文將會介紹NLP中常見的詞袋模型(Bag of Words)以及如何利用詞袋模型來計算句子間的相似度(余弦相似度羊苟,cosine similarity)胶惰。
??首先鹉戚,讓我們來看一下垫桂,什么是詞袋模型师幕。我們以下面兩個簡單句子為例:

sent1 = "I love sky, I love sea."
sent2 = "I like running, I love reading."

??通常,NLP無法一下子處理完整的段落或句子诬滩,因此霹粥,第一步往往是分句和分詞。這里只有句子疼鸟,因此我們只需要分詞即可后控。對于英語句子,可以使用NLTK中的word_tokenize函數(shù)空镜,對于中文句子浩淘,則可使用jieba模塊。故第一步為分詞吴攒,代碼如下:

from nltk import word_tokenize
sents = [sent1, sent2]
texts = [[word for word in word_tokenize(sent)] for sent in sents]

輸出的結(jié)果如下:

[['I', 'love', 'sky', ',', 'I', 'love', 'sea', '.'], ['I', 'like', 'running', ',', 'I', 'love', 'reading', '.']]

??分詞完畢张抄。下一步是構(gòu)建語料庫,即所有句子中出現(xiàn)的單詞及標(biāo)點洼怔。代碼如下:

all_list = []
for text in texts:
    all_list += text
corpus = set(all_list)
print(corpus)

輸出如下:

{'love', 'running', 'reading', 'sky', '.', 'I', 'like', 'sea', ','}

??可以看到署惯,語料庫中一共是8個單詞及標(biāo)點。接下來镣隶,對語料庫中的單詞及標(biāo)點建立數(shù)字映射极谊,便于后續(xù)的句子的向量表示。代碼如下:

corpus_dict = dict(zip(corpus, range(len(corpus))))
print(corpus_dict)

輸出如下:

{'running': 1, 'reading': 2, 'love': 0, 'sky': 3, '.': 4, 'I': 5, 'like': 6, 'sea': 7, ',': 8}

??雖然單詞及標(biāo)點并沒有按照它們出現(xiàn)的順序來建立數(shù)字映射安岂,不過這并不會影響句子的向量表示及后續(xù)的句子間的相似度怀酷。
??下一步,也就是詞袋模型的關(guān)鍵一步嗜闻,就是建立句子的向量表示。這個表示向量并不是簡單地以單詞或標(biāo)點出現(xiàn)與否來選擇0桅锄,1數(shù)字琉雳,而是把單詞或標(biāo)點的出現(xiàn)頻數(shù)作為其對應(yīng)的數(shù)字表示,結(jié)合剛才的語料庫字典友瘤,句子的向量表示的代碼如下:

# 建立句子的向量表示
def vector_rep(text, corpus_dict):
    vec = []
    for key in corpus_dict.keys():
        if key in text:
            vec.append((corpus_dict[key], text.count(key)))
        else:
            vec.append((corpus_dict[key], 0))

    vec = sorted(vec, key= lambda x: x[0])

    return vec

vec1 = vector_rep(texts[0], corpus_dict)
vec2 = vector_rep(texts[1], corpus_dict)
print(vec1)
print(vec2)

輸出如下:

[(0, 2), (1, 0), (2, 0), (3, 1), (4, 1), (5, 2), (6, 0), (7, 1), (8, 1)]
[(0, 1), (1, 1), (2, 1), (3, 0), (4, 1), (5, 2), (6, 1), (7, 0), (8, 1)]

讓我們稍微逗留一會兒翠肘,來看看這個向量。在第一句中I出現(xiàn)了兩次,在預(yù)料庫字典中,I對應(yīng)的數(shù)字為5脆诉,因此在第一句中5出現(xiàn)2次醇份,在列表中的元組即為(5,2)尼变,代表單詞I在第一句中出現(xiàn)了2次骂租。以上的輸出可能并不那么直觀蚊夫,真實的兩個句子的代表向量應(yīng)為:

[2, 0, 0, 1, 1, 2, 0, 1, 1]
[1, 1, 1, 0, 1, 2, 1, 0, 1]

??OK券时,詞袋模型到此結(jié)束邮旷。接下來黄选,我們會利用剛才得到的詞袋模型,即兩個句子的向量表示婶肩,來計算相似度办陷。
??在NLP中,如果得到了兩個句子的向量表示律歼,那么民镜,一般會選擇用余弦相似度作為它們的相似度,而向量的余弦相似度即為兩個向量的夾角的余弦值险毁。其計算的Python代碼如下:

from math import sqrt
def similarity_with_2_sents(vec1, vec2):
    inner_product = 0
    square_length_vec1 = 0
    square_length_vec2 = 0
    for tup1, tup2 in zip(vec1, vec2):
        inner_product += tup1[1]*tup2[1]
        square_length_vec1 += tup1[1]**2
        square_length_vec2 += tup2[1]**2

    return (inner_product/sqrt(square_length_vec1*square_length_vec2))


cosine_sim = similarity_with_2_sents(vec1, vec2)
print('兩個句子的余弦相似度為: %.4f制圈。'%cosine_sim)

輸出結(jié)果如下:

兩個句子的余弦相似度為: 0.7303。

??這樣辱揭,我們就通過句子的詞袋模型离唐,得到了它們間的句子相似度。
??當(dāng)然问窃,在實際的NLP項目中亥鬓,如果需要計算兩個句子的相似度,我們只需調(diào)用gensim模塊即可域庇,它是NLP的利器嵌戈,能夠幫助我們處理很多NLP任務(wù)。下面為用gensim計算兩個句子的相似度的代碼:

sent1 = "I love sky, I love sea."
sent2 = "I like running, I love reading."

from nltk import word_tokenize
sents = [sent1, sent2]
texts = [[word for word in word_tokenize(sent)] for sent in sents]
print(texts)

from gensim import corpora
from gensim.similarities import Similarity

#  語料庫
dictionary = corpora.Dictionary(texts)

# 利用doc2bow作為詞袋模型
corpus = [dictionary.doc2bow(text) for text in texts]
similarity = Similarity('-Similarity-index', corpus, num_features=len(dictionary))
print(similarity)
# 獲取句子的相似度
new_sensence = sent1
test_corpus_1 = dictionary.doc2bow(word_tokenize(new_sensence))

cosine_sim = similarity[test_corpus_1][1]
print("利用gensim計算得到兩個句子的相似度: %.4f听皿。"%cosine_sim)

輸出結(jié)果如下:

[['I', 'love', 'sky', ',', 'I', 'love', 'sea', '.'], ['I', 'like', 'running', ',', 'I', 'love', 'reading', '.']]
Similarity index with 2 documents in 0 shards (stored under -Similarity-index)
利用gensim計算得到兩個句子的相似度: 0.7303熟呛。

注意,如果在運行代碼時出現(xiàn)以下warning:

gensim\utils.py:1209: UserWarning: detected Windows; aliasing chunkize to chunkize_serial
  warnings.warn("detected Windows; aliasing chunkize to chunkize_serial")

gensim\matutils.py:737: FutureWarning: Conversion of the second argument of issubdtype from `int` to `np.signedinteger` is deprecated. In future, it will be treated as `np.int32 == np.dtype(int).type`.
  if np.issubdtype(vec.dtype, np.int):

如果想要去掉這些warning尉姨,則在導(dǎo)入gensim模塊的代碼前添加以下代碼即可:

import warnings
warnings.filterwarnings(action='ignore',category=UserWarning,module='gensim')
warnings.filterwarnings(action='ignore',category=FutureWarning,module='gensim')

??本文到此結(jié)束庵朝,感謝閱讀!如果不當(dāng)之處又厉,請速聯(lián)系筆者九府,歡迎大家交流!祝您好運~

注意:本人現(xiàn)已開通微信公眾號: Python爬蟲與算法(微信號為:easy_web_scrape)覆致, 歡迎大家關(guān)注哦~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侄旬,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子煌妈,更是在濱河造成了極大的恐慌儡羔,老刑警劉巖宣羊,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異汰蜘,居然都是意外死亡仇冯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門鉴扫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赞枕,“玉大人,你說我怎么就攤上這事坪创】簧簦” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵莱预,是天一觀的道長柠掂。 經(jīng)常有香客問我,道長依沮,這世上最難降的妖魔是什么涯贞? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮危喉,結(jié)果婚禮上宋渔,老公的妹妹穿的比我還像新娘。我一直安慰自己辜限,他們只是感情好皇拣,可當(dāng)我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著薄嫡,像睡著了一般氧急。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上毫深,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天吩坝,我揣著相機與錄音,去河邊找鬼哑蔫。 笑死钉寝,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的闸迷。 我是一名探鬼主播嵌纲,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼稿黍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起崩哩,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤巡球,失蹤者是張志新(化名)和其女友劉穎言沐,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酣栈,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡险胰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了矿筝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片起便。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖窖维,靈堂內(nèi)的尸體忽然破棺而出榆综,到底是詐尸還是另有隱情,我是刑警寧澤铸史,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布鼻疮,位于F島的核電站,受9級特大地震影響琳轿,放射性物質(zhì)發(fā)生泄漏判沟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一崭篡、第九天 我趴在偏房一處隱蔽的房頂上張望挪哄。 院中可真熱鬧,春花似錦琉闪、人聲如沸迹炼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疗涉。三九已至,卻和暖如春吟秩,著一層夾襖步出監(jiān)牢的瞬間咱扣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工涵防, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留闹伪,地道東北人。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓壮池,卻偏偏與公主長得像偏瓤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子椰憋,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容