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

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

引言

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

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

640.webp.jpg

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

640.webp (1).jpg

示例問題JSON

動(dòng)手干吧

第一個(gè)任務(wù)就是要從JSON文件中讀取數(shù)據(jù)。訓(xùn)練集總共大約有9000個(gè)問題,而測(cè)試集總共約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_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的簇?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 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

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

640 (1).png

第二個(gè)簇里有不少“在線廣告、營(yíng)銷工具”

640 (2).png

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

640 (3).png

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

640.jpg

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

640 (1).jpg

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

這個(gè)簇里為啥有國(guó)際象棋(Chess)?

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

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

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

立即登錄,閱讀全文
版權(quán)說明:
本文內(nèi)容來自于AI源創(chuàng)評(píng)論,本站不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。文章內(nèi)容系作者個(gè)人觀點(diǎn),不代表快出海對(duì)觀點(diǎn)贊同或支持。如有侵權(quán),請(qǐng)聯(lián)系管理員(zzx@kchuhai.com)刪除!
個(gè)人VIP