coursera 吳恩達機器學習 machine learning 作業/習題 歸納 + 腳本測試 (ex12345678)

記錄一下做作業的時候遇到的問題。
coursera吳恩達機器學習網站

PS:這裏代碼片沒寫啥語言,可以查,懶得了,發現不寫的話,我這裏顯示的是品紅色(看吳恩達發現這紅叫品紅hhh),還是挺好看的:
在這裏插入圖片描述
用的是谷歌瀏覽器,然後下了個 “dark reader” 的插件,真的是完美保護狗眼,之前對着白屏真的要瞎了。
後來補充:發現只是編輯的時候是這個品紅色,閱讀的時候發現是白色。。

點擊傳送:
Ex1
Ex2
Ex3
Ex4
Ex5
Ex6
Ex7
Ex8


Ex1

零零碎碎的筆記:

  1. nx1,或1xn的叫vector,向量,記作RnR^n,nxm的叫矩陣,記作 R n x m
  2. 那個密碼點了編程作業纔看到的,看了視頻之後想試試結果發現找不到那個密碼。。。

1. warmUpExercise

A = eye(5);

視頻也給了答案了,開門紅,拿到我們第一個"Nice Work!"
注意的地方是加上分號吧,如果不用測試的話,不然一堆東西輸出… 然後輸出好像不影響結果,返回的東西對就可以了。


2. Computing Cost (for One Variable)

prediction = X*theta;
cost = (prediction - y).^2;
J = 1/(2*m)*sum(cost);

注意 .^2 加個 “.” 就是逐個元素的操作


3. Gradient Descent (for One Variable)
在這裏插入圖片描述
照公式寫就可以了。

delta = X'*(X*theta - y); %X'可以不加括號
theta = theta - alpha/m*delta;

要注意矩陣的大小關係,比如 delta = X’ * (X * theta - y); 不能寫成 (X*theta - y)*X’; 因爲 X’ 是 20x2 的,一個是 20 x 1的,而delta(也就是theta的導數,大小跟theta一樣)是 2x1,所以 X’ 要寫在前面。這個問題手推式子的時候比較難發現。至於那些參數的長和寬是多少要用黑框打印來看看。

這個問題在第2周submitting programming assignments裏面的閱讀材料提到了,當時看還不知道是怎麼回事。。。寫完後偶然點到才發現原來在講這個問題。


4. Feature Normalization
特徵歸一化處理,這裏的normalize是 (x - 平均數) / 標準差。。。
寫了個 (x - 平均數) / (max-min),一直wa。。。貼一發吧,不然白寫了:

mu = mean(X_norm')
mu = mu' * ones(1,3);
sigma = std(X_norm');
X_norm = (X_norm-mu)./(max(X_norm')'*ones(1,3)-min(X_norm')'*ones(1,3))

主要是:這裏的x是每行爲一個例子(example),每列是一個特徵(feature),所以調用mean、std、max函數的時候需要轉置一下。。。因爲它們應該是按一列一列計算的,在單行的vector裏看不出,但是在矩陣上就看得出了。


5. Computing Cost (for Multiple Variables)
同 Computing Cost (for One Variable),照貼就可以了。


6. Gradient Descent (for Multiple Variables)
同 Gradient Descent (for One Variable),照貼就可以了。矩陣運算的魅力啊。


7. Normal Equations
在這裏插入圖片描述
theta = (pinv(X’ * X))*(X’) * y
逆矩陣的時候寫了 -1 。。。不記得 X-1 代表什麼了,也不是逆矩陣和轉置矩陣= =

最後紀念一下 ex1 完成吧 ~
在這裏插入圖片描述


Ex2

1. Sigmoid Function

g = ones(size(z,1),size(z,2))./(1+exp(-z));

不容易注意的是點除( ./ )吧,然後注意一下分子不能寫1,因爲這個1是1x1維的,然後分母可以,因爲 1和後面正確維度的exp(-z)相加,維度會合併到大的。


2. Logistic Regression Cost
哈哈,終於不得已看了一下submit文件,2和3都是調用costFunction的,不過一個檢查J一個檢查grad而已。然後發現3中的J寫錯了。其實3說得不對,J因爲logistic的函數按照linear寫下來的話不是凸函數,所以需要變一下形式:
在這裏插入圖片描述
很好辦,找打就是了,矩陣相乘的大小也圖中處理好了:

prediction = ones(size(X*theta,1),size(X*theta,2))./(1+exp(-X*theta));
cost = (prediction - y).^2;
%J = 1/(2*m)*sum(cost); Wrong!!!
J = 1/m*(-y'*log(prediction)-(1-y)'*log(1-prediction));
grad = X'*(prediction - y)/m;

3. Logistic Regression Gradient - costFunction
想做第二個的,結果通過的是第三個(???)

prediction = ones(size(X*theta,1),size(X*theta,2))./(1+exp(-X*theta));
cost = (prediction - y).^2
J = 1/(2*m)*sum(cost)
grad = X'*(prediction - y)/m

因爲logistic的跟linear的cost(J)和 cost 的梯度計算式子是一樣的,只要把prediction(z)換一換就行了 。就前面代碼複製粘貼一下。


4. Predict
突然發現一個文件夾(吧)裏的函數可以互相調用。。

%X(1,:)
%theta
for i=1:m
  if sigmoid(X(i,:)*theta)>=0.5
    p(i) = 1;
  endif
endfor

注意的地方就是要看看X和theta的長和寬吧,要契合,i就是用來便利每行(每組)的X,然後都乘上theta就可以了,p(i)就是第i行(組)的結果。emmm,這裏用了for循環,想不到怎麼不用for來更新每行的p(i)。
剛寫完就想到了(hh我真聰明),想起Python裏面有 a = [X>0] … 差不多這種(語法好像是錯的,ReLu的時候用的),大致就是把矩陣X裏面每個元素判斷一下,看看是否>0,然後賦給a(也是個矩陣)。然後這裏在黑框裏仿照了一下:
在這裏插入圖片描述
這波照葫蘆畫瓢很OK!所以繼續仿照一下:

predict = sigmoid(X*theta)
p = predict>=0.5

就過了。不用for,直接到矩陣上運算。


5. &6. Regularized Logistic Regression Cost & Regularized Logistic Regression Gradient
測試的都是一個文件,合起來寫了。

h = sigmoid(X*theta)
J = 1/m*(-y'*log(h)-(1-y)'*log(1-h))+lambda/2/m*(sum(theta.^2)-theta(1)*theta(1)) 
grad = X'*(h-y)/m + lambda/m*theta
grad(1) = grad(1) - lambda/m*theta(1)

J 的參照:
在這裏插入圖片描述
上面有說矩陣怎麼算:
在這裏插入圖片描述
免掉了 Σ ,是因爲 y是 mx1 ,yT是 1xm ,h是mx1,用 size() 打印一下就知道他們的長和寬就行了。
一開始交的是:

J = 1/m*(-y'*log(h)-(1-y)'*log(1-h))+lambda/2/m*sum(theta.^2)

就會彈出提示,說要注意θ(1)不用操作,然後改一改就行了。注意θ下標是1,而不是0,又報錯了。
然後是grad的參照:網站:Regularized Linear Regression
在這裏插入圖片描述
看回昨天寫的代碼:
在這裏插入圖片描述
照葫蘆畫瓢一下:

grad = X'*(h-y)/m + lambda/m*theta
grad(1) = grad(1) - lambda/m*theta(1)

注意下標是1,然後grad(1)是不用正則化的,加上去就減掉好了。
想不出更簡潔的方法,不過至少這樣 J 和 grad 都不用for了,靈活運用矩陣乘法。

做完啦,最後截圖紀念:
在這裏插入圖片描述


Ex3

1. Regularized Logistic Regression

h = sigmoid(X*theta);
J = 1/m*(-y'*log(h)-(1-y)'*log(1-h))+lambda/2/m*(sum(theta.^2)-theta(1)*theta(1)) ;
grad = X'*(h-y)/m + lambda/m*theta;
grad(1) = grad(1) - lambda/m*theta(1);

粘貼ex2的就過了… …


2. One-vs-All Classifier Training
卡了40分鐘。。題目比較長,還有給了個fmincg不會用(該來的還是要來啊):

initial_theta = zeros(n + 1, 1);
options = optimset('GradObj','on','MaxIter',50);
for c = 1:num_labels
  %initial_theta = zeros(n + 1, 1); 沒有加上但是還是過了
  k = fmincg(@(t)(lrCostFunction(t,X,(y==c),lambda)),initial_theta,options)
  k';
  all_theta(c,:) = k';
  all_theta;
endfor

在這裏插入圖片描述
什麼 iteration 就是 fmincg 跑了多少次,cost就是損失函數,腦抽了一開始還以爲是報錯。。。

題目思路就是跑num_labels遍,第x遍fmincg給出一個最佳的theta,放到all_theta的第x行,因爲給的這個theta是個列向量,所以放到all_theta的某一行中就需要轉置一下。

總結一下all_theta的第x行是用來存放第x個最佳的theta的,這個theta是針對 y 分別爲1、2、3、4(因爲num_labels = 4)的情況來得出的,這裏x就是1~4。

爲了方便轉置,我用 k 來存一下列向量theta,然後轉置一下 k,然後賦值給all_theta的某一行,也就是上面的代碼,如果省掉一個參數 k 的話就是:

initial_theta = zeros(n + 1, 1);
options = optimset('GradObj','on','MaxIter',50);
for c = 1:num_labels
  %initial_theta = zeros(n + 1, 1); 沒有加上但是還是過了
  all_theta(c,:) = fmincg(@(t)(lrCostFunction(t,X,(y==c),lambda)),initial_theta,options)'; %最後加上轉置" ' "
endfor

由於沒有考慮到轉置的問題,一開始寫的是:

for c = 1:num_labels
  all_theta(c) = fmincg(@(t)(lrCostFunction(t,X,(y==c),lambda)),all_theta(c),options)
endfor

可以說是錯誤百出了,首先( c )不是第c行,是矩陣按照列排下來後的第c個,然後後面 all_theta 應該是 initial_theta 。另外,細心點可以發現 initial_theta 每次遍歷都沒有清零,不過沒有關係,因爲這個 fmincg 算法足夠強大,而且theta全設爲0,不也不是最好的嗎?

不過等等,真的需要 initial_theta 嗎?all_theta 一開始不也是每一行都是 0 嗎?於是我們還可以再省一個參數 initial_theta !要做的只是把 all_theta 的行拿出來,然後稍稍轉置一下,代替 initial_theta 的位置就可以了:

options = optimset('GradObj','on','MaxIter',50);
for c = 1:num_labels
  all_theta(c,:) = fmincg(@(t)(lrCostFunction(t,X,(y==c),lambda)),all_theta(c,:)',options)';
endfor

很棒,現在代碼比一開始提交正確的代碼要精簡多了,而且也是正確的 ヾ(≧∇≦*)ヾ


3. One-vs-All Classifier Prediction
老方法,用 size() 輸出一下 all_theta 和 X 的長和寬,知道了 X 是 m x 3 維,all_theta 是 num_labels x 3 維(4 x 3),首先 max 函數有4種:
在這裏插入圖片描述
max(X) 找 X 中最大的元素
max( X , [] , 1 ) 找 X 每列最大的元素
max( X , [] , 2 ) 找 X 每行最大的元素
[ a , b ] = max (X) ,a 爲 X 每列最大的元素,b 爲 X 每列最大元素的下標
max( X , Y ) 爲取 X 和 Y 矩陣每個位置上最大的元素

我們主要找的是 theta 乘上 X 之後,對於每一組(行),找出4種 y 誰的概率最大,得出那一種,存放在 p 對應的行中。然後用的 max 函數是得出每列的最大元素的下標,因此我們設想的是,因爲有 4 種,所以搞 4 行出來,然後列就是這 4 種對應的概率,調用 max 函數的時候,就能得到每一列中,概率最大的那一種的下標。因此這個矩陣是 4 x m 大小的,所以是 all_theta * X’ 。湊出來之後得到 最大概率的下標 組成的 行向量,轉置一下就是 p 了:

t = all_theta*X';
[a,b] = max(t);
p = b';

對了,不加sigmoid激活,是因爲θx本來就是遞增的,sigmoid也是,大的越大,所以沒有必要加


4. Neural Network Prediction Function
寫的時候有點亂,不知道最終輸出的矩陣是多少,看了一眼別人代碼,發現隱藏層少了加了1,輸入層記得,隱藏層忘記了:

X = [ones(m, 1) X];
z2 = sigmoid(X*Theta1');
size(z2);
a2 = [ones(m,1) z2];
a3 = a2*Theta2';
t = a3';
[a,b] = max(t);
p = b';

輸入層矩陣是 m x 2 -> m x 3
隱藏層輸入矩陣是 m x 3 * 3 x 4 = m x 4
隱藏層輸出矩陣是 m x 4 - > m x 5
輸出層矩陣是 m x 5 * 5 x 4 = m x 4
最終,m x 4(或者 4 x m) 的意思是有m組輸入,然後對應4組輸出(的概率)
另外,過了之後看了下別人寫的,原來還有[a,b] = max(A,[],2)這樣的騷操作,意思差不多,不過一個針對行向量,一個針對列向量:

X = [ones(m, 1) X]
z2 = sigmoid(X*Theta1');
size(z2);
a2 = [ones(m,1) z2];
a3 = sigmoid(a2*Theta2');
[a,b] = max(a3,[],2);
p = b;

果然還是要看看別人代碼,各取所長。

sigmod最後可加可不加,因爲都是遞增的,不過加了有 “概率” 的含義,還是加了。

磕磕絆絆吧,做完發現也不算難(萬物真理:懂了就覺得不難),最後慣例截圖紀念一下:
在這裏插入圖片描述


Ex4

Feedforward and Cost Function & Regularized Cost Function
因爲複習很久沒打了,生疏,卡了很久:
參考公式:
在這裏插入圖片描述

[hx,dummy] = predict(Theta1,Theta2,X);
Y = zeros(m,num_labels);
for i=1:m
  Y(i,y(i))=1;
endfor
t1 = log(hx).*Y + log(1-hx).*(1-Y);
sum_xita = sum(sum(Theta1(:,2:end).^2)) + sum(sum(Theta2(:,2:end).^2));
J = -1/m*sum(sum(t1)) + lambda/2/m*sum_xita;

% 不能夠直接矩陣乘法,因爲矩陣乘法的話,log(hx_k)和跟下一組y_k+1等乘在一起,是不對的
% 正確的理解應該是點乘,自己乘回自己,這裏沒有理解,卡了很久
% 然後theta點乘的時候,第一位是要省略不乘的,可以用語法簡易截取

predict 是改了文件中的:
在這裏插入圖片描述


Sigmoid Gradient
根據公式:

g = sigmoid(z).*(1-sigmoid(z));

看了一下Sigmoid函數的求導證明。。有點難


Neural Network Gradient (Backpropagation) & Regularized Gradient
寫到崩了,參考別人的
在nnCostFunction後面繼續補上:

X = [ones(m,1) X];
for i=1:m
  a1 = X(i,:);  %1x3
  z2 = a1*Theta1'; %1x4
  a2 = [1 sigmoid(z2)];
  z3 = a2*Theta2';
  a3 = sigmoid(z3);
  deta3 = a3-Y(i,:); % 1 x 4
  deta3 = deta3'
  deta2 = Theta2(:,2:end)'*deta3.*sigmoidGradient(z2')
  size(z2)
  size(deta2)
  size(Theta2(:,2:end)')
  size(deta3)
  size(a2')
  Theta2_grad = Theta2_grad + deta3*a2; % 4 x 5
  Theta1_grad = Theta1_grad + deta2*a1; % 4 x 3
endfor
Theta1(:,1) = 0;
Theta2(:,1) = 0;
Theta1_grad = (Theta1_grad + lambda*Theta1)/m;
Theta2_grad = (Theta2_grad + lambda*Theta2)/m;

知識參考:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
【詳細過程的描述】
講一下,寫了一個下午 踩了什麼坑:

  1. 不清楚 a 和 z 分別是啥,搞了很久,又不看之前的筆記,剛剛貼圖的時候才發現 pdf 有
  2. 然後第一層輸入層是要加 x0 = 1的,呵呵
  3. 小寫 delta(δ),那個是 θTδθ^T*δ,我居然覺得無所謂,就寫了 δTθδ^T*θ,錯到飛天
  4. 最後pdf裏面D應該是△和λθ都除以 m

從上午十點寫到下午五點多,什麼坑都踩了,紀念一下吧:
在這裏插入圖片描述
ex4 寫得磕磕絆絆的,有空看看論壇的問題。


Ex5

Regularized Linear Regression Cost Function & Regularized Linear Regression Gradient
參考圖片:
在這裏插入圖片描述
腦抽了寫了註釋那部分,後來看了別人的發現不用乘x的i次方,過了一會才發現x的上標指的是第幾個x,而不是x的冪。
在這裏插入圖片描述
然後就是計算梯度,grad
因爲這裏的grad要用regression,正則化。
看回Ex2的做題筆記:(這張水印有點難去)Regularized Linear Regression
在這裏插入圖片描述
然後藍色框住那部分就是grad,即 J 對 θ 的梯度。
然後就是完整代碼:

h = zeros(m,1);
h = X*theta;
J = 1/2/m*(sum((h-y).^2))+lambda/2/m*sum(theta(2:end).^2)
grad = X'*(h-y)/m + lambda/m*theta
grad(1) = grad(1) - lambda/m*theta(1)

記得第一個θ不需要正則化。


Learning Curve
要求是畫出隨着樣本數目 i 增大,求出cross vailidation 的 error 和 trainning test 的 error 。並且畫出這兩個的圖,通常情況是:(這裏 N 是 i )
在這裏插入圖片描述
然後發現個很透的問題:我不會用Octave畫圖。如果不是測試的話,就會畫圖,但是如果submit了的話,會迭代很多次,然後畫的圖也有問題,畫出來的圖就很亂。
有點煩,網上的教程都是 matlab 的,進度有點趕,又不想學matlab,考完試暑假再看看吧。
代碼:(一開始沒有理解,看了別人畫的圖,才知道是要幹嘛(隨着N增加話兩個 error 的圖))

for i = 1:m
  theta = trainLinearReg(X(1:i,:),y(1:i,:),lambda);
  error_val(i) = linearRegCostFunction(Xval,yval,theta,0);
  %theta = trainLinearReg(X,y,lambda)
  error_train(i) = linearRegCostFunction(X(1:i,:),y(1:i,:),theta,0);
endfor

Polynomial Feature Mapping
計算 X,變爲 [X(i) X(i).^2 X(i).^3 … X(i).^p],代碼:

for i=1:size(X,1)
  for j=1:p
  X_poly(i,j) = X(i).^j; 
endfor

看別人文章的時候,發現可以更充分運用矩陣的性質:

X 
for i=1:p
  X_poly(:,i) = X.^i; 
endfor
X_poly

在這裏插入圖片描述
突然發現打印出來,跟我理解的很不同= = ,好吧,沒有認真審題,看着式子就套兩個for循環,但還是做對了。
貼個看matlab圖片的博客:https://blog.csdn.net/weixin_40807247/article/details/81359042
最後慣例:
在這裏插入圖片描述
PS:我覺得這次做得不是很好= = ,有點沒耐心讀題,不通過,想了一會就去看別人的代碼,也不是說不好,但是要讀好題吧。


Ex6

Gaussian Kernel
計算高斯kernel的公式:
在這裏插入圖片描述
||u|| 的計算方法:(u爲2維)
在這裏插入圖片描述
把 u 替換成 x1 - x2,正確代碼:

t = x1-x2;
sim = exp(-sum(t.^2)/(2*sigma^2))

錯誤代碼:

sim = exp(-(x1-x2).^2/(2*sigma^2))

顯然沒有理解公式。


Parameters (C, sigma) for Dataset 3
一臉懵逼,然後想起宿友說有個文檔要下載的:
在這裏插入圖片描述
Life suck. 裏面有腳本,還有介紹題目的pdf,(可能還有別的數據啥的),一開始叫我們下載的東東里面有的會沒有。

不過宿友說感覺沒啥用就介紹一下背景,所以我一直以來沒有看那個"here"的文件,所以相安無事。

這次的作業就真的頂不住了,去看了下載的文件,發現其實提示了很多,包括沒有提及的函數的用法啥的,課裏沒講。

題意就是找出最好的C和sigma(方差 / σ),然後用 svmPredict ,其實用 svmPredict 的時候會發現要用 svmTrain,然後裏面的第四個參數要用個@啥啥的,另外svmTrain的東西也要看回代碼,看代碼可以發現 x1、x2 是不用定義的,因爲直接賦值是(1,0),也符合課上講的。然後 pdf 裏面也提示了 C 和 sigma 推薦的參數,兩重循環暴力找就行了:

vec_C = [0.01;0.03;0.1;0.3;1;3;10;30];
vec_sigma = [0.01;0.03;0.1;0.3;1;3;10;30];
%x1 = [1 2 1 5 9 8]; x2 = [0 4 -1 7 6 5]; 見有人定義了x1 x2
%x1 x2這裏怎麼定義沒所謂,因爲svmTrain中kernelFunction的用法是(1,0)
vec_errors = 10000000;
for i=1:length(vec_C)
  for j=1:length(vec_sigma)
    model= svmTrain(X, y, vec_C(i), @(x1, x2) gaussianKernel(x1, x2, vec_sigma(j)));
    pred = svmPredict(model,Xval);
    error = mean(double(pred~=yval));    
    if (error < vec_errors)
      a = i;
      b = j;
      vec_errors = error;
    endif
  endfor
endfor
C = vec_C(a); % 注意要記得賦值
sigma = vec_sigma(b);
vec_errors;
model = svmTrain(X,y,vec_C(i),@(x1, x2) gaussianKernel(x1, x2, vec_sigma(j)));
visualizeBoundaryLinear(X,y,model); % 看ex6.m知道的,可以用來看圖

Email Preprocessing
暴力比較就行:

    for i=1:size(vocabList)
      if (strcmp(str,vocabList(i,1)))
        word_indices = [word_indices;i];
        break;
      endif
    endfor

emailFeatures
同暴力:

for i = 1:size(word_indices)
  x(word_indices(i)) = 1;
endfor

感覺這次比較簡單,可能由 pdf 看吧 hh,而且實現也不用自己寫:
在這裏插入圖片描述


Ex7

Find Closest Centroids (k-Means)
注意一下是 X 某行減掉 centroids 某行(因爲centroids(μ)是 X 中的一個點(吧)),所以維度一樣。
而不是 X(i) - centroids(j)

m = size(X,1);
for i=1:m
  min = 1000000000;
  for j=1:K
    t = X(i,:) - centroids(j,:);
    s = sum(t.^2);
    if (s<min)
      min = s;
      idx(i) = j;
    endif
  endfor
endfor

Compute Centroid Means (k-Means)
可以用矩陣來運算,知道有個find但不是很熟悉,後來就用for了,看了別人的進行下修改:

%自己寫的:
##for i=1:K
##  cnt = 0;
##  for j=1:m
##    if (idx(j)==i)
##      centroids(i,:) += X(j,:);    
##      cnt++;
##    endif
##  endfor
##  centroids(i,:) /= cnt;
##endfor

%別人用了find的,進行更改:
for i=1:K
  t = find(idx==i);
  centroids(i,:) = sum(X(t,:))/length(t);
endfor

K-means 用於圖像壓縮
至此,跑一下腳本ex7:
在這裏插入圖片描述
感覺還不錯,挺有趣的。

看到 pdf 裏面有個關於圖像壓縮的,就是設置 K 個color(比如16色),然後跑 K-means。
首先要寫個 kMeansInitCentroids,文件裏面有:

% randidx存的是大小爲X的行數的,然後把用X(randidx(1:K),:)分出打亂後的前K行
randidx = randperm(size(X,1)); % Randomly reorder the indices of examples
centroids = X(randidx(1:K),:); % Take the first K examples as centroids

關於 randperm 的用法測試如下。
在這裏插入圖片描述
用一個變量保存一個向量,再用另一個矩陣把行關聯到這個向量中,這種方法 / 過程用 C 寫的話有點繞,但是這裏完美運行(感覺Python這麼寫也行),雖然簡短,但是編譯器也懂你的想法,很方便。

然後命令窗口跑一下這個腳本:
在這裏插入圖片描述
K = 16時:
在這裏插入圖片描述
改一下腳本,K = 8:
在這裏插入圖片描述
K = 1 :
在這裏插入圖片描述
K = 1024:
在這裏插入圖片描述


PCA

在這裏插入圖片描述

開局一張圖,代碼全靠編:

sigma = X'*X/m;
[U,S,X] = svd(sigma);

Project Data (PCA)

U = U(:,1:K);
Z = X*U; %懶得紙上算了,長寬瞎搞

Recover Data (PCA)

X_rec = Z*U(:,1:K)'; % 看回projectData

還有一次編程練習就結束啦!!!
在這裏插入圖片描述


Ex8

Estimate Gaussian Parameters

在這裏插入圖片描述

mu = mean(X)';
t = mu'.*ones(m,n);
sigma2 = sum( (X-t).^2 )'/m;

t 用來擴充一下矩陣,因爲不想用 for
在這裏插入圖片描述
看了一下別人代碼:

X
mu = mean(X)
size(mu)
size(X)
sigma2=sum((X - mu) .^ 2)/m;

emmm跑出來也是對的。。。
發現 - 也跟乘一樣,遵循橫乘豎,我對代碼還是不熟悉啊 = =
在這裏插入圖片描述


Select Threshold
照打就是了,注意<epsilon的是1:

    pval;
    yval;
    fp = sum((pval<epsilon)&(yval==0));
    tp = sum((pval<epsilon)&(yval==1));
    fn = sum((pval>=epsilon)&(yval==1));

    prec = tp/(tp+fp);
    rec = tp/(tp+fn);

    F1 = 2*prec*rec/(prec+rec);

在這裏插入圖片描述
在這裏插入圖片描述


Collaborative Filtering Cost & Collaborative Filtering Gradient
沒有regularized的cost和gradient:

% without regularization 
% version 1.0
J = sum(sum((X*Theta'-Y).^2.*R))/2;
for j=1:size(R,2)
  for i=1:size(R,1)
    if (R(i,j)==1)
      [i,j];
      X_grad(i,:) += (X(i,:)*Theta(j,:)'-Y(i,j))*Theta(j,:);
      Theta_grad(j,:) += (X(i,:)*Theta(j,:)'-Y(i,j))*X(i,:);
    endif
  endfor
endfor

J 的參考:
在這裏插入圖片描述在這裏插入圖片描述
在這裏插入圖片描述
因爲 Y 是 nm * nu 大小的矩陣,所以 X 和 Theta 要換一下位置,這裏是 XThetaTX*Theta^T
然後用R來確定某個 i 行 j 列的位置是否有效,1爲有效,0爲無效,所以是點乘。
最後因爲 J 是個數字,所以要用兩個 sum 求和一個 vector。

Gradient 的參考:
在這裏插入圖片描述
大概瞄了一眼配套 pdf 裏面的提示,說要用 for 循環,然後寫不出來…
最後還是去仔細思考矩陣的含義:(當然,X和X_grad含義一致(因爲是梯度關係),Theta也同理)
X 矩陣:每行表示一個電影(num_movies)(下圖的x1 x2),每列表示一種特徵(num_features)(romance和action的程度)
Theta 矩陣:每行表示一個用戶(num_users)(Alice Bob Carol Dave),每列表示一種特徵(num_features)(給romance和action兩個種類的喜愛程度)
配合圖看更清楚一點:(注:圖的Theta矩陣是一列爲一個用戶,每行表示一個特徵,第一行0是爲了和沒出現X0相乘,可以忽略)
在這裏插入圖片描述
然後看回我們的定義:
在這裏插入圖片描述
根據剛剛對矩陣的梳理和上面的公式,其實 X_grad 是每行每行地更新的,然後是( Theta 的第 j 行的轉置)和( X 的第 i 行)相乘,注意:這裏出來的是一個數字,不是矩陣。然後和 Theta 的第 j 行相乘,記得把答案累加,因爲對於 i 行(第 i 個電影),有不同的分數(列 / feature),這裏寫的是兩個循環,每次僅針對 i 行 j 列的數據,所以要把結果累加。
然後 Theta_grad 也是同理啦,這裏 R( i , j )表示的是" if the i-th movie was rated by the j-th user ",因此對於Theta_grad 來說,更新的是 j 行,X_grad 則是 i 行。

突然發現 pdf 下一頁還有提示。。。講如何找到 j:r(i,j)=1 的:
在這裏插入圖片描述
照葫蘆畫瓢又有新的代碼:

% without regularization 
% version 2.0
J = sum(sum((X*Theta'-Y).^2.*R))/2;
for i=1:size(R,1)
  idx = find(R(i,:)==1); % 即找出符合的 j; 
  X_grad(i,:) += (X(i,:)*Theta(idx,:)'-Y(i,idx))*Theta(idx,:);
endfor

for j=1:size(R,2)
  idx = find(R(:,j)==1); % 即找出符合的 i
  Theta_grad(j,:) += (X(idx,:)*Theta(j,:)'-Y(idx,j))'*X(idx,:);
endfor

注意最後的Theta_grad計算式子中,- Y 的結果要轉置一下,不然又報錯:
在這裏插入圖片描述
寫完之後跑一下那個 ex8_cofi,得到一個圖:
在這裏插入圖片描述
不太知道是啥…
Regularized Cost & Regularized Gradient
這裏添加上 regularization,然後就只在之前的基礎上稍加修改就可以了。
參考:
在這裏插入圖片描述
在這裏插入圖片描述

% with regularization

J = sum(sum((X*Theta'-Y).^2.*R))/2 + lambda/2*sum(sum(Theta.^2))+ lambda/2*sum(sum(X.^2));
for i=1:size(R,1)
  idx = find(R(i,:)==1); % 即找出符合的 j; 
  X_grad(i,:) += (X(i,:)*Theta(idx,:)'-Y(i,idx))*Theta(idx,:)+lambda*X(i,:);
endfor

for j=1:size(R,2)
  idx = find(R(:,j)==1); % 即找出符合的 i
  Theta_grad(j,:) += (X(idx,:)*Theta(j,:)'-Y(idx,j))'*X(idx,:)+lambda*Theta(j,:);
endfor

不過第一次的時候會超時不知道爲啥。。。再submit一次就可以了:
在這裏插入圖片描述
最後跑一下ex8_cofi,感覺怪怪的,評分都是5.0,但是題目又全通過了:
在這裏插入圖片描述
最後一次編程作業啦,完結撒花!!!
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章