2014-02-15 107 views
3

我已經經歷了堆棧溢出中的許多代碼並在同一行上創建了自己的代碼。這個代碼有一些問題,我無法理解。我存儲的價值theta1和theta2以及成本函數分析的目的。 x和y的數據可從此 Openclassroom頁面下載。它具有可以在記事本中打開的.dat文件形式的x和Y數據。梯度下降Matlab實現

%Single Variate Gradient Descent Algorithm%% 
    clc 
clear all 
close all; 
% Step 1 Load x series/ Input data and Output data* y series 

x=load('D:\Office Docs_Jay\software\ex2x.dat'); 
y=load('D:\Office Docs_Jay\software\ex2y.dat'); 
%Plot the input vectors 
plot(x,y,'o'); 
ylabel('Height in meters'); 
xlabel('Age in years'); 

% Step 2 Add an extra column of ones in input vector 
[m n]=size(x); 
X=[ones(m,1) x];%Concatenate the ones column with x; 
% Step 3 Create Theta vector 
theta=zeros(n+1,1);%theta 0,1 
% Create temporary values for storing summation 

temp1=0; 
temp2=0; 
% Define Learning Rate alpha and Max Iterations 

alpha=0.07; 
max_iterations=1; 
     % Step 4 Iterate over loop 
     for i=1:1:max_iterations 

    %Calculate Hypothesis for all training example 
    for k=1:1:m 
     h(k)=theta(1,1)+theta(2,1)*X(k,2); %#ok<AGROW> 
     temp1=temp1+(h(k)-y(k)); 
     temp2=temp2+(h(k)-y(k))*X(k,2); 
    end 
    % Simultaneous Update 
     tmp1=theta(1,1)-(alpha*1/(2*m)*temp1); 
     tmp2=theta(2,1)-(alpha*(1/(2*m))*temp2); 
     theta(1,1)=tmp1; 
     theta(2,1)=tmp2; 
     theta1_history(i)=theta(2,1); %#ok<AGROW> 
     theta0_history(i)=theta(1,1); %#ok<AGROW> 
     % Step 5 Calculate cost function 
     tmp3=0; 
     tmp4=0; 
     for p=1:m 
     tmp3=tmp3+theta(1,1)+theta(2,1)*X(p,1); 
     tmp4=tmp4+theta(1,1)+theta(2,1)*X(p,2); 
     end 
     J1_theta0(i)=tmp3*(1/(2*m)); %#ok<AGROW> 
     J2_theta1(i)=tmp4*(1/(2*m)); %#ok<AGROW> 


     end 
     theta 
     hold on; 
     plot(X(:,2),theta(1,1)+theta(2,1)*X); 

我越來越

theta的值作爲 0.0373 和0.1900應該是0.0745和0.3800

這個值是大約兩倍,我期待。

+0

我們無法在沒有數據的情況下重現您的問題。 – Daniel

+0

嘿謝謝你的回覆。我已經添加了輸入數據鏈接的鏈接。 – Incpetor

+0

你好,你必須使用矩陣屬性。這個頁面上的答案http://stackoverflow.com/a/33215224/2046575是非常好的。 –

回答

0

這裏有一些評論:

  1. max_iterations設置爲1。典型地運行梯度下降,直到目標函數的降低低於某個閾值或者梯度的幅度低於某個閾值,這可能會多於一次迭代。

  2. 因子1 /(2 * m)在技術上不正確。這不應該導致算法失敗,但會有效地降低學習速度。

  3. 您不計算正確的目標。正確的線性迴歸目標應該是平方殘差平均值的二分之一或平方殘差總和的二分之一。

  4. 與其使用for-loops,您應該利用matlab的矢量化計算。例如,res=X*theta-y; obj=.5/m*res'res;應計算殘差(res)和線性迴歸目標(obj)。

+0

感謝您的回覆。爲了測試,迭代次數有意保留爲1。 iter = 1的理想結果是0.0745和0.3800。請參閱我有問題的鏈接。我刪除了1 /(2 * m)部分並得到了不希望的結果。對不起,但我不明白在我的代碼中進行更改的位置。 – Incpetor

5

我設法創建了一個算法,該算法使用了更多的Matlab支持的向量化屬性。 我的算法與你的算法有一點不同,但按照你的要求進行梯度下降處理。 在我作出的執行和驗證(使用polyfit函數)之後,我認爲在openclassroom(練習2)中預期變量theta(0)= 0.0745和theta(1)= 0.3800的值在1500次迭代後是錯誤的步驟0.07(我沒有對此作出迴應)。這就是我將結果與一張圖中的數據一起繪製並將您的所需結果與另一張圖中的數據一起繪製的原因,並且我在數據擬合過程中看到了很大的差異。

首先看看的代碼:

% Machine Learning : Linear Regression 

clear all; close all; clc; 

%% ======================= Plotting Training Data ======================= 
fprintf('Plotting Data ...\n') 

x = load('ex2x.dat'); 
y = load('ex2y.dat'); 

% Plot Data 
plot(x,y,'rx'); 
xlabel('X -> Input') % x-axis label 
ylabel('Y -> Output') % y-axis label 

%% =================== Initialize Linear regression parameters =================== 
m = length(y); % number of training examples 

% initialize fitting parameters - all zeros 
theta=zeros(2,1);%theta 0,1 

% Some gradient descent settings 
iterations = 1500; 
Learning_step_a = 0.07; % step parameter 

%% =================== Gradient descent =================== 

fprintf('Running Gradient Descent ...\n') 

%Compute Gradient descent 

% Initialize Objective Function History 
J_history = zeros(iterations, 1); 

m = length(y); % number of training examples 

% run gradient descent  
for iter = 1:iterations 

    % In every iteration calculate hypothesis 
    hypothesis=theta(1).*x+theta(2); 

    % Update theta variables 
    temp0=theta(1) - Learning_step_a * (1/m)* sum((hypothesis-y).* x); 
    temp1=theta(2) - Learning_step_a * (1/m) *sum(hypothesis-y); 

    theta(1)=temp0; 
    theta(2)=temp1; 

    % Save objective function 
    J_history(iter)=(1/2*m)*sum((hypothesis-y).^2); 

end 

% print theta to screen 
fprintf('Theta found by gradient descent: %f %f\n',theta(1), theta(2)); 
fprintf('Minimum of objective function is %f \n',J_history(iterations)); 

% Plot the linear fit 
hold on; % keep previous plot visible 
plot(x, theta(1)*x+theta(2), '-') 

% Validate with polyfit fnc 
poly_theta = polyfit(x,y,1); 
plot(x, poly_theta(1)*x+poly_theta(2), 'y--'); 
legend('Training data', 'Linear regression','Linear regression with polyfit') 
hold off 

figure 
% Plot Data 
plot(x,y,'rx'); 
xlabel('X -> Input') % x-axis label 
ylabel('Y -> Output') % y-axis label 

hold on; % keep previous plot visible 
% Validate with polyfit fnc 
poly_theta = polyfit(x,y,1); 
plot(x, poly_theta(1)*x+poly_theta(2), 'y--'); 

% for theta values that you are saying 
theta(1)=0.0745; theta(2)=0.3800; 
plot(x, theta(1)*x+theta(2), 'g--') 
legend('Training data', 'Linear regression with polyfit','Your thetas') 
hold off 

確定的結果如下:

隨着THETA(0)和θ(1),從我的算法作爲結果產生行適合的數據。

Gradient descent - theta0=0.063883, theta1=0.750150

隨着THETA(0)和θ(1)爲固定值,結果,線不適合的數據。

Gradient descent - theta0=0.0745, theta1=0.3800

+0

是否正確:假設= theta(1)。* x + theta(2); 可能是你應該像這樣修復>假設= theta(1)+ theta(2)。* x; –

+0

@monakons如何從csv文件或dat文件加載數據ex:'ex2x.csv' – Eka

+0

dir_of_csv = sprintf('dir其中csv是'); list_of_csv = dir(fullfile(dir_of_csv,'*。csv')); list_of_csv_names = {list_of_csv.name}'; –

0

你需要把 temp1目錄= 0 TEMP2 = 0 在迭代循環的第一個評論; 因爲如果你不這樣做,你當前的溫度會影響下一次迭代,這是錯誤的

22

我一直在試圖用矩陣和向量實現迭代步驟(即不更新theta的每個參數)。 這裏是我想出了(只有梯度步驟,是在這裏):

h = X * theta; # hypothesis 
err = h - y; # error 
gradient = alpha * (1/m) * (X' * err); # update the gradient 
theta = theta - gradient; 

難的把握的是,在前面的例子中的梯度步驟「和」實際上是由矩陣乘法進行X'*err。 你也可以寫爲(err'*X)'

+1

我們也可以寫sum(X。* err,1)'它有效(但它不太漂亮)。 –

+0

感謝cmantas澄清矩陣乘法的處理,那是什麼讓我堅持我的代碼。 @FlorianCourtial說,我打算這麼做,但現在我明白了。 – M090009

+0

你能解釋一下爲什麼X'* err也是一個求和步驟。我看到它的工作原理,但只是抓住了我的想法爲什麼它 – yasgur99

0

Ɵ您的期望和計劃的結果(THETA)的值,有一點可以注意到,預期值的兩倍結果。

您所犯的可能錯誤是您使用1/(2*m)代替1/m中的衍生計算代碼。在該衍生物中分母的2消失作爲原始術語是(H Ɵ(X) - Y)其上分化產生2 *(H Ɵ(X) - y)的。 2s取消。

修改這些代碼行:

J1_theta0(i)=tmp3*(1/(2*m)); %#ok<AGROW> 
J2_theta1(i)=tmp4*(1/(2*m)); %#ok<AGROW> 

J1_theta0(i)=tmp3*(1/m); %#ok<AGROW> 
J2_theta1(i)=tmp4*(1/m); %#ok<AGROW> 

希望它能幫助。

0

線條代碼中的37和38:

tmp1=theta(1,1)-(alpha*(1/(2*m))*temp1); 
tmp2=theta(2,1)-(alpha*(1/(2*m))*temp2); 

被不必要地減半輸出。我相信改進的代碼會有這些代替:

tmp1=theta(1,1)-(alpha*(1/(m))*temp1); 
    tmp2=theta(2,1)-(alpha*(1/(m))*temp2); 

祝你好運..!

PS:看起來像有人已經明白這一點..!