机器学习—单变量线性回归

本篇讲述以下内容:

  • 单变量线性回归
  • 代价函数
  • 梯度下降

单变量线性回归

回顾上节,在回归问题中,我们给定输入变量,试图映射到连续预期结果函数上从而得到输出。单变量线性回归就是从一个输入值预测一个输出值。输入/输出的对应关系就是一个线性函数。

下面是一个根据房屋面积预测房屋价格的例子。

假设有一个数据集,我们称作训练集,数据集包括房屋面积和房屋价格数据。

x:表示输入变量,也叫特征变量。

y:表示输出变量,也叫目标变量。

(xi,yi):表示一个识训练样本,训练集的一行。i 表示 第 i 个训练样本。

m:表示训练样本的数量。

在接下来的学习之前,先了解一下监督学习的一般工作方式。如下图,训练集通过学习算法训练后,得到一个h(hypothesis),它表示为一个函数。

函数的输入为房屋大小,输出为房屋的价格。通过这个函数我们则可以预测房屋价格,这就是机器学习中的回归问题。

在单变量线性回归中,我们的假设函数为:hθ(x)=θ01x ,其中θ0 和θ1为模型参数。

讲到这肯定有疑惑为什么要选这个函数,实际应用可能不是线性的函数,可能会是更复杂的函数。这里只是为了从简单线性方程的例子入手,假设房屋的面积和价格是一个线性关系。

好继续, 我们有了假设函数,接下来要做的就是如何选择不同的参数θ0 和θ1。下图可以看到不同的参数值会得到不同的假设函数。

我们选择参数θ0 和θ1得到的直线,应该尽量和训练数据拟合。这样才能做出比较精准的预测。

那么如何来使它来更好的拟合数据呢?我们的想法是hθ(x) 应该最接近 y 值,即问题转化成了一个mininize(hθ(x) -y) 的问题,有没有感觉转化成数学问题了。

代价函数

接下来引入一个代价函数Cost Function,也被称作平方误差函数。

函数定义如下,每个训练样本 hθ(x)-y 的平方和,再求平均。再乘1/2是为了接下来的计算上的方便。

我们想要做的就是关于θ0 和θ1对函数J(θ0 ,θ1)求最小值。即找到使得J(θ0 ,θ1)最小值的时候,θ0 和θ1的值。接下来介绍一种算法,梯度下降。它能自动的找出使 J 最小化的参数θ0 和θ1的值

梯度下降

了解梯度下降前,我们了解一下J(θ0 ,θ1) 的函数图像。

θ0 为0时,随着的变化θ1 将会得到下图的效果。θ1取1的时候 J 为最小值 

 

 当θ0 和θ1都有值时。

 

好了,回到我们之前问题描述,我们有一个代价函数J(θ0 ,θ1),想通过一个算法来使用得 J 最小化。

那么梯度下降的思想就是:

开始给定一个(θ0 ,θ1)初始值,我们想通过不断的改变θ0 ,θ1的值,每次改都使得 J 减少。最终J 减少到最小。

下面通过图我们来看梯度下降是如何工作的。

首先想象一下,对θ0 ,θ1赋以某个初始值(一般可以初始化为0)。假设初始化后,J 对应是下图的标红的这个点。

我们想象这是一座山,你站在山上的这个点上。在梯度下降中,我们要做的是看看周周围,并问自己我想要通过小碎步下山,朝哪个方向能最快下山?并朝着这个方向前行。

每走一步都需要调整最快的那个方向。最终你走出了这么一条轨迹。最终走到一个局部最优解——山脚下。当然如果你是站在另一个点,你可以会走出另一条轨迹。

 

上面是通过图直观的感受,那么事实上在这走一步的方向,其实就是梯度的负方向。梯度其实就是J的导数,对于一个线性函数,也就是线的斜率。

如果把每一步的长度定义为学习速率。那么每走一步的这个动作,其实就是 θ0 ,θ1 都朝梯度的负方向进行更新。控制着更新的幅度。

下图是数学定义:即按照一定的学习速率,不断重复更新θ0 ,θ1 直到 J 局部收敛到最小值。

 

下图是对一元线性函数的直客感受,如下图函数上的某点,沿红色方向,即斜率的反方向下降一个步长到另一点。θ1将得到 -* 斜率的更新。

 另一个方向也是同样效果。

其中关于学习速率大小的的选择对算法的影响 ,如果速率太小,则下降的速度比较慢。如果速率过大,会无法收敛到最小值。

如果θ1的选择一开始就是最优点。那么这个点的导数为0,θ1则不会得到更新。

 

梯度下降的过程中,导数的值会不断变小,下降的幅度也会自然的减少。所有没有必要在下降的过程中调整学习速率。

 

在线性回归中,梯度下降的具体实现

前面讲了梯度下降的数学特性,那么在线性回归的训练算法中是如何应用的呢。

下图左边是梯度下降的算法,右边是线性回归的模型。

要实现这个算法,我们还差这个关键项。它表示分别对θ0 ,θ1求导,可以参数数学上的求导方法。

θ0 求导后得到

θ1求导后得到

然后代到梯度下降的公式中。每一次循环,都要分别求出θ0 ,θ1的更新值然后更新。

课后练习代码,Octave实现。

现在有一家餐饮连锁公司,关于城市人口和利润的数据。我们要得到城市人口和利润的预测函数。

先用可视化的方式Plot 这些数据。

%% ======================= Part 2: Plotting =======================
fprintf('Plotting Data ...\n')
data = load('ex1data1.txt');
X = data(:, 1); y = data(:, 2);
m = length(y); % number of training examples

% Plot Data
% Note: You have to complete the code in plotData.m
plotData(X, y);

fprintf('Program paused. Press enter to continue.\n');
pause;

 

function plotData(x, y)
%PLOTDATA Plots the data points x and y into a new figure 
%   PLOTDATA(x,y) plots the data points and gives the figure axes labels of
%   population and profit.

% ====================== YOUR CODE HERE ======================
% Instructions: Plot the training data into a figure using the 
%               "figure" and "plot" commands. Set the axes labels using
%               the "xlabel" and "ylabel" commands. Assume the 
%               population and revenue data have been passed in
%               as the x and y arguments of this function.
%
% Hint: You can use the 'rx' option with plot to have the markers
%       appear as red crosses. Furthermore, you can make the
%       markers larger by using plot(..., 'rx', 'MarkerSize', 10);

figure; % open a new figure window

plot(x, y, 'rx','MarkerSize',10); %Plot the data

ylabel('Profit in $10,000s'); %Set the y-axis lable

xlabel('Population of City in 10,000s'); %Set the x-axis lable

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

end

 用梯度下降方法,得到一个最佳似合直线。

%% =================== Part 3: Gradient descent ===================
fprintf('Running Gradient Descent ...\n')

X = [ones(m, 1), data(:,1)]; % Add a column of ones to x
theta = zeros(2, 1); % initialize fitting parameters

% Some gradient descent settings
iterations = 1500; %定义循环次数
alpha = 0.01; %定义学习速率

% compute and display initial cost
computeCost(X, y, theta)

% run gradient descent
theta = gradientDescent(X, y, theta, alpha, iterations);


 CostFunction 代价函数实现,

function J = computeCost(X, y, theta)
%COMPUTECOST Compute cost for linear regression
%   J = COMPUTECOST(X, y, theta) computes the cost of using theta as the
%   parameter for linear regression to fit the data points in X and y

% Initialize some useful values
m = length(y); % number of training examples

% You need to return the following variables correctly 
J = 0;

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta
%               You should set J to the cost.

temp = (X * theta) - y ;

J = (1 / (2 * m)) * sum( (temp.^2) ) ; 
% 矩阵运算方式
% temp'*temp 
% =========================================================================

end

 梯度下降实现

function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)
%GRADIENTDESCENT Performs gradient descent to learn theta
%   theta = GRADIENTDESENT(X, y, theta, alpha, num_iters) updates theta by 
%   taking num_iters gradient steps with learning rate alpha

% Initialize some useful values
m = length(y); % number of training examples
J_history = zeros(num_iters, 1);

for iter = 1:num_iters

    % ====================== YOUR CODE HERE ======================
    % Instructions: Perform a single gradient step on the parameter vector
    %               theta. 
    %
    % Hint: While debugging, it can be useful to print out the values
    %       of the cost function (computeCost) and gradient here.
    %

temp1 = theta(1) - (alpha / m) * sum((X * theta - y ).*X(:,1));

temp2 = theta(2) - (alpha / m) * sum((X * theta - y).* X(:,2));  

theta(1) = temp1;

theta(2) = temp2;
% 矩阵运算方式 % theta = theta - alpha * (X' * (X * theta - y)) / m; % ============================================================ % Save the cost J in every iteration J_history(iter) = computeCost(X, y, theta); end end

 打印结果

% print theta to screen
fprintf('Theta found by gradient descent: ');
fprintf('%f %f \n', theta(1), theta(2));

% Plot the linear fit
hold on; % keep previous plot visible
plot(X(:,2), X*theta, '-')
legend('Training data', 'Linear regression')
hold off % don't overlay any more plots on this figure

% Predict values for population sizes of 35,000 and 70,000
predict1 = [1, 3.5] *theta;
fprintf('For population = 35,000, we predict a profit of %f\n',...
    predict1*10000);
predict2 = [1, 7] * theta;
fprintf('For population = 70,000, we predict a profit of %f\n',...
    predict2*10000);

fprintf('Program paused. Press enter to continue.\n');
pause;

 

 

 

 

注:上述学习资料参考:https://www.coursera.org/learn/machine-learning

posted on 2015-11-20 15:17  张日海  阅读(3667)  评论(0编辑  收藏  举报

导航