LSI和LDA模型初試驗
從文本到向量
import csv
# 出于試驗目的,只讀取前5條評論
with open('comments.csv', 'r', newline='') as f:
comments_reader = csv.reader(f, dialect='excel')
corpus = [comment[1] for comment in comments_reader][1:6]
for i, comment in enumerate(corpus):
print(i + 1, comment)
1 京東速度杠杠的!信任京東!昨晚11:30付的尾款!本來顯示的是預計12號送達的!結(jié)果下午還是送來了!效率沒得說!要的就是這速度!東西看著還不錯吧!小巧玲瓏的很好看!目前沒發(fā)現(xiàn)什么問題!我個人覺得這屏幕分辨率太低了點!!不知道這個電子狗功能是不是雞肋!看上的就是這個功能,希望好用!因為我原車本來就自帶記錄儀的!雖然還沒有上車使用!但因為信任京東,信任360就先好評了!具體表現(xiàn)要明天使用后才知道!后續(xù)再補充!
2 喜歡這款行車記錄儀,大家認真看看評價吧,差不多花了不到一半的價格買到它的,衛(wèi)︿新,去∧艘~東家羊毛~你懂得哦,這個宮宗皓可以享半價哦!多少年了一直買京東,從來不知道還有補貼,不過知道它的人不多,經(jīng)常省個百八十不成問題,不光這一個,所有商品基本都有。商家發(fā)貨快,問了客服很多問題,照著提示已經(jīng)安裝好了,安裝也方便,裝上去也不占地方,很上檔次,中間遇上了一點小麻煩,咨詢了客服,態(tài)度不錯很快就幫我解決了,今天開出去溜了一下,看起來也很上檔次,圖像拍攝的很清晰,正品,效果非常棒了,但是基本能滿足,也對得起這個價格。物有所值,買到合心意質(zhì)量好的東東,質(zhì)量好杠杠滴,贊一個!而且價格超級劃算,我就是關住了 ~ 東 家 羊 毛 ~,這個威威宮宗號。半價買的,排在第一個才是哦。一如既往的支持京東。
3 生產(chǎn)日期很美麗!2017-11,東西還沒用上去,但是從體積上肯定不錯,畢竟不會被遮擋。隱藏的很好,而且參數(shù)我看過,和后視鏡版本M302幾乎一樣,勝在不占空間。東西也比較簡約,使用過一段日子再來評價。外觀還不錯!
4 這是我精挑細選的一款記錄儀,不用支架,小巧玲瓏,攜帶方便,攝像高清,還可以無線聯(lián)網(wǎng),非常棒
5 看個一分鐘錄像,卡了一個小時,下載四五次,還下不下來,真**上火,APP也卸載了重新安裝,行車記錄儀也恢復出廠設置,鼓搗一晚上還是這樣,氣死我了
# 分別對各文本進行預處理,流程為:1、分詞,2、去除只在整個語料庫中出現(xiàn)1次的詞,
# 3、去除停用詞
# 分詞
import jieba
texts = [[w for w in jieba.cut(text)] for text in corpus]
# 去除停用詞
with open('stoplist_ch.txt', 'r', encoding='utf-8') as f:
stoplist = [w.rstrip('\n') for w in f.readlines()]
texts = [[w for w in text if w not in stoplist]
for text in texts]
# 去除只在整個語料庫中出現(xiàn)1次的詞
fdist = {}
for text in texts:
for w in text:
fdist[w] = fdist.get(w, 0) + 1
texts = [[w for w in text if fdist[w] > 1]
for text in texts]
print(texts)
[['京東', '速度', '杠杠', '信任', '京東', '11', '本來', '速度', '東西', '不錯', '小巧玲瓏', '問題', '知道', '功能', '功能', '本來', '記錄儀', '使用', '信任', '京東', '信任', '使用', '知道', '再'], ['行車', '記錄儀', '評價', '價格', '買到', '半價', '買', '京東', '知道', '知道', '一個', '客服', '問題', '安裝', '好', '安裝', '占', '上檔次', '客服', '不錯', '上檔次', '棒', '價格', '買到', '質(zhì)量', '好', '質(zhì)量', '好', '杠杠', '一個', '價格', '半價', '買', '京東'], ['11', '東西', '不錯', '好', '占', '東西', '使用', '再', '評價', '不錯'], ['記錄儀', '小巧玲瓏', '棒'], ['一個', '行車', '記錄儀']]
# 將這些詞編號,以詞典鍵值對的方式表示
from gensim import corpora
dictionary = corpora.Dictionary(texts)
print(dictionary)
Dictionary(29 unique tokens: ['11', '不錯', '東西', '京東', '使用']...)
# 以"詞:編號"的方式shi顯示
print(dictionary.token2id)
{'11': 0, '不錯': 1, '東西': 2, '京東': 3, '使用': 4, '信任': 5, '再': 6, '功能': 7, '小巧玲瓏': 8, '本來': 9, '杠杠': 10, '知道': 11, '記錄儀': 12, '速度': 13, '問題': 14, '一個': 15, '上檔次': 16, '買': 17, '買到': 18, '價格': 19, '半價': 20, '占': 21, '好': 22, '安裝': 23, '客服': 24, '棒': 25, '行車': 26, '評價': 27, '質(zhì)量': 28}
# 用詞袋的方法將各詞在各文本的出現(xiàn)次數(shù),即詞頻表示出來
corpus_mm = [dictionary.doc2bow(text) for text in texts]
print(corpus_mm)
[[(0, 1), (1, 1), (2, 1), (3, 3), (4, 2), (5, 3), (6, 1), (7, 2), (8, 1), (9, 2), (10, 1), (11, 2), (12, 1), (13, 2), (14, 1)], [(1, 1), (3, 2), (10, 1), (11, 2), (12, 1), (14, 1), (15, 2), (16, 2), (17, 2), (18, 2), (19, 3), (20, 2), (21, 1), (22, 3), (23, 2), (24, 2), (25, 1), (26, 1), (27, 1), (28, 2)], [(0, 1), (1, 2), (2, 2), (4, 1), (6, 1), (21, 1), (22, 1), (27, 1)], [(8, 1), (12, 1), (25, 1)], [(12, 1), (15, 1), (26, 1)]]
這樣一來,語料庫中各文本就表示成了文本中各詞的出現(xiàn)次數(shù)了,比如,第1個文本的詞向量即為:1, 1, 1, 3, 2, 3, 1, 2, 1, 2, 1, 2, 1, 2, 1。值得注意的是,沒有出現(xiàn)的詞不會在打印中表示。
向量轉(zhuǎn)換
上述步驟得到的是以詞頻作為向量各緯度的值,但并沒有表現(xiàn)出詞與詞之間的關系,這是詞袋的不足之一。
因此,在詞袋向量的基礎上,應進一步提取更多信息。為了達到這個目的,可以將向量各緯度的值轉(zhuǎn)換成另外一種值。比如下面介紹的TF-IDF。
# 轉(zhuǎn)換初始化,指定要轉(zhuǎn)換為TF-IDF向量
import gensim
tfidf_trans = gensim.models.TfidfModel(corpus_mm)
# 轉(zhuǎn)換為TF-IDF向量
corpus_tfidf = tfidf_trans[corpus_mm]
for doc in corpus_tfidf:
print(doc)
[(0, 0.10650413173766084), (1, 0.05937530265887042), (2, 0.10650413173766084), (3, 0.31951239521298247), (4, 0.21300826347532167), (5, 0.5612141915880775), (6, 0.10650413173766084), (7, 0.3741427943920516), (8, 0.10650413173766084), (9, 0.3741427943920516), (10, 0.10650413173766084), (11, 0.21300826347532167), (12, 0.025936866279295836), (13, 0.3741427943920516), (14, 0.10650413173766084)]
[(1, 0.04686268994890363), (3, 0.1681193991574051), (10, 0.08405969957870255), (11, 0.1681193991574051), (12, 0.020470991612052493), (14, 0.08405969957870255), (15, 0.1681193991574051), (16, 0.29529681509070516), (17, 0.29529681509070516), (18, 0.29529681509070516), (19, 0.4429452226360578), (20, 0.29529681509070516), (21, 0.08405969957870255), (22, 0.2521790987361076), (23, 0.29529681509070516), (24, 0.29529681509070516), (25, 0.08405969957870255), (26, 0.08405969957870255), (27, 0.08405969957870255), (28, 0.29529681509070516)]
[(0, 0.29823262853716886), (1, 0.3325251761267265), (2, 0.5964652570743377), (4, 0.29823262853716886), (6, 0.29823262853716886), (21, 0.29823262853716886), (22, 0.29823262853716886), (27, 0.29823262853716886)]
[(8, 0.6968503263117378), (12, 0.1697034043219193), (25, 0.6968503263117378)]
[(12, 0.1697034043219193), (15, 0.6968503263117378), (26, 0.6968503263117378)]
# 更進一步,探究各文本在語義上傾向于哪個主題
# 先劃分主題,使用LSI模型
lsi_trans = gensim.models.LsiModel(corpus_tfidf, id2word=dictionary,
num_topics=4) # 轉(zhuǎn)換初始化,指定劃分4個主題
corpus_lsi = lsi_trans[corpus_tfidf] # 詞袋->TF-IDF->LSI
# 看看各個主題都有什么主題詞
lsi_trans.print_topics(4)
[(0,
'0.315*"東西" + 0.258*"一個" + 0.254*"信任" + 0.253*"好" + 0.230*"使用" + 0.224*"京東" + 0.218*"行車" + 0.210*"價格" + 0.198*"不錯" + 0.187*"小巧玲瓏"'),
(1,
'0.537*"一個" + 0.509*"行車" + -0.281*"東西" + -0.222*"信任" + -0.204*"使用" + -0.162*"11" + -0.162*"再" + 0.149*"價格" + -0.148*"速度" + -0.148*"功能"'),
(2,
'0.662*"小巧玲瓏" + 0.638*"棒" + -0.150*"東西" + -0.144*"一個" + -0.131*"行車" + 0.129*"記錄儀" + -0.118*"好" + -0.093*"評價" + -0.093*"占" + -0.091*"不錯"'),
(3,
'-0.387*"信任" + -0.329*"行車" + -0.278*"一個" + 0.268*"價格" + -0.258*"速度" + -0.258*"本來" + -0.258*"功能" + 0.241*"好" + 0.179*"質(zhì)量" + 0.179*"安裝"')]
# 看看各文本在各主題上的分布
for doc in corpus_lsi:
print(doc)
[(0, 0.6151990923970965), (1, -0.43114870816315265), (2, 0.10554078138694145), (3, -0.5507585471447924)]
[(0, 0.6452603721867233), (1, 0.36676022694119653), (2, -0.14588731937618363), (3, 0.48322823901839956)]
[(0, 0.6091519197175418), (1, -0.43608218559430395), (2, -0.2693719615275453), (3, 0.23616797769920406)]
[(0, 0.2721984576989459), (1, 0.11753367175861239), (2, 0.9274598337066065), (3, 0.12780692177247774)]
[(0, 0.34886155667911756), (1, 0.7516857754005692), (2, -0.16957436157580397), (3, -0.43465064036045764)]
可以看出,從語義上說,第1、2、3個文本偏向第1個主題,第4個文本偏向第3個主題,第5個文本偏向第2個主題。
LDA模型
上面的LSI模型得到的可以看作是"語義向量",可用于計算文本之間的相似性,而LDA模型則側(cè)重于計算某個主題所對應詞在該主題下的權(quán)重,也可以看作是某主題下詞的概率分布。
# LDA模型由詞袋向量轉(zhuǎn)換而來
lda_trans = gensim.models.LdaModel(corpus_mm, id2word=dictionary,
num_topics=4) # 轉(zhuǎn)換初始化,指定劃分4個主題
corpus_lda = lda_trans[corpus_mm] # 詞袋->LDA
# 看看各主題都有什么主題詞
lda_trans.print_topics(4)
[(0,
'0.092*"京東" + 0.072*"知道" + 0.050*"信任" + 0.047*"好" + 0.041*"價格" + 0.038*"功能" + 0.037*"速度" + 0.037*"不錯" + 0.036*"使用" + 0.036*"杠杠"'),
(1,
'0.055*"信任" + 0.053*"本來" + 0.052*"使用" + 0.051*"京東" + 0.043*"功能" + 0.043*"速度" + 0.042*"知道" + 0.038*"記錄儀" + 0.037*"小巧玲瓏" + 0.037*"問題"'),
(2,
'0.069*"信任" + 0.060*"不錯" + 0.060*"使用" + 0.054*"東西" + 0.049*"本來" + 0.048*"速度" + 0.045*"功能" + 0.044*"知道" + 0.043*"京東" + 0.043*"再"'),
(3,
'0.075*"記錄儀" + 0.061*"不錯" + 0.060*"一個" + 0.060*"好" + 0.052*"東西" + 0.048*"價格" + 0.047*"評價" + 0.046*"棒" + 0.045*"行車" + 0.040*"質(zhì)量"')]
# 看看各文本在各主題上的分布
for doc in corpus_lda:
print(doc)
[(0, 0.9686841), (1, 0.010232531), (2, 0.0106450515), (3, 0.0104383305)]
[(0, 0.42112163), (3, 0.56442404)]
[(0, 0.02371528), (1, 0.023032475), (2, 0.02412851), (3, 0.92912376)]
[(0, 0.06447045), (1, 0.06305108), (2, 0.06310642), (3, 0.809372)]
[(0, 0.06418085), (1, 0.06276632), (2, 0.06285436), (3, 0.8101985)]
計算相似性
# TODO: 現(xiàn)在有一個新文本,需要分析與其相似的文本有哪些
浙公網(wǎng)安備 33010602011771號