Doc2Vec训练相似文章识别模型

一、需求描述

     由于在平台上发布的文章是来源于不同渠道和作者的,发布的文章也存在一定程度上的抄袭或者太相似。为了避免对用户体验造成影响,避免不必要的文章费用支出,需要识别出哪些文章是相似的。数据源是若干文章(中文),初步选择方法为利用doc2vec模型,它类似于word2vec,下面就让我们看看是怎么达到我们的目的。

二、数据预处理

  1. 从mysql源表导入到hive
  2. 由于某些文章的内容是图片,这种我们还无法识别相似,因此,过滤掉汉字内容太少的文章。
  3. 数据源可能包含标题,内容,标签等信息,因为是识别相似文章,有的作者可能会改下标题,但是内容却不变,因此,我们这里就选择文章的内容作为输入,而不考虑标题和标签。

三、工具选择

     选择python的gensim包中的Doc2Vec。

gensim doc2vec文档

由于目前spark还没有doc2vec的支持,但是看到有deepdist工具可以实现,也可以参照:

DeepDist

分词工具呢,还是采用jieba分词。

四、模型训练简述

  1. 分词, 注意,这里没有做去除停用词的处理

    wordList = jieba.cut(s, cut_all=False)

  2. 将数据输入用LabeledSentence方法封装

    sentence = models.doc2vec.LabeledSentence(words=list(seg_list), tags=[int(id)])

  3. 模型训练

    model = models.Doc2Vec(sentences,alpha=.025, min_alpha=.025, min_count=1,workers=8, iter=6, size=500)

  4. 计算,获得相似文章

    similar_result = model.docvecs.most_similar(info_id, topn=20)

五、调参

  1. 数据源,当需要识别的文章参与模型训练后,计算出的相似度准确率较高
  2. 学习速率
  3. 迭代次数
  4. 向量的维度

六、结果展示

查询结果:
文章id为 277878的相似文章

我们看到278561的文章与277878的文章相似度达到86%,实际发现的确是一样的文章

这里写图片描述

七、存在的问题

  1. 怎样确定阈值标示是否相似
  2. 怎样实现模型的增量训练
  3. 怎样计算一个新文章的相似文章(可以用infer_vector)

八、code

import jieba
import re
from deepdist import DeepDist
from gensim.models.doc2vec import Doc2Vec, LabeledSentence
from pyspark.sql import HiveContext
from pyspark import SparkConf,SparkContext
from gensim import models
from pyspark.sql import SparkSession

#spark = SparkSession.builder.master("local").appName("Word Count").config("spark.some.config.option", "some-value").getOrCreate()
#appName = "Doc2Vec model training"
#conf = SparkConf().setAppName(appName)
#sc = SparkContext(conf = conf)
#spark = HiveContext(sc)

regex=u"[\u4e00-\u9fa5]+"
p = re.compile(regex)


def split(jieba_list, iterator):
    sentences = []
    for i in iterator:

regex=u"[\u4e00-\u9fa5]+"
p = re.compile(regex)


def split(jieba_list, iterator):
    sentences = []
    for i in iterator:
        try:
            seg_list = []
            #out_str = ""
            s = ""
            for c in i:
                if not c is None:
                    s += c.encode('utf-8')
            id = s.split("__")[0]
            s = s.split("__")[1]
            wordList = jieba.cut(s, cut_all=False)
            for word in wordList:
                if word in jieba_list:
                    continue
                if re.search(regex, word):
                    seg_list.append(word)
            sentence = models.doc2vec.LabeledSentence(words=list(seg_list), tags=[int(id)])
            sentences.append(sentence)
        except:
            continue
    return sentences


spark.sql("use databaseName")
df = spark.sql("SELECT concat(id,'__',description) FROM similar_info_regonize_data_source_final")

take = df.rdd.repartition(500).mapPartitions(lambda it: split([u'\u5fae\u8f6f',u'\u96c5\u9ed1',u'\u8f6c\u81ea'],it))

print("start build model...")

sentences = take.collect()
model = models.Doc2Vec(sentences,alpha=.025, min_alpha=.025, min_count=1,workers=8, iter=6, size=500)
model.train(sentences)

print("save model")

model.save("/home/rd/python/workspace/duankai/similarity_model1.doc2vec")

print("success")

猜你喜欢

转载自blog.csdn.net/chunyun0716/article/details/71937766