# 人人汽车推荐系统调研综述

## 下面是一个初步的推荐算法引擎，只使用了科学计算包numpy和基于numpy的数据处理的包pandas。基于协同过滤算法，后面会考虑使用tensorflow surprise python-recsys等框架提供的SVD、余弦相似度算法和深度学习神经网络开发更多推荐引擎。

In [2]:
import numpy as np
import pandas as pd
import os
# 使用pandas加载csv数据

# 去掉无用的维度
ratings.drop(['timestamp'],axis=1,inplace=True)

Out[2]:
movieId title genres
0 1 Toy Story (1995) Adventure|Animation|Children|Comedy|Fantasy
2 3 Grumpier Old Men (1995) Comedy|Romance
3 4 Waiting to Exhale (1995) Comedy|Drama|Romance
4 5 Father of the Bride Part II (1995) Comedy

In [3]:

Out[3]:
userId movieId rating
0 1 31 2.5
1 1 1029 3.0
2 1 1061 3.0
3 1 1129 2.0
4 1 1172 4.0

In [4]:
# 将movieid替换为moviename
def replace_name(x):
return movies[movies["movieId"]==x].title.values[0]

ratings.movieId = ratings.movieId.map(replace_name)

In [5]:

Out[5]:
userId movieId rating
0 1 Dangerous Minds (1995) 2.5
1 1 Dumbo (1941) 3.0
2 1 Sleepers (1996) 3.0
3 1 Escape from New York (1981) 2.0

In [6]:
# 建立一个透视表
M = ratings.pivot_table(index=['userId'],columns=['movieId'],values='rating')

In [7]:
# 当前维度
M.shape

Out[7]:
(671, 9064)

In [8]:
# M是一个非常稀疏的透视表
M

Out[8]:
movieId "Great Performances" Cats (1998) \$9.99 (2008) 'Hellboy': The Seeds of Creation (2004) 'Neath the Arizona Skies (1934) 'Round Midnight (1986) 'Salem's Lot (2004) 'Til There Was You (1997) 'burbs, The (1989) 'night Mother (1986) (500) Days of Summer (2009) ... Zulu (1964) Zulu (2013) [REC] (2007) eXistenZ (1999) loudQUIETloud: A Film About the Pixies (2006) xXx (2002) xXx: State of the Union (2005) ¡Three Amigos! (1986) À nous la liberté (Freedom for Us) (1931) İtirazım Var (2014)
userId
1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
5 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
6 NaN NaN NaN NaN NaN NaN NaN 4.0 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
7 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
8 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
9 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
10 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
11 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
12 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
13 NaN NaN NaN NaN NaN NaN NaN NaN NaN 4.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
14 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
15 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN 3.0 NaN 1.0 NaN 4.0 NaN NaN
16 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
17 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN 5.0 NaN NaN NaN NaN NaN NaN
18 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
19 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
20 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
21 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
22 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
23 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN 4.0 NaN NaN NaN NaN NaN NaN
24 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
25 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
26 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
27 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
28 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
29 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
30 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
642 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
643 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
644 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
645 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
646 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN 4.0 NaN NaN
647 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
648 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
649 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
650 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
651 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
652 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN 5.0 NaN NaN NaN NaN NaN NaN
653 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
654 NaN NaN NaN NaN NaN NaN NaN 4.0 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN 4.5 NaN NaN
655 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
656 NaN NaN NaN NaN NaN NaN 4.0 NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
657 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
658 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
659 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
660 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
661 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
662 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
663 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
664 NaN NaN NaN NaN NaN NaN NaN NaN NaN 3.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
665 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
666 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
667 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
668 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
669 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
670 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
671 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

671 rows × 9064 columns

# 核心算法方面使用皮尔逊的R来计算距离

### 上式定义了总体相关系数，常用希腊小写字母 ρ (rho) 作为代表符号。估算样本的协方差和标准差，可得到样本相关系数(样本皮尔逊系数)，常用英文小写字母 r 代表：

In [14]:
# 算法实现
def pearson(s1, s2):
s1_c = s1 - s1.mean()
s2_c = s2 - s2.mean()
#     print(f"s1_c={s1_c}")
#     print(f"s2_c={s2_c}")
denominator = np.sqrt(np.sum(s1_c ** 2) * np.sum(s2_c ** 2))
if denominator == 0:
return 0
return np.sum(s1_c * s2_c) / denominator

### 算法引擎2可以考虑比较文本相似度的余弦相似性算法，这也是推荐系统常用的算法。其中，打分被看成n维空间中的向量，而相似性是基于这些向量之间的角度进行计算的。可以使用sklearn的pairwise_distances函数来计算余弦相似性。注意，输出范围从0到1，因为打分都是正的。

In [15]:
# 永不妥协   碟中谍2
pearson(M['Erin Brockovich (2000)'],M['Mission: Impossible II (2000)'])
# 永不妥协  指环王
# pearson(M['Erin Brockovich (2000)'],M['Fingers (1978)'])
# 永不妥协 哈利波特与密室
# pearson(M['Erin Brockovich (2000)'],M['Harry Potter and the Chamber of Secrets (2002)'])
# 哈利波特与密室  哈利波特与阿兹卡班的囚徒
# pearson(M['Harry Potter and the Chamber of Secrets (2002)'],M['Harry Potter and the Prisoner of Azkaban (2004)'])

Out[15]:
0.070185736110215988

In [16]:
def get_recs(movie_name, M, num):
reviews = []
for title in M.columns:
if title == movie_name:
continue
cor = pearson(M[movie_name], M[title])
if np.isnan(cor):
continue
else:
reviews.append((title, cor))
reviews.sort(key=lambda tup: tup[1], reverse=True)
return reviews[:num]

In [22]:
# %%time
recs = get_recs('Clerks (1994)', M, 10)
recs[:10]

Out[22]:
[('Go Fish (1994)', 0.3873045237464075),
('Chasing Amy (1997)', 0.37484047898675804),
('Audrey Rose (1977)', 0.36586597215212963),
("Razor's Edge, The (1984)", 0.36586597215212957),
('Trekkies (1997)', 0.35608001316844984),
('Everything Must Go (2010)', 0.34925991438868215),
('Out of Sight (1998)', 0.33809493392702311),
('Haunting, The (1963)', 0.33177831773334998),
('Barefoot in the Park (1967)', 0.33153641267942063),
('Flawless (1999)', 0.32978207127880155)]

In [23]:
# %%time
anti_recs = get_recs('Clerks (1994)', M, 8551)
anti_recs[-10:]

Out[23]:
[('Enron: The Smartest Guys in the Room (2005)', -0.22634116531793105),
('Shot in the Dark, A (1964)', -0.22997876750526428),
('Boyhood (2014)', -0.23082944937869748),