1.引导脚本ex8_cofi.m
%% Machine Learning Online Class % Exercise 8 | Anomaly Detection and Collaborative Filtering % Instructions % --------------------------------------------------------------- % This file contains code that helps you get started on the % exercise. You will need to complete the following functions: % % estimateGaussian.m % selectThreshold.m % cofiCostFunc.m % % For this exercise, you will not need to change any code in this file, % or any other files other than those mentioned above. %% =============== Part 1: Loading movie ratings dataset ================ % You will start by loading the movie ratings dataset to understand the % structure of the data. % fprintf('Loading movie ratings dataset.\n\n'); % Load data load ('ex8_movies.mat'); % Y is a 1682x943 matrix, containing ratings (1-5) of 1682 movies on % 943 users % % R is a 1682x943 matrix, where R(i,j) = 1 if and only if user j gave a % rating to movie i % From the matrix, we can compute statistics like average rating. fprintf('Average rating for movie 1 (Toy Story): %f / 5\n\n', ... mean(Y(1, R(1, :)))); % We can "visualize" the ratings matrix by plotting it with imagesc imagesc(Y); ylabel('Movies'); xlabel('Users'); fprintf('\nProgram paused. Press enter to continue.\n'); pause; %% ============ Part 2: Collaborative Filtering Cost Function =========== % You will now implement the cost function for collaborative filtering. % To help you debug your cost function, we have included set of weights % that we trained on that. Specifically, you should complete the code in % cofiCostFunc.m to return J. % Load pre-trained weights (X, Theta, num_users, num_movies, num_features) load ('ex8_movieParams.mat'); % Reduce the data set size so that this runs faster num_users = 4; num_movies = 5; num_features = 3; X = X(1:num_movies, 1:num_features); Theta = Theta(1:num_users, 1:num_features); Y = Y(1:num_movies, 1:num_users); R = R(1:num_movies, 1:num_users); % Evaluate cost function J = cofiCostFunc([X(:) ; Theta(:)], Y, R, num_users, num_movies, num_features, 0); fprintf(['Cost at loaded parameters: %f '... '\n(this value should be about 22.22)\n'], J); fprintf('\nProgram paused. Press enter to continue.\n'); pause; %% ============== Part 3: Collaborative Filtering Gradient ============== % Once your cost function matches up with ours, you should now implement % the collaborative filtering gradient function. Specifically, you should % complete the code in cofiCostFunc.m to return the grad argument. fprintf('\nChecking Gradients (without regularization) ... \n'); % Check gradients by running checkNNGradients checkCostFunction; fprintf('\nProgram paused. Press enter to continue.\n'); pause; %% ========= Part 4: Collaborative Filtering Cost Regularization ======== % Now, you should implement regularization for the cost function for % collaborative filtering. You can implement it by adding the cost of % regularization to the original cost computation. % Evaluate cost function J = cofiCostFunc([X(:) ; Theta(:)], Y, R, num_users, num_movies, ... num_features, 1.5); fprintf(['Cost at loaded parameters (lambda = 1.5): %f '... '\n(this value should be about 31.34)\n'], J); fprintf('\nProgram paused. Press enter to continue.\n'); pause; %% ======= Part 5: Collaborative Filtering Gradient Regularization ====== % Once your cost matches up with ours, you should proceed to implement % regularization for the gradient. fprintf('\nChecking Gradients (with regularization) ... \n'); % Check gradients by running checkNNGradients checkCostFunction(1.5); fprintf('\nProgram paused. Press enter to continue.\n'); pause; %% ============== Part 6: Entering ratings for a new user =============== % Before we will train the collaborative filtering model, we will first % add ratings that correspond to a new user that we just observed. This % part of the code will also allow you to put in your own ratings for the % movies in our dataset! movieList = loadMovieList(); % Initialize my ratings my_ratings = zeros(1682, 1); % Check the file movie_idx.txt for id of each movie in our dataset % For example, Toy Story (1995) has ID 1, so to rate it "4", you can set my_ratings(3) = 4; % Or suppose did not enjoy Silence of the Lambs (1991), you can set my_ratings(98) = 2; % We have selected a few movies we liked / did not like and the ratings we % gave are as follows: my_ratings(41) = 3; my_ratings(67)= 5; my_ratings(85) = 4; my_ratings(127)= 5; my_ratings(173)= 3; my_ratings(214) = 5; my_ratings(498) = 1; my_ratings(696) = 3; my_ratings(1028)= 2; my_ratings(1147)= 5; my_ratings(1246)= 4; my_ratings(1498)= 5; my_ratings(1572)= 5; fprintf('\n\nNew user ratings:\n'); for i = 1:length(my_ratings) if my_ratings(i) > 0 fprintf('Rated %d for %s\n', my_ratings(i), ... movieList{i}); end end fprintf('\nProgram paused. Press enter to continue.\n'); pause; %% ================== Part 7: Learning Movie Ratings ==================== % Now, you will train the collaborative filtering model on a movie rating % dataset of 1682 movies and 943 users fprintf('\nTraining collaborative filtering...\n'); % Load data load('ex8_movies.mat'); % Y is a 1682x943 matrix, containing ratings (1-5) of 1682 movies by 943 users % R is a 1682x943 matrix, where R(i,j) = 1 if and only if user j gave a rating to movie i % Add our own ratings to the data matrix Y = [my_ratings Y]; R = [(my_ratings ~= 0) R]; % Normalize Ratings [Ynorm, Ymean] = normalizeRatings(Y, R); % Useful Values num_users = size(Y, 2); num_movies = size(Y, 1); num_features = 10; % Set Initial Parameters (Theta, X) X = randn(num_movies, num_features); Theta = randn(num_users, num_features); initial_parameters = [X(:); Theta(:)]; % Set options for fmincg options = optimset('GradObj', 'on', 'MaxIter', 100); % Set Regularization lambda = 10; theta = fmincg (@(t)(cofiCostFunc(t, Ynorm, R, num_users, num_movies, ... num_features, lambda)), ... initial_parameters, options); % Unfold the returned theta back into U and W X = reshape(theta(1:num_movies*num_features), num_movies, num_features); Theta = reshape(theta(num_movies*num_features+1:end), ... num_users, num_features); fprintf('Recommender system learning completed.\n'); fprintf('\nProgram paused. Press enter to continue.\n'); pause; %% ================== Part 8: Recommendation for you ==================== % After training the model, you can now make recommendations by computing % the predictions matrix. p = X * Theta'; my_predictions = p(:,1) + Ymean; movieList = loadMovieList(); [r, ix] = sort(my_predictions, 'descend'); fprintf('\nTop recommendations for you:\n'); for i=1:10 j = ix(i); fprintf('Predicting rating %.1f for movie %s\n', my_predictions(j), movieList{j}); end fprintf('\n\nOriginal ratings provided:\n'); for i = 1:length(my_ratings) if my_ratings(i) > 0 fprintf('Rated %d for %s\n', my_ratings(i), ... movieList{i}); end end
2.cofiCostFunc.m
核心函数:计算协同过滤推荐算法的损失函数J值以及J对X,Theta的偏导值。里面的计算推荐用向量化的方式写,可以提高运行性能。一开始可以写成for循环验证结果是否正确,正确之后再慢慢想怎么改成向量化的表达方式。
function [J, grad] = cofiCostFunc(params, Y, R, num_users, num_movies, num_features, lambda) %COFICOSTFUNC Collaborative filtering cost function % [J, grad] = COFICOSTFUNC(params, Y, R, num_users, num_movies, ... % num_features, lambda) returns the cost and gradient for the % collaborative filtering problem. % Unfold the U and W matrices from params X = reshape(params(1:num_movies*num_features), num_movies, num_features); Theta = reshape(params(num_movies*num_features+1:end), ... num_users, num_features); % You need to return the following values correctly X_grad = zeros(size(X)); Theta_grad = zeros(size(Theta)); % ====================== YOUR CODE HERE ====================== % Instructions: Compute the cost function and gradient for collaborative % filtering. Concretely, you should first implement the cost % function (without regularization) and make sure it is % matches our costs. After that, you should implement the % gradient and use the checkCostFunction routine to check % that the gradient is correct. Finally, you should implement % regularization. % % Notes: X - num_movies x num_features matrix of movie features % Theta - num_users x num_features matrix of user features % Y - num_movies x num_users matrix of user ratings of movies % R - num_movies x num_users matrix, where R(i, j) = 1 if the % i-th movie was rated by the j-th user % % You should set the following variables correctly: % % X_grad - num_movies x num_features matrix, containing the % partial derivatives w.r.t. to each element of X % Theta_grad - num_users x num_features matrix, containing the % partial derivatives w.r.t. to each element of Theta % 循环法 % [m,n] = size(R); % sum = 0; % for i = 1 : m % for j = 1 : n % if R(i,j) == 1 % sum = sum + (Theta(j,:) * X(i,:)' - Y(i,j)).^2; % end % end % end % 计算J值 % J = 1 / 2 * sum; % 矩阵化法 predY = (X*Theta') .* R; J = 1/2 * sum(sum((predY-Y).^2)) + lambda/2 * sum(sum(Theta.^2)) + lambda/2 * sum(sum(X.^2)); % 计算X_grad for i = 1 : num_movies % <!---这里的sum一定要在内层循环开始前清零---!> sum1 = zeros(1,num_features); for j = 1 : num_users if R(i,j) == 1 sum1 = sum1 + (Theta(j,:) * X(i,:)' - Y(i,j)) .* Theta(j,:); end end X_grad(i,:) = sum1 + lambda * X(i,:); end % 计算Theta_grad for j = 1 : num_users % <!---这里的sum一定要在内层循环开始前清零---!> sum2 = zeros(1,num_features); for i = 1 : num_movies if R(i,j) == 1 sum2 = sum2 + (Theta(j,:) * X(i,:)' - Y(i,j)) .* X(i,:); end end Theta_grad(j,:) = sum2 + lambda * Theta(j,:); end grad = [X_grad(:); Theta_grad(:)]; end
1.将每个用户对每个电影的评分用Matlab自带的imagesc函数可视化一下:
2.一些计算值的正确性验证:
3.进行100次迭代训练CF算法的参数:
4.在我们自己对一些电影评分后,利用CF算法对我们可能喜欢的电影进行预测(推荐),并返回top50我们可能会喜欢的电影(预测我们对这1682部电影的评分,然后将评分降序排列,取top50来展示):