0
本文作者: AI研習(xí)社-譯站 | 2018-09-21 14:43 |
本文為 AI 研習(xí)社編譯的技術(shù)博客,原標(biāo)題:
Clustering Quora Question Tags with Doc2Vec.
翻譯 | nick李、csnoooong 校對(duì) | 凡江 整理 | 志豪
原文鏈接:https://medium.com/@samriddhisinha/clustering-quora-question-tags-with-doc2vec-d4fb3c5177f7
Quora是一個(gè)流行的知識(shí)分享平臺(tái),我常常在Quora上分享我的想法。這個(gè)平臺(tái)是基于問答的形式,它因其簡易的設(shè)計(jì)和平滑的用戶體驗(yàn)而出名。
當(dāng)新的問題被添加到Quora時(shí),這些問題由機(jī)器人自動(dòng)基于問題的上下文進(jìn)行標(biāo)記并稍后由用戶進(jìn)行編輯。這些標(biāo)簽反映了問題被歸入的話題類別。如下是一個(gè)問題的基本概貌。
最近我在尋找合適的數(shù)據(jù)集,然后我偶然看到了Quora里的一個(gè)這個(gè)頁面: Programming Challenges。我選擇了這個(gè)叫做Answered的二分類問題挑戰(zhàn)。其中,包括了近10000個(gè)問題(訓(xùn)練集和測試集總計(jì))。每個(gè)問題和其話題標(biāo)簽以及其他的一些信息被以JSON格式儲(chǔ)存。下圖是一個(gè)JSON的示例。
示例問題JSON
第一個(gè)任務(wù)就是要從JSON文件中讀取數(shù)據(jù)。訓(xùn)練集總共大約有9000個(gè)問題,而測試集總共約1000個(gè)問題。
import json f = open("answered_data_10k.in").read().split("\n")train_set = f[1:9001]test_set = f[9002:-1]train = [json.loads(i) for i in train_set]test = [json.loads(i) for i in test_set]questions = train + test
接下來就要提取出所有數(shù)據(jù)集中的主題標(biāo)簽。在JSON文件中,主題存儲(chǔ)在鍵"key"中。不同的問題有不同數(shù)量的主題標(biāo)簽。單個(gè)問題所允許存在的最大標(biāo)簽數(shù)為26。同時(shí)也存在沒有關(guān)聯(lián)主題標(biāo)簽的問題。
# Create the list of topics topic_list = []for question in questions:if len(question["topics"]) > 0:for topic in question["topics"]:topic_list = topic_list + [topic["name"]]topic_list = list(set(topic_list))print(len(topic_list))
在這個(gè)挑戰(zhàn)所提供的數(shù)據(jù)中,一共有8762個(gè)主題標(biāo)簽。
在提取出主題標(biāo)簽之后,我們需要將具有相同標(biāo)簽的問題聚類。在動(dòng)手之前,我們先對(duì)數(shù)據(jù)進(jìn)行分析,因?yàn)槿绻苯訉?duì)8762個(gè)進(jìn)行聚類將會(huì)很困難而且聚類的質(zhì)量也難以保證。
因此我們限定了每一個(gè)主題下的最小問題數(shù)來解決這個(gè)問題。擁有多于1個(gè)問題的主題有3275個(gè)。擁有5個(gè)問題的主題恰好有900個(gè),這個(gè)數(shù)量相對(duì)更適合進(jìn)行聚類。
最終,我們決定將主題下的最小問題數(shù)規(guī)定為5個(gè),這主要有兩個(gè)原因。首先是為了更好地用向量來表示主題,其次因?yàn)榫哂休^少問題的主題大多數(shù)情況下是和無關(guān)的問題所關(guān)聯(lián)的。
#Assigning question to topics.question_list = []final_topic_list = []for topic in topic_list:temp = []for question in questions:context = [i["name"] for i in question["topics"]]if topic in context:temp.append(question['question_text']) if len(temp) >= 5:question_list.append(temp)final_topic_list.append(topic)topic_list = final_topic_list
接下來,我們寫一個(gè)函數(shù),通過轉(zhuǎn)換為小寫、去除標(biāo)點(diǎn)符號(hào)和停用詞來正則化每個(gè)段落。每個(gè)話題下有五到多個(gè)問題。我們把每個(gè)話題下的問題的集合當(dāng)做一個(gè)文檔。
這樣,我們先遍歷話題標(biāo)簽,然后把問題聚集成段落,再把段落正則化化。然后我們把段落和段落的話題標(biāo)簽喂給Gensim的TaggedDocument函數(shù),進(jìn)行進(jìn)一步的正則化。
from nltk import word_tokenizefrom nltk.corpus import stopwordsfrom gensim import modelsfrom gensim.models.doc2vec import TaggedDocument#Function for normalizing paragraphs.def normalize(string):lst = word_tokenize(string)lst =[word.lower() for word in lst if word.isalpha()]lst = [w for w in lst if not w in stopwords.words('english')]return(lst)# Aggregate questions under each topic tag as a paragraph. # Normalize the paragraph # Feed the normalized paragraph along with the topic tag into Gensim's Tagged Document function. # Append the return value to docs.docs = []for index, item in enumerate(topic_list):question = " ".join(question_list[index])question = normalize(question)docs.append(TaggedDocument(words=question, tags=[item]))
為Gensim的DocVec準(zhǔn)備數(shù)據(jù)
接下來我們訓(xùn)練Doc2Vec模型。
應(yīng)該調(diào)整vector_size和window,直到結(jié)果是最優(yōu)的。
import gensimmodel = gensim.models.Doc2Vec(vector_size= 200, window= 3, min_count= 0, workers=4, epochs= 40)model.build_vocab(docs)model.train(docs, total_examples=model.corpus_count, epochs=model.iter)
Doc2Vec Training
Doc2Vec模型訓(xùn)練好后,我們就用KMeans算法聚類了文檔向量。簇的數(shù)量從100到50之間進(jìn)行了檢查。接近100的簇?cái)?shù)會(huì)導(dǎo)致大簇被切分成小簇,而簇?cái)?shù)等于50時(shí)會(huì)使得沒有相關(guān)性的簇被組合成大簇。在仔細(xì)評(píng)估聚簇結(jié)果后,最后選擇60作為簇?cái)?shù)。
from sklearn.cluster import KMeansfrom sklearn import metricsimport pylab as plimport matplotlib.pyplot as pltfrom sklearn.decomposition import PCAkmeans_model = KMeans(n_clusters= 60, init='k-means++', max_iter=100) X = kmeans_model.fit(model.docvecs.doctag_syn0)labels= kmeans_model.labels_.tolist()l = kmeans_model.fit_predict(model.docvecs.doctag_syn0)#map each centroid to its topic tagword_centroid_map = dict(zip( model.docvecs.offset2doctag, l))#Print Cluster Listfor cluster in range(0,100): print("\nCluster %d" % cluster)words = []for i in range(0,len(word_centroid_map.values())):if(list(word_centroid_map.values())[i] == cluster ):words.append(list(word_centroid_map.keys())[i])print(words)
擬合KMeans模型并取回簇的列表
......
想要繼續(xù)閱讀文章,并且查看該篇文章更多代碼、鏈接和參考文獻(xiàn)?
戳鏈接:http://www.gair.link/page/TextTranslation/840
AI研習(xí)社每日更新精彩內(nèi)容,點(diǎn)擊文末【閱讀原文】即可觀看更多精彩內(nèi)容:雷鋒網(wǎng)雷鋒網(wǎng)雷雷鋒網(wǎng)
基于 NLTK 和 SpaCy 的命名實(shí)體識(shí)別功能實(shí)現(xiàn)
AI初學(xué)者必須要了解的術(shù)語盤點(diǎn)
從 App 描述介紹文字中發(fā)掘 Python 文本數(shù)據(jù)預(yù)處理實(shí)例
通過搖滾樂隊(duì)來學(xué)習(xí) TensorFlow,Word2Vec 模型和 TSNE 算法
等你來譯:
如何用Anchors來為你的模型可解釋性立足
如何用機(jī)器學(xué)習(xí)來處理假新聞
通過 Spotify 上面的播放列表,我們分析了 50 位音樂家,結(jié)果發(fā)現(xiàn)——
機(jī)器學(xué)習(xí)當(dāng)中的數(shù)學(xué)閃光:如何直觀地理解 LDA
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。