brunch

You can make anything
by writing

C.S.Lewis

by 라인하트 Feb 15. 2021

머신러닝 옥타브 실습(8-3):협업 필터링 구현

   온라인 강의 플랫폼 코세라의 창립자인 앤드류 응 (Andrew Ng) 교수는 인공지능 업계의 거장입니다. 그가 스탠퍼드 대학에서 머신 러닝 입문자에게 한 강의를 그대로 코세라 온라인 강의 (Coursera.org)에서 무료로 배울 수 있습니다. 이 강의는 머신러닝 입문자들의 필수코스입니다. 인공지능과 머신러닝을 혼자 공부하면서 자연스럽게 만나게 되는 강의입니다. 


Programming Exercise 8: 

Anomaly Detection and Recommender Systems (이상 탐지와 추천 시스템)


2. Recommender Systems (추천 시스템)


   In this part of the exercise, you will implement the collaborative filtering learning algorithm and apply it to a dataset of movie ratings. This dataset consists of ratings on a scale of 1 to 5. The dataset has nu = 943 users, and nm = 1682 movies. For this part of the exercise, you will be working with the script ex8 cofi.m.

   In the next parts of this exercise, you will implement the function cofiCostFunc.m that computes the collaborative filtering objective function and gradient. After implementing the cost function and gradient, you will use fmincg.m to
learn the parameters for collaborative filtering.


   이번 실습은 협업 필터링 학습 알고리즘을 구현하고 영화 등급 데이터 셋에 적용합니다. 그룹 렌즈 연구소의 'MoviesLens 100K dataset'에서 등급은 1 ~ 5 단계로 측정합니다. 데이터셋의 nu= 943, nm = 1692개입니다. 이번 실습은 ex8_confi.m 파일을 사용합니다. 

   이번 실습에서 협업 필터링 목적 함수와 기울기를 계산하는 cofiCostFunc.m 파일을 작성합니다. 비용 함수와 기울기를 구현한 후 fminch.m 파일을 사용하여 협업 필터링을 위한 파라미터를 학습합니다. 



2.1 Movie ratings dataset (영화 등급 데이터셋)


   The first part of the script ex8 cofi.m will load the dataset ex8 movies.mat, providing the variables Y and R in your Octave/MATLAB environment.

   The matrix Y (a num movies × num users matrix) stores the ratings y(i,j) (from 1 to 5). The matrix R is an binary-valued indicator matrix, where R(i, j) = 1 if user j gave a rating to movie i, and R(i, j) = 0 otherwise. The objective of collaborative filtering is to predict movie ratings for the movies that users have not yet rated, that is, the entries with R(i, j) = 0. This will allow us to recommend the movies with the highest predicted ratings to the user.

   To help you understand the matrix Y, the script ex8 cofi.m will compute the average movie rating for the first movie (Toy Story) and output the average rating to the screen.


   ex8_confi.m 파일의 첫 번째 파트는 데이터셋 ex8_movies.mat 파일을 옥타브/ 매트랩 프로그램에 로드합니다. 변수 Y와 R은 자동으로 제공합니다. 

   행렬 Y는 영화의 수 X 사용자 수 차원입니다. 행렬 Y의 성분 y^(i,j)는 1에서 5까지의 값을 가집니다. 행렬 R은 사용자 j가 영화 i에 등급을 지정하면 R^(i,j) = 1이고, 그렇지 않으면 R^(i,j) = 0입니다. 따라서, 행렬 R은 이진수로 구성된 행렬입니다. 협업 필터링의 목적은 사용자가 아직 평가하지 않은 영화 (R^(i,j) = 0)에 대한 영화 등급을 예측하는 것입니다. 왜냐하면 예상 등급이 가장 높은 영화를 사용자에게 추천할 수 있기 때문입니다. 

   행렬 Y를 이해할 수 있도록 ex8_confi.m 파일은 첫 번째 영화인 토이 스토리 (Toy Story)의 평균 영화 등급을 계산하고 평균 등급을 출력합니다. 



   Throughout this part of the exercise, you will also be working with the matrices, X and Theta. The i-th row of X corresponds to the feature vector x(i) for the i-th movie, and the j-th row of Theta corresponds to one parameter vector θ(j), for the j-th user. Both x(i) and θ(j) are n-dimensional vectors. For the purposes of this exercise, you will use n = 100, and therefore, x(i) ∈ R100 and θ(j) ∈ R100. Correspondingly, X is a nm × 100 matrix and Theta is a nu × 100 matrix.


      이번 실습은 행렬 X와 Theta를 설계합니다. 행렬 X의 i 번째 행은 i 번째 영화에 대한 피처 벡터 x^(i)이고, 행렬 Theta의 j 번째 행은 j번째 사용자에 대한 파라미터 벡터 θ^(j)입니다. x^(i)와 θ^(j)는 모두 n 차원 벡터입니다. 이번 실습에서 n = 100 이므로 x^(i)와 θ^(j)는 R^(100) 차원 벡터입니다. 따라서 행렬 X는 nm X100 행렬이고, Theta는 nu X 100 행렬입니다.



<Part 1 : 영화 등급 데이터셋 시각화>


(1) 데이터 로드 


clear ;             % 옥타브 프로그램에 모든 변수를 제거

close all;         % 터미널 이외의 창을 닫음

clc                   % 터미널을 깨끗이 정리 


    ex8_movies.mat 파일은 2개의 데이터셋을 옥타브 프로그램에 로드합니다. 


load ('ex8_movies.mat');


    데이터 행렬 R은 1682 X 943차원의 행렬로 1682개 영화에 대해 943 사용자가 영화 등급에 대한 평가 여부를 보유합니다. 데이터 행렬 Y는 1682 X 943차원의 행렬로 1682개 영화에 대한  943 사용자가 평가한 영화 등급을 보유합니다. 


>> load ('ex8_movies.mat');

>> whos

Variables in the current scope:


   Attr Name        Size                     Bytes  Class

   ==== ====        ====                     =====  =====

        R                1682x943                  1586126  logical

        Y                1682x943                 12689008  double


Total is 3172252 elements using 14275134 bytes


>> R

R =

 Columns 1 through 17:

   1   1   0   0   1   1   0   0   0   1   0   0   1   0   1   1   1

   1   0   0   0   1   0   0   0   0   0   0   0   1   0   0   0   0

   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

   1   0   0   0   0   0   1   0   0   1   0   1   1   0   0   1   0

   1   0   0   0   0   0   0   0   0   0   0   0   1   0   0   0   0

   ...


>> Y

Y =

 Columns 1 through 17:

   5   4   0   0   4   4   0   0   0   4   0   0   3   0   1   5   4

   3   0   0   0   3   0   0   0   0   0   0   0   3   0   0   0   0

   4   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

   3   0   0   0   0   0   5   0   0   4   0   5   5   0   0   5   0

   3   0   0   0   0   0   0   0   0   0   0   0   1   0   0   0   0


(2) 첫 번째 영화의 평균 영화 등급


   첫 번째 영화 토이 스토리의 모든 평가 결과를  실제 평가한 사용자 수로 나눕니다. 


> Y(1,:)     % 첫 번째 영화의 모든 평가 지표

ans =

 Columns 1 through 17:

   5   4   0   0   4   4   0   0   0   4   0   0   3   0   1   5   4


 Columns 18 through 34:

   5   0   3   5   0   5   0   5   3   0   0   0   0   0   0   0   0


...


>> sum(Y(1,:))

ans =  1753


>> R(1,:)     % 첫 번째 영화를 평가 여부 

ans =

 Columns 1 through 17:

   1   1   0   0   1   1   0   0   0   1   0   0   1   0   1   1   1


 Columns 18 through 34:

   1   0   1   1   0   1   0   1   1   0   0   0   0   0   0   0   0


   ....


>> sum(R(1,:))

ans =  452


      다음과 같이 계산합니다.


>> sum(Y(1,:) / sum(R(1,:)))

ans =  3.8783




%%% mean() 함수의 이해 


   평균을 구하는 함수는 mean()입니다. 


>> A= magic(3)

A =

   8   1   6

   3   5   7

   4   9   2


>> mean(A)

ans =

   5   5   5


>> mean(A,2)

ans =


   5

   5

   5


%%% 코드를 단순하게 만들기


   코드를 더욱 단순하게 만들 수 있습니다. 결국 필요한 것은 Y(1,:)의 데이터 중에서  R(1,:) == 1 인 데이터를 찾는 것입니다. 


>> Y(1,find(R(1,:) ==1))

ans =

 Columns 1 through 17:

   5   4   4   4   4   3   1   5   4   5   3   5   5   5   3   5   4


 Columns 18 through 34:

   5   5   4   5   2   4   4   5   5   2   2   3   4   3   3   3   4


...


 Columns 443 through 452:

   5   3   3   4   3   2   3   4   4   5


>>  mean(Y(1,find(R(1,:) ==1)))

ans =  3.8783


>> mean(Y(1,R(1,:)))

ans =  3.8783



(3) 데이터 시각화

 

   1682 X 943차원의 행렬 Y를 시각화합니다. 행렬 Y는 0 ~ 5까지의 별점을 가지고 있습니다.  이것을 효과적으로 이해할 수 있도록 시각화합니다.


imagesc(Y);

ylabel('Movies');

xlabel('Users');




   좀 더 보기 편하게 변경합니다.


colorbar            % 컬러가 의미하는 바를 표시 

hold on

imagesc(Y);

ylabel('Movies');

xlabel('Users');

hold off


2.2 Collaborative filtering learning algorithm


   Now, you will start implementing the collaborative filtering learning algo- rithm. You will start by implementing the cost function (without regulariza- tion). The collaborative filtering algorithm in the setting of movie recommendations considers a set of n-dimensional parameter vectors x(1) , ..., x(nm ) and θ(1),...,θ(nu), where the model predicts the rating for movie i by user j as y(i,j) = (θ(j))T x(i). Given a dataset that consists of a set of ratings produced by some users on some movies, you wish to learn the parameter vectors x(1),...,x(nm),θ(1),..., θ(nu) that produce the best fit (minimizes the squared error).

   You will complete the code in cofiCostFunc.m to compute the cost func- tion and gradient for collaborative filtering. Note that the parameters to the function (i.e., the values that you are trying to learn) are X and Theta. In order to use an off-the-shelf minimizer such as fmincg, the cost function has been set up to unroll the parameters into a single vector params. You had previously used the same vector unrolling method in the neural networks programming exercise.


   이제 협업 필터링 알고리즘 구현을 시작합니다. 먼저 정규화가 없는 비용 함수를 구현합니다.  영화를 추천하는 협업 필터링 알고리즘은 n차원 파라미터 벡터 x(1) , ..., x(nm ) and θ(1),...,θ(nu)를 고려합니다. 모델은 사용자 j가 영화 i에 대한 등급 y(i,j) = (θ^(j))^T x^(i)로 예측합니다. 영화의 일부만을 사용자의 일부가 생성한 평가 등급으로 구성된 데이터 셋이 있다면, 파라미터 변수 벡터   x(1) , ..., x(nm ) and θ(1),...,θ(nu)는 오차의 제곱을 최소화하는 최적의 적합을 배웁니다. 

   cofiCostFunc.m 파일은 협업 필터링을 위한 비용 함수와 기울기를 계산합니다. 학습해야 하는 함수에 대한 파라미터는 X와 Theta입니다. fmincg와 같은 라이브러리 함수는 단일 벡터 파라미터를 계산할 수 있도록 설정되어 있습니다. 과거에 신경망 프로그래밍 실습에서와 동일하게  언롤링 방법으로 벡터를 사용했습니다.



2.2.1 Collaborative filtering cost function 

         (협업 필터링 비용 함수)


   The collaborative filtering cost function (without regularization) is given by


You should now modify cofiCostFunc.m to return this cost in the vari- able J. Note that you should be accumulating the cost for user j and movie i only if R(i,j) = 1.

   After you have completed the function, the script ex8 cofi.m will run your cost function. You should expect to see an output of 22.22.

   You should now submit your solutions.


   정규화 항이 없는  협업 필터링 비용 함수는 다음과 같습니다.  

   cofiCostFunc.m 파일을 작성하고 비용 J를 반환합니다. R(i,j)= 1인 경우에만 사용자 j 및 영화 i에 대한 비용을 누적합니다. 

   ex8_confi.m 파일은 비용 함수를 실행하고 비용을 22.22로 출력합니다. 

   완료하면 submit 명령어로 제출합니다.



Implementation Note: 

   We strongly encourage you to use a vectorized implementation to compute J, since it will later by called many times by the optimization package fmincg. As usual, it might be easiest to first write a non-vectorized implementation (to make sure you have the right answer), and the modify it to become a vectorized implementation (checking that the vectorization steps don’t change your algorithm’s out- put). To come up with a vectorized implementation, the following tip might be helpful: You can use the R matrix to set selected entries to 0. For example, R .* M will do an element-wise multiplication between M and R; since R only has elements with values either 0 or 1, this has the effect of setting the elements of M to 0 only when the corresponding value in R is 0. Hence, sum(sum(R.*M)) is the sum of all the elements of M for which the corresponding element in R equals 1.


구현 노트 : 

   최적화 패키지 fmincg 패키지는 비용 함수 J를 계산하기 위해 cofiCostFunc.m 파일을 여러 번 호출합니다. 벡터화된 구현을 하는 것이 좋습니다. 벡터화된 구현이 어려울 경우 for 루프를 작성한 후 수정하는 것도 좋습니다. 벡터화된 구현은 다음 팁이 도움이 될 것입니다.

   R 행렬을 사용하여 선택한 항목을 0 설정할 수 있습니다. 예를 들어, R .* M은 M과 R의 각 성분 별 곱셈을 수행합니다. R의 성분은 0 또는 1이므로 M의 성분 중에 R의 값이 1 성분의 위치가 같은 값만 남습니다. 남은 행렬의 모든 값을 합산할 때는 다음 코드는 R(i,j) = 1 인 모든 성분을 합산합니다.


 sum (sum(R .* M))




<Part 2: 협업 필터링 비용 함수>


(1) 데이터 로드 


clear ; close all; clc  



   ex8_movies.mat 파일과 ex8_movieParams.mat 파일을 옥타브 프로그램에 로드합니다. 


load ('ex8_movies.mat');

load ('ex8_movieParams.mat'); 


   데이터셋 X는 1682 X 10차원 행렬로 1682개 영화에 대한 특징을 나타내는 프로파일이고, 데이터셋 Theta는 943 X 10차원 행렬로 943명의 사용자에 대한 영화 취향을 나타내는 프로파일입니다. 


>> load ('ex8_movieParams.mat');

>> whos

Variables in the current scope:


   Attr Name              Size                     Bytes  Class

   ==== ====              ====                     =====  =====

        Theta           943x10                     75440  double

        X              1682x10                    134560  double

        num_features      1x1                          8  double

        num_movies        1x1                          8  double

        num_users         1x1                          8  double


Total is 26253 elements using 210024 bytes


>> Theta   % 사용자 프로파일

Theta =

 Columns 1 through 5:

   2.8544e-01  -1.6843e+00   2.6294e-01  -2.8732e-01   5.8573e-01

   5.0501e-01  -4.5465e-01   3.1746e-01  -1.1509e-01   5.6770e-01

  -4.3192e-01  -4.7880e-01   8.4671e-01  -1.1731e-02  -1.3858e-01

   7.2860e-01  -2.7189e-01   3.2684e-01  -2.5072e-01  -4.7102e-01

   5.2119e-02  -1.3807e+00   6.3794e-01  -2.3198e-01   2.4634e-01

   ...


>> X           % 영화 프로파일

X =

 Columns 1 through 5:

   1.0487e+00  -4.0023e-01   1.1941e+00   3.7113e-01   4.0761e-01

   7.8085e-01  -3.8563e-01   5.2120e-01   2.2736e-01   5.7011e-01

   6.4151e-01  -5.4785e-01  -8.3796e-02  -5.9852e-01  -1.7694e-02

   4.5362e-01  -8.0022e-01   6.8048e-01  -8.1743e-02   1.3660e-01

   9.3754e-01   1.0609e-01   3.6195e-01   8.6646e-02   2.8751e-01


>> num_users             % 총 사용자 수

num_users =  943


>> num_movies           % 총 영화 수 

num_movies =  1682


>> num_features         % 총 피처 수

num_features =  10



(2) 빠른 실행을 위한 데이터를 축소


   실행 속도를 높이기 위해 데이터셋의 크기를 줄입니다. 실제 앞에서 다른 표를 그대로 활용합니다. 


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);


각 데이터 행렬이 어떤 모양인지를 확인합니다. 


>> R              % 영화에 대한 사용자 평가 여부 (영화 수 X 사용자 수) : 5 X 4차원 

R =


   1   1   0   0

   1   0   0   0

   1   0   0   0

   1   0   0   0

   1   0   0   0


>> Y              % 영화에 대한 사용자 평가 (영화 수 X 사용자 수) : 5 X 4차원 

Y =

   5   4   0   0

   3   0   0   0

   4   0   0   0

   3   0   0   0

   3   0   0   0


>> X              % 영화 프로파일 (영화 수 X 영화 피처의 수) : 5 X 3차원

X =

   1.048686  -0.400232   1.194119

   0.780851  -0.385626   0.521198

   0.641509  -0.547854  -0.083796

   0.453618  -0.800218   0.680481

   0.937538   0.106090   0.361953


>> Theta        % 사용자 프로파일 (사용자 수 X 영화 피처의 수) : 4 X 3차원

Theta =

   0.28544  -1.68427   0.26294

   0.50501  -0.45465   0.31746

  -0.43192  -0.47880   0.84671

   0.72860  -0.27189   0.32684


(3) 비용 계산하기


   비용을 계산하는 cofiCostFunc.m 파일을 작성합니다. 파일을 호출할 때 영화 프로파일  X(:)과 사용자 프로파일 Theta(:)로 만든 벡터 param , 영화에 대한 사용자 평가 척도 Y, 영화에 대한 사용자 평가 여부 R, 총 사용자 수 num_users, 총 영화 수 num_movies, 총 피처 수 num_features, 그리고 정규화 파라미터 lambda를 전달합니다.


J = cofiCostFunc([X(:) ; Theta(:)], Y, R, num_users, num_movies,  num_features, 0);           


   cofiCostFunc.m 파일은 비용 J를 반환합니다. 파일은 인공 신경망 때와 마찬가지로 데이터를 벡터 단위로 처리합니다. m X n 차원 행렬을 언롤링하여 벡터로 재배열합니다. 


>> X               % 행렬 X는 5 X 3차원

X =

   1.048686  -0.400232   1.194119

   0.780851  -0.385626   0.521198

   0.641509  -0.547854  -0.083796

   0.453618  -0.800218   0.680481

   0.937538   0.106090   0.361953

 

>> X(:)           % 언롤링 벡터 X는 15 X 1차원 

ans =

   1.048686

   0.780851

   0.641509

   0.453618

   0.937538

  -0.400232

  -0.385626

  -0.547854

  -0.800218

   0.106090

   1.194119

   0.521198

  -0.083796

   0.680481

   0.361953


>> Y               % 행렬 Y는 5 X 4차원

Y =


   5   4   0   0

   3   0   0   0

   4   0   0   0

   3   0   0   0

   3   0   0   0


>> Y(:)          % 언롤링 벡터 Y는 120X 1차원 

ans =

   5

   3

   4

   3

   3

   4

   0

   0

   0

   0

   0

   0

   0

   0

   0

   0

   0

   0

   0

   0


   그리고 이 두 벡터를 벡터 param으로 다시 언롤링합니다.  벡터 param은 27 X 1차원 행렬입니다.


>> [X(:) ; Theta(:)]

ans =

   1.048686

   0.780851

   0.641509

   0.453618

   0.937538

  -0.400232

  -0.385626

  -0.547854

  -0.800218

   0.106090

   1.194119

   0.521198

  -0.083796

   0.680481

   0.361953

   0.285444

   0.505013

  -0.431917

   0.728598

  -1.684265

  -0.454648

  -0.478804

  -0.271894

   0.262939

   0.317462

   0.846711

   0.326844


>> size ([X(:) ; Theta(:)])

ans =

   27    1



(4) cofiCostFunc.m 파일 분석



function [J, grad] = cofiCostFunc(params, Y, R, num_users, num_movies, ...

                                  num_features, lambda)

%COFICOSTFUNC 협업 필터링 비용 함수 

%   [J, grad] = COFICOSTFUNC(params, Y, R, num_users, num_movies, ...

%   num_features, lambda) 

%           협업 필터링 문제의 비용 J와 경사도를 반환 


% 언롤링된 파라미터 벡터 X와 Theta를 다시 원래  X와 Theta의 차원으로 재배열 

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);


            

% 변수 초기화 

J = 0;

X_grad = zeros(size(X));

Theta_grad = zeros(size(Theta));


% ====================== YOUR CODE HERE ======================

% Instructions: 

%          협업 필터링의 비용 함수와 기울기를 계싼 비용 함수와 계산

%          우선, 정규화 항이 없는 비용 함수를 계산하고 예상 비용도 같은 지를 확인

%          다음, 기울기를 계산하고 기울기가 맞는 지 checkCostFunction 루틴으로 확인

%          마지막으로, 정규화를 구현

                   

% Notes: 

            X : num_movies  x num_features.    : 영화 프로파일 행렬

%        Theta : num_users  x num_features: 사용자 프로파일 행렬 

%        Y : num_movies x num_users  : 사용자의 영화 평가 점수 행렬 

%        R : num_movies x num_users  : 사용자의 영화 평가 여부 행렬

%                                                              (R(i,j) = 1 이면 평가, 

%

% 다음 변수를 올바르게 선언하시오

%        X_grad : num_movies x num_features : X의 각 성분에 대한 편미분 행렬 

%        Theta_grad : num_users x num_features : Theta의 각 성분에 대한 편미분 행렬

%






% =============================================================


grad = [X_grad(:); Theta_grad(:)];


end



%%% 벡터 params에서 X와 Theta의 원래 행렬로 재배열 

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);


   cofiCostFunc.m 파일로 입력된 값을 다시 재배열합니다. 


>> params = [X(:) ; Theta(:)]

>> 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);


>> X

X =

   1.048686  -0.400232   1.194119

   0.780851  -0.385626   0.521198

   0.641509  -0.547854  -0.083796

   0.453618  -0.800218   0.680481

   0.937538   0.106090   0.361953


>> Theta

Theta =

   0.28544  -1.68427   0.26294

   0.50501  -0.45465   0.31746

  -0.43192  -0.47880   0.84671

   0.72860  -0.27189   0.32684


   정상적으로 X와 Theta를 다시 복원합니다. 


(5) 정규화 항이 없는 비용 함수 작성


    정규화 항이 없는 비용 함수 J의 공식은 다음과 같습니다.


   벡터화된 구현으로 정리합니다. Theta는 4 X 3 행렬이고, X는 5 X 3 행렬입니다. 행렬 계산을 위해 Theta와 X의 위치를 바꾸고 Theta를 전치합니다. 


>> Theta * X

error: operator *: nonconformant arguments (op1 is 4x3, op2 is 5x3)


>> X * Theta

error: operator *: nonconformant arguments (op1 is 5x3, op2 is 4x3)


>> X * Theta'

ans =

   1.287418   1.090653   0.749762   1.263181

   1.009428   0.735125   0.288681   0.844126

   1.083812   0.546449  -0.085715   0.588972

   1.656187   0.808928   0.763394   0.770491

   0.184102   0.540142  -0.149265   0.772545


   사용자가 영화를 평가한 점수를 나타내는 Y는 5X4 행렬로 '총 영화 수 X 총 사용자 수'입니다. X*Theta' 도 똑같이 5 X 4 행렬로 나타냅니다. 


>> Y

Y =

   5   4   0   0

   3   0   0   0

   4   0   0   0

   3   0   0   0

   3   0   0   0


    두 행렬에 대한 뺄셈과 함께 제곱을 계산하고, 합산을 합니다.  


>> X * Theta' - Y     % 오차를 계산

ans =

  -3.712582  -2.909347   0.749762   1.263181

  -1.990572   0.735125   0.288681   0.844126

  -2.916188   0.546449  -0.085715   0.588972

  -1.343813   0.808928   0.763394   0.770491

  -2.815898   0.540142  -0.149265   0.772545


>> (X * Theta' - Y) .^2          % 오차의 제곱

ans =

   1.3783e+01   8.4643e+00   5.6214e-01   1.5956e+00

   3.9624e+00   5.4041e-01   8.3337e-02   7.1255e-01

   8.5042e+00   2.9861e-01   7.3470e-03   3.4689e-01

   1.8058e+00   6.5437e-01   5.8277e-01   5.9366e-01

   7.9293e+00   2.9175e-01   2.2280e-02   5.9683e-01


>> sum((X * Theta' - Y) .^2)         % 오차를 열 단위로 합산 

ans =

   35.9849   10.2494    1.2579    3.8455


>> sum(sum((X * Theta' - Y) .^2))      % 오차를 행 단위로 합산

ans =  51.338


>> 1/2 * sum(sum((X * Theta' - Y) .^2))     % 1/2을 곱함

ans =  25.669


 따라서, 비용 J = 25.669입니다. 




(6) 실제로 영화를 평가한 사용자들의 데이터만을 비용 함수 J를 보정


   문제에서 비용 J = 22.22라고 했습니다. cofiCostFunc.m 파일에서 비용 J를 작성하면서 빠뜨린 전제가 있습니다. 바로 R(i,j)= 1인 경우에만 사용자 j 및 영화 i에 대한 비용을 누적합니다. 평가하지 않은 평가 항목은 누적해서는 안됩니다. 


   어떻게 할 수 있을까요?


>> X * Theta' - Y      % 5 X 4 행렬

ans =

  -3.712582  -2.909347   0.749762   1.263181

  -1.990572   0.735125   0.288681   0.844126

  -2.916188   0.546449  -0.085715   0.588972

  -1.343813   0.808928   0.763394   0.770491

  -2.815898   0.540142  -0.149265   0.772545


>> R                    % 행렬 R은 5 X 4 행렬로 사용자가 영화에 대한 평가 여부를 표시

R =

   1   1   0   0

   1   0   0   0

   1   0   0   0

   1   0   0   0

   1   0   0   0


   두 5 X 4 행렬의 각 성분끼리 곱셈을 한다면 R(i,j) = 1인 값은 남고, R(i,j) = 0인 값은 0이 됩니다. 


>> (X * Theta' - Y) .* R

ans =

  -3.71258  -2.90935   0.00000   0.00000

  -1.99057   0.00000   0.00000   0.00000

  -2.91619   0.00000  -0.00000   0.00000

  -1.34381   0.00000   0.00000   0.00000

  -2.81590   0.00000  -0.00000   0.00000


   비용 함수 J를 계산하는 코드를 다시 작성합니다. 


>> J = 1/2 * sum(sum(((X * Theta' - Y) .* R) .^2))

J =  22.225


    문제와 같은 비용 J를 출력합니다.


(7) 정답


function [J, grad] = cofiCostFunc(params, Y, R, num_users, num_movies, ...

                                  num_features, lambda)

%COFICOSTFUNC 협업 필터링 비용 함수 

%   [J, grad] = COFICOSTFUNC(params, Y, R, num_users, num_movies, ...

%   num_features, lambda) 

%           협업 필터링 문제의 비용 J와 경사도를 반환 


% 언롤링된 파라미터 벡터 X와 Theta를 다시 원래  X와 Theta의 차원으로 재배열 

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);


            

% 변수 초기화 

J = 0;

X_grad = zeros(size(X));

Theta_grad = zeros(size(Theta));


% ====================== YOUR CODE HERE ======================

% Instructions: 

%          협업 필터링의 비용 함수와 기울기를 계산 비용 함수와 계산

%          우선, 정규화 항이 없는 비용 함수를 계산하고 예상 비용도 같은 지를 확인

%          다음, 기울기를 계산하고 기울기가 맞는지 checkCostFunction 루틴으로 확인

%          마지막으로, 정규화를 구현

                   

% Notes: 

            X : num_movies  x num_features.    : 영화 프로파일 행렬

%        Theta : num_users  x num_features: 사용자 프로파일 행렬 

%        Y : num_movies x num_users  : 사용자의 영화 평가 점수 행렬 

%        R : num_movies x num_users  : 사용자의 영화 평가 여부 행렬

%                                                              (R(i,j) = 1 이면 평가, 

%

% 다음 변수를 올바르게 선언하시오

%        X_grad : num_movies x num_features : X의 각 성분에 대한 편미분 행렬 

%        Theta_grad : num_users x num_features : Theta의 각 성분에 대한 편미분 행렬

%


J = 1/2 * sum(sum(((X * Theta' - Y) .* R) .^2));




% =============================================================


grad = [X_grad(:); Theta_grad(:)];


end


(8) 결과 확인




2.2.2 Collaborative filtering gradient (협업 필터링 기울기) 


   Now, you should implement the gradient (without regularization). Specifi- cally, you should complete the code in cofiCostFunc.m to return the vari- ables X grad and Theta grad. Note that X grad should be a matrix of the same size as X and similarly, Theta grad is a matrix of the same size as Theta. The gradients of the cost function is given by:


   정규화 항이 없는 기울기를 구현합니다. cofiCostFunc.m는 X_grad와 Theta_grad를 반환합니다. X_grad는 X와 같은 크기의 행렬이고, Theta_grad는 Theta와 같은 차원의 행렬입니다. 비용 함수의 기울기는 다음과 같습니다.  



   Note that the function returns the gradient for both sets of variables by unrolling them into a single vector. After you have completed the code to compute the gradients, the script ex8 cofi.m will run a gradient check (checkCostFunction) to numerically check the implementation of your gradients. If your implementation is correct, you should find that the analytical and numerical gradients match up closely.

   You should now submit your solutions.


   이 함수는 두 변수가 단일 벡터로 언롤링하여 기울기를 반환합니다. cofiCostFunc.m 파일에서 기울기를 계산하는 코드를 완료합니다. 그리고 ex8_cofi.m 파일은 checkCostFunction.m 파일을 호출하여 기울기 구현을 수치적으로 검사합니다. 구현이 올바를 경우 분석 및 수치 기울기가 밀접하게 일치합니다. 

   이제 설루션을 제출합니다. 


Implementation Note: 

   You can get full credit for this assignment without using a vectorized implementation, but your code will run much more slowly (a small number of hours), and so we recommend that you try to vectorize your implementation.

   To get started, you can implement the gradient with a for-loop over movies (for computing ∂J/∂xk^(i) ) and a for-loop over users (for computing ∂J /∂θk^(j)). When you first implement the gradient, you might start with an unvectorized version, by implementing another inner for-loop that computes each element in the summation. After you have completed the gradient computation this way, you should try to vectorize your implementation (vectorize the inner for-loops), so that you’re left with only two for-loops (one for looping over movies to compute ∂J / ∂ xk^(i) for each movie, and one for looping 

over users to compute ∂J/ ∂θk^(i) for each user).


구현 노트:

   벡터화된 구현을 사용하지 않고 코드를 작성할 수 있지만 훨씬 더 느리게 실행됩니다. 벡터화 구현으로 작성합니다. 영화에 대한 for 루프와 사용자에 대한 for 루프로 기울기를 구현합니다. 기울기를 처음 구현할 때 합산의 각 요소를 계산하는 또 다른 내부 for 루프를 구현하여 벡터화되지 않은 코드를 작성할 수 있습니다. 이런 식으로 기울기를 계산한 후 벡터화 구현으로 전환할 수 있습니다. 



<Part 3 : 협업 필터링 기울기 >


(1) 비용과 기울기 계산하기


   비용과 기울기를 계산하는 cofiCostFunc.m 파일을 작성합니다. 파일을 호출할 때 영화 프로파일  X(:)과 사용자 프로파일 Theta(:)로 만든 벡터 param , 영화에 대한 사용자 평가 척도 Y, 영화에 대한 사용자 평가 여부 R, 총 사용자 수 num_users, 총 영화 수 num_movies, 총 피처 수 num_features, 그리고 정규화 파라미터 lambda를 전달합니다.


J = cofiCostFunc([X(:) ; Theta(:)], Y, R, num_users, num_movies,  num_features, 0);           


   cofiCostFunc.m 파일은 비용 J를 반환합니다. 파일은 인공 신경망 때와 마찬가지로 데이터를 벡터 단위로 처리합니다. m X n 차원 행렬을 언롤링하여 벡터로 재배열합니다. 



(2) 기울기를 계산


   기울기를 계산하는 공식은 다음과 같습니다. 


&&& X_grad 계산하기


>> ((X * Theta' - Y) .* R)          % 5 X 4 행렬

ans =

  -3.71258  -2.90935   0.00000   0.00000

  -1.99057   0.00000   0.00000   0.00000

  -2.91619   0.00000  -0.00000   0.00000

  -1.34381   0.00000   0.00000   0.00000

  -2.81590   0.00000  -0.00000   0.00000


>> Theta                                % 4 X 3 행렬

Theta =

   0.28544  -1.68427   0.26294

   0.50501  -0.45465   0.31746

  -0.43192  -0.47880   0.84671

   0.72860  -0.27189   0.32684


>> ((X * Theta' - Y) .* R) * Theta   % 5 X 3 행렬로 영화 수 X 피처수를 나타나는 영화 프로파일

ans =

  -2.52899   7.57570  -1.89979

  -0.56820   3.35265  -0.52340

  -0.83241   4.91163  -0.76678

  -0.38358   2.26334  -0.35334

  -0.80378   4.74272  -0.74041


   따라서, X_grad를 계산하는 공식은 다음과 같습니다. 


 X_grad = ((X * Theta' - Y) .* R) * Theta


&&& Theta_grad 계산하기


>>  ((X * Theta' - Y) .* R)            % 5 X 4 행렬

ans =

  -3.71258  -2.90935   0.00000   0.00000

  -1.99057   0.00000   0.00000   0.00000

  -2.91619   0.00000  -0.00000   0.00000

  -1.34381   0.00000   0.00000   0.00000

  -2.81590   0.00000  -0.00000   0.00000


>> X                                        % 5 X 3 행렬

X =

   1.048686  -0.400232   1.194119

   0.780851  -0.385626   0.521198

   0.641509  -0.547854  -0.083796

   0.453618  -0.800218   0.680481

   0.937538   0.106090   0.361953


>>  ((X * Theta' - Y) .* R)* X

error: operator *: nonconformant arguments (op1 is 5x4, op2 is 5x3)


>>  ((X * Theta' - Y) .* R)' * X        % 4 X 3 행렬로 사용자 수 X 피처수를 나타나는 사용자 프로파일

ans =

  -10.56802    4.62776   -7.16004

   -3.05099    1.16441   -3.47411

    0.00000    0.00000    0.00000

    0.00000    0.00000    0.00000


   따라서, Theta_grad를 계산하는 공식은 다음과 같습니다. 


 Theta_grad = ((X * Theta' - Y) .* R)' * X



&&& X_grad와 Theta_grad를 반환하기  


  cofiCostFunc.m 파일의 마지막 부분에 다음 코드가 있습니다.  X_grad는 5 X 3 행렬이고, Theta_grad는 4 X 3 행렬입니다. 두 변수를 언롤링하여 grad 벡터로 반환합니다. 


grad = [X_grad(:); Theta_grad(:)];



(3) 정답


function [J, grad] = cofiCostFunc(params, Y, R, num_users, num_movies, ...

                                  num_features, lambda)

%COFICOSTFUNC 협업 필터링 비용 함수 

%   [J, grad] = COFICOSTFUNC(params, Y, R, num_users, num_movies, ...

%   num_features, lambda) 

%           협업 필터링 문제의 비용 J와 경사도를 반환 


% 언롤링된 파라미터 벡터 X와 Theta를 다시 원래  X와 Theta의 차원으로 재배열 

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);


            

% 변수 초기화 

J = 0;

X_grad = zeros(size(X));

Theta_grad = zeros(size(Theta));


% ====================== YOUR CODE HERE ======================

% Instructions: 

%          협업 필터링의 비용 함수와 기울기를 계산 비용 함수와 계산

%          우선, 정규화 항이 없는 비용 함수를 계산하고 예상 비용도 같은 지를 확인

%          다음, 기울기를 계산하고 기울기가 맞는지 checkCostFunction 루틴으로 확인

%          마지막으로, 정규화를 구현

                   

% Notes: 

            X : num_movies  x num_features.    : 영화 프로파일 행렬

%        Theta : num_users  x num_features: 사용자 프로파일 행렬 

%        Y : num_movies x num_users  : 사용자의 영화 평가 점수 행렬 

%        R : num_movies x num_users  : 사용자의 영화 평가 여부 행렬

%                                                              (R(i,j) = 1 이면 평가, 

%

% 다음 변수를 올바르게 선언하시오

%        X_grad : num_movies x num_features : X의 각 성분에 대한 편미분 행렬 

%        Theta_grad : num_users x num_features : Theta의 각 성분에 대한 편미분 행렬

%


J = 1/2 * sum(sum(((X * Theta' - Y) .* R) .^2));


X_grad = ((X * Theta' - Y) .* R) * Theta;

Theta_grad = ((X * Theta' - Y) .* R)' * X;



% =============================================================


grad = [X_grad(:); Theta_grad(:)];


end



(4) checkCostFunction.m 파일로 기울기 값을 확인 


   checkCostFunction.m 파일은 기울기가 제대로 계산되었는 지를 확인합니다. 예전 실습에서 이미 다루었던 파일입니다. 임의의 행렬을 생성하여 cofiCostFunc.m 파일이 제대로 동작하는 지를 확인합니다. 



>> checkCostFunction;

   2.628228   2.628228

  -5.725822  -5.725822

   1.265145   1.265145

   6.689451   6.689451

   1.457377   1.457377

   1.278375   1.278375

  -1.098819  -1.098819

   5.615828   5.615828

  -0.059222  -0.059222

   4.410051   4.410051

   0.894004   0.894004

   0.070086   0.070086

  -5.017339  -5.017339

  -1.690612  -1.690612

   3.220169   3.220169

   6.325980   6.325980

  -1.316771  -1.316771

  -3.311288  -3.311288

  -0.582514  -0.582514

  -3.766595  -3.766595

  -5.919167  -5.919167

  -1.181623  -1.181623

   3.229887   3.229887

   0.026727   0.026727

  -0.240171  -0.240171

   1.898631   1.898631

   1.910831   1.910831

The above two columns you get should be very similar.

(Left-Your Numerical Gradient, Right-Analytical Gradient)


If your cost function implementation is correct, then

the relative difference will be small (less than 1e-9).


Relative Difference: 1.40157e-12


   이미 분석한 파일이므로 분석을 생략합니다. 



(5) 결과 확인


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari