基于知识的推荐系统(案例学习)

1. 简单的流程

knowledge-based推荐系统没有考虑特殊用户的偏好;也没有尝试去推断不同电影之间的相似性。以Internet Movie Database (IMDB)为例,基本流程可以概述为:

  • 选择度量(或评分标准)为电影打分
  • 决定电影在排行榜上出现的先决条件
  • 计算每一部满足条件的电影的得分
  • 按照分数的递减顺序输出电影列表

2. 度量 metric

以电影推荐为例:如果一部电影的评分高于另一部电影,那么它就被认为比另一部电影更好。鲁棒而可靠的度量标准对于电影评分来说非常重要,是影响推荐结果的关键。

度量的选择可以是任意的。例如,最简单的指标之一是电影评分。然而,这也有许多缺点。首先,电影评分不考虑电影的受欢迎程度。因此,一部被10万用户评为9.0级的电影将低于一部被100用户评为9.5级的电影。这是不可取的,因为一部只有100人观看和评分的电影很有可能迎合(cater to...)一个非常特殊的细分市场(a very specific niche),对普通人的吸引力不如前者大。众所周知,随着投票者人数的增加,一部电影的评分具有一定的“权威性”,并且可以反映电影质量和大众化的价值。换句话说,评分很低的电影并不十分可靠。一部由五位用户评为10/10的电影并不一定意味着它是一部好电影。因此,我们需要的是一个能够在某种程度上考虑电影评分和它获得的投票数的指标。这将使10万人观看的大片(评分8)比100人观看的艺术片(评分9)更受欢迎。这里,将直接使用IMDB的加权评分公式作为度量

  • v是电影获得的票数
  • m是电影在图表中所需的最小投票数(前提条件)
  • R是电影的平均得分
  • C是数据库中所有电影的平均得分

3. 先决条件 Prerequisties

在上面公式中,m明显是先决条件,也就是说,只有投票数超过一定阈值的电影才有可能参与最终评分的计算。

和度量一样,m值的选择也是任意的。换言之,m没有统一的取值原则。最好先尝试m的不同取值,然后选择能给出最佳推荐结果对应的m值。唯一需要记住的是,m值越高,对电影受欢迎程度的强调越高,因此被选择的概率越高。

对于此处的推荐系统设计,我们将使用第80百分位电影获得的票数作为m的值。换句话说,对于要在排名中考虑的电影,它必须获得超过我们数据集中存在的电影的至少80%的选票。此外,第80百分位电影获得的选票用前面描述的加权公式计算分数值。

import pandas as pd
import numpy as np
df = pd.read_csv('C:/Users/Administrator/Desktop/RecoSys/data/movies_metadata.csv')
m = df['vote_count'].quantile(0.80)
print(m)
>>> 50.0

另一个先决条件是电影的持续时间。这里只考虑长度大于45分钟小于300分钟的电影。因此,定义一个新的DataFrame,用它保存所有满足条件的电影列表。

q_movie = df[ (df['runtime'] >= 45) & (df['runtime'] <= 300) ]
q_movie = q_movie[ q_movie['vote_count'] >= m ]
print(q_movie.shape)
>>> (8963, 24)

4. 计算得分 Score

在计算最终电影分数之前,需要计算最后一个值是C(数据集中所有电影的平均评分):

C = df[ 'vote_average' ].mean()
print(C)
>>> 5.618207215133889

因此,我们可以根据上面的公式,对于满足先决条件的电影计算得分:

def weighted_rating(x, m=m, C=C):
    v = x[ 'vote_count' ]
    R = x[ 'vote_average' ]
    return ( v/(v+m) * R ) + (m/(v+m) * C)

q_movie['score'] = q_movie.apply(weighted_rating, axis = 1)
print(q_movie['score'].head(5))

>>>
0    7.680953
1    6.873979
2    6.189510
4    5.681661
5    7.646235
Name: score, dtype: float64

5. 排序和输出 Sorting and Output

q_movie = q_movie.sort_values('score', ascending=False)
q_movie[['title', 'vote_count', 'vote_average', 'score', 'runtime']].head(10)

6. 总结与提升

在推荐系统设计中,往往还需要人机交互的功能。在前面设计基础上,需要执行以下任务:

  • 向用户询问他/她正在寻找的电影类型
  • 向用户询问电影的持续时间
  • 向用户询问推荐的电影时间表
  • 使用收集的信息,向用户推荐具有高评分(根据IMDB公式)且满足上述条件的电影

查看原始数据集中包含的所有的特征:

import pandas as pd
import numpy as np
df = pd.read_csv('C:/Users/Administrator/Desktop/RecoSys/data/movies_metadata.csv')
df.columns
>>> 
Index(['adult', 'belongs_to_collection', 'budget', 'genres', 'homepage', 'id',
       'imdb_id', 'original_language', 'original_title', 'overview',
       'popularity', 'poster_path', 'production_companies',
       'production_countries', 'release_date', 'revenue', 'runtime',
       'spoken_languages', 'status', 'tagline', 'title', 'video',
       'vote_average', 'vote_count'], dtype='object')

削减DataFrame,使得新的数据结构仅仅包括我们需要的特征:

df = df[ ['title','genres', 'release_date', 'runtime', 'vote_average', 'vote_count'] ]
df.head()

从release_date特征中提取出year,并且提出year特征中的异常值(NAN):

# convert release_date into pandas datetime format
df['release_date'] = pd.to_datetime(df['release_date'], errors = 'coerce')
# Extract year from datetime
df['year'] = df['release_date'].apply(lambda x: str(x).split('-')[0] if x != np.nan else np.nan)

# conver object to int; and convert NAT to 0
def convert_int(x):
    try:
        return int(x)
    except:
        return 0
    
df['year'] = df['year'].apply(convert_int)
df['year']

有了year特征,就不在需要release_date特征了,因此删除:

df = df.drop('release_date', axis=1)
df.head(5)

从上面图我们可以看出来,genres特征并不满足交互处理的需求,首先看一下genres特征的内容:

type(df.iloc[0]['genres'])
print(df.iloc[0]['genres'])
>>>
str
[{'id': 16, 'name': 'Animation'}, {'id': 35, 'name': 'Comedy'}, {'id': 10751, 'name': 'Family'}]

我们可以观察到输出是一个字符串化的字典。为了使这个特性可用,我们必须将这个字符串转换成一个Python字典。幸运的是,python允许我们访问一个名为literal_eval(在ast库中可用)的函数,它正好做到了这一点。literal_eval解析传入它的任何字符串,并将其转换为相应的python对象。此外,应该注意的是,上面的genre输出包括了id和name两个要素。在我们实际应用上,我们仅仅需要name属性:

from ast import literal_eval

#Convert all NaN into stringified empty lists
df['genres'] = df['genres'].fillna('[]')
#Apply literal_eval to convert to the list object
df['genres'] = df['genres'].apply(literal_eval)
#Convert list of dictionaries to a list of strings
df['genres'] = df['genres'].apply(lambda x: [i['name'] for i in x] if isinstance(x,list) else [])
df.head()

如果电影有多个流派,我们将创建该电影的多个副本,每个电影都有一个流派。例如, 电影Just Go With It 具有 romance 和
comedy 属性, 这时候我们需要把它拆分成两行: 一行是 Just Go With It (具有romance属性);另一行是 Just Go With It (具有comedy 属性)。

#Create a new feature by exploding genres
s = df.apply(lambda x: pd.Series(x['genres']),axis=1).stack().reset_index(level=1,drop=True)
#Name the new feature as 'genre'
s.name = 'genre'
#Create a new dataframe gen_df which by dropping the old 'genres' feature and adding the new 'genre'.
gen_df = df.drop('genres', axis=1).join(s)
gen_df.head()

这样,原始的DataFrame经过数据清洗后,就很方便进行推荐系统设计了。

===========================================================================================

设计人机交互式推荐系统功能,需要满足三个功能子模块:

  • 获得用户偏好的输入
  • 提取电影库中所有与用户偏好相关的电影
  • 利用前面的方法反馈推荐结果
def build_RecSys(gen_df, percentile=0.8):
    print("Input preferred genre")
    genre = input()
    print("Input shortest duration")
    low_time = int(input())
    print("Input longest duration")
    high_time = int(input())
    print("Input earliest year")
    low_year = int(input())
    print("Input latest year")
    high_year = int(input())

    movies = gen_df.copy()
    movies = movies[(movies['genre'] == genre) & 
                    (movies['runtime'] >= low_time) & (movies['runtime'] <= high_time) & 
                    (movies['year'] >= low_year) &(movies['year'] <= high_year)]
    C = movies['vote_average'].mean()
    m = movies['vote_count'].quantile(percentile)
    q_movies = movies.copy().loc[movies['vote_count'] >= m]
    q_movies['score'] = q_movies.apply(lambda x: (x['vote_count']/(x['vote_count']+m) * x['vote_average'])
                                       + (m/(m+x['vote_count']) * C),axis=1)
    q_movies = q_movies.sort_values('score', ascending=False)
    
    return q_movies

测试结果:

 

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
机器学习是人工智能及模式识别领域的共同研究热点,其理论和方法已被广泛应用于解决工程应用和科学领域的复杂问题。2010年的图灵奖获得者为哈佛大学的Leslie vlliant教授,其获奖工作之一是建立了概率近似正确(Probably Approximate Correct,PAC)学习理论;2011年的图灵奖获得者为加州大学洛杉矶分校的Judea Pearll教授,其主要贡献为建立了以概率统计为理论基础的人工智能方法。这些研究成果都促进了机器学习的发展和繁荣。 [2] 机器学习是研究怎样使用计算机模拟或实现人类学习活动的科学,是人工智能中最具智能特征,最前沿的研究领域之一。自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到应用,而且在自然语言理解、非单调推理、机器视觉、模式识别等许多领域也得到了广泛应用。一个系统是否具有学习能力已成为是否具有“智能”的一个标志。机器学习的研究主要分为两类研究方向:第一类是传统机器学习的研究,该类研究主要是研究学习机制,注重探索模拟人的学习机制;第二类是大数据环境下机器学习的研究,该类研究主要是研究如何有效利用信息,注重从巨量数据中获取隐藏的、有效的、可理解的知识。 [2] 机器学习历经70年的曲折发展,以深度学习为代表借鉴人脑的多分层结构、神经元的连接交互信息的逐层分析处理机制,自适应、自学习的强大并行信息处理能力,在很多方面收获了突破性进展,其中最有代表性的是图像识别领域。
毕业设计是高等教育阶段学生在完成学业前所进行的一项重要学术任务,旨在检验学生通过学习所获得的知识、技能以及对特定领域的深刻理解能力。这项任务通常要求学生运用所学专业知识,通过独立研究和创新,完成一个实际问题的解决方案或者开展一项有价值的项目。 首先,毕业设计的选择通常由学生根据个人兴趣、专业方向以及实际需求来确定。学生需要在导师的指导下明确研究目标、问题陈述,确立研究的范围和深度。毕业设计可以包括文献综述、需求分析、方案设计、实施与测试等多个阶段,以确保整个过程的科学性和系统性。 其次,毕业设计的完成通常需要学生具备一定的独立思考和解决问题的能力。在研究过程中,学生可能需要采用各种研究方法,如实验、调查、案例分析等,以获取必要的数据和信息。通过这些活动,学生能够培养扎实的专业技能,提升解决实际问题的实际能力。 第三,毕业设计的撰写是整个过程的重要组成部分。学生需要将研究过程、方法、结果以及结论等详细记录在毕业论文中,以展示其研究的全貌和成果。同时,撰写毕业设计还有助于提高学生的学术写作水平,培养清晰、逻辑的表达能力。 最后,毕业设计的评价通常由导师和相关专业人士进行。评价标准包括研究的创新性、实用性、方法的科学性以及论文的质量等方面。学生在毕业设计中获得的成绩也将直接影响其最终的学业成绩和学位授予。 总的来说,毕业设计是高等教育中的一项重要环节,通过此过程,学生不仅能够巩固所学知识,还能培养独立思考和解决问题的能力,为将来的职业发展奠定坚实的基础。
Dendral专家系统是上世纪60年代和70年代开发的一个早期机器学习项目。该系统最初是由斯坦福大学的Edward Feigenbaum教授和Joshua Lederberg等科学家开发的,目的是用人工智能技术模拟有机化合物的确定结构。 Dendral专家系统是通过对化学家分析问题和解决问题的方法和技巧进行建模,从而实现机器自动分析和解决化学问题。它通过推理和搜索技术,结合大量的化学知识和规则,来识别和描述化合物的结构。 为了实现这一目标,Dendral系统利用了化学家专门训练的数据集,以及构建了一个基于逻辑的知识库。该系统使用的算法基于规则和约束,以确定每个化合物中的原子数量、类型和连接方式。 Dendral系统是一个非常重要的专家系统案例,它为计算机科学和人工智能领域的发展做出了巨大贡献。它的成功证明了专家系统在解决复杂问题方面的潜力,也为之后的机器学习知识推理技术的发展奠定了基础。 然而,由于Dendral系统的设计是基于特定的化学知识和规则,所以其在应用范围上存在一定的局限性。随着时间的推移,专家系统的发展也逐渐朝着更加灵活和泛化的方向发展,不再仅限于特定领域的问题。 总的来说,Dendral专家系统是一个标志性的案例,它证明了在特定领域中,专家系统可以通过模拟专家的思维过程,实现类似专家的判定和推理能力。它对于人工智能和机器学习领域的进步具有重要的指导意义。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值