2022.08.01开启新的一章!
2022.08.02继续学习
2022.08.04继续学习
2022.08.05继续学习
2022.08.06收工!去学下一章!
假设我们有一个网站或者公司出售或者出租电影和其它东西,像亚马逊、Netflix,还有 iTunes(感觉他整个公司都能算例子),假设我们让我们的用户评价不同的电影,用 1 到 5 星级评级,所以用户可能会评定一星、二星、三星、四星或五星,为了让这个例子更好理解一些,我们将允许评级为 0 到 5 星,因为这会使得数学运算变得更加简单,虽然大多数网站使用 1 星到 5 星。

在这里,有 5 部电影(上图),分别是 Love at last(《终末之爱》)、Romance forever(《永恒浪漫》)、Cute puppies of love(《爱情傻狗》)、Nonstop car chases(《无尽车战》)、Swords vs. karate(《剑·空手道》)(应该都是杜撰的电影,顺手意译一下,XD)。并且有 4 个用户,他们分别是 Alice、Bob、Carol 和 Dave,名字的首字母分别是 A、B、C、D,我们称呼他们用户 1、2、3 和用户 4。假设 Alice 非常喜欢 Love at last,给其 5 星好评,并且也给 Romance forever 5星好评,她没有看过 Cute puppies of love,故没有进行评价,因此我们没有他的评分,Alice 并不喜欢 Nonstop car chases 和 Swords vs. karate,故都给出了 0 分的评价;另一个用户 Bob(用户 2),可能对其他电影进行评级,他可能喜欢 Love at last ,并没有看过 Romance forever 剩下的三个分别给出了 4 星、0 星、0 星;对于第三个用户,他的评级为 0 星、没看过、0 星、5 星、5 星;四号用户随便填几个。
下面来介绍一些符号,这些符号我们接下来都会用到:
n
u
=
n
o
.
u
s
e
r
s
n
m
=
n
o
.
m
o
v
i
e
s

对于这个例子,比如我们有 3 部爱情片(或者成为爱情喜剧片)(上图左绿框中内容),有 2 部动作片(上图左红框圈出)。如果你观察这个例子,你就会发现 Alice 和 Bob 给这些爱情片很高的评价(上图中绿框),给了动作片很低的评价(上图中红框),而对于 Carol 和 Dave,评价恰好相反, Carol 和 Dave(用户 3 和用户 4)比较喜欢动作片(上图右红框),并给了它们较高的星级,但他们不喜欢爱情片(上图右绿框)。
具体来说,在推荐系统的问题中,给定以下数据,我们的数据组成如下:
r
(
i
,
j
)
=
1
i
f
u
s
e
r
j
h
a
s
r
a
t
e
d
m
o
v
i
e
i
y
(
i
,
j
)
=
r
a
t
i
n
g
g
i
v
e
n
b
y
u
s
e
r
j
t
o
m
o
v
i
e
i
(
d
e
f
i
n
e
d
o
n
l
y
i
f
r
(
i
,
j
)
=
1
)
我们有一种值 r(i,j),当 r(i,j) = 1 时,代表用户 j 给电影 i 进行了评分,用户仅仅评价了一部分电影(即有一些电影我们没有获得该用户的评价);当 r(i,j) = 1,也就是当用户 i 对电影 j 进行评分后,我们会得到一个值 y(i,j),它表示用户 j 对电影 i 所给出的评分,因此 y(i,j) 是用从 0 到 5 的数字表示的,而这些具体的数值则取决于用户对电影进行的 0 到 5 星评级,因此推荐系统的问题是给出了 r(i,j) 和 y(i,j) 数据,然后去查找那些没有被评级的电影,并试图预测这些电影的评价星级。在这个特殊的例子中,只有较少的电影以及少量用户数量,因此大多数用户都对大多数电影进行了评价,但在现实情况中,每个用户可能仅评价我们所有电影中的一小部分。
观察这些数据,如果 Alice 和 Bob 都喜欢爱情片,我们就可以假设 Alice 会给 Cute puppies of love 评价 5 星,Bob 或许会给 Romance forever 评价 4.5 星,或者是更高的星级,并且我们认为 Carol 和 Dave 可能给爱情片非常低的评价,如果 Dave 真的喜欢动作片,那么他可能会给 Swords vs. karate 评价 4 星或者 5 星。
因此,如果我们想开发一个推荐系统,那我们的工作就是想出一个学习算法,一个能自动为我们填补这些缺失值的算法,这样我们就可以看一下该用户还有哪些电影没看过,并推荐新电影给该用户,我们可以去预测什么是用户会感兴趣的内容。
这是推荐系统问题的主要形式,下一节中我们将开发一个学习算法来解决这个问题。
这是之前的一个数据集:

回顾一下之前的符号,我们使用 nu 表示用户的数量,在这里 nu = 4,同时 nm 表示电影的数量,在这里 nm = 5。那么怎样才能预测这些未知量(上图粉色圆圈圈出部分)的值呢?假设对于每一部电影,我们都有一个对应的特征集,特别的,我们假设每一个电影都有两个特征,我们用 x1 和 x2 来表示,其中 x1 衡量一部电影为爱情片的程度,x2 来衡量一部电影为动作片的程度。
举个例子,第一部电影 Love at last ,他为爱情片的程度是 0.9,这是一部纯爱情片,而它为动作片的程度是 0,所以这部电影几乎没有动作片剧情,而第二部电影 Romance forever 的爱情片程度为 1.0,包含大量爱情内容和 0.01 的动作内容,这 0.01 的动作成分大概是因为这部电影里有一起小型车祸(韩剧无疑)或者其他因素;Swords vs. karate 的爱情片程度为 0,没有任何爱情成分但有大量的动作成分,而 Nonstop car chases 这部电影里可能有一点点爱情成分,但主要的是动作成分,而电影 Cute puppies of love 又是一部没有动作成分的爱情片。
所以如果我们有类似这样的特征,那么每部电影就可以用一个特征向量来表示,比如说第一个电影有两个特征值 0.9 和 0,这两个特征值就是 x1 和 x2 的值。和往常一样,我们再加一个额外特征,称为截距特征 x0,它的值是 1。然后把这些整理在一起,我们有一个特征量 x(1)(下式),上标 1 表示它是电影 1 的特征向量,这个特征向量的第一个元素是 1,也就是 x0,然后是两个特征量 0.9 和 0。
x
(
1
)
=
[
1
0.9
0
]
因此,对于 Love at last 我们会有一个特征向量 x(1),对于电影 Romance forever,我们会有单独的特征量 x(2),以此类推,对于 Sword vs. karate 我们有单独的特征向量 x(5),并且,与之前用的符号相同,我们用 n 来表示特征数量,不包括 x0 这项,所以 n = 2,因为我们有两个特征量 x1 和 x2 来表示每部电影里的爱情程度和动作程度。
F
o
r
e
a
c
h
u
s
e
r
j
,
l
e
a
r
n
a
p
a
r
a
m
e
t
e
r
θ
(
j
)
∈
R
3
(
θ
(
j
)
∈
R
n
+
1
,
n
=
2
)
.
P
r
e
d
i
c
t
u
s
e
r
j
a
s
r
a
t
i
n
g
m
o
v
i
e
i
w
i
t
h
(
θ
(
j
)
)
T
x
(
i
)
s
t
a
r
s
.
现在为了作出预测,我们可以把每个用户的评价预测值看做是一个线性回归问题。特别规定,对于每一个用户 j,我们要学习参数向量 θ(j),它是一个 3 维向量,通常来说,θ(j) 是 n + 1 维的,其中 n 是特征的数量,不包括 x0 这一项,然后我们要预测用户 j 评价电影 i 的值,也就是参数向量 θ 与特征量 x(i) 的内积。
举一个特殊的例子,比如说用户 1,也就是 Alice,与 Alice 相关的是某个参数向量 θ(1),第二个用户是 Bob 就和另一个参数向量 θ(2) 相关,Carol 将会和参数向量 θ(3) 相关,Dave 和参数 θ(4)相关。假如我们想预测 Alice 对电影的评价,那么那部电影就会有某个参数向量 x(3)(下式),对于这个例子,假设我们用某种方式得到了 Alice 的参数向量 θ(1),我们之后会详细说明我们是怎么得到这个参数向量的。
x
(
3
)
=
[
1
0.99
0
]
θ
(
1
)
=
[
0
5
0
]
(
θ
(
1
)
)
T
x
(
3
)
=
5
×
0.99
=
4.95
现在我们先假设我们用某个学习算法学习出了参数向量 θ(1),并且它等于 [0;5;0](上式),所以我们对于 Alice 对 Cute puppies of love 的评分的预测,就会等于是 θ(1) 的转置(Alice 的参数向量的转置)再乘以 x(3)(Cute puppies of love 的特征向量),于是,这两个向量的内积是 4.95(上式),因此我们对上图第一个粉圈位置的值的预测就会是 4.95,它看起来是个合理的值。所以我们这里的操作是对每一个用户应用了不同的线性回归的副本,假如说 Alice 有参数向量 θ(1),我们用它来预测她的评价,并表示成一个方程,表示电影包含爱情和动作的程度,并且 Bob、Carol 和 Dave 他们每个人都有一个不同的线性方程来表示电影包含爱情成分的程度和包含动作成分的程度,这就是我们预测评价的方法。
更正式一些,我们把具体问题写出来:
Problem
formulation
Ⅰ
r
(
i
,
j
)
=
1
i
f
u
s
e
r
h
a
s
r
a
t
e
d
m
o
v
i
e
i
(
0
o
t
h
e
r
w
i
s
e
)
y
(
i
,
j
)
=
r
a
t
i
n
g
b
y
u
s
e
r
j
o
n
m
o
v
i
e
i
(
i
f
d
e
f
i
n
e
d
)
Ⅱ
θ
(
j
)
=
p
a
r
a
m
e
t
e
r
v
e
c
t
o
r
f
o
r
u
s
e
r
j
x
(
i
)
=
f
e
a
t
u
r
e
v
e
c
t
o
r
f
o
r
m
o
v
i
e
i
F
o
r
u
s
e
r
j
,
m
o
v
i
e
i
,
p
r
e
d
i
c
t
e
d
r
a
t
i
n
g
:
(
θ
(
j
)
)
T
(
x
(
i
)
)
Ⅲ
m
(
j
)
=
n
o
.
o
f
m
o
v
i
e
s
r
a
t
e
d
b
y
u
s
e
r
j
T
o
l
e
a
r
n
θ
(
j
)
:
min
θ
(
j
)
1
2
m
(
j
)
∑
i
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
2
+
λ
2
m
(
j
)
∑
k
=
1
n
(
θ
k
(
j
)
)
2
如果用户 j 评价了电影 i,我们就将 r(i,j) 记为 1,而 y(i,j) 是对该电影的评价,如果评价存在的话(即该用户评价过该电影)。
在前面的小节里我们也定义了 θ(j),它是每个用户 x(i) 的一个参数,而 x(i) 是特定电影的一个特征向量,对于每一个用户和电影,我们会进行这样的预测(上式Ⅱ)。
我们暂时介绍一下这个新的标记 m(j)(上式Ⅲ),我们用 m(j) 表示评价了电影 j 的用户数量(我们仅在本小节使用该符号)。为了学习参数向量 θ(j),我们该怎么做呢?这是一个基本的线性回归问题,我们可以直接选择一个参数向量 θ(j),那么这里的预测值会尽可能接近我们在训练集中观察的值。
为了学习参数向量 θ(j),我们来最小化参数向量各个 θ(j) 的和,我们要把用户 j 所评价的所有电影进行求和,写出来就是: ∑i:r(i,j)=1(上式Ⅲ绿色部分),这个求和式读起来就是:对所有的 i 值求和,所以 r(i,j) 等于 1。这样就是对所有用户 j 评价的所有电影求和。
然后我们要计算 θ(j) 的转置乘以 x(i) ,所以这就是用户 j 对电影 i 评价的预测值,减去 y(i,j),这就是实际观测值的平方。接着我们在除以用户 j 的评价过的电影数量,也就是 1 / (2m(i)),这像是最小平方回归,就像线性回归,我们选择参数向量 θ(j),来最小化这种方差项,并且如果我们想的话,我们也可以加入一个正则化项(上式Ⅲ蓝色部分),在末尾加上 λ / 2m(j) ,因为我们有 m(j) 个样本,因为如果用户 j 评价了许多电影,这有点像我们有许多数据点来对应参数 θ(j),接着我们在这里加入我们的正则化项的剩余部分,通常这个求和项是从 k = 1 加到 n 的,所以这里 θ(j) 就会是一个 n + 1 维的向量(在之前的例子里 n 等于 2,这里指的是一般情况,n 是每个电影所拥有的特征数量)。通常我们不会对 θ(0) 进行正则化(不对偏执单元进行正则化),因为和是从 k = 1 到 n 的。
如果我们将 θ(j) 这个公式最小化,我们会得到一个好的结果,会得到一个相当好的对参数向量 θ(j) 的估计值,用来对用户 j 的电影评价做预测。对于推荐系统,我们会将这个符号稍微改动一下,简化之后的数学公式,我们将去掉 m(j) 这项(上式Ⅲ标红部分),这只是一个常数,我们可以删掉它而不会改变 θ(j) 的值,所以我们把它从优化过程中去掉,如果我们总体地看一下整个表达式,把他乘以 m(j) ,这样就去掉了这个常数,当我们最小化它时,我们仍然能得到和之前一样的 θ(j) 的值。
Optimization
objective:
T
o
l
e
a
r
n
θ
(
j
)
(
p
a
r
a
m
e
t
e
r
f
o
r
u
s
e
r
j
)
:
min
θ
(
j
)
1
2
∑
i
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
2
+
λ
2
∑
k
=
1
n
(
θ
k
(
j
)
)
2
T
o
l
e
a
r
n
θ
(
1
)
,
θ
(
2
)
,
.
.
.
,
θ
(
n
u
)
min
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
1
2
∑
j
=
1
n
u
∑
i
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
2
+
λ
2
∑
j
=
1
n
u
∑
k
=
1
n
(
θ
k
(
j
)
)
2
Optimization
algorithm:
min
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
1
2
∑
j
=
1
n
u
∑
i
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
2
+
λ
2
∑
j
=
1
n
u
∑
k
=
1
n
(
θ
k
(
j
)
)
2
G
r
a
d
i
e
n
t
d
e
s
c
e
n
t
u
p
d
a
t
e
:
θ
k
(
j
)
:
=
θ
k
(
j
)
−
α
∑
i
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
x
k
(
i
)
(
f
o
r
k
=
0
)
θ
k
(
j
)
:
=
θ
k
(
j
)
−
α
(
∑
i
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
x
k
(
i
)
+
λ
θ
k
(
j
)
)
(
f
o
r
k
≠
0
)

这是之前的数据集,我们假定每一部电影都有一些人来评价并告诉我们这部电影爱情的程度是多少,又包含多少动作成分,但是想一下就知道,很难去花费时间以及花钱让每个人都实际地看完每一部电影后告诉你这部电影包含多少爱情,包含多少动作,而且我们通常还想要这两个特征之外的其它特征,那么该怎样得到这些特征呢?
我们先换个问题,假如我们有一个数据集,但我们不知道这些特征的值是多少,比如我们得到一些关于电影的数据,不同用户对电影的评分,也不知道每部电影的爱情指数以及每部电影的动作指数,所以我们把这些东西都换成问号。

现在我们稍微改变一下这个假设,假设我们采访了每一位用户,而且每一位用户都告诉我们他们喜欢爱情电影的程度以及喜欢动作电影的程度。这样 Alice 就有了对应的参数 θ(1),Bob 的是 θ(2),Carol 的是 θ(3) ,Dave 的是 θ(4) ,对应如下的四个向量:
θ
(
1
)
=
[
0
5
0
]
θ
(
2
)
=
[
0
5
0
]
θ
(
3
)
=
[
0
0
5
]
θ
(
4
)
=
[
0
0
5
]
并且,假如说 Alice 告诉我们她十分喜欢爱情电影,于是 Alice 的特征 x1 对应的值就是 5,假设 Alice 告诉我们她很讨厌动作电影,于是 x2 对应的就是 0,Bob 也有相似度喜好,所以我们有上面的 θ(2) ,但 Carol 告诉我们她非常喜欢动作电影,于是对应的特征 x2 就被记录为 5,但是别忘了我们有 x0 = 1,假设 Carol 告诉我们她不喜欢爱情电影之类的,而且 Dave 也是这样,于是我们就得到了 θ(3) 和 θ(4) 。假设在某种程度上我们可以听取用户的意见,每个用户 j 都告诉我们他们各自的 θ(j) 是什么,这就向我们指明了他们对不同题材电影的喜欢程度。
如果我们能够从用户那里得到这些参数 θ 的值,那么我们理论上就能推测出每部电影的 x1 以及 x2 的值。举例来说,假如观察电影 1 对应的特征向量 x1,我们假装不知道电影的名字,我们只知道 Alice 喜欢这部电影,Bob 也喜欢这部电影,Carol 和 Dave 不喜欢它,那么我们能推断出什么呢?我们能从特征向量中知道 Alice 和 Bob 喜欢爱情电影(因为他们的 x1 都评了 5 分),但对于 Carol 和 Dave,我们知道他们不喜欢爱情电影,但是他们喜欢动作电影(从 θ(3) 和 θ(4) 中可以得出)。
同时,由于我们知道 Alice 和 Bob 喜欢电影 1,而 Carol 和 Dave 不喜欢它,我们可以推断这可能是一部爱情片,而不太可能是动作片。这个例子在数学上可能某种程度上简化了,但我们真正需要的是特征向量 x(1) 应该是什么才能让 θ(1) 的转置乘以 x(1) 约等于 5,也就是 Alice 的评分值,然后 θ(2) 的转置乘以 x(1) 也近似于 5,而 θ(3) 的转置乘以 x(1) 约等于 0,这是 Carol 的评分,而 θ(4) 的转置乘以 x(1) 也约等于 0。
(
θ
(
1
)
)
T
x
(
1
)
≈
5
(
θ
(
2
)
)
T
x
(
1
)
≈
5
(
θ
(
3
)
)
T
x
(
1
)
≈
0
(
θ
(
4
)
)
T
x
(
1
)
≈
0
由此可知,x(1) 的第一个元素是 1,这个 1 是截距项,再是 1.0 和 0.0,这样才能得出 Alice、Bob、Carol 和 Dave 四个人对电影评分的结果。一般来说,我们可以继续进行列举,并试着弄明白电影还有什么合适的特征。
x
(
1
)
=
[
1
1.0
0
]
我们把之前章节讨论的算法以及刚刚讲的算法都总结一下:
Collaborative
filtering
Ⅰ
G
i
v
e
n
x
(
1
)
,
.
.
.
,
x
(
n
m
)
(
a
n
d
m
o
v
i
e
r
a
t
i
n
g
s
)
,
c
a
n
e
s
t
i
m
a
t
e
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
Ⅱ
G
i
v
e
n
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
,
c
a
n
e
s
t
i
m
a
t
e
x
(
1
)
,
.
.
.
,
x
(
n
m
)
上一节中我们讲的是,如果我们有所有电影评分的集合(Ⅰ部分),即 σ(i,j) 和 y(i,j),我们有这些评分数据,于是根据不同电影的特征,我们可以学习参数 θ,如果我们已知这些特征,就能学习出不同用户的参数 θ 。我们在前面的小节中讲的是(Ⅱ部分),如果我们的用户愿意为我们提供这些参数,我们就能估计出各种电影的特征值,这有点像鸡和蛋的问题,先有鸡还是先有蛋?如果已知 θ,就能求出这些 x;如果已知 x,也能学习出 θ。
G
u
e
s
s
θ
→
x
→
θ
→
x
→
θ
→
x
→
.
.
.
我们能做的就是(并且实际上也是可行有效的),随机地猜取一些 θ 值,在有了这些随机初始化的 θ 值以后,我们就能继续去用我们刚刚讲的方法来学习出不同电影的特征,然后在有这些初始的特征之后,我们就能运用前面的章节谈到的第一种方法来得到一个更好的对参数 θ 值得估计,这样我们就有了一系列能更好地估计用户的 θ 值,通过这些 θ 又可以得到更好的特征,以此类推。我们把这个迭代过程不断地重复进行,得到更好的 θ,x,θ,x,θ,x,并且效果确实很好。如果我们重复这个过程,那么我们的算法将会收敛到一组合理的电影特征,以及一组对合理的对不同用户的参数的估计,这就是最基本的协同过滤算法,这实际并不是最后我们要使用的算法,下一节将改进这个算法,让其在计算时更为高效。
通过上面的内容,我们可以明白如何规划出一个问题能让我们同时从这些电影中学习出参数和特征,对于这个推荐系统问题,该问题仅建立在每位用户都对数个电影进行了评价,并且每部电影都被数位用户评价过的情况下,这样我们才能重复这个迭代过程,来估计出 θ 和 x 。
在本节中我们见到了基本的协同过滤算法,协同过滤算法指的是当我们执行算法时,要观察大量的用户,观察这些用户的实际行为,来协同地得到更佳的每个人对电影的评分值,因为如果每个用户都对一部分电影作出了评价,那么每个用户都在帮助算法学习出更适合的特征,也就是说,通过自己对几部电影进行评分,我们就能帮助这个系统更好地学习特征,然后这些学习出的特征又可以被用来更好地预测其他用户的评分。协同的另一层意思是说每位用户都在帮助算法更好地进行特征学习。这就是协同过滤,在下一节中,我们会用这些我们所讨论的这些思想来尝试开发一种更好的算法,一种更好的协同过滤算法。
Collaborative
filtering
optimization
objective:
G
i
v
e
n
x
(
1
)
,
.
.
.
,
x
(
n
m
)
,
e
s
t
i
m
a
t
e
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
:
min
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
1
2
∑
j
=
1
n
u
∑
i
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
2
+
λ
2
∑
j
=
1
n
u
∑
k
=
1
n
(
θ
k
(
j
)
)
2
G
i
v
e
n
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
,
e
s
t
i
m
a
t
e
x
(
1
)
,
.
.
.
,
x
(
n
m
)
:
min
x
(
1
)
,
.
.
.
,
x
(
n
m
)
1
2
∑
i
=
1
n
m
∑
j
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
2
+
λ
2
∑
i
=
1
n
m
∑
k
=
1
n
(
x
k
(
i
)
)
2
M
i
n
i
m
i
z
i
n
g
x
(
1
)
,
.
.
.
,
x
(
n
m
)
a
n
d
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
s
i
m
u
l
t
a
n
e
o
u
s
l
y
:
J
(
x
(
1
)
,
.
.
.
,
x
(
n
m
)
,
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
)
=
1
2
∑
(
i
,
j
)
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
2
+
λ
2
∑
i
=
1
n
m
∑
k
=
1
n
(
x
k
(
i
)
)
2
+
λ
2
∑
j
=
1
n
u
∑
k
=
1
n
(
θ
k
(
j
)
)
2
min
x
(
1
)
,
.
.
.
,
x
(
n
m
)
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
J
(
x
(
1
)
,
.
.
.
,
x
(
n
m
)
,
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
)
前面讲过,假如我们有了电影的特征,我们就可以解出上面一式对应的最小化问题,找到用户参数 θ;然后我们也讲过,如果我们拥有参数 θ,我们也可以用该参数估计特征 x,办法是通过解决上面二式对应的最小化问题得到 x 。那么我们可以做的事是不停地重复这些计算,或许是随机初始化这些参数,然后解出 θ,解出 x 再解出 θ,再解出 x,但实际上,存在一个更有效率地算法,可以让我们不再需要这样不停地计算 x 和 θ,而是能够将 x 和 θ 同时计算出来。
上面三式就是这种算法:我们需要做的是将这两个优化目标函数结合为一个,所以我们要定义这个新的优化目标函数 J,它是一个代价函数,是关于特征 x 和参数 θ 的函数,它其实就是上面那两个优化目标函数,但是我们将它们结合在一起。
为了把这个解释清楚,首先我们指出,一式和二式中的两个平方误差项(粉色标注)实际上是相同的,可能两个求和看起来有点不同,但让我们来看看它们到底在做什么:一式中的两个求和运算是所有用户 j 的总和,和所有被该用户评分过的电影总和(这其实是将所有 (i,j) 对全加起来,每项对应被某一用户评分过的某一电影,关于 j 的求和的意思是对每个用户对该用户评分的所有电影求和);二式中的两个求和运算进行相反的计算,它表示对于每部电影 i,将所有对它评分过的用户 j 求和。
一式和二式的两个求和运算都是对所有 r(i,j) = 1 的 (i,j) 对求和,就是对所有有评分的用户-电影对进行求和,因此,这两个式子其实就是三式的第一项(粉色标注),注意三个式子中每个的第一项绿色标注部分的变化,三式中写着所有 r(i,j) 值为 1 的 (i,j) 对求和。
我们要做的是定义一个我们想将其最小化的合并后的优化目标函数,让我们能同时解出 x 和 θ,优化目标函数里的另一些项分别是一式和二式中的 θ 所进行的正则化项(分别用红色和蓝色对应)。这个优化目标函数 J 有一个很有趣的特性,如果我们假设 x 为常数,并关于 θ 优化的话,我们其实就是在计算这个式子,反过来也一样,如果我们把 θ 作为常量,然后关于 x 求 J 的最小值的话,那就与第二个式子相等,因为如果只关于 x 或 θ 进行最小化运算的话,后面的两项中会有一项变为常数。
S
e
t
x
(
1
)
,
.
.
.
,
x
(
n
m
)
a
s
c
o
n
s
t
a
n
t
:
J
(
x
(
1
)
,
.
.
.
,
x
(
n
m
)
,
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
)
=
J
(
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
)
=
1
2
∑
j
=
1
n
u
∑
i
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
2
+
λ
2
∑
j
=
1
n
u
∑
k
=
1
n
(
θ
k
(
j
)
)
2
S
e
t
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
a
s
c
o
n
s
t
a
n
t
:
J
(
x
(
1
)
,
.
.
.
,
x
(
n
m
)
,
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
)
=
J
(
x
(
1
)
,
.
.
.
,
x
(
n
m
)
)
=
1
2
∑
i
=
1
n
m
∑
j
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
2
+
λ
2
∑
i
=
1
n
m
∑
k
=
1
n
(
x
k
(
i
)
)
2
所以这个优化目标将关于 x 和 θ 的两个代价函数合并起来。为了提出一个综合的优化目标问题,我们要做的是将这个代价函数视为特征 x 和用户参数θ的函数,对它整体最小化(本小节开始处的三式下面紫色标注的式子),作为一个既关于 x 也关于 θ 的函数,这和前面的算法之间唯一的不同是不需要反复计算(不用不断地重复进行迭代过程,得到更好的 θ 和 x),不用我们需要做的就是对这两组参数同时进行最小化。
最后一件事是,当我们以这样的方法学习特征量时,之前我们所遵循的惯例是我们所使用的特征 x0 = 1,对应于一个截距项。当我们以这种形式真的去学习特征量时,我们不再遵循这一惯例,这些我们将学习的特征量 x 是 n 维实数,而先前所有的特征值 x 是 n + 1 维(包括截距项),删除掉 x0,我们现在只有 n 维的 x ,同样地,因为参数 θ 具有相同的维度,所以 θ 也是 n 维的,因为如果没有 x0,那么 θ0 也不再需要。我们放弃这个惯例的理由是,我们现在是在学习所有的特征,我们没有必要将一个特征值硬编码为 1,因为如果算法真的需要一个特征永远为 1,它可以选择靠自己去获得 1 这个数值,如果这算法想要的话,它可以将特征值 x1 设为 1,所以没有必要将 1 这个特征定死,现在算法有了灵活性去自行学习。
把所有讲的这些合起来,就是我们的协同过滤算法。
Collaborative
filtering
algorithm
1.
I
n
i
t
i
a
l
i
z
e
x
(
1
)
,
.
.
.
,
x
(
n
m
)
,
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
t
o
s
m
a
l
l
r
a
n
d
o
m
v
a
l
u
e
s
.
2.
M
i
n
i
m
i
z
e
J
(
x
(
1
)
,
.
.
.
,
x
(
n
m
)
,
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
)
u
s
i
n
g
g
r
a
d
i
e
n
t
d
e
s
c
e
n
t
(
o
r
a
n
a
d
v
a
n
c
e
d
o
p
t
i
m
i
z
a
t
i
o
n
a
l
g
o
r
i
t
h
m
)
.
E
.
g
.
f
o
r
e
v
e
r
y
j
=
1
,
.
.
.
,
n
u
,
i
=
1
,
.
.
.
n
m
:
x
k
(
i
)
:
=
θ
k
(
j
)
−
α
(
∑
j
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
θ
k
(
j
)
+
λ
x
k
(
i
)
)
θ
k
(
j
)
:
=
θ
k
(
j
)
−
α
(
∑
i
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
x
k
(
i
)
+
λ
θ
k
(
j
)
)
3.
F
o
r
a
u
s
e
r
w
i
t
h
p
a
r
a
m
e
t
e
r
s
θ
a
n
d
a
m
o
v
i
e
w
i
t
h
(
l
e
a
r
n
e
d
)
f
e
a
t
u
r
e
s
x
,
p
r
e
d
i
c
t
a
s
t
a
r
r
a
t
i
n
g
o
f
θ
T
x
.

我们希望可以找到另一种方法写出协同过滤算法的预测值。首先,这是我们的数据集(上图),包括五部电影,四个用户,这个矩阵 Y 是 5 行 4 列的矩阵。正如我们所知,构成矩阵时要包括所有的元素和所有的数据,包括问号,然后把它们按组写入矩阵。当然这个矩阵的第 (i,j) 个元素,我们之前说的 y(i,j),上标代表它是第 j 个用户给第 i 部电影的评分。
给定的矩阵 Y 包含所有我们已知的评分,有另一种方法可以写出这个算法的所有预测评分,尤其是如果你想查看某一个用户对某一个电影的评分预测,用户 j 对电影 i 的评分预测由下面这个公式给出:
Predicted
ratings:
Y
=
[
5
5
0
0
5
?
?
0
?
4
0
?
0
0
5
4
0
0
5
?
]
[
(
θ
(
1
)
)
T
(
x
(
1
)
)
(
θ
(
2
)
)
T
(
x
(
1
)
)
.
.
.
(
θ
(
n
u
)
)
T
(
x
(
1
)
)
(
θ
(
1
)
)
T
(
x
(
2
)
)
(
θ
(
2
)
)
T
(
x
(
2
)
)
.
.
.
(
θ
(
n
u
)
)
T
(
x
(
2
)
)
.
.
.
.
.
.
.
.
.
.
.
.
(
θ
(
1
)
)
T
(
x
(
n
m
)
)
(
θ
(
2
)
)
T
(
x
(
n
m
)
)
.
.
.
(
θ
(
n
u
)
)
T
(
x
(
n
m
)
)
]
因此,如果你有一个预测评分的矩阵,你所拥有的就是上面那个矩阵,矩阵元素的标号为 i, j,这对应了预测的用户 j 给电影 i 的打分,这与 (θ(j))T 乘以 x(i) 的值相等。因此,这个矩阵中第一个元素(即第一行第一列的元素,红色标注)是第一个用户对第一部电影的评分预测,第一行的第二个元素(蓝色标注),它是第二个用户对第一部电影的评分预测,以此类推,绿色标注的元素是第一个用户对最后一部电影的评分预测。如果我们要预测,上面右侧矩阵中红色的评分就是对左侧矩阵中红色的值的预测,右侧矩阵中粉色的评分就是对左侧矩阵中粉色的值的预测,以此类推。
现在,给定这个预测评分矩阵,则有一个比较简单的或者向量化的方法来写出它们,比如说,如果我们定义矩阵 X,其可以写成下面的形式:
X
=
[
——
(
x
(
1
)
)
T
——
——
(
x
(
2
)
)
T
——
.
.
.
——
(
x
(
n
m
)
)
T
——
]
Θ
=
[
——
(
θ
(
1
)
)
T
——
——
(
θ
(
2
)
)
T
——
.
.
.
——
(
θ
(
n
u
)
)
T
——
]
像之前讲过的线性回归的矩阵形式,第一行是 x(1) 的转置,然后第二行是 x(2) 的转置,一直到 x(nm) 的转置,我将提取所有的电影的特征,然后逐行地写入到矩阵中。所以如果将每部电影看做一个样本,将不同的电影的所有属性都按行写入矩阵,如果我们找到一个矩阵,用大写的 Θ 表示,我们要做的是取出每个用户参数向量,像上面的方式按行写入。
现在已经给出了对矩阵 X 的定义以及矩阵 Θ 的定义,为了获得一个向量化方法来计算预测矩阵,我们可以只计算 X 乘以矩阵 Θ 的转置,它就是一个向量化的方法来计算这个矩阵。这个协同过滤算法有另一个名字,它也叫做低秩矩阵分解(Low rank matrix factorization),人们谈论低秩矩阵分解,基本上他们所说的就是我们正在讨论的这个算法,这个术语来自于这个矩阵的数学性质,矩阵 X 乘以矩阵 Θ 的转置在线性代数中有一个数学性质称为低秩矩阵(Low rank matrix),这就是算法起名叫低秩矩阵分解的原因(矩阵 X 乘以矩阵 Θ 的转置具有低秩性质,低秩的意思就是秩为 1)。

为了了解均值归一化的作用,我们考虑这样一个例子,有一个没有给任何电影评分的用户,加上之前我们的四个用户 Alice、Bob、Carol 和 Dave,我们现在加上了第五个用户 Eve,她没有给任何电影评分,看看协同过滤算法会对这个用户做什么。
min
x
(
1
)
,
.
.
.
,
x
(
n
m
)
θ
(
1
)
,
.
.
.
,
θ
(
n
u
)
1
2
∑
(
i
,
j
)
:
r
(
i
,
j
)
=
1
(
(
θ
(
j
)
)
T
x
(
i
)
−
y
(
i
,
j
)
)
2
+
λ
2
∑
i
=
1
n
m
∑
k
=
1
n
(
x
k
(
i
)
)
2
+
λ
2
∑
j
=
1
n
u
∑
k
=
1
n
(
θ
k
(
j
)
)
2
假设 n 等于 2,所以我们要学习两个特征变量,我们要学习出一个参数向量 θ(5)(这是一个二维向量,提醒一下,这个向量是 n 维的,而不是 n + 1 维的)。我们要学习 5 号用户 Eve 的参数向量 θ(5),如果我们看这个优化目标的第一项(蓝色标注),用户 Eve 没给任何电影打过分,所以对用户 Eve 来说没有电影满足 r(i,j) = 1 这个条件,所以第一项完全不影响 θ(5) 的值,因为没有电影被 Eve 评过分,所以这是影响 θ(5) 值的唯一项(绿色标注),这就是说,我们想选一个向量 θ(5),使得最后的正则化项尽可能地小,换句话说,想要最小化这个式子:
λ
2
[
(
θ
1
(
5
)
)
2
+
(
θ
2
(
5
)
)
2
]
这就是这个与用户 5 有关的正则化项的成分。当然,如果我们目标是最小化上面这一项,那么我们最终得到的就会是 θ(5) = [0;0],因为正则化项会让我们的参数接近 0,如果没有数据能够使得参数远离 0,因为这第一项不影响 θ(5) 值,我们就会得到 θ(5) 等于零向量的结果,所以当我们要预测用户 5 会如何给电影打分,有 θ(5) 的转置乘以 x(i),对任意 i,结果都会等于 0 ,因为对任意 x 值,θ(5) 都是 0,这个内积就会等于 0 。因此我们会得到,我们将预测 Eve 给所有电影的评分都是 0 颗星,但是这个结果看起来没什么用,就是说如果我们看不同的电影,比如第一个电影 Love at last,有两个人给它评了 5 星,对于电影 Sword vs. karate,也有人评了 5 星。有些人确实很喜欢某些电影,所以仅预测出 Eve 会给它们全部评 0 星是没用的。但实际上,如果预测出 Eve 会给所有电影评 0 星,我们还是没有任何好办法推荐电影给 Eve,因为所有这些电影都会被 Eve 给出一样的预测评分,所以没有一部电影拥有高一点儿的预测评分,使得能推荐给她,所以这种结果不太好。
均值归一化的想法可以解决这个问题,下面介绍它是如何工作的。
和之前一样,我们把所有的评分都放到矩阵 Y 里,就是把所有这些评分全部整合到矩阵 Y 中,Y 矩阵中全是问号的这列对应 Eve 没有给任何电影评分。现在要实现均值归一化,我们要做的就是计算每个电影所得评分的均值,我们要把它们存在一个叫 μ 的向量中:
Mean
normalization:
Y
=
[
5
5
0
0
?
5
?
?
0
?
?
4
0
?
?
0
0
5
4
?
0
0
5
0
?
]
μ
=
[
2.5
2.5
2
2.25
1.25
]
→
Y
=
[
2.5
2.5
−
2.5
−
2.5
?
2.5
?
?
−
2.5
?
?
2
−
2
?
?
−
2.25
−
2.25
2.75
1.75
?
−
1.25
−
1.25
3.75
−
1.25
?
]
所以第一个电影得到了两个 5 星和两个 0 星的评价,均值就是 2.5 星,而第二个电影的平均评价是 2.5 星等等,最后一个电影的评分是 0 0 5 0(最后一个改成 0 了,和前面的有点不一样),所以这四个数字的平均值就是 1.25星,我们要做的就是观察一下这些电影评分,现在我们要减去均分,得到上面的的矩阵 Y,我们所做的就是把每个电影评分都归一化,使其均分为 0 。
接下来我们要做的就是对这个评分数据集使用协同过滤算法,所以我们要假设上面的矩阵 Y 就是从用户那里得到的数据,或者假设它们就是我们从用户得到的实际评分,我们要把这个当做我们的数据集,用它来学习我们的参数 θ(j) 和特征 x(i),这就是用这些均值归一化后的电影评分来学习。