利用 Doc2Vec 对 Quora 问题标签聚类

  引言

  Quora是一个流行的知识分享平台,我常常在Quora上分享我的想法。这个平台是基于问答的形式,它因其简易的设计和平滑的用户体验而出名。

  当新的问题被添加到Quora时,这些问题由机器人自动基于问题的上下文进行标记并稍后由用户进行编辑。这些标签反映了问题被归入的话题类别。如下是一个问题的基本概貌。

  最近我在寻找合适的数据集,然后我偶然看到了Quora里的一个这个页面:Programming Challenges。我选择了这个叫做Answered的二分类问题挑战。其中,包括了近10000个问题(训练集和测试集总计)。每个问题和其话题标签以及其他的一些信息被以JSON格式储存。下图是一个JSON的示例。

  示例问题JSON

  动手干吧

  第一个任务就是要从JSON文件中读取数据。训练集总共大约有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)foriintrain_set]

  test= [json.loads(i)foriintest_set]

  questions = train +test

  接下来就要提取出所有数据集中的主题标签。在JSON文件中,主题存储在键key中。不同的问题有不同数量的主题标签。单个问题所允许存在的最大标签数为26。同时也存在没有关联主题标签的问题。

  # Create thelistof topics

  topic_list = []

  forquestion in questions:

  iflen(question[topics]) 0:

  fortopic in question[topics]:

  topic_list = topic_list + [topic[name]]

  topic_list =list(set(topic_list))

  print(len(topic_list))

  在这个挑战所提供的数据中,一共有8762个主题标签。

  在提取出主题标签之后,我们需要将具有相同标签的问题聚类。在动手之前,我们先对数据进行分析,因为如果直接对8762个进行聚类将会很困难而且聚类的质量也难以保证。

  因此我们限定了每一个主题下的最小问题数来解决这个问题。拥有多于1个问题的主题有3275个。拥有5个问题的主题恰好有900个,这个数量相对更适合进行聚类。

  最终,我们决定将主题下的最小问题数规定为5个,这主要有两个原因。首先是为了更好地用向量来表示主题,其次因为具有较少问题的主题大多数情况下是和无关的问题所关联的。

  #Assigning questiontotopics.

  question_list = []

  final_topic_list = []

  fortopic in topic_list:

  temp = []

  forquestion in questions:

  context = [i[name]fori in question[topics]]

  iftopic in context:

  temp.append(question['question_text'])

  iflen(temp) =5:

  question_list.append(temp)

  final_topic_list.append(topic)

  topic_list = final_topic_list

  接下来,我们写一个函数,通过转换为小写、去除标点符号和停用词来正则化每个段落。每个话题下有五到多个问题。我们把每个话题下的问题的集合当做一个文档。

  这样,我们先遍历话题标签,然后把问题聚集成段落,再把段落正则化化。然后我们把段落和段落的话题标签喂给Gensim的TaggedDocument函数,进行进一步的正则化。

  fromnltkimportword_tokenize

  fromnltk.corpusimportstopwords

  fromgensimimportmodels

  fromgensim.models.doc2vecimportTaggedDocument

  #Function for normalizing paragraphs.

  defnormalize(string):

  lst = word_tokenize(string)

  lst =[word.lower()forwordinlstifword.isalpha()]

  lst = [wforwinlstifnotwinstopwords.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 = []

  forindex, iteminenumerate(topic_list):

  question = .join(question_list[index])

  question = normalize(question)

  docs.append(TaggedDocument(words=question, tags=[item]))

  为Gensim的DocVec准备数据

  接下来我们训练Doc2Vec模型。

  应该调整vector_size和window,直到结果是最优的。

  importgensim

  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模型训练好后,我们就用KMeans算法聚类了文档向量。簇的数量从100到50之间进行了检查。接近100的簇数会导致大簇被切分成小簇,而簇数等于50时会使得没有相关性的簇被组合成大簇。在仔细评估聚簇结果后,最后选择60作为簇数。

  fromsklearn.clusterimportKMeans

  fromsklearnimportmetrics

  importpylabaspl

  importmatplotlib.pyplotasplt

  fromsklearn.decompositionimportPCA

  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

  forclusterinrange(0,100):

  print(\nCluster %d% cluster)

  words = []

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

  下面是一些簇的例子。

  第一个簇里有相当多的“设计、UI/UX设计、软件开发、web开发和网站”。

  第二个簇里有不少“在线广告、营销工具”

  第三个簇里有许多像“生活、自我提升”这样的话题。

  看到这个簇你就能明白数据库里大部分跟性有关的话题都是关于培养孩子和性-教育的方面。其他的热门关键词都没有出现。

  这个簇是一个政-治和经济话题的大杂烩。同时,这也揭示了经济与政-治之间的内在联系,以及一个地区的经济因素是如何成为该地区发展的主要评价标准的。

  影视、美术、书籍、音乐以及其他形式的创造性艺术。

  这个簇里为啥有国际象棋(Chess)?

  这个非常有趣,主要聚焦在宗-教-信-仰(Religion)上。有三件事我希望你们注意:假设问题(Hypothesis Questions)在这个簇里。伦-理(Ethics)在这个簇里。基于LGBTQ的问题跟宗-教-信-仰最相关,而(Homosexuality)和亲子(Parenting and Children)在一个簇里。

  很清晰的是,簇形成的方式反映出了关于Quora上的话题之间互相关联的方式,以及问题被询问的方式。调查问题(Servey Questions)由于它的独特性,自己形成了一个簇,而政-治(Politics)有非常多的相关话题。

  这是60个簇中我觉得值得一提的一些。你也可以提一下自己发现的有趣的簇。这个项目的代码可以在Github找到。

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值