当前位置:   article > 正文

吴恩达老师机器学习作业-ex8(推荐系统)

吴恩达老师机器学习作业-ex8(推荐系统)

导入库并读取数据

因为这次的数据是mat文件,需要使用scipy库中的loadmat进行读取数据。

通过对数据类型的分析,发现是字典类型,查看该字典的键,可以发现又X等关键字。

  1. import numpy as np
  2. import scipy.io as sio
  3. from scipy.optimize import minimize
  4. #读取数据
  5. path_movies = "./ex8_movies.mat"
  6. data_movies = sio.loadmat(path_movies)
  7. # print(data_movies.keys())
  8. Y = data_movies.get("Y")
  9. R = data_movies.get("R")
  10. path_movieParams = "./ex8_movieParams.mat"
  11. data_movieParams = sio.loadmat(path_movieParams)
  12. # print(data_movieParams.keys())
  13. X = data_movieParams.get("X")
  14. Theta = data_movieParams.get("Theta")
  15. num_users = data_movieParams.get("num_users")
  16. num_movies = data_movieParams.get("num_movies")
  17. num_features = data_movieParams.get("num_features")
  18. # print(num_users[0][0])

均值归一化

当对于一个没有对任何电影评过分的用户E会进行怎样的操作呢?

当最小化代价函数的时候,只有\frac{\lambda }{2}\sum_{j=1}^{n_{u}}\sum_{k=1}^{n}(\theta _{k}^{(j)})^{2}这一项可以影响代价函数,因此为了保证代价函数足够小,会将\theta都赋值为0,那么用户E对所有电影的评分都为0,这样就会没有任何意义。

为了避免这种情况的发生,我们可以对数据进行均值归一化,也就是先按行算出评分的平均值,然后Y=Y-\mu。拿新的Y矩阵再去预测评分,预测完之后,需要将平均值再加回去。这样可以确保第一次位用户进行预测时,每个电影的评分都为平均值。

  1. #均值归一化
  2. def standardization(Y,R):
  3. means = (np.sum(Y,axis=1) / np.sum(R,axis=1)).reshape(-1,1)
  4. Y_norm = (Y - means) * R
  5. return Y_norm,means

序列化和解序列化

这里说一下为什么要序列化参数,其实就是改变矩阵的形状,我们后面会用到opt.minimize()这个函数方法,这个优化方法里面需要的参数X0一定得是一维数组(nums,)

  1. #序列化和解序列化
  2. def serialization(X,Theta):
  3. return np.append(X.flatten(),Theta.flatten())
  4. def deserialization(params,nu,nm,nf):
  5. X = params[:nm[0][0] * nf[0][0]].reshape(nm[0][0],nf[0][0])
  6. Theta = params[nm[0][0] * nf[0][0]:].reshape(nu[0][0],nf[0][0])
  7. return X,Theta

代价函数

J(\theta ,x)=\frac{1}{2}\sum_{(i,j):r(i,j)=1}^{}((\theta ^{(j)})^{T}X^{(i)}-y^{(i,j)})^{2}+\frac{\lambda }{2}\sum_{i=1}^{n_{m}}\sum_{k=1}^{n}(x_{k}^{(i)})^{2}+\frac{\lambda }{2}\sum_{j=1}^{n_{u}}\sum_{k=1}^{n}(\theta _{k}^{(j)})^{2}

  1. #代价函数
  2. def cost_func(params,nu, nm, nf,Y,R,lamda):
  3. X, Theta = deserialization(params, nu, nm, nf)
  4. cost = np.sum(np.power((X @ Theta.T - Y) * R,2))/ 2
  5. reg1 = np.sum(np.power(X, 2)) * lamda / 2
  6. reg2 = np.sum(np.power(Theta, 2)) * lamda / 2
  7. return cost+reg1+reg2

梯度下降

  1. #梯度下降
  2. def gradient_descent(params,nu,nm,nf,Y,R,lamda):
  3. X,Theta = deserialization(params,nu,nm,nf)
  4. Theta_grad = ((Theta @ X.T - Y.T) * R.T) @ X + lamda * Theta
  5. X_grad = ((X @ Theta.T - Y) * R) @ Theta + lamda * X
  6. return serialization(X_grad,Theta_grad)

初始化参数

  1. #初始化参数
  2. X = np.random.random((num_movies[0][0],num_features[0][0]))
  3. Theta = np.random.random((num_users[0][0],num_features[0][0]))
  4. lamda = 5
  5. params = serialization(X, Theta)
  6. Y_normal,means = standardization(Y,R)

优化

  1. #优化
  2. res = minimize(x0=params,
  3. fun=cost_func,
  4. args=(num_users,num_movies,num_features,Y_normal,R,lamda),
  5. method="TNC",
  6. jac=gradient_descent,
  7. options={'maxiter': 100})
  8. fit_params = res.x
  9. fit_X,fit_Theta = deserialization(fit_params,num_users,num_movies,num_features)

添加新用户和评分

  1. my_ratings = np.zeros((num_movies[0][0], 1))
  2. # 添加电影评分
  3. my_ratings[9] = 5
  4. my_ratings[66] = 5
  5. my_ratings[96] = 5
  6. my_ratings[121] = 4
  7. my_ratings[148] = 4
  8. my_ratings[285] = 3
  9. my_ratings[490] = 4
  10. my_ratings[599] = 4
  11. my_ratings[643] = 4
  12. my_ratings[958] = 5
  13. my_ratings[1117] = 3

预测

  1. #预测
  2. Y_pre = fit_X @ fit_Theta.T
  3. y_pre = Y_pre[:,-1] + means.flatten()
  4. index = np.argsort(-y_pre)
  5. print(index[:10])

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/958284
推荐阅读
相关标签
  

闽ICP备14008679号