2014-02-15 114 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:看起来像有人已经明白这一点..!