二 、推荐系统算法

python编程快速上手(持续更新中…)

推荐系统基础


2.1.Model-Based 协同过滤算法

随着机器学习技术的逐渐发展与完善,推荐系统也逐渐运用机器学习的思想来进行推荐。将机器学习应用到推荐系统中的方案真是不胜枚举。以下对Model-Based CF算法做一个大致的分类:

  • 基于分类算法、回归算法、聚类算法
  • 基于矩阵分解的推荐
  • 基于神经网络算法
  • 基于图模型算法

接下来我们重点学习以下几种应用较多的方案:

  • 基于回归模型的协同过滤推荐
  • 基于矩阵分解的协同过滤推荐

2.2基于回归模型的协同过滤推荐

如果我们将评分看作是一个连续的值而不是离散的值,那么就可以借助线性回归思想来预测目标用户对某物品的评分。其中一种实现策略被称为Baseline(基准预测)。

Baseline基准预测:

Baseline设计思想基于以下的假设:

  • 有些用户的评分普遍高于其他用户,有些用户的评分普遍低于其他用户。比如有些用户天生愿意给别人好评,心慈手软,比较好说话,而有的人就比较苛刻,总是评分不超过3分(5分满分)

  • 一些物品的评分普遍高于其他物品,一些物品的评分普遍低于其他物品。比如一些物品一被生产便决定了它的地位,有的比较受人们欢迎,有的则被人嫌弃。
    这个用户或物品普遍高于或低于平均值的差值,我们称为偏置(bias)

Baseline目标:

  • 找出每个用户普遍高于或低于他人的偏置值
  • 找出每件物品普遍高于或低于其他物品的偏置值
  • 我们的目标也就转化为寻找最优的

使用Baseline的算法思想预测评分的步骤如下:

  • 计算所有电影的平均评分(即全局平均评分)
  • 计算每个用户评分与平均评分
  • 计算每部电影所接受的评分与平均评分
    预测用户对电影的评分:
    在这里插入图片描述
    举例:通过Baseline来预测用户A对电影“阿甘正传”的评分
  • 首先计算出整个评分数据集的平均评分是3.5分
  • 用户A比较苛刻,普遍比平均评分低0.5分,即用户A的偏置值是-0.5;
  • “阿甘正传”比较热门且备受好评,评分普遍比平均评分要高1.2分,“阿甘正传”的偏置是+1.2
  • 因此就可以预测出用户A对电影“阿甘正传”的评分为:​,也就是4.2分。
    对于所有电影的平均评分是直接能计算出的,因此问题在于要测出每个用户的评分偏置和每部电影的得分偏置。对于线性回归问题,我们可以利用平方差构建损失函数如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

方法一:随机梯度下降法优化

方法一:随机梯度下降法优化

step 1:梯度下降法推导

在这里插入图片描述

step 2:随机梯度下降

由于随机梯度下降法本质上利用每个样本的损失来更新参数,而不用每次求出全部的损失和,因此使用SGD时:
在这里插入图片描述

step 3:算法实现

tips pandas 版本不要过低 pandas 0.24.2

数据加载

import pandas as pd
import numpy as np

dtype = {"userId": np.int32, "movieId": np.int32, "rating": np.float32}
dataset = pd.read_csv('../data/ml-latest-small/ratings.csv', dtype=dict(dtype), usecols=range(3))
dataset

在这里插入图片描述
2.根据userid聚合

# 根据userid聚合
users_ratings = dataset.groupby('userId').agg([list])
users_ratings

在这里插入图片描述
3.根据umovieId聚合

# 根据umovieId聚合
items_ratings = dataset.groupby('movieId').agg([list])
items_ratings

在这里插入图片描述
4.计算全局平均分

# 计算全局平均分
global_mean = dataset['rating'].mean()
global_mean

3.5015569

5.初始化 bu bi

# 初始化 bu bi
bu = dict(zip(users_ratings.index, np.zeros(len(users_ratings))))
bi = dict(zip(items_ratings.index, np.zeros(len(items_ratings))))
bu

在这里插入图片描述

list(dataset.itertuples(index=False))

在这里插入图片描述
6.利用梯度下降优化

# 利用梯度下降优化
#number_epochs 迭代次数 alpha学习率  reg 正则化系数
number_epochs = 10
alpha = 0.1
reg = 0.1
for i in range(number_epochs):
    print("iter%d" % i)
    for uid, iid, real_rating in dataset.itertuples(index=False):
        # 损失
        error = real_rating - (global_mean + bu[uid] + bi[iid])
        bu[uid] += alpha * (error - reg * bu[uid])
        bi[iid] += alpha * (error - reg * bi[iid])

在这里插入图片描述
bu
在这里插入图片描述
7.预测评分

# 预测评分
def predict(uid, iid):
    predict_rating = global_mean + bu[uid] + bi[iid]
    return predict_rating

# 1号用户对1号商品
predict(1, 1)

4.368831380758709

Step 4: 准确性指标评估

添加test方法,然后使用之前实现accuary方法计算准确性指标

1.数据集拆分

# 数据集拆分
def data_split(data_path, x=0.8, random=False):
    '''
    切分数据集, 这里为了保证用户数量保持不变,将每个用户的评分数据按比例进行拆分
    :param data_path: 数据集路径
    :param x: 训练集的比例,如x=0.8,则0.2是测试集
    :param random: 是否随机切分,默认False
    :return: 用户-物品评分矩阵
    '''
    print("开始切分数据集...")
    # 设置要加载的数据字段的类型
    dtype = {"userId": np.int32, "movieId": np.int32, "rating": np.float32}
    # 加载数据,我们只用前三列数据,分别是用户ID,电影ID,已经用户对电影的对应评分
    ratings = pd.read_csv(data_path, dtype=dtype, usecols=range(3))

    testset_index = []
    # 为了保证每个用户在测试集和训练集都有数据,因此按userId聚合
    for uid in ratings.groupby("userId").any().index:
        user_rating_data = ratings.where(ratings["userId"]==uid).dropna()
        if random:
            # 因为不可变类型不能被 shuffle方法作用,所以需要强行转换为列表
            index = list(user_rating_data.index)
            np.random.shuffle(index)    # 打乱列表
            _index = round(len(user_rating_data) * x)
            testset_index += list(index[_index:])
        else:
            # 将每个用户的x比例的数据作为训练集,剩余的作为测试集
            index = round(len(user_rating_data) * x)
            testset_index += list(user_rating_data.index.values[index:])

    testset = ratings.loc[testset_index]
    trainset = ratings.drop(testset_index)
    print("完成数据集切分...")
    return trainset, testset

trainset, testset = data_split(’…/data/ml-latest-small/ratings.csv’)
开始切分数据集…
完成数据集切分…

2.trainset

trainset

在这里插入图片描述
3.预测测试集数据

# 预测测试集数据
def test(testset):
    '''预测测试集数据'''
    for uid, iid, real_rating in testset.itertuples(index=False):
        try:
            pred_rating = predict(uid, iid)
        except Exception as e:
            print(e)
        else:
            yield uid, iid, real_rating, pred_rating

4.准确性指标计算方法

# 准确性指标计算方法
def accuray(predict_results, method="all"):
    '''
    准确性指标计算方法
    :param predict_results: 预测结果,类型为容器,每个元素是一个包含uid,iid,real_rating,pred_rating的序列
    :param method: 指标方法,类型为字符串,rmse或mae,否则返回两者rmse和mae
    :return:
    '''

    def rmse(predict_results):
        '''
        rmse评估指标
        :param predict_results:
        :return: rmse
        '''
        length = 0
        _rmse_sum = 0
        for uid, iid, real_rating, pred_rating in predict_results:
            length += 1
            _rmse_sum += (pred_rating - real_rating) ** 2
        return round(np.sqrt(_rmse_sum / length), 4)

    def mae(predict_results):
        '''
        mae评估指标
        :param predict_results:
        :return: mae
        '''
        length = 0
        _mae_sum = 0
        for uid, iid, real_rating, pred_rating in predict_results:
            length += 1
            _mae_sum += abs(pred_rating - real_rating)
        return round(_mae_sum / length, 4)

    def rmse_mae(predict_results):
        '''
        rmse和mae评估指标
        :param predict_results:
        :return: rmse, mae
        '''
        length = 0
        _rmse_sum = 0
        _mae_sum = 0
        for uid, iid, real_rating, pred_rating in predict_results:
            length += 1
            _rmse_sum += (pred_rating - real_rating) ** 2
            _mae_sum += abs(pred_rating - real_rating)
        return round(np.sqrt(_rmse_sum / length), 4), round(_mae_sum / length, 4)

    if method.lower() == "rmse":
        rmse(predict_results)
    elif method.lower() == "mae":
        mae(predict_results)
    else:
        return rmse_mae(predict_results)

5.testset
testset
在这里插入图片描述
6.预测

# 预测
test_result = test(testset)
accuray(test_result)

(0.7841, 0.5922)

方法二:交替最小二乘法优化

使用交替最小二乘法优化算法预测Baseline偏置值

step 1: 交替最小二乘法推导
  • 最小二乘法和梯度下降法一样,可以用于求极值。
  • 最小二乘法思想:对损失函数求偏导,然后再使偏导为0
    在这里插入图片描述
step 2: 交替最小二乘法应用

通过最小二乘推导,我们最终分别得到了bu和bi​bu和bi​的表达式,但他们的表达式中却又各自包含对方,因此这里我们将利用一种叫交替最小二乘的方法来计算他们的值:

  • 计算其中一项,先固定其他未知参数,即看作其他未知参数为已知
  • 如求bu时,将bi看作是已知;求bi时,将bu​bu时,将bi看作是已知;求bi时,将bu​看作是已知;如此反复交替,不断更新二者的值,求得最终的结果。这就是交替最小二乘法(ALS)
step 3: 算法实现
  • 数据加载初始化与之前完全相同
  • 迭代更新bu bi

1.初始化bu、bi的值,全部设为0

# 初始化bu、bi的值,全部设为0
bu = dict(zip(users_ratings.index, np.zeros(len(users_ratings))))
bi = dict(zip(items_ratings.index, np.zeros(len(items_ratings))))
for i in range(15):
    print("iter%d" % i)
    for iid, uids, ratings in items_ratings.itertuples(index=True):
        _sum = 0
        for uid, rating in zip(uids, ratings):
            _sum += rating - global_mean - bu[uid]
        bi[iid] = _sum / (0.1 + len(uids))

    for uid, iids, ratings in users_ratings.itertuples(index=True):
        _sum = 0
        for iid, rating in zip(iids, ratings):
            _sum += rating - global_mean - bi[iid]
        bu[uid] = _sum / (0.1 + len(iids))

在这里插入图片描述
2.predict(1, 1)

predict(1, 1)

4.670576814116479

2.3基于矩阵分解的CF算法

矩阵分解发展史

Traditional SVD:

通常SVD矩阵分解指的是SVD(奇异值)分解技术,在这我们姑且将其命名为Traditional SVD(传统并经典着)其公式如下:
在这里插入图片描述
Traditional SVD分解的形式为3个矩阵相乘,中间矩阵为奇异值矩阵。如果想运用SVD分解的话,有一个前提是要求矩阵是稠密的,即矩阵里的元素要非空,否则就不能运用SVD分解。

很显然我们的数据其实绝大多数情况下都是稀疏的,因此如果要使用Traditional SVD,一般的做法是先用均值或者其他统计学方法来填充矩阵,然后再运用Traditional SVD分解降维,但这样做明显对数据的原始性造成一定影响。

FunkSVD(LFM)

刚才提到的Traditional SVD首先需要填充矩阵,然后再进行分解降维,同时存在计算复杂度高的问题,因为要分解成3个矩阵,所以后来提出了Funk SVD的方法,它不在将矩阵分解为3个矩阵,而是分解为2个用户-隐含特征,项目-隐含特征的矩阵,Funk SVD也被称为最原始的LFM模型
在这里插入图片描述
借鉴线性回归的思想,通过最小化观察数据的平方来寻求最优的用户和项目的隐含向量表示。同时为了避免过度拟合(Overfitting)观测数据,又提出了带有L2正则项的FunkSVD,上公式:
在这里插入图片描述
以上两种最优化函数都可以通过梯度下降或者随机梯度下降法来寻求最优解。

BiasSVD:

在FunkSVD提出来之后,出现了很多变形版本,其中一个相对成功的方法是BiasSVD,顾名思义,即带有偏置项的SVD分解:
在这里插入图片描述
它基于的假设和Baseline基准预测是一样的,但这里将Baseline的偏置引入到了矩阵分解中

SVD++:

人们后来又提出了改进的BiasSVD,被称为SVD++,该算法是在BiasSVD的基础上添加了用户的隐式反馈信息:
在这里插入图片描述
显示反馈指的用户的评分这样的行为,隐式反馈指用户的浏览记录、购买记录、收听记录等。
SVD++是基于这样的假设:在BiasSVD基础上,认为用户对于项目的历史浏览记录、购买记录、收听记录等可以从侧面反映用户的偏好。

2.4基于矩阵分解的CF算法实现(一):LFM

LFM也就是前面提到的Funk SVD矩阵分解

LFM原理解析

LFM(latent factor model)隐语义模型核心思想是通过隐含特征联系用户和物品,如下图:
在这里插入图片描述

  • P矩阵是User-LF矩阵,即用户和隐含特征矩阵。LF有三个,表示共总有三个隐含特征。
  • Q矩阵是LF-Item矩阵,即隐含特征和物品的矩阵
  • R矩阵是User-Item矩阵,有P*Q得来
  • 能处理稀疏评分矩阵

利用矩阵分解技术,将原始User-Item的评分矩阵(稠密/稀疏)分解为P和Q矩阵,然后利用P∗Q​P∗Q​还原出User-Item评分矩阵R​R​。整个过程相当于降维处理,其中:
矩阵值P11​P11​表示用户1对隐含特征1的权重值
矩阵值Q11​Q11​表示隐含特征1在物品1上的权重值
矩阵值R11就表示预测的用户1对物品1的评分,且
在这里插入图片描述
在这里插入图片描述
利用LFM预测用户对物品的评分, k ​ k​ k表示隐含特征数量:
在这里插入图片描述
因此最终,我们的目标也就是要求出P矩阵和Q矩阵及其当中的每一个值,然后再对用户-物品的评分进行预测。

损失函数

同样对于评分预测我们利用平方差来构建损失函数:
在这里插入图片描述
加入L2正则化:
在这里插入图片描述

随机梯度下降法优化

在这里插入图片描述

算法实现

1.数据加载
users_ratings = dataset.groupby('userId').agg([list])
items_ratings = dataset.groupby('movieId').agg([list])
2.初始化Q和P
# 初始化Q和P
# User-LF  10 代表 隐含因子个数是10个
P = dict(zip(users_ratings.index,np.random.rand(len(users_ratings),10).astype(np.float32)))
P
Q = dict(zip(items_ratings.index,np.random.rand(len(items_ratings),10).astype(np.float32)))
Q

在这里插入图片描述

3.梯度下降优化损失函数
# 梯度下降优化损失函数
for i in range(15):
    print('*'*10,i)
    for uid,iid,real_rating in dataset.itertuples(index = False):
        #遍历 用户 物品的评分数据 通过用户的id 到用户矩阵中获取用户向量
        v_puk = P[uid]
        # 通过物品的uid 到物品矩阵里获取物品向量
        v_qik = Q[iid]
        #计算损失
        error = real_rating-np.dot(v_puk,v_qik)
        # 0.02学习率 0.01正则化系数
        v_puk += 0.02*(error*v_qik-0.01*v_puk)
        v_qik += 0.02*(error*v_puk-0.01*v_qik)

        P[uid] = v_puk
        Q[iid] = v_qik

在这里插入图片描述

4.评分预测
# 评分预测
def predict2(uid, iid):
    # 如果uid或iid不在,我们使用全剧平均分作为预测结果返回
    if uid not in users_ratings.index or iid not in items_ratings.index:
        return global_mean
    p_u = P[uid]
    q_i = Q[iid]

    return np.dot(p_u, q_i)
5.预测
predict2(1, 1)

4.9007773

2.5基于内容的推荐算法(Content-Based)

简介

基于内容的推荐方法是非常直接的,它以物品的内容描述信息为依据来做出的推荐,本质上是基于对物品和用户自身的特征或属性的直接分析和计算。

例如,假设已知电影A是一部喜剧,而恰巧我们得知某个用户喜欢看喜剧电影,那么我们基于这样的已知信息,就可以将电影A推荐给该用户。

基于内容的推荐实现步骤

画像构建,顾名思义,画像就是刻画物品或用户的特征。本质上就是给用户或物品贴标签。

物品画像:例如给电影《战狼2》贴标签,可以有哪些?
在这里插入图片描述
“动作”、“吴京”、“吴刚”、“张翰”、“大陆电影”、“国产”、“爱国”、"军事"等等一系列标签是不是都可以贴上

用户画像:例如已知用户的观影历史是:"《战狼1》"、"《战狼2》"、"《建党伟业》"、"《建军大业》"、"《建国大业》"、"《红海行动》"、"《速度与激情1-8》"等,我们是不是就可以分析出该用户的一些兴趣特征如:“爱国”、“战争”、“赛车”、“动作”、“军事”、“吴京”、"韩三平"等标签。

问题:物品的标签来自哪儿?

PGC 物品画像–冷启动

  • 物品自带的属性(物品一产生就具备的):如电影的标题、导演、演员、类型等等
  • 服务提供方设定的属性(服务提供方为物品附加的属性):如短视频话题、微博话题(平台拟定)
  • 其他渠道:如爬虫

UGC 冷启动问题

  • 用户在享受服务过程中提供的物品的属性:如用户评论内容,微博话题(用户拟定)
    根据PGC内容构建的物品画像的可以解决物品的冷启动问题
基于内容推荐的算法流程:

在这里插入图片描述

物品冷启动处理

在这里插入图片描述

2.6基于内容的电影推荐:物品画像

1.物品画像构建步骤:

在这里插入图片描述

2.基于TF·IDF提取TOP-N关键词,构建电影画像

TF-IDF算法便是其中一种在自然语言处理领域中应用比较广泛的一种算法。可用来提取目标文档中,并得到关键词用于计算对于目标文档的权重,并将这些权重组合到一起得到特征向量。

算法原理

TF-IDF自然语言处理领域中计算文档中词或短语的权值的方法,是词频(Term Frequency,TF)和逆转文档频率(Inverse Document Frequency,IDF)的乘积。

代码实现

1、加载数据

import pandas as pd
import numpy as np

# 加载基于所有电影的标签
# 由于ml-latest-small中标签数据太多,因此借助其来扩充
_tags = pd.read_csv("../data/ml-latest-small/all-tags.csv", usecols=range(1, 3)).dropna()
tags = _tags.groupby("movieId").agg(list)
tags

在这里插入图片描述

 # 加载电影列表数据集
movies = pd.read_csv("../data/ml-latest-small/movies.csv", index_col="movieId")
movies

在这里插入图片描述
2.将类别词分开

# 将类别词分开
movies["genres"] = movies["genres"].apply(lambda x: x.split("|"))
movies

在这里插入图片描述
3.为每部电影匹配对应的标签数据,如果没有将会是NAN

# 为每部电影匹配对应的标签数据,如果没有将会是NAN
movies_index = set(movies.index) & set(tags.index)
new_tags = tags.loc[list(movies_index)]
ret = movies.join(new_tags)
ret

在这里插入图片描述

list(ret.itertuples())

在这里插入图片描述
4.构建电影数据集,包含电影Id、电影名称、类别、标签四个字段

# 构建电影数据集,包含电影Id、电影名称、类别、标签四个字段
temp = map(lambda x: (x[0], x[1], x[2], x[2]+x[3]) if x[3] is not np.nan else (x[0], x[1], x[2], []), ret.itertuples())
# 执行了就没了数据
# list(temp)
# 如果电影没有标签数据,那么就替换为空列表
# map(fun,可迭代对象)
movie_dataset = pd.DataFrame(temp, columns=["movieId", "title", "genres","tags"])
movie_dataset

在这里插入图片描述
5.添加标签

movie_dataset.set_index("movieId", inplace=True)
movie_dataset

在这里插入图片描述
6.获取tags

# 获取tags
dataset1 = movie_dataset['tags'].values
dataset1

在这里插入图片描述
7.创建dict对象

from gensim.corpora import Dictionary
from gensim.models import TfidfModel

# 创建dict对象
# 根据数据集建立词袋,并统计词频,将所有词放入一个词典,使用索引进行获取
dct = Dictionary(dataset1)

# 单词出现频率
dct.doc2bow(['Comedy', 'Romance', 'moldy', 'old', 'Ann Margaret', 'Burgess Meredith', 'Daryl Hannah', 'fishing', 'good soundtrack', 'fishing', 'good soundtrack'])




在这里插入图片描述
8.根据将每条数据,返回对应的词索引和词频

# 根据将每条数据,返回对应的词索引和词频
corpus = [dct.doc2bow(line) for line in dataset1]
corpus

在这里插入图片描述
9.训练TF-IDF模型,即计算TF-IDF值

# 训练TF-IDF模型,即计算TF-IDF值
model = TfidfModel(corpus)
# vector = model[corpus[1]]
# vector

 # 按照TF-IDF值得到top-n的关键词
movie_tags = sorted(vector, key=lambda x: x[1], reverse=True)[:30]
movie_tags

在这里插入图片描述
10.根据关键词提取对应的名称

# 根据关键词提取对应的名称
dict(map(lambda x:(dct[x[0]], x[1]), movie_tags))

在这里插入图片描述
11.通过标签找到对应的电影名

# 通过标签找到对应的电影名
def create_movie_profile(movie_dataset):
    movie_profile = {}
    for i, mid in enumerate(movie_dataset.index):
        # 根据每条数据返回,向量
        vector = model[corpus[i]]
        # 按照TF-IDF值得到top-n的关键词
        movie_tags = sorted(vector, key=lambda x: x[1], reverse=True)[:30]
        # 根据关键词提取对应的名称
        movie_profile[mid] = dict(map(lambda x:(dct[x[0]], x[1]), movie_tags))
        
    return movie_profile

create_movie_profile(movie_dataset)

在这里插入图片描述
12.使用tfidf,分析提取topn关键词

# 使用tfidf,分析提取topn关键词
def create_movie_profile2(movie_dataset):
    # 训练TF-IDF模型,即计算TF-IDF值
    model = TfidfModel(corpus)

    _movie_profile = []
    for i, data in enumerate(movie_dataset.itertuples()):
        mid = data[0]
        title = data[1]
        genres = data[2]
        vector = model[corpus[i]]
        movie_tags = sorted(vector, key=lambda x: x[1], reverse=True)[:30]
        topN_tags_weights = dict(map(lambda x: (dct[x[0]], x[1]), movie_tags))
        # 将类别词的添加进去,并设置权重值为1.0
        for g in genres:
            topN_tags_weights[g] = 1.0
        topN_tags = [i[0] for i in topN_tags_weights.items()]
        _movie_profile.append((mid, title, topN_tags, topN_tags_weights))

    movie_profile = pd.DataFrame(_movie_profile, columns=["movieId", "title", "profile", "weights"])
    movie_profile.set_index("movieId", inplace=True)
    return movie_profile
movie_profile = create_movie_profile2(movie_dataset)
movie_profile

在这里插入图片描述
13.建立tag-物品的倒排索引

# 建立tag-物品的倒排索引
def create_inverted_table(movie_profile):
    inverted_table = {}
    for mid, weights in movie_profile['weights'].iteritems():
        for tag, weight in weights.items():
            #到inverted_table dict 用tag作为Key去取值 如果取不到就返回[]
            _ = inverted_table.get(tag, [])
            #将电影的id 和 权重 放到一个tuple中 添加到list中
            _.append((mid, weight))
            #将修改后的值设置回去 
            inverted_table.setdefault(tag, _)
    return inverted_table
inverted_table = create_inverted_table(movie_profile)
inverted_table

在这里插入图片描述

2.7基于内容的电影推荐:用户画像

1.用户画像构建步骤

在这里插入图片描述

2.代码实现

watch_record = pd.read_csv("../data/ml-latest-small/ratings.csv", usecols=range(2), dtype={"userId":np.int32, "movieId": np.int32})
watch_record = watch_record.groupby("userId").agg(list)
watch_record

在这里插入图片描述

movie_profile.head()

在这里插入图片描述

record_movie_prifole = movie_profile.loc[[1, 3, 6, 47, 50, 70, 101, 110, 151, 157, 163]]
record_movie_prifole

在这里插入图片描述

from functools import reduce
import collections

temp = reduce(lambda x,y : list(x)+list(y), record_movie_prifole['profile'].values)
temp

在这里插入图片描述

# 统计
counter = collections.Counter(temp)
counter

在这里插入图片描述

# 取出出现次数最多的词 出现的次数
maxcount = interest_words[0][1]
maxcount

5

# 利用次数计算权重 出现次数最多的词权重为1
interest_words = [(w,round(c/maxcount, 4)) for w,c in interest_words]
interest_words

在这里插入图片描述

2.9基于内容的电影推荐:物品冷启动处理

1.词向量

在这里插入图片描述

2.文档向量

在这里插入图片描述

3.代码实现

在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值