概述
点击查看我的知乎专栏:推荐搜索广告
本文以文章推荐为例,编写一个推荐系统,应用基于内容推荐算法解决问题。
实现过程
基于内容推荐的过程一般包括以下三步:
1、给出物品表示:为每个物品抽取出一些特征来表示此物品;
2、学习用户偏好:利用一个用户过去喜欢(及不喜欢)的物品的特征数据,来学习出此用户偏好;
3、生成推荐列表:根据候选物品表示和用户偏好,为该用户生成其最可能感兴趣的 n 个物品。
注:有关基于内容推荐的基本理论框架可参见之前的文章《推荐算法分类:协同过滤推荐、基于内容推荐、基于知识推荐、混合推荐》
本文的具体实现过程如下:
1、给出物品表示 - 基于向量空间模型的方法,具体采用了基于 TF-IDF 的文本表示法;
2、学习用户偏好 - 把用户所有喜欢的物品对应的向量的平均值作为此用户的 profile;
3、生成推荐列表 - 把候选物品里与此用户最相关(余弦相似度最大)的 N 个物品推荐给此用户。
基于 TF-IDF 的文本表示法
文本相似计算是进行文本聚类的基础,和传统结构化数值数据的聚类方法类似,文本聚类是通过计算文本之间"距离"来表示文本之间的相似度并产生聚类。文本相似度的常用计算方法有余弦定理和 Jaccard 系数。但是文本数据与普通的数值数据或类属数据不同,文本数据是一种半结构化数据,在进行文本挖掘之前必须要对文本数据源进行处理,如分词、向量化表示等。其目的就是使用量化的数值来表达这些半结构化的文本数据,使其适用于分析计算。下面以基于 TF-IDF 的文档表示法为例,先介绍 TF-IDF 算法,再基于 TF-IDF 算法表示文本。
TF-IDF
TF-IDF 是一种加权技术,它通过统计的方法来计算和表达某个关键词在文本中的重要程度。
TF-IDF 是由两部分组成,一部分是词频 TF(Token Frequency),TFtd=Ftd/Sd,关键词 t 在文档 d 中的词频=关键词 t 在文档 d 中出现的次数/所有关键词在文档 d 中出现的总次数。另一部分是逆向文档频率 IDF(Inverse Document Frequency),IDFt=ln((1+|D|)/|Dt|),关键词 t 的逆向文档频率=ln((1+文档总数)/包含关键词 t 的文档数量)。
TF-IDF 的值就是由这两部分相乘得到的,TF-IDFtd=TFtd*IDFt。要指出的是 TF-IDF 不是指某一个特定的公式,而是表示了一系列基于基本 TF-IDF 方法变形(分别对 TF 和 IDF 这两部分进行处理)的公式的集合,上述公式是被多数系统证明比较有效的一个公式。
TF-IDF 表示文本
通过上面的介绍可以发现,每个文本中的每个关键词都有属于自己的 TF-IDF 值,所以我们的思路大致是:
1、获取关键词表;
2、计算每个关键词的 TF-IDF 值;
3、使用 TF-IDF 表示一个文本。
1、获取关键词表
现有两个文本 d1 和 d2,将所有文本分词后得到关键词表【A, B, C, D, E, F, G】。
2、计算每个关键词的 TF-IDF 值
文本 d1 关键词分布:【A, B, C, C, E, D, A, B, F, E, E, E, F, G, G】
文本 d2 关键词分布:【C, E, E, F, G, G, A, B, E, B】
关键词 t 在文档 d 中出现的次数如下:
d1 | d2 | |
---|---|---|
A | 2 | 1 |
B | 2 | 2 |
C | 2 | 1 |
D | 1 | 0 |
E | 4 | 3 |
F | 2 | 1 |
G | 2 | 2 |
词频矩阵如下:
d1 | d2 | |
---|---|---|
A | 0.13 | 0.10 |
B | 0.13 | 0.20 |
C | 0.13 | 0.10 |
D | 0.07 | 0.00 |
E | 0.27 | 0.30 |
F | 0.13 | 0.10 |
G | 0.13 | 0.20 |
然后再计算每个关键词对应的逆向文档频率即 IDF 的值。如下表所示:
ln | |
---|---|
A | 0.4 |
B | 0.4 |
C | 0.4 |
D | 1.1 |
E | 0.4 |
F | 0.4 |
G | 0.4 |
最后将正规化后的词频与IDF值相乘,结果如下:
d1 | d2 | |
A | 0.052 | 0.040 |
B | 0.052 | 0.080 |
C | 0.052 | 0.040 |
D | 0.077 | 0.000 |
E | 0.108 | 0.120 |
F | 0.052 | 0.040 |
G | 0.052 | 0.080 |
3、使用 TF-IDF 表示一个文本
使用TF-IDF表示文本其实就是个填表的过程,将每一个文本中的每一个关键词对应关键词表的索引进行填值。
关键词表【A, B, C, D, E, F, G】
文本 d1 的文本表示:[0.052, 0.052, 0.052, 0.077, 0.108, 0.052, 0.052]
文本 d2 的文本表示:[0.040, 0.080, 0.040, 0.000, 0.120, 0.040, 0.080]
代码实例
#!/usr/bin/env python
# coding: utf-8
"""
@Time: Created on 2021-02-23 | Updated on 2021-02-23
@Author: 小小磊
@Website:
@Description: 基于 TF-IDF 的文本表示。具体地,
1、获取关键词表;
2、计算每个关键词的 TF-IDF 值;
3、使用 TF-IDF 表示一个文本。;
"""
import jieba
import numpy as np
import math
class TfIdf(object):
"""基于 TF-IDF 的文本表示法"""
def __init__(self, corpus):
self.corpus = corpus
self.vocab = self.get_vocab()
def get_vocab(self):
"""获取关键词表"""
vocab = list()
for doc in self.corpus:
for w in jieba.lcut(doc):
if w not in vocab and len(w) > 1:
vocab.append(w)
return vocab
def get_tfidf(self, doc):
"""计算每个关键词的 TF-IDF 值,此处:
TFtd=Ftd/Sd,关键词 t 在文档 d 中的词频=关键词 t 在文档 d 中出现的次数/
所有关键词在文档 d 中出现的总次数,
IDFt=ln((1+|D|)/|Dt|),关键词 t 的逆向文档频率=ln((1+文档总数)/
包含关键词 t 的文档数量)。
"""
item_tfidf = dict()
word_list = [w for w in jieba.lcut(doc) if w in self.vocab]
word_set = set([w for w in word_list])
word_len = len(word_list)
corpus_len = len(self.corpus)
for word in word_set:
tf = word_list.count(word) / word_len
idf = math.log((1 + corpus_len) /
len([1 for doc in self.corpus
if word in jieba.lcut(doc)]))
item_tfidf[word] = tf * idf
return item_tfidf
def transform(self, item_tfidf):
"""使用 TF-IDF 表示一个文本"""
arr = list()
for w in self.vocab:
arr.append(item_tfidf.get(w, 0.0))
return np.array(arr).reshape([-1, len(self.vocab)])
def run(self, mode=1):
item_rst = dict()
array_rst = np.empty([0, len(self.vocab)])
for idx, doc in enumerate(self.corpus):
item_tfidf = self.get_tfidf(doc)
item_rst[idx] = item_tfidf
arr = self.transform(item_tfidf)
# arr /= np.sqrt(np.sum(np.power(arr, 2)))
# l2正则
array_rst = np.append(array_rst, arr, axis=0)
if mode == 0:
return item_rst
elif mode == 1:
return array_rst
if __name__ == '__main__':
text = ["教育、戏曲、悬疑、悬疑、科幻、军事、教育、戏曲、
动作、科幻、科幻、科幻、动作、资讯、资讯",
"悬疑、科幻、科幻、动作、资讯、资讯、教育、戏曲、科幻、戏曲"]
print(TfIdf(text).get_vocab())
print("n")
print(TfIdf(text).run(mode=0))
print("n")
print(TfIdf(text).run(mode=1))
['教育', '戏曲', '悬疑', '科幻', '军事', '动作', '资讯']
{0: {'军事': 0.07324081924454065, '动作': 0.05406201441442192, '悬疑': 0.05406201441442192, '科幻': 0.10812402882884384, '资讯': 0.05406201441442192, '戏曲': 0.05406201441442192, '教育': 0.05406201441442192}, 1: {'动作': 0.04054651081081644, '悬疑': 0.04054651081081644, '科幻': 0.12163953243244931, '资讯': 0.08109302162163289, '戏曲': 0.08109302162163289, '教育': 0.04054651081081644}}
[[0.05406201 0.05406201 0.05406201 0.10812403 0.07324082 0.05406201
0.05406201]
[0.04054651 0.08109302 0.04054651 0.12163953 0.
0.04054651
0.08109302]]
基于内容推荐
代码实例
#!/usr/bin/env python
# coding: utf-8
"""
@Time: Created on 2021-02-23 | Updated on 2021-02-23
@Author: 小小磊
@Description: 编写一个文章推荐系统,应用基于内容推荐算法解决问题。具体地,
1、给出物品表示 - 基于向量空间模型的方法,具体采用了基于 TF-IDF 的文本
表示法;
2、学习用户偏好 - 把用户所有喜欢的物品对应的向量的平均值作为此用户的
profile;
3、生成推荐列表 - 把候选物品里与此用户最相关(余弦相似度最大)的 N 个
物品推荐给此用户。
"""
import numpy as np
# ======================= 给出物品表示 =======================
# 候选文章对应的向量(可以采用上述基于 TF-IDF 的文本表示法获得)
opt_item = [[0.05406201, 0.05406201, 0.05406201, 0.10812403, 0.07324082, 0.05406201, 0.05406201],
[0.04054651, 0.08109302, 0.04054651, 0.12163953, 0.
, 0.04054651, 0.08109302]]
# ======================= 学习用户偏好 =======================
# 用户所有喜欢的文章对应的向量(可以采用上述基于 TF-IDF 的文本表示法获得)
saw_item = [[0.05406201, 0.05406201, 0.05406201, 0.10812403, 0.07324082, 0.05406201, 0.05406201],
[0.05406201, 0.05406201, 0.05406201, 0.10812403, 0.07324082, 0.05406201, 0.05406201]]
# 把用户所有喜欢的物品对应的向量的平均值作为此用户的 profile
user_profile = (np.array(saw_item[0]) + np.array(saw_item[1])) / 2
# ======================= 生成推荐列表 =======================
# 计算候选物品与此用户的余弦相似度
def cos_sim(a, b):
a_norm = np.linalg.norm(a)
b_norm = np.linalg.norm(b)
cos = np.dot(a,b)/(a_norm * b_norm)
return cos
cos1 = cos_sim(user_profile, opt_item[0])
cos2 = cos_sim(user_profile, opt_item[1])
print(cos1, cos2)
# 把候选物品里与此用户最相关(余弦相似度最大)的 N 个物品推荐给此用户
1.0 0.8830933645514039
END
公众号:TSGshare
欢迎留言批评指正!
最后
以上就是动人歌曲为你收集整理的实例-基于内容推荐实现过程基于 TF-IDF 的文本表示法基于内容推荐的全部内容,希望文章能够帮你解决实例-基于内容推荐实现过程基于 TF-IDF 的文本表示法基于内容推荐所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复