一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
吴恩达机器学习作业8 - 异常检测和推荐系统(Python实现)
Introduction
在第一个实验中,将实现异常检测算法,并应用于检测网络上出现故障的服务器。在第二个实验中,将使用协同过滤来构建一个电影推荐系统。
1 Anomaly detection(异常检测)
在本实验中,将实现一个异常检测算法来检测服务器计算机中的异常行为。特征测量的是每个服务器的响应速度(mb/s
)和延迟(ms
)。当服务器运行时,收集了
个计算机行为的样本,因此有一个未标记的数据集
,其中绝大多数样本是正常的,但还是有一小部分的样本是异常的。
使用高斯模型来检测数据集中的异常样本,首先从一个2D
数据集开始,对算法运行过程进行可视化。在该数据集上,拟合一个高斯分布,然后找到概率比较低的值,以它为标准,比它低就认为是异常。推广:把异常检测算法应用于具有多个维度的数据集。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.io import loadmat
复制代码
data=loadmat("./data/ex8data1.mat")
data.keys()
复制代码
dict_keys(['__header__', '__version__', '__globals__', 'X', 'Xval', 'yval'])
复制代码
X=data['X']
Xval,yval=data['Xval'],data['yval']
X.shape,Xval.shape,yval.shape
复制代码
((307, 2), (307, 2), (307, 1))
复制代码
def plot_data(X):
plt.figure(figsize=(8,6))
plt.plot(X[:,0],X[:,1],'x',color="blue")
plt.xlabel("Latency (ms)")
plt.ylabel("Throughput (mb/s)")
plt.title("The first dataset")
复制代码
plot_data(X)
复制代码
1.1 Gaussian distribution(高斯分布)
要执行异常检测,首先需要将数据的分布匹配一个模型。给定训练集 ,估计每个特征 的高斯分布,求得 来拟合数据。
其中 是平均值, 控制方差。
1.2 Estimating parameters for a Gaussian(高斯分布的参数估计)
估计参数 :
编写函数estimateGaussian
:以数据矩阵X
作为输入,并且输出一个
维向量
(包含
个特征的平均值),另一个
维向量
(包含
个特征的方差)。
完成上述函数编写之后,可视化拟合的高斯分布的轮廓,可以看到大多数的样本是在概率最高的区域,而异常的样本是在概率较低的区域。
def estimateGaussian(X):
mu=X.mean(axis=0)
sigma=X.var(axis=0)
return mu,sigma
复制代码
mu,sigma=estimateGaussian(X)
mu,sigma
复制代码
(array([14.11222578, 14.99771051]), array([1.83263141, 1.70974533]))
复制代码
计算 参数下的高斯分布模型中每个样本的概率值:
def gaussian(X,mu,sigma):
#X:(m,n)
m,n=X.shape
if(np.ndim(sigma)==1):
sigma=np.diag(sigma)
left=1.0/(np.power(2*np.pi,n/2)*np.sqrt(np.linalg.det(sigma)))
right=np.zeros((m,1))
for row in range(m):
x=X[row]
right[row]=np.exp(-0.5*(x-mu)[email protected](sigma)@(x-mu))
return left*right
复制代码
# xplot = np.linspace(0, 25, 100) # 分割为m=100份
# yplot = np.linspace(0, 25, 100) # 分割为n=100份
# Xplot, Yplot = np.meshgrid(xplot, yplot) # 生成n*m的矩阵
# points=np.c_[Xplot.flatten(),Yplot.flatten()]
# Z = gaussian(points, mu, sigma).reshape(Xplot.shape)
# contour = ax.contour(Xplot, Yplot, Z, [10**-11, 10**-7, 10**-5, 10**-3, 0.1], colors='k') # 绘制等高线
# ax.plot(X[:, 0], X[:, 1], 'x', color="blue")
# ax.set_xlabel("Latency (ms)")
# ax.set_ylabel("Throughput (mb/s)")
# ax.set_title(" The Gaussian distribution contours of the distribution fit to the dataset")
# plt.show()
复制代码
将数据可视化:
def plotContours(fig=None,ax=None):#用于绘制等高线
xplot=np.linspace(0,25,100)#分割为m=100份
yplot=np.linspace(0,25,100)#分割为n=100份
Xplot,Yplot=np.meshgrid(xplot,yplot)#生成n*m的矩阵
# Z=np.exp(-0.5*(np.power(Xplot-mu[0],2)/sigma[0]+np.power(Yplot-mu[1],2)/sigma[1]))
Z = gaussian(points, mu, sigma).reshape(Xplot.shape)
contour=ax.contour(Xplot, Yplot, Z,[10**-11, 10**-7, 10**-5, 10**-3, 0.1],colors='k')#绘制等高线
ax.plot(X[:,0],X[:,1],'x',color="blue")
ax.set_xlabel("Latency (ms)")
ax.set_ylabel("Throughput (mb/s)")
ax.set_title(" The Gaussian distribution contours of the distribution fit to the dataset")
# plt.show()
复制代码
# plt.figure(figsize=(8,6))
fig,ax=plt.subplots(figsize=(8,6))
plotContours(fig,ax)
plt.show()
复制代码
从上图可以清晰的看到,哪些样本的概率高,哪些样本的概率低,概率低的样本很大程度上就是异常值。
1.3 Selecting the threshold(选择阈值)
现在已经估计了高斯参数,可以研究哪些样本在给定的分布下的概率非常高,哪些样本的概率非常低。概率低的样本很有可能是数据集中的异常值。确定哪些样本是异常值可以考虑基于交叉验证集选择一个阈值。在本节实验中,将实现一个算法:使用交叉验证集上的 分数来选择阈值 。
编写函数selectThreshold
:使用交叉验证集
(其中,
对应一个异常样本,而
对应一个正常样本)。对于每个交叉验证样本,将计算
。概率向量
传递给函数selectThreshold
作为参数pval
,标签
传递给函数selectThreshold
作为参数yval
。函数selectThreshold
返回两个参数:阈值
(样本x
的概率
,那么它被认为是一个异常样本),
分数(在阈值
下寻找真异常样本的好坏)
分数使用prec
和rec
进行计算:
而 ,
tp
:本身是异常值并且模型预测成异常值,即真的异常值fp
:本身是正常值并且模型预测成异常值,即假的异常值fn
:本身是异常值并且模型预测成正常值,即假的正常值precision
:表示预测为异常值的样本中有多少是真的异常值的样本recall
:表示实际为异常值的样本中有多少成功预测出是异常值
使用SciPy
内置的方法stats
:计算数据点属于正态分布的概率:
from scipy import stats
dist=stats.norm(mu[0],sigma[0])
dist.pdf(15)
复制代码
0.1935875044615038
复制代码
数组传递给概率密度函数,并获得数据集中每个点的概率密度:
dist.pdf(X[:,0])[0:10]
复制代码
array([0.183842 , 0.20221694, 0.21746136, 0.19778763, 0.20858956,
0.21652359, 0.16991291, 0.15123542, 0.1163989 , 0.1594734 ])
复制代码
计算并保存上述的高斯模型参数的数据集中每个值的概率密度:
p=np.zeros((X.shape))
p[:,0]=stats.norm(mu[0],sigma[0]).pdf(X[:,0])
p[:,1]=stats.norm(mu[1],sigma[1]).pdf(X[:,1])
p.shape
复制代码
(307, 2)
复制代码
计算并保存上述的高斯模型参数的验证集中每个值的概率密度:
pval=np.zeros((Xval.shape))
pval[:,0]=stats.norm(mu[0],sigma[0]).pdf(Xval[:,0])
pval[:,1]=stats.norm(mu[1],sigma[1]).pdf(Xval[:,1])
pval.shape
复制代码
(307, 2)
复制代码
编写函数selectThreshold
:为不同的
值计算
分数(
是真阳性,假阳性和假阴性的数量的函数),从而找到给定概率密度值和真实标签的最佳阈值。如果运行给定的数据集,得到的最佳的
约为
。
def selectThreshold(pval,yval):
best_e,best_f1,f1=0,0,0
step=(pval.max()-pval.min())/1000
for e in np.arange(pval.min(),pval.max(),step):
preds=pval<e
tp=np.sum(np.logical_and(preds==1,yval==1))
fp=np.sum(np.logical_and(preds==1,yval==0))
fn=np.sum(np.logical_and(preds==0,yval==1))
precision=tp/(tp+fp)
recall=tp/(tp+fn)
f1=(2*precision*recall)/(precision+recall)
if(f1>best_f1):
best_f1=f1
best_e=e
return best_e,best_f1
复制代码
epsilon, f1 = selectThreshold(pval, yval)
epsilon, f1
复制代码
<ipython-input-92-c5a1372ada03>:9: RuntimeWarning: invalid value encountered in long_scalars
precision=tp/(tp+fp)
(0.009566706005956842, 0.7142857142857143)
复制代码
将得到的最佳阈值应用于数据集,并可视化结果:
首先查看预测得到的异常样本:第一个数组是异常样本编号,第二个数组是异常样本对应的 。
out_index=np.where(p<epsilon)
out_index
复制代码
(array([300, 301, 301, 303, 303, 304, 306, 306], dtype=int64),
array([1, 0, 1, 0, 1, 0, 0, 1], dtype=int64))
复制代码
下图中红点是被标记为异常样本的点,但存在一些异常样本(但没有被标记),比如右上角也可能是一个异常样本。求出的最佳
以及绘制的图片不太理想。接下来换一个方法来求解:使用之前的函数gaussian
求解样本的概率,而不是直接用scipy
的库函数。
fig,ax=plt.subplots(figsize=(8,6))
plotContours(fig,ax)
plt.xlabel("Latency (ms)")
plt.ylabel("Throughput (mb/s)")
plt.title("The classified anomalies")
plt.scatter(X[out_index[0],0],X[out_index[0],1],s=100,facecolors="none",edgecolors="r")
plt.show()
复制代码
下面求解出的最佳 符合要求,并且绘制的图形也是比较理想的。
p = gaussian(X, mu, sigma)
pval = gaussian(Xval, mu, sigma)
epsilon, f1 = selectThreshold(pval, yval)
epsilon, f1
复制代码
<ipython-input-92-c5a1372ada03>:9: RuntimeWarning: invalid value encountered in long_scalars
precision=tp/(tp+fp)
(8.990852779269496e-05, 0.8750000000000001)
复制代码
out_index=np.where(p<epsilon)
out_index
复制代码
(array([300, 301, 303, 304, 305, 306], dtype=int64),
array([0, 0, 0, 0, 0, 0], dtype=int64))
复制代码
fig,ax=plt.subplots(figsize=(8,6))
plotContours(fig,ax)
plt.xlabel("Latency (ms)")
plt.ylabel("Throughput (mb/s)")
plt.title("The classified anomalies")
plt.scatter(X[out_index[0],0],X[out_index[0],1],s=100,facecolors="none",edgecolors="r")
plt.show()
复制代码
1.4 High dimensional dataset
在本节实验中的数据集中,每个样本都有
个特征,包含了计算服务器的更多属性。用上述的代码估计高斯参数
,根据这些参数评估数据集X
和交叉验证集Xval
中的样本的概率。最后,使用函数selectThreshold
求得最佳阈值
,最佳
约为
,并且发现
个异常样本。
data2=loadmat("./data/ex8data2.mat")
X2=data2['X']
Xval2,yval2=data2['Xval'],data2['yval']
X2.shape,Xval2.shape,yval2.shape
复制代码
((1000, 11), (100, 11), (100, 1))
复制代码
mu,sigma=estimateGaussian(X2)
p = gaussian(X2, mu, sigma)
pval = gaussian(Xval2, mu, sigma)
epsilon, f1 = selectThreshold(pval, yval2)
epsilon, f1
复制代码
<ipython-input-92-c5a1372ada03>:9: RuntimeWarning: invalid value encountered in long_scalars
precision=tp/(tp+fp)
(1.3772288907613575e-18, 0.6153846153846154)
复制代码
查看异常样本的个数: ,符合答案要求。
out_index=np.where(p<epsilon)
len(out_index[0])
复制代码
117
复制代码
2 Recommender Systems
在这部分实验中,将实现协同过滤学习算法,并将其应用于电影评级的数据集。数据集由
级的评分组成,数据集有
用户和
电影。在本实验的下一节中,将实现函数cofiCostFunc
:计算协同拟合目标函数和梯度。在实现成本函数和梯度之后,将使用函数fmincg
来学习协同过滤的参数。
2.1 Movie ratings dataset
数据集ex8 movies.mat
中的变量有Y
和R
,其中矩阵Y
(
)是不同电影的不同用户的评分,行数为电影数目,列数为用户数目;矩阵R
是二进制矩阵,
表示用户
对电影
有评分,
表示用户
对电影
没有评分。协同过滤的目标是预测用户对他未评分的电影的评分,也就是
的项,从而向用户推荐预测收视率最高的电影。
在这节实验中,将使用矩阵X
和Theta
:
X
第
行代表第
个电影的特征向量
,Theta
矩阵的第
列代表第
用户的参数向量
。因此,矩阵X
是一个
的矩阵,Theta
是一个
的矩阵。
data=loadmat("./data/ex8_movies.mat")
data.keys()
复制代码
dict_keys(['__header__', '__version__', '__globals__', 'Y', 'R'])
复制代码
Y,R=data['Y'],data['R']
nm,nu=Y.shape#y(i,j)∈[0,5],0表示未评分
Y.shape,R.shape
复制代码
((1682, 943), (1682, 943))
复制代码
先求第一个电影评分的平均值(有些人没有对这电影评分)。
Y[0].sum()/R[0].sum()
复制代码
3.8783185840707963
复制代码
plt.figure(figsize=(8,8*(1692/943)))
plt.imshow(Y,cmap="rainbow")
plt.colorbar()#显示不同颜色对应的值
plt.xlabel("Users ({})".format(nu))
plt.ylabel("Movies ({})".format(nm))
plt.show()
复制代码
2.2 Collaborative filtering learning algorithm(协同过滤学习算法)
现在将开始实现协同过滤学习算法。将从实现成本函数开始(不进行正则化)。在电影推荐中的协同过滤算法考虑了一组 维参数向量 和 ,其中模型预测用户 对电影 的评分 。给定用户对电影的评级的数据集,学习参数向量 和 ,得到最好的拟合,使成本函数最小。
编写函数cofiCostFunc
:计算协同过滤算法的成本函数和梯度,需要传入的参数为矩阵X
和Theta
。为了使用一个现成的最小化函数,如fmincg
,需要将参数X
和Theta
展开成一维向量参数。
data=loadmat("./data/ex8_movieParams.mat")
data.keys()
复制代码
dict_keys(['__header__', '__version__', '__globals__', 'X', 'Theta', 'num_users', 'num_movies', 'num_features'])
复制代码
X,Theta,nu,nm,nf=data['X'],data['Theta'],data['num_users'],data['num_movies'],data['num_features']
nu,nm,nf=map(int,(nu,nm,nf))
nu,nm,nf
复制代码
(943, 1682, 10)
复制代码
减小数据集的大小,加快算法的速度:
nu,nm,nf=4,5,3
X=X[:nm,:nf]
Theta=Theta[:nu,:nf]
Y=Y[:nm,:nu]
R=R[:nm,:nu]
复制代码
X.shape,Theta.shape
复制代码
((5, 3), (4, 3))
复制代码
2.2.1 Collaborative filtering cost function
协同过滤算法的代价函数(无正则化):
加入正则化的成本函数:协同过滤算法的参数都不需要加偏置项,故都可以正则化。
接下来编写函数cofiCostFunc
:返回成本函数变量J
。累加用户
和电影
的成本(
)。运行该函数,期望答案:不进行正则化的成本函数结果约为
;进行正则化的成本函数结果约为
。
def serialize(X,Theta):#将X和Theta展开成一维
return np.r_[X.flatten(),Theta.flatten()]
复制代码
def deserialize(seq,nm,nu,nf):
return seq[:nm*nf].reshape(nm,nf),seq[nm*nf:].reshape(nu,nf)
复制代码
def cofiCostFunc(seq,Y,R,nm,nu,nf,l=0):
#Y : 评分矩阵 (nm, nu)
#R :0-1矩阵,用户j对电影i有无评分
#X:(nm,nf)每行表示电影i的nf个特征
#Theta:(nu,nf)每行表示用户i的nf个特征
X,Theta=deserialize(seq, nm, nu, nf)
error=0.5*np.sum(np.multiply(np.power([email protected],2),R))
reg1=0.5*l*np.sum(np.power(Theta,2))#加入正则化
reg2=0.5*l*np.sum(np.power(X,2))
return error+reg1+reg2
复制代码
seq=serialize(X, Theta)
cofiCostFunc(seq, Y, R, nm, nu, nf),cofiCostFunc(seq, Y, R, nm, nu, nf,1.5)
复制代码
(22.224603725685675, 31.34405624427422)
复制代码
2.2.2 Collaborative filtering gradient
现在实现梯度函数(无正则化),编写函数cofiGradient
,返回变量X_grad
(规模和X
一样)和Theta_grad
(规模和Theta
一样),将两变量展开为单个向量来返回它们的梯度。编写函数checkCostFunction
检查梯度函数,如果函数实现无误,那么分析梯度和数值梯度非常匹配。
加入正则化的梯度函数:
def cofiGradient(seq,Y,R,nm,nu,nf,l=0):
X,Theta=deserialize(seq, nm, nu, nf)
X_grad=np.multiply((([email protected])-Y),R)@Theta+l*X
Theta_grad=np.multiply((([email protected])-Y),R).T@X+l*Theta
return serialize(X_grad, Theta_grad)
复制代码
def checkCostFunction(seq,Y,R,nm,nu,nf,l=0):
grad=cofiGradient(seq,Y,R,nm,nu,nf,l)
e=0.0001#Δ值
len_seq=len(seq)
e_vec=np.zeros(len_seq)#向量的渐变值
for i in range(10):
idx=np.random.randint(0,len_seq)
e_vec[idx]=e
loss1=cofiCostFunc(seq-e_vec,Y,R,nm,nu,nf,l)
loss2=cofiCostFunc(seq+e_vec,Y,R,nm,nu,nf,l)
num_grad=(loss2-loss1)/(2*e)
e_vec[idx]=0
diff=np.linalg.norm(num_grad-grad[idx])/np.linalg.norm(num_grad+grad[idx])
print('num_grad:%.15f \t grad[idx]:%.15f \t 差值%.15f' %(num_grad, grad[idx], diff))
复制代码
print("Checking gradient with lambda = 0:")
checkCostFunction(serialize(X,Theta), Y, R, nm, nu, nf)
print("\nChecking gradient with lambda = 1.5:")
checkCostFunction(serialize(X,Theta), Y, R, nm, nu, nf, l=1.5)
复制代码
Checking gradient with lambda = 0:
num_grad:4.742718424690651 grad[idx]:4.742718424695921 差值0.000000000000556
num_grad:-10.568020204448914 grad[idx]:-10.568020204450614 差值0.000000000000080
num_grad:-0.803780061460202 grad[idx]:-0.803780061452057 差值0.000000000005067
num_grad:-0.568195965513496 grad[idx]:-0.568195965515757 差值0.000000000001990
num_grad:-7.160044429745938 grad[idx]:-7.160044429740946 差值0.000000000000349
num_grad:7.575703079698570 grad[idx]:7.575703079709334 差值0.000000000000710
num_grad:-0.383582784628800 grad[idx]:-0.383582784622124 差值0.000000000008702
num_grad:1.164413669449971 grad[idx]:1.164413669446225 差值0.000000000001609
num_grad:7.575703079698570 grad[idx]:7.575703079709334 差值0.000000000000710
num_grad:-0.766778776704058 grad[idx]:-0.766778776703673 差值0.000000000000251
Checking gradient with lambda = 1.5:
num_grad:0.129856157187191 grad[idx]:0.129856157163688 差值0.000000000090497
num_grad:0.482440977869203 grad[idx]:0.482440977879083 差值0.000000000010239
num_grad:1.092897577699148 grad[idx]:1.092897577688307 差值0.000000000004960
num_grad:1.092897577699148 grad[idx]:1.092897577688307 差值0.000000000004960
num_grad:-0.892473343601097 grad[idx]:-0.892473343597432 差值0.000000000002053
num_grad:4.901853273224788 grad[idx]:4.901853273231165 差值0.000000000000650
num_grad:-0.647874841526175 grad[idx]:-0.647874841514519 差值0.000000000008996
num_grad:1.092897577699148 grad[idx]:1.092897577688307 差值0.000000000004960
num_grad:-0.647874841526175 grad[idx]:-0.647874841514519 差值0.000000000008996
num_grad:2.101362561361952 grad[idx]:2.101362561388682 差值0.000000000006360
复制代码
2.3 Learning movie recommendations(电影推荐)
完成了协同过滤算法的成本函数和梯度之后,可以开始训练电影推荐算法。先获取所有电影的名称、编号,然后输入用户对电影的偏好,从而获得该用户的电影推荐。
movies=[]#电电影列表
with open("./data/movie_ids.txt","r",encoding='gbk') as f:
for line in f:
movie=line.strip().split(' ')#移除字符串头尾空格
movies.append(' '.join(movie[1:]))
movies=np.array(movies)
复制代码
ratings = np.zeros((1682, 1))
#接用参考博客的数据来设置喜好值
ratings[0] = 4
ratings[6] = 3
ratings[11] = 5
ratings[53] = 4
ratings[63] = 5
ratings[65] = 3
ratings[68] = 5
ratings[97] = 2
ratings[182] = 4
ratings[225] = 5
ratings[354] = 5
ratings.shape
复制代码
(1682, 1)
复制代码
将用户的评分向量添加到现有数据集中,用于模型中。矩阵Y
(
)是不同电影的不同用户的评分,行数为电影数目,列数为用户数目;矩阵R
是二进制矩阵,
表示用户
对电影
有评分,
表示用户
对电影
没有评分。协同过滤的目标是预测用户对他未评分的电影的评分,也就是
的项,从而向用户推荐预测收视率最高的电影。
data=loadmat("./data/ex8_movies.mat")
Y=data['Y']
R=data['R']
复制代码
Y.shape,R.shape
复制代码
((1682, 943), (1682, 943))
复制代码
Y=np.append(ratings,Y,axis=1)
R=np.append(ratings!=0,R,axis=1)
复制代码
Y.shape,R.shape
复制代码
((1682, 944), (1682, 944))
复制代码
初始化参数矩阵X
,Theta
:
nm,nu=Y.shape
nf=10
l=10
X=np.random.random(size=(nm,nf))
Theta=np.random.random(size=(nu,nf))
seq=serialize(X, Theta)
复制代码
X.shape,Theta.shape,seq.shape
复制代码
((1682, 10), (944, 10), (26260,))
复制代码
标准化数据,这样可以使一个完全没有评分的的特征最后也会获得非零值,因为最后要加回均值。其中只对有评分的数据求均值,没有评分的数据不包含在内,所有需要用R
矩阵判断。
def normalizeRatings(Y,R):
Y_mean=((Y.sum(axis=1))/(R.sum(axis=1))).reshape(-1,1)
Y_norm=np.multiply(Y-Y_mean,R)
return Y_norm,Y_mean
复制代码
Y_norm,Y_mean=normalizeRatings(Y,R)
复制代码
Y_norm.shape,Y_mean.shape
复制代码
((1682, 944), (1682, 1))
复制代码
学习模型训练:
import scipy.optimize as opt
res=opt.minimize(fun=cofiCostFunc,x0=seq,args=(Y_norm,R,nm,nu,nf,l),method='TNC',jac=cofiGradient)#运行1min~2min
复制代码
res
复制代码
fun: 70124.80723141175
jac: array([ 0.12481091, 3.80257643, 4.25142191, ..., -0.2913018 ,
0.386691 , 0.7792457 ])
message: 'Max. number of function evaluations reached'
nfev: 100
nit: 9
status: 3
success: False
x: array([0.73096179, 0.16482085, 0.39889075, ..., 0.30653932, 0.17673335,
0.97425473])
复制代码
训练好的参数:X
和Theta
,使用这些参数来为用户提供电影推荐。
X_train,Theta_train=deserialize(res.x,nm,nu,nf)
复制代码
X_train.shape,Theta_train.shape
复制代码
((1682, 10), (944, 10))
复制代码
最后,使用训练出的参数模型来推荐电影:
predition=X_train@Theta_train.T
user_predition=predition[:,0]+Y.mean()
idx=np.argsort(-user_predition)#降序排序,得到下标
复制代码
idx.shape
复制代码
(1682,)
复制代码
user_predition[idx][:10]
复制代码
array([4.03635302, 3.96571345, 3.86437942, 3.8627442 , 3.86094835,
3.85971196, 3.83496685, 3.83174567, 3.71952258, 3.70899912])
复制代码
print("Top recommendations for you:")
for i in range(10):
print('Predicting rating %.1f for movie %s'%(user_predition[idx[i]],movies[idx[i]]))#5分制
print("\nOriginal ratings provided:")
for i in range(len(ratings)):
if ratings[i] > 0:
print('Rated %d for movie %s'% (ratings[i],movies[i]))
复制代码
Top recommendations for you:
Predicting rating 4.0 for movie Star Wars (1977)
Predicting rating 4.0 for movie Raiders of the Lost Ark (1981)
Predicting rating 3.9 for movie Empire Strikes Back, The (1980)
Predicting rating 3.9 for movie Titanic (1997)
Predicting rating 3.9 for movie Good Will Hunting (1997)
Predicting rating 3.9 for movie Shawshank Redemption, The (1994)
Predicting rating 3.8 for movie Braveheart (1995)
Predicting rating 3.8 for movie Return of the Jedi (1983)
Predicting rating 3.7 for movie Usual Suspects, The (1995)
Predicting rating 3.7 for movie Schindler's List (1993)
Original ratings provided:
Rated 4 for movie Toy Story (1995)
Rated 3 for movie Twelve Monkeys (1995)
Rated 5 for movie Usual Suspects, The (1995)
Rated 4 for movie Outbreak (1995)
Rated 5 for movie Shawshank Redemption, The (1994)
Rated 3 for movie While You Were Sleeping (1995)
Rated 5 for movie Forrest Gump (1994)
Rated 2 for movie Silence of the Lambs, The (1991)
Rated 4 for movie Alien (1979)
Rated 5 for movie Die Hard 2 (1990)
Rated 5 for movie Sphere (1998)
复制代码
用非归一化的数据Y
重新训练的:
Y_norm = Y - Y.mean()
Y_norm.mean()
复制代码
4.6862111343939375e-17
复制代码
import scipy.optimize as opt
res=opt.minimize(fun=cofiCostFunc,x0=seq,args=(Y_norm,R,nm,nu,nf,l),method='TNC',jac=cofiGradient)#运行了2min38s
复制代码
res
复制代码
fun: 69380.70267946126
jac: array([ 3.22931558e-06, 4.74670755e-06, 1.53795013e-06, ...,
-1.04391592e-06, 1.12803573e-06, -5.47338254e-07])
message: 'Converged (|f_n-f_(n-1)| ~= 0)'
nfev: 1430
nit: 56
status: 1
success: True
x: array([0.75326985, 0.44698399, 0.4576434 , ..., 0.36815454, 0.46085362,
0.66916822])
复制代码
X_train,Theta_train=deserialize(res.x,nm,nu,nf)
predition=X_train@Theta_train.T
user_predition=predition[:,0]+Y.mean()
idx=np.argsort(-user_predition)#降序排序,得到下标
复制代码
user_predition[idx][:10]
复制代码
array([4.28262534, 4.11498853, 3.98044977, 3.9058028 , 3.88817712,
3.87460875, 3.87178834, 3.86527196, 3.76237659, 3.75394194])
复制代码
print("Top recommendations for you:")
for i in range(10):
print('Predicting rating %.1f for movie %s'%(user_predition[idx[i]],movies[idx[i]]))
print("\nOriginal ratings provided:")
for i in range(len(ratings)):
if ratings[i] > 0:
print('Rated %d for movie %s'% (ratings[i],movies[i]))
复制代码
Top recommendations for you:
Predicting rating 4.3 for movie Titanic (1997)
Predicting rating 4.1 for movie Star Wars (1977)
Predicting rating 4.0 for movie Raiders of the Lost Ark (1981)
Predicting rating 3.9 for movie Good Will Hunting (1997)
Predicting rating 3.9 for movie Shawshank Redemption, The (1994)
Predicting rating 3.9 for movie Braveheart (1995)
Predicting rating 3.9 for movie Return of the Jedi (1983)
Predicting rating 3.9 for movie Empire Strikes Back, The (1980)
Predicting rating 3.8 for movie Terminator 2: Judgment Day (1991)
Predicting rating 3.8 for movie As Good As It Gets (1997)
Original ratings provided:
Rated 4 for movie Toy Story (1995)
Rated 3 for movie Twelve Monkeys (1995)
Rated 5 for movie Usual Suspects, The (1995)
Rated 4 for movie Outbreak (1995)
Rated 5 for movie Shawshank Redemption, The (1994)
Rated 3 for movie While You Were Sleeping (1995)
Rated 5 for movie Forrest Gump (1994)
Rated 2 for movie Silence of the Lambs, The (1991)
Rated 4 for movie Alien (1979)
Rated 5 for movie Die Hard 2 (1990)
Rated 5 for movie Sphere (1998)
复制代码