Word2Vec計算相似文章

第一步:得到用戶帖子的點擊日誌。

from pyspark.sql.types import BooleanType,LongType
from scipy.stats import norm, t
from pyspark.sql import SparkSession, DataFrame, functions as F
from pyspark.sql.functions import udf,lit
from dateutil.parser import parse
import string
from pyspark.sql.types import IntegerType, ArrayType
import pandas as pd
import pymysql
import jieba
import re
from pyspark.sql.functions import udf
from pyspark.sql.types import ArrayType, StringType
from pyspark.sql.functions import col,udf, json_tuple, lit
from datetime import datetime
from pyspark.ml.feature import Word2Vec, Word2VecModel


dp='2020-05-07'
start_date='2020-04-20'
end_date='2020-04-20'
#1.讀取最近3天用戶點擊日誌,有條件的用戶可以天級別日誌+當天實時日誌,效果更佳。
log_sql = """select uid, post_id, log_time, dp from %s where dp >= '%s' and dp <= '%s'""" % ('dm.post_click_daily', start_date, end_date)
df = spark.sql(log_sql)
log = df.select('uid', 'post_id', 'log_time')

得到點擊日誌:

第二步【選做】:按照uid、post_id去重。

log = log.groupBy('uid', 'post_id').agg(F.first('log_time').alias('log_time'))

即某個用戶最近三天可能點擊了某個帖子 三次。只需要隨機取一次即可。

第三步:得到每個用戶的點擊序列。

 
# 組成post_id,date_time兩列。然後按照第二列排序,把第一列存到list中,得到用戶按時間排序的點擊序列。
def sort2seq(arr):
    """將用戶瀏覽的post_id按照瀏覽時間升序排序
    :param arr: {list}
    :return: {list} list of target_ids
    """
    # 按照瀏覽時間排序
    sorted_arr = sorted(arr, key=lambda x: x[1])
    return [row[0] for row in arr]
#註冊UDF
sort2seq = F.udf(sort2seq, returnType=ArrayType(StringType()))

post_struct = F.struct('post_id', 'log_time')
user_seq = log.groupBy('uid') \
    .agg(F.collect_list(post_struct).alias('seq')) \
    .select('uid', sort2seq('seq').alias('post_ids'))

得到用戶的點擊序列:

第四步【選做】:過濾點擊序列太長、太短的用戶。

#選取 瀏覽過10~600個帖子的用戶
size_limit = (10, 600)
training = user_seq.filter(F.size('post_ids').between(*size_limit))

第五步:用戶點擊序列訓練Word2Vec

#把用戶的帖子點擊序列當成 文章。訓練得到每個帖子的vec。
word2vec = Word2Vec(vectorSize=40, minCount=5, maxIter=5, numPartitions=40,
                    # window_size設置一個超大的數,這樣就會把用戶瀏覽過的所有物品都組合一遍
                    windowSize=50, inputCol='post_ids', outputCol="user_vec",maxSentenceLength=200)
model = word2vec.fit(training)    
#  DataFrame[word: string, c: vector]
target_df = model.getVectors().select(
    # 這裏注意,把target_id轉爲bigint
    F.col('word').cast(LongType()).alias('post_id'),
    F.col('vector').alias('target_vec'),
)

target_df:每一個帖子都有了一個40維(vectorSize)的向量來表示。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章