Press "Enter" to skip to content

推荐系统:实现文章相似推荐的简单实例

看了一篇文章实现了文章的内容相似度计算实现相似推荐,算法比较简单,非常适合我这种初学入门的人。

 

来自一篇英文文章: 地址

 

文章标题为:How to build a content-based movie recommender system with Natural Language Processing

 

文章的代码在: 地址

 

该文章实现相似推荐的步骤:

 

1、将CSV加载到pandas.pd

 

2、提取其中的标题、题材分类、导演、演员、情节描述4个字段;

 

3、将单词都变小写,人名中的空格合并(英文才需要这样);

 

4、题材分类、导演、演员这几个特征都是结构化的不需要处理;而标题、情节描述这类字段是长段文本,使用nltk库做关键词提取(如果是中文可以用jieba分词库也有关键词提取功能)

 

5、将第四步骤的分类、导演、演员、关键词列表,合并到一个词列表(这一处理其实暗含了分类、导演、演员三个特征和关键词一样重要,没有做加权处理)

 

6、使用CountVectorizer做每个词语的计数,得到了每个文章的向量;

 

7、使用sklearn的cosin做笛卡尔积的相似度计算;

 

8、计算结果是一个二维矩阵,按行查询某一个文章的推荐结果,按相似度值排序得到最相似的文章

 

从里面能学到不少知识的运用:

 

1、全流程用pandas运行,尤其是for each row,做单个列的各种map计算;

 

2、计算相似度时使用了多个特征,包括Title,Genre,Director,Actors,Plot,统一成一个bag of words参与计算

 

3、使用from sklearn.metrics.pairwise import cosine_similarity用于相似度计算;

 

4、使用from sklearn.feature_extraction.text import CountVectorizer用于单词计数;

 

5、使用from rake_nltk import Rake用于关键词提取;

 

代码实现关键部分:

 

作者用到的一些库:

 

import pandas as pd
from rake_nltk import Rake
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import CountVectorizer

 

pandas的dataframe中,直接替换一列的语法:

 

df['Director'] = df['Director'].map(lambda x: x.split(' '))

 

pd按行以此处理某个列的方法:

 

for index, row in df.iterrows():
    row['Actors'] = [x.lower().replace(' ','') for x in row['Actors']]
    row['Director'] = ''.join(row['Director']).lower()

 

pd.df删除某一列的方法:

 

df.drop(columns = ['Plot'], inplace = True)

 

pd.df从columns中提取一列作为index的方法:

 

df.set_index('Title', inplace = True)

 

作者将能使用的所有列,都放在了一个词包中用于相似度计算,按我的想法,这些特征列其实应该有不同的权重?

 

df['bag_of_words'] = ''
columns = df.columns
for index, row in df.iterrows():
    words = ''
    for col in columns:
        if col != 'Director':
            words = words + ' '.join(row[col])+ ' '
        else:
            words = words + row[col]+ ' '
    row['bag_of_words'] = words
    
df.drop(columns = [col for col in df.columns if col!= 'bag_of_words'], inplace = True)

 

sklearn使用词计数的调用:

 

count = CountVectorizer()
count_matrix = count.fit_transform(df['bag_of_words'])

 

sklearn实现矩阵相似度计算的方法:

 

# generating the cosine similarity matrix
cosine_sim = cosine_similarity(count_matrix, count_matrix)

 

怎样实现不同特征列的融合相似度计算?

 

这个问题纠结我很久,查询了一些文章,大都是人工指定加权权重,或者使用模型拟合权重值,没有多幺简单的方法,而作者使用的其实是直接把分类、演员等字段,和关键词直接融合的方法

 

作者在文章中提到一句话:

 

I decided to use CountVectorizer
rather than  TfIdfVectorizer
for one simple reason: I need a simple frequency counter for each word in my  bag_of_words
column. Tf-Idf tends to give less importance to the words that are more present in the entire corpus (our whole column, in this case) which is not what we want for this application,
because every word is important to detect similarity

!

 

对于标题、介绍这种纯文本内容,我们可以用TF/IDF提取关键词,物理含义就是降低全局出现的词频很多的词语;但是其实对于作者、演员、题材这类特征列,他们并不需要降低全局词频,使用词频计数即可。

 

有哪些可以提升的地方

 

作者的方法确实可以实现相似推荐,不过我感觉有一些可以提升的地方:

 

1、标题、简介,提取关键词后,可以查询业界的word2vec做向量扩展,这样能实现恰恰和伦巴舞这类词语的相似度度量,直接的关键词查询是得不到这样的信息;

 

2、分类、导演、演员这三个特征,需要和描述得到的关键词区分开,可以用加权的方法进行,按照产品的需求,加重分类、导演的相似度权重,降低演员、关键词的权重等,如果需要可以从点击率等出发,用模型计算这些权重;

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注