在本节中,我们将基于内容的推荐算法,与基于协同过滤的推荐算法,集合在一起,形成深度学习推荐算法,同时为了提高运行效率,我们还将介绍算法的向量表示。
在这里我们希望同时学习学生对题目需要程度的参数集{θ(1),θ(2),...,θ(nu)}
{
θ
(
1
)
,
θ
(
2
)
,
.
.
.
,
θ
(
n
u
)
}
和每道题目的特征向量{x(1),x(2),...,x(nm)}
{
x
(
1
)
,
x
(
2
)
,
.
.
.
,
x
(
n
m
)
}
,我们可以将上两节的代价函数进行合并,上两节的代价函数如下所示:
J(θ(1),θ(2),...,θ(nu))=12∑j=1nu∑i:r(i,j)=1(θ(j)2x(i)−y(i,j))2+λ2∑j=1nu∑k=1nθ(j)k2 J ( θ ( 1 ) , θ ( 2 ) , . . . , θ ( n u ) ) = 1 2 ∑ j = 1 n u ∑ i : r ( i , j ) = 1 ( θ ( j ) 2 x ( i ) − y ( i , j ) ) 2 + λ 2 ∑ j = 1 n u ∑ k = 1 n θ k ( j ) 2
J(x(1),x(2),...,x(nm))=12∑i=1nm∑i:r(i,j)=1(θ(j)2x(i)−y(i,j))2+λ2∑i=1nm∑k=1nx(i)k2 J ( x ( 1 ) , x ( 2 ) , . . . , x ( n m ) ) = 1 2 ∑ i = 1 n m ∑ i : r ( i , j ) = 1 ( θ ( j ) 2 x ( i ) − y ( i , j ) ) 2 + λ 2 ∑ i = 1 n m ∑ k = 1 n x k ( i ) 2
我们先来分析第一项也就是平方和叠加项,第一个公式的意思是对每个用户,求出该用户所有打过分的影片,求出计算出的打分与用户实际打分之间误差的平方和,第二个公式的意思是对每部影片,求出所有对这部影片打过分的用户,求出计算出的打分与用户实际打分之间误差的平方和。实际上,这两个求误差平方和项计算出来的结果都是所有打过分的影片,计算的打分值与实际打分值之差的平方和,即这两项都等价于:
∑i:r(i,j)=1(θ(j)2x(i)−y(i,j))2 ∑ i : r ( i , j ) = 1 ( θ ( j ) 2 x ( i ) − y ( i , j ) ) 2
所以我们得到新的代价函数公式为:
J(x(1),x(2),...,x(nm),θ(1),θ(2),...,θ(nu))=∑i:r(i,j)=1(θ(j)2x(i)−y(i,j))2+λ2∑i=1nm∑k=1nx(i)k2+λ2∑j=1nu∑k=1nθ(j)k2 J ( x ( 1 ) , x ( 2 ) , . . . , x ( n m ) , θ ( 1 ) , θ ( 2 ) , . . . , θ ( n u ) ) = ∑ i : r ( i , j ) = 1 ( θ ( j ) 2 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
我们学习算法要优化的目标就变为:
minx(1),x(2),...,x(nm)θ(1),θ(2),...,θ(nu)J(x(1),x(2),...,x(nm),θ(1),θ(2),...,θ(nu)) min x ( 1 ) , x ( 2 ) , . . . , x ( n m ) θ ( 1 ) , θ ( 2 ) , . . . , θ ( n u ) J ( x ( 1 ) , x ( 2 ) , . . . , x ( n m ) , θ ( 1 ) , θ ( 2 ) , . . . , θ ( n u ) )
与之前算法不同的是,我们这里不再需要传统线性回归
y=wx+b
y
=
w
x
+
b
因为根据上一节内容,
θ(0)=0
θ
(
0
)
=
0
,所以我们不再需要向
x
x
和
θ
θ
上添加第0维了,因此
x∈Rn,θ∈Rn
x
∈
R
n
,
θ
∈
R
n
,在我们这个问题中
n=2
n
=
2
,表示题目是知识点1还是知识点2。
我们首先利用随机数初始化
{θ(1),θ(2),...,θ(nu)}
{
θ
(
1
)
,
θ
(
2
)
,
.
.
.
,
θ
(
n
u
)
}
和每道题目的特征向量
{x(1),x(2),...,x(nm)}
{
x
(
1
)
,
x
(
2
)
,
.
.
.
,
x
(
n
m
)
}
为小的随机数。
对于
i=1,…,nm;k=1,…,n
i
=
1
,
…
,
n
m
;
k
=
1
,
…
,
n
:
x(i)k=x(i)k−α(∑i:r(i,j)=1(θ(j)Tx(i)−y(i,j))θ(j)k+λx(i)k) x k ( i ) = x k ( i ) − α ( ∑ i : r ( i , j ) = 1 ( θ ( j ) T x ( i ) − y ( i , j ) ) θ k ( j ) + λ x k ( i ) )
对于
j=1,…,nu;k=1,…,n
j
=
1
,
…
,
n
u
;
k
=
1
,
…
,
n
:
θ(j)k=θ(j)k−α(∑i:r(i,j)=1(θ(j)Tx(i)−y(i,j))x(i)k+λθ(j)k) θ k ( j ) = θ k ( j ) − α ( ∑ i : r ( i , j ) = 1 ( θ ( j ) T x ( i ) − y ( i , j ) ) x k ( i ) + λ θ k ( j ) )
当训练完成之后,如果学生j没有见过题目i,我们希望预测学生j对题目i的需要程度,进而决定是否向学生j推荐题目i,方法如下所示:
θ(j)Tx(i) θ ( j ) T x ( i )
得到这个值之后,我们就可以决定是否向学生j推荐题目i了。
在前面章节中,我们讨论算法时都是用下标形式来讨论的,这样做的好处是比较直观,我们很容易理解算法。但是在实际应用中,如果直接应用前面章节中的公式,那么计算效率将是比较低的。因此,我们通常将算法转化为矩阵运算形式。
我们来看我们所研究的数据集:
* | 题目 | 张一 | 李二 | 王三 | 赵四 |
x(1) x ( 1 ) | 题目1 | 5 | 5 | 0 | 0 |
x(2) x ( 2 ) | 题目2 | 5 | ? | ? | 0 |
x(3) x ( 3 ) | 题目3 | ? | 4 | 0 | ? |
x(4) x ( 4 ) | 题目4 | 0 | 0 | 5 | 4 |
x(5) x ( 5 ) | 题目5 | 0 | 0 | 5 | ? |
我们可以将上述评分结果,组成一个结果矩阵Y,如下所示:
Y=⎡⎣⎢⎢⎢⎢⎢⎢5.05.0?0.00.05.0?4.00.00.00.0?0.05.05.00.00.0?4.0?⎤⎦⎥⎥⎥⎥⎥⎥ Y = [ 5.0 5.0 0.0 0.0 5.0 ? ? 0.0 ? 4.0 0.0 ? 0.0 0.0 5.0 4.0 0.0 0.0 5.0 ? ]
由上面定义可以看出,
Y∈Rnm×nu
Y
∈
R
n
m
×
n
u
,即行对应于某道题目,列对应于某个用户。我们以前的
y(i,j)=Yi,j=θ(j)Tx(i)
y
(
i
,
j
)
=
Y
i
,
j
=
θ
(
j
)
T
x
(
i
)
。
则结果矩阵可以表示为:
Y=⎡⎣⎢⎢⎢⎢⎢⎢5.05.0?0.00.05.0?4.00.00.00.0?0.05.05.00.00.0?4.0?⎤⎦⎥⎥⎥⎥⎥⎥=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢θ(1)Tx(1)θ(1)Tx(2)θ(1)Tx(3)θ(1)Tx(4)θ(1)Tx(5)θ(2)Tx(1)θ(2)Tx(2)θ(2)Tx(3)θ(2)Tx(4)θ(2)Tx(5)θ(3)Tx(1)θ(3)Tx(2)θ(3)Tx(3)θ(3)Tx(4)θ(3)Tx(5)θ(4)Tx(1)θ(4)Tx(2)θ(4)Tx(3)θ(4)Tx(4)θ(4)Tx(5)⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥ Y = [ 5.0 5.0 0.0 0.0 5.0 ? ? 0.0 ? 4.0 0.0 ? 0.0 0.0 5.0 4.0 0.0 0.0 5.0 ? ] = [ θ ( 1 ) T x ( 1 ) θ ( 2 ) T x ( 1 ) θ ( 3 ) T x ( 1 ) θ ( 4 ) T x ( 1 ) θ ( 1 ) T x ( 2 ) θ ( 2 ) T x ( 2 ) θ ( 3 ) T x ( 2 ) θ ( 4 ) T x ( 2 ) θ ( 1 ) T x ( 3 ) θ ( 2 ) T x ( 3 ) θ ( 3 ) T x ( 3 ) θ ( 4 ) T x ( 3 ) θ ( 1 ) T x ( 4 ) θ ( 2 ) T x ( 4 ) θ ( 3 ) T x ( 4 ) θ ( 4 ) T x ( 4 ) θ ( 1 ) T x ( 5 ) θ ( 2 ) T x ( 5 ) θ ( 3 ) T x ( 5 ) θ ( 4 ) T x ( 5 ) ]
我们令设计矩阵X为:
X=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢x(1)Tx(2)Tx(3)Tx(4)Tx(5)T⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥ X = [ x ( 1 ) T x ( 2 ) T x ( 3 ) T x ( 4 ) T x ( 5 ) T ]
其中
X∈Rnm×n
X
∈
R
n
m
×
n
的矩阵。
上式中两侧的横线代有将列向量转置为行向量,同样我们令参数矩阵
Θ
Θ
为:
Θ=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢θ(1)Tθ(2)Tθ(3)Tθ(4)Tθ(5)T⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥ Θ = [ θ ( 1 ) T θ ( 2 ) T θ ( 3 ) T θ ( 4 ) T θ ( 5 ) T ]
其中
Θ∈Rnu×n
Θ
∈
R
n
u
×
n
。
有了上面两个定义,我们就可以将结果矩阵表示为:
Y=X⋅ΘT=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢x(1)Tx(2)Tx(3)Tx(4)Tx(5)T⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⋅[θ(1)θ(2)θ(3)θ(4)] Y = X ⋅ Θ T = [ x ( 1 ) T x ( 2 ) T x ( 3 ) T x ( 4 ) T x ( 5 ) T ] ⋅ [ θ ( 1 ) θ ( 2 ) θ ( 3 ) θ ( 4 ) ]
上面讨论的是前向传播问题,而在计算梯度和利用随机梯度下降算法来进行学习时,还需要用我们之前介绍的公式来计算。
有了这些理论知识之后,我们就可以来解决一类非常常见的推荐问题了,例如学生j观做过题目i,我们就可以向学生j推荐5个他可能需要的题目了。
我们首先取出题目
i
i
的特征向量x(i)x(i),然后对所有其他题目算出欧式距离
d(l)
d
(
l
)
:
d(l)=∥x(i)−x(l)∥22,l=1,2,...,nm且l≠i d ( l ) = ‖ x ( i ) − x ( l ) ‖ 2 2 , l = 1 , 2 , . . . , n m 且 l ≠ i
对于所有
d(l)
d
(
l
)
按从小到大进行排序,选出其中距离值最小的5个,就可以作为结果推荐给用户
j
j
<script type="math/tex" id="MathJax-Element-41">j</script>了。
这里面实际上还有一个问题,如果我们有成千上万部影片,我们算出某部影片的与其他所有影片的欧式距离,并从小到大排序,最后选出5个最小的推荐给用户,这将花费很长时间,用户肯定不愿意等待那么长时间。怎么解决这一问题呢?我们可以通过一个定时启动的后台线程,算出所有影片之间的欧式距离,并按从小到大排序,然后缓存在NoSQL数据库中,这样需要向用户推荐时,直接返回缓存中结果就可以了。如果我们定时启动的后台线程运行频率足够的话,我们就可以得到相对实时的效果了。
在这一节中,我们讲述了基于深度学习的推荐系统。但是在这里我们有一个实际问题,我们一直没有讨论,就是推荐系统的冷启动问题,如何从对学生一无所知开始进行推荐,这是一个非常实际的问题,在下一节中,我们将讨论怎样解决这个问题。