任务7 使用Word2Vec对用户进行聚类

任务7 使用Word2Vec对用户进行聚类

文章核心思想参考了这篇文章

1. 算法思想

Word2Vec的算法原理和过程就不多说了, 网上的资料很多. 下面谈谈怎么把Word2Vec运用到推荐系统领域

首先让我们回顾一下, Word2Vec的最核心的思想是什么

如果两个单词总是出现在同一个上下文当中, 那么这两个单词就极有可能在语义上是相似的

问题来了, 如果我们要将Word2Vec运用到推荐系统的领域. 那么必须要解决下面两个问题

  1. "上下文"是什么
  2. "单词"是什么

先来回答第二个问题, 不难理解"单词"就是我们要计算相似度的那个对象. 这里我们是对用户进行聚类, 所以"单词"指的是用户(当然如果是要对物品进行聚类那么"单词"指的就是物品)

接下来我们考虑第一个问题, "上下文"在这个场景下指的是什么?

我们可以这么考虑, 如果两个用户对某个电影打出的分数总是相似的, 我们可以认为这两个用户在偏好上极有可能是相似的.

不难发现, "上下文"在这里应当是, 某个电影所对应的所有用户的打分

下面我们实现代码时需要完成以下几个任务
1.基于打分, 我们来判断某个用户是不是喜欢一部电影. 在这里我们不妨认为, 打分高于3分说明用户是喜欢这部电影的, 低于3分表示用户不喜欢这部电影
2. 对于某部电影, 我们将喜欢这部电影的用户聚集起来, 组成一个"句子". 将不喜欢这部电影的用户聚集起来形成另外一个"句子"

有了句子之后, 我们只需要放入到Word2Vec模型当中训练即可

2. 代码实现

导入需要用到的包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
from gensim.models import Word2Vec
from utils import loadData

读取数据集(相关函数的定义可以见之前的博客)

rating_data = loadData('./data/', 'ml-100k')
rating_data.head()

userid movieid rating timestamp liked
0 196 242 3 881250949 0
1 186 302 3 891717742 0
2 22 377 1 878887116 0
3 244 51 2 880606923 0
4 166 346 1 886397596 0

下面实现将用户按照喜好判断用户是否喜欢这个物品, 然后按照用户是否喜欢这个物品, 将对于某个物品喜欢和不喜欢的用户聚集在一起

def rating_splitter(df):
	# 大于3分说明用户喜欢这部电影, 小于说明用户不喜欢这部电影
    df['liked'] = np.where(df['rating'] >= 4, 1, 0)
    df['movieid'] = df['movieid'].astype('str')
    # 按照是否喜欢这部电影以及电影的id来对数据集进行分组
    gp_movie_like = df.groupby(['liked', 'movieid'])
    #把分组之后的数据当中的用户id进行采集起来, 组成一个列表,这个就是我们的句子
    return ([gp_movie_like.get_group(gp)['userid'].tolist() for gp in gp_movie_like.groups])
splitted_users = rating_splitter(rating_data)

在训练之前先把里面的用户id打乱一下顺序

import random

for user_list in splitted_users:
    random.shuffle(user_list)

把生成的"句子" 放到word2vec模型当中去跑
模型的参数定义如下

  1. sentence: 就是输入的句子, 这里放入我们之前划分好的那个列表
  2. epoches: 迭代次数, 这里象征性的迭代10次
  3. min_count: 这个参数的含义是如果某个单词出现的次数少于min_count就直接将这个单词过滤掉
  4. vector_size: 想要得到的向量的维度, 简单的设置为100维
  5. sg: 是否使用skip-gram模型
  6. hs, negtivie: 和负采样有关系, 具体见官方给的文档
  7. worker: 模型训练的时候使用的线程总数
  8. window: 窗口大小, 我们这里考虑窗口没有意义, 因为用户id的先后顺序没有任何实际意义, 所以我们设置窗口大小为1000(用户总数也就900多人)
model = Word2Vec(sentences=splitted_users
                , epochs=10
                , min_count=1
                , vector_size=100
                , workers=4
                , sg=1
                
                , hs=0
                , negative=5
                , window=1000)

跑完把模型的参数保存起来, 后面可能用得到

model.wv.save_word2vec_format('usersvec.txt')

我们读取一下之前保存的参数(txt文件要去手动掉前面两行)

df1 = pd.read_csv('usersvec.txt', sep=' ', header=None)
df1.head()

在这里插入图片描述
第0列是用户的id编号, 后面的100列是用户的embedding表示

下面对数据列名处理一下

df1.rename(columns={0:'userid'}, inplace=True)

在这里插入图片描述
直接用Kmeans对用户进行聚类

from sklearn.cluster import KMeans
Xtrain = df1.loc[:,1:]
ylabel = m1.fit_predict(Xtrain)
print(ylabel)

array([8, 3, 8, 8, 8, 8, 3, 8, 3, 8, 6, 8, 1, 1, 1, 1, 8, 1, 1, 8, 7, 1,
1, 8, 8, 8, 8, 8, 8, 8, 3, 8, 8, 1, 8, 3, 7, 1, 3, 1, 3, 7, 8, 7,
1, 8, 1, 1, 3, 3, 7, 1, 1, 3, 7, 7, 7, 8, 3, 8, 3, 1, 8, 8, 3, 3,
7, 7, 3, 3, 7, 7, 7, 8, 1, 8, 1, 3, 7, 1, 3, 1, 7, 3, 7, 8, 7, 8,
1, 3, 8, 8, 6, 4, 3, 8, 3, 1, 7, 8, 3, 3, 8, 7, 7, 3, 7, 8, 2, 1,
8, 8, 8, 7, 7, 8, 8, 8, 1, 8, 3, 3, 8, 8, 3, 8, 1, 1, 7, 7, 0, 1,
7, 7, 3, 8, 1, 3, 7, 8, 1, 3, 0, 0, 7, 3, 8, 3, 1, 7, 3, 1, 7, 1,
1, 8, 7, 1, 1, 8, 8, 5, 7, 3, 1, 7, 7, 1, 1, 8, 3, 1, 3, 7, 7, 7,
8, 8, 1, 1, 8, 1, 8, 1, 7, 8, 8, 1, 7, 7, 7, 8, 3, 7, 8, 7, 3, 7,
7, 7, 7, 3, 3, 7, 7, 1, 1, 8, 3, 7, 3, 1, 8, 3, 8, 8, 3, 8, 7, 1,
7, 0, 1, 3, 7, 1, 7, 7, 1, 5, 5, 1, 1, 7, 3, 7, 1, 8, 3, 6, 7, 1,
7, 8, 6, 0, 1, 1, 3, 5, 8, 8, 5, 1, 1, 7, 7, 7, 8, 7, 3, 1, 1, 8,
5, 5, 7, 7, 1, 3, 7, 7, 8, 5, 1, 7, 7, 1, 7, 1, 1, 1, 7, 7, 3, 3,
7, 1, 3, 8, 1, 7, 7, 8, 1, 1, 8, 8, 3, 3, 8, 6, 1, 7, 1, 1, 0, 7,
6, 7, 7, 0, 1, 0, 7, 7, 1, 7, 1, 7, 5, 3, 6, 3, 7, 7, 2, 7, 8, 6,
1, 1, 6, 5, 0, 2, 6, 5, 6, 7, 8, 8, 6, 6, 6, 1, 6, 6, 5, 4, 7, 3,
3, 1, 8, 7, 3, 8, 3, 0, 1, 3, 8, 3, 1, 0, 2, 1, 2, 7, 1, 8, 5, 7,
1, 3, 5, 8, 3, 5, 1, 8, 1, 3, 8, 1, 7, 1, 0, 1, 1, 1, 7, 7, 2, 6,
3, 0, 8, 3, 1, 8, 3, 3, 7, 1, 8, 4, 3, 7, 6, 0, 8, 5, 7, 0, 7, 5,
8, 7, 6, 3, 4, 0, 3, 3, 0, 3, 8, 3, 1, 8, 6, 0, 9, 5, 5, 1, 1, 3,
1, 1, 6, 4, 6, 1, 5, 3, 8, 6, 3, 5, 4, 5, 1, 8, 8, 6, 7, 7, 0, 0,
6, 6, 5, 1, 6, 1, 1, 1, 7, 3, 6, 8, 4, 4, 8, 5, 9, 5, 6, 5, 1, 8,
5, 6, 1, 5, 7, 8, 4, 5, 3, 4, 1, 3, 1, 9, 5, 7, 8, 0, 0, 7, 5, 3,
1, 6, 0, 6, 5, 7, 5, 5, 4, 5, 7, 8, 5, 2, 0, 4, 3, 5, 1, 1, 3, 0,
4, 3, 5, 3, 9, 6, 5, 0, 3, 6, 5, 0, 5, 7, 3, 1, 8, 0, 0, 3, 1, 6,

2, 5, 4, 2, 5, 0, 2, 9, 0, 2, 2, 9, 9, 4, 0, 9, 7, 7, 7, 0, 0, 4,
4, 2, 3, 4, 4, 8, 0, 0, 2, 3, 4, 2, 2, 2, 6, 2, 9, 9, 2, 6, 2, 5,
9, 9, 2, 7, 9, 9, 2, 4, 4, 2, 2, 4, 2, 9, 0, 4, 3, 4, 2, 9, 2, 1,
2, 3, 6, 7, 6, 2, 2, 2, 7, 0, 3, 2, 2, 2, 6, 2, 6, 9, 2, 0, 4, 2,
9, 9, 2, 6, 9, 2, 9, 6, 4, 9, 3, 2, 9, 4, 9, 2, 0, 2, 6])

聚类完成, 把结果按照用户id进行排个序, 然后保存一下

df1['ylabel'] = ylabel
df2 = df1.sort_values(by='userid').reset_index(drop=True)
df2.to_csv('usersvec(labels).csv')
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值