利用Doc2Vec對Quora問題標(biāo)簽聚類

來源: AI源創(chuàng)評論
作者:雷鋒字幕組
時間:2021-06-21
17982
Quora是一個流行的知識分享平臺,我常常在Quora上分享我的想法。這個平臺是基于問答的形式,它因其簡易的設(shè)計和平滑的用戶體驗而出名。

引言

Quora是一個流行的知識分享平臺,我常常在Quora上分享我的想法。這個平臺是基于問答的形式,它因其簡易的設(shè)計和平滑的用戶體驗而出名。

當(dāng)新的問題被添加到Quora時,這些問題由機器人自動基于問題的上下文進(jìn)行標(biāo)記并稍后由用戶進(jìn)行編輯。這些標(biāo)簽反映了問題被歸入的話題類別。如下是一個問題的基本概貌。

640.webp.jpg

最近我在尋找合適的數(shù)據(jù)集,然后我偶然看到了Quora里的一個這個頁面:Programming Challenges。我選擇了這個叫做Answered的二分類問題挑戰(zhàn)。其中,包括了近10000個問題(訓(xùn)練集和測試集總計)。每個問題和其話題標(biāo)簽以及其他的一些信息被以JSON格式儲存。下圖是一個JSON的示例。

640.webp (1).jpg

示例問題JSON

動手干吧

第一個任務(wù)就是要從JSON文件中讀取數(shù)據(jù)。訓(xùn)練集總共大約有9000個問題,而測試集總共約1000個問題。

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文件中,主題存儲在鍵"key"中。不同的問題有不同數(shù)量的主題標(biāo)簽。單個問題所允許存在的最大標(biāo)簽數(shù)為26。同時也存在沒有關(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))

在這個挑戰(zhàn)所提供的數(shù)據(jù)中,一共有8762個主題標(biāo)簽。

在提取出主題標(biāo)簽之后,我們需要將具有相同標(biāo)簽的問題聚類。在動手之前,我們先對數(shù)據(jù)進(jìn)行分析,因為如果直接對8762個進(jìn)行聚類將會很困難而且聚類的質(zhì)量也難以保證。

因此我們限定了每一個主題下的最小問題數(shù)來解決這個問題。擁有多于1個問題的主題有3275個。擁有5個問題的主題恰好有900個,這個數(shù)量相對更適合進(jìn)行聚類。

最終,我們決定將主題下的最小問題數(shù)規(guī)定為5個,這主要有兩個原因。首先是為了更好地用向量來表示主題,其次因為具有較少問題的主題大多數(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

接下來,我們寫一個函數(shù),通過轉(zhuǎn)換為小寫、去除標(biāo)點符號和停用詞來正則化每個段落。每個話題下有五到多個問題。我們把每個話題下的問題的集合當(dāng)做一個文檔。

這樣,我們先遍歷話題標(biāo)簽,然后把問題聚集成段落,再把段落正則化化。然后我們把段落和段落的話題標(biāo)簽喂給Gensim的TaggedDocument函數(shù),進(jìn)行進(jìn)一步的正則化。

from nltk import word_tokenize

from nltk.corpus import stopwords

from gensim import models

from 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 gensim

model=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的簇數(shù)會導(dǎo)致大簇被切分成小簇,而簇數(shù)等于50時會使得沒有相關(guān)性的簇被組合成大簇。在仔細(xì)評估聚簇結(jié)果后,最后選擇60作為簇數(shù)。

from sklearn.cluster import KMeans

from sklearn import metrics

import pylab as pl

import matplotlib.pyplot as plt

from sklearn.decomposition import PCA

kmeans_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 tag

word_centroid_map=dict(zip(model.docvecs.offset2doctag,l))

#Print Cluster List

for 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模型并取回簇的列表

下面是一些簇的例子。

640.png

第一個簇里有相當(dāng)多的“設(shè)計、UI/UX設(shè)計、軟件開發(fā)、web開發(fā)和網(wǎng)站”。

640 (1).png

第二個簇里有不少“在線廣告、營銷工具”

640 (2).png

第三個簇里有許多像“生活、自我提升”這樣的話題。

640 (3).png

看到這個簇你就能明白數(shù)據(jù)庫里大部分跟性有關(guān)的話題都是關(guān)于培養(yǎng)孩子和性-教育的方面。其他的熱門關(guān)鍵詞都沒有出現(xiàn)。

640.jpg

這個簇是一個政-治和經(jīng)濟話題的大雜燴。同時,這也揭示了經(jīng)濟與政-治之間的內(nèi)在聯(lián)系,以及一個地區(qū)的經(jīng)濟因素是如何成為該地區(qū)發(fā)展的主要評價標(biāo)準(zhǔn)的。

640 (1).jpg

影視、美術(shù)、書籍、音樂以及其他形式的創(chuàng)造性藝術(shù)。

這個簇里為啥有國際象棋(Chess)?

這個非常有趣,主要聚焦在宗-教-信-仰(Religion)上。有三件事我希望你們注意:假設(shè)問題(Hypothesis Questions)在這個簇里。倫-理(Ethics)在這個簇里?;贚GBTQ的問題跟宗-教-信-仰最相關(guān),而(Homosexuality)和親子(Parenting and Children)在一個簇里。

很清晰的是,簇形成的方式反映出了關(guān)于Quora上的話題之間互相關(guān)聯(lián)的方式,以及問題被詢問的方式。調(diào)查問題(Servey Questions)由于它的獨特性,自己形成了一個簇,而政-治(Politics)有非常多的相關(guān)話題。

這是60個簇中我覺得值得一提的一些。你也可以提一下自己發(fā)現(xiàn)的有趣的簇。這個項目的代碼可以在Github找到。

立即登錄,閱讀全文
版權(quán)說明:
本文內(nèi)容來自于AI源創(chuàng)評論,本站不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。文章內(nèi)容系作者個人觀點,不代表快出海對觀點贊同或支持。如有侵權(quán),請聯(lián)系管理員(zzx@kchuhai.com)刪除!
優(yōu)質(zhì)服務(wù)商推薦
更多