吴恩达机器学习作业翻译1——linear regression

程序设计练习1: 线性回归

介绍

    在本练习中,你将实现线性回归,并明确它对数据的作用。在开始这个练习之前,我们强烈建议你观看视频讲座并完成相关主题的复习问题。

    要开始练习,你需要下载起始代码并将其内容解压缩到你希望完成练习的目录中。如果需要,请在开始本练习之前使用Octave/MATLAB中的cd命令更改到此目录。

    你也可以在课程网站的“环境设置说明”中找到安装Octave/MATLAB的说明。

本练习中包含的文件

ex1.m - 指导你完成练习的 Octave/MATLAB 脚本
ex1_multi.m - 练习的后面部分 Octave/MATLAB 脚本
ex1data1.txt - 单变量线性回归数据集
ex1data2.txt - 多变量线性回归数据集
submit.m - 将你的答案发送到我们服务器的提交脚本

[*] warmUpExercise.m -  Octave/MATLAB 中的简单示例函数
[*] plotData.m - 展示数据集的函数
[*] computeCost.m - 线性回归代价函数
[*] gradientDescent.m - 梯度下降函数
[†] computeCostMulti.m - 多变量代价函数
[†] gradientDescentMulti.m - 多变量梯度下降
[†] featureNormalize.m - 用于规范化功能的函数
[†] normalEqn.m - 计算正规方程的函数

* 标示必须完成的文件
† 标示可选练习

    在整个练习中,你将使用脚本ex1.m和ex1_multi.m。
这些脚本为题目设置数据集并调用你将要编写的函数。你不需要修改这两个脚本其中任何一个,只需要按照本作业中的说明修改其他文件中的函数。

    对于这个编程练习你只需要完成第一部分练习实现单变量线性回归,第二部分的多变量线性回归是可选的。

在哪里寻求帮助

    本课程的练习使用非常适合数值计算的高级编程语言Octave或MATLAB。如果你没有安装Octave或MATLAB,请参阅课程网站上“环境设置说明”中的安装说明。

    在Octave/MATLAB命令行中输入help紧跟函数名称会显示内建的函数说明。比如输入help plot会显示绘图函数的帮助信息。更多Octave和MATLAB的函数说明请在Octave官网MATLAB官网查阅。

    我们也非常鼓励使用在线讨论与其他学生讨论练习。但是,不要查看任何源代码或与他人共享源代码。


1、简单的Octave/MATLAB函数

    ex1.m的第一部分给出了使用Octave/matlab的语法和作业提交流程。在warmupexercise.m文件中,有一个Octave/matlab函数的框架。通过填充以下代码修将其修改为返回5 x 5单位矩阵的函数:

    A = eye(5);

    当你完成后,运行(假设你在正确的目录中,
在Octave/matlab的提示下键入“ex1”)ex1.m文件,应该会看到类似下面的输出:

    ans =
    Diagonal Matrix
        1 0 0 0 0
        0 1 0 0 0
        0 0 1 0 0
        0 0 0 1 0
        0 0 0 0 1

    现在,ex1.m将暂停,直你按下其他键,然后运行下一任务的代码。如果要退出,键入ctrl-c将在运行过程中终止程序。

1.1 提交答案

    完成部分练习后,你可以提交答案并在Octave/MATLAB。提交脚本将提示你输入登录的e-mail和提交的token,并询问你要提交哪些文件。你可以网页中获得本次作业的token。

            ==你现在应该提交答案==

    你可以多次提交答案,我们只考虑最高分数。


2、单变量线性回归

    在这部分练习中,你将实现单变量线性回归来预测快餐车的利润问题。假设你是一家餐厅的CEO并且正在考虑在不同城市开设分店的问题。该连锁店在早已经其他城市有快餐车并且你有各个城市的利润数据和人口数据。
你希望使用此数据帮助选择下一步要扩展的城市。

    文件ex1data1.txt包含线性回归问题的数据集。第一列是一个城市的人口,第二列是该城市快餐车的利润,利润负值表示损失。

    已经设置了ex1.m来为你加载数据。

2.1 绘制数据

    在开始任何任务之前,通过可视化来理解数据通常是很有用的。对于此数据集,你可以使用散点图来可视化数据,因为它只有两个属性需要绘制(利润和人口)。(许多在现实生活中遇到的其他问题是多维的,不能在二维平面上绘制)
在ex1.m中,将数据集从数据文件加载到变量 Xy 中:

    data = load('ex1data1.txt'); % read comma separated data
    X = data(:, 1); y = data(:, 2);
    m = length(y); % number of training examples

    接下来,脚本调用plotData函数来创建这些数据的散点图。你的任务是完成plotDat.m来绘图;修改文件并填写以下代码:

    plot(x, y, 'rx', 'MarkerSize', 10); % Plot the data
    ylabel('Profit in $10,000s'); % Set the y−axis label
    xlabel('Population of City in 10,000s'); % Set the x−axis label

    现在,当你继续运行ex1.m,我们的最终结果应该如图1所示,有红色“x”标记和轴标记。
要了解plot命令的更多信息,你可以在Octave/MATLAB命令提示符中键入help plot,或者在线搜索绘图文档。
(为了将标记改为红色的“x”,我们在plot命令中使用了选项“rx”);


Figure 1: Scatter plot of training data

2.2 梯度下降

    在这部分中,你将使用梯度下降法拟合线性回归中的参数θ到我们的数据集。

2.2.1 更新方程

    线性回归的目标是使代价函数最小化

    该假设函数的线性模型如下

    回想一下,模型的参数是$θ_j$,你将通过调整它来最小化代价函数J(θ)。一种方法是使用批量梯度下降算法,批量梯度下降每次都迭代更新下面的式子:

    每一步的梯度下降,参数$θ_j$都会更加接近使代价函数J(θ)最低的最优值。

#

注意:我们将每个样本作为一行存储在Octave/MATLAB中的X矩阵中。考虑到截距项(θ0),我们在X上增加了额外的第一列,并把它的所有值设为1。这样我们就可以把$θ_0$当做另一个简单“特征”。

2.2.2 实现

在ex1.m中我们已经建立了线性回归的数据。接下来,我们向数据中添加第一列(全部为1)以适应$θ_0$截距项。我们还将初始化参数,使为θ为0,学习率为0.01。

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

2.2.3 计算代价函数

    当你执行低度下降学习最小化代价函数J(θ)时,通过计算代价函数来监控收敛是很有帮助的。在这一小节,你将实现一个函数来计算J(θ),这样你就可以查看自己梯度下降算法的收敛。你的下一个任务是完成computeCost.m文件(计算J(θ)的函数)中的代码。当你做这个作业的时候要记得变量X和y不是标量,而是矩阵,矩阵中的每一行代表训练集中的一个样本。完成该功能后,ex1.m中的下一步将使用值为0的θ运行computeCost,你会看到代价函数的结果打印到屏幕上,并且为32.07。

            ==你现在应该提交答案==

2.2.4 梯度下降

    接下来你将在gradientDescent.m文件中实现梯度下降算法。

    循环结构已经为你写好了,你只需要补充每次迭代时更新θ的代码就好。

    在写代码时,请确保你已经理解了要优化的内容以及正在更新的内容。请记住,代价函数J(θ)是通过向量θ参数化的,而不是X和y。也就是说,我们是通过改变向量θ的值来最小化J(θ)的值,而不是通过改变X或y来最小化J(θ)的值。如果不确定的话请参考讲义和视频中的公式。

    确认梯度下降是否正确执行的一个方法是检查J(θ)的值是否每次都递减。给出的gradientDescent.m文件中每次迭代都调用了computeCost并且打印了代价函数的值。假设你已经完美实现了梯度下降法和computeCost,你的J(θ)不应该出现增加的值,而是最终收敛于一个稳定值的算法。

    当你完成后,ex1.m将使用最终参数来绘制线性拟合。结果应该如图2所示:


Figure 2: Training data with linear regression fit

    最终值θ也将用来预测35000和70000人的利润。请注意ex1.m中以下行使用矩阵乘法而不是显式求和或循环来计算预测。这是Octave/MATLAB中代码向量化的一个例子。

            ==你现在应该提交答案==

    predict1 = [1, 3.5] * theta;
    predict2 = [1, 7] * theta;

2.3 调试

    下面是实现梯度下降时需要记住的一些要点:

  • Octave / MATLAB数组索引从一开始,而不是零。如果将$θ_0$$θ_1$存储在名为theta的向量中,则值将为theta(1)和theta(2)。
  • 如果在运行时出现错误,请检查你的矩阵排列,以确保你正在相加和相乘维度可兼容的矩阵。使用size命令打印变量的维度信息将有助于调试。
  • 默认情况下,Octave/MATLAB将数学运算符解释为矩阵运算符。这是大小不兼容错误的常见来源。如果在Octave/MATLAB中不想要矩阵乘法,则需要添加“.”符号。例如,AB执行矩阵乘法,而A.B执行逐元素乘法。

2.4 可视化J(θ)

    为了更好地理解代价函数J(θ),现在要在一个二维网格中绘制$θ_0$$θ_1$的值。这部分你不需要编写新代码,但是你要理解你写过的代码是如果绘制这些图像的。

    在ex1.m的下一步中,有代码使用你写过的computeCost函数计算J(θ)的网格值。

    % initialize J vals to a matrix of 0's
    J vals = zeros(length(theta0 vals), length(theta1 vals));
    % Fill out J vals
    for i = 1:length(theta0 vals)
    for j = 1:length(theta1 vals)
    t = [theta0 vals(i); theta1 vals(j)];
    J vals(i,j) = computeCost(x, y, t);
    end
    end

    执行上面的代码后,你将得到一个J(θ)值的二维数组。然后脚本ex1.m将使用这些值使用surf和contour命令生成J(θ)的曲面图和等高线图。这些图应该类似于图3:


Figure 3: Cost function J(θ)

    这些图的目的是向你展示J(θ)如何随着θ0和θ1变化。 代价函数J(θ)是碗状的并且具有全局最小值。(这在等高线图中比在3D表面图中更容易看到)。该最小值是$θ_0$$θ_1$的最佳点,并且梯度下降的每一步都更接近该点。


选做练习

    如果你已经完成了前面部分的内容,那么恭喜你!你已经掌握了线性回归,并且可以将其运用到自己的数据集上。
    本次作业的内容还包括下面的可选作业题,它将是你对线性回归有更深层次的理解,如果你学有余力,我们鼓励你完成下面的部分。


3、多变量线性回归

    在这一部分你将使用多变量线性回归预测房屋价格。假设你准备卖掉自己的房子并且想知道卖多少才算一个好的市场价,比较好的方法就是收集最近的房屋成交信息并建立一个房屋估价模型。

    文件ex1data2.txt包含俄勒冈州波特兰市的房价训练集。第一列是房子的大小(单位是平方英尺),第二列是卧室的数量,第三列是房子的价格。

    准备好的ex1_multi.m脚本将帮你一步步完成本次练习。

3.1 特征标准化

    ex1_multi.m从加载和展示数据集中的一些值开始。观察这些值会注意到房屋大小大约是卧室数量的1000倍。当特征值差别比较大的时候,进行特征缩放可以使梯度下降收敛得更快。

    你目前的任务是完成featureNormalize.m中的代码完成以下要求:

  • 从数据集中减去每个特征的平均值
  • 在减去平均值之后,再用特征值除以它们各自的“标准差”

    标准偏差是一种衡量特征值在特定范围内变化幅度的方法(大多数数据点将位于平均值的±2标准偏差范围内),这是获取值范围(max-min)的替代方法。在Octave/MATLAB中,可以使用“std”函数计算标准差。例如,在featureNormalize.m中,X(:,1)包含了训练集中所有x1(房屋大小)的值,所以std(X(:,1))会计算房屋大小的标准差。在调用featureNormalize.m的时候,矩阵X的第一列$x_0$=1还没有添加(详情见ex1_multi.m)。

    你将对所有特征执行上面的操作,并且你的代码应该使用所有数据(任意数量的特性/示例)。

            ==你现在应该提交答案==

注意:在对特征进行规范化时,重要的是要存储用于标准化的值——用于计算的平均值和标准差。在从模型中学习参数之后,我们想要预测我们以前没有见过的房价。给定一个新的x值(房屋面积和卧室数量),首先,我们必须使用之前从训练集中计算出的均值和标准差对x进行归一化。

3.2 梯度下降

    以前,你在单变量回归问题上实现了梯度下降。现在唯一的不同是,矩阵X中多了一个特征。假设函数和批处理梯度下降更新规则仍然不变。

    你应该完成computeCostMulti.m和gradientDescentMulti.m文件中的代码以实现多变量线性回归的代价函数和梯度下降。如果你之前完成单变量作业题的代码支持多变量,你在这里可以直接用它。

    确保你的代码支持任意数量的特征,并且支持向量化。你可以使用“size(X, 2)”来找出数据集中有多少个特征。

            ==你现在应该提交答案==

注意:在多元情况下,代价函数也可以写成如下矢量形式,矢量化的版本在使用像Octave/MATLAB这样的数字计算工具时非常有效。


如果你是矩阵运算的专家,你可以证明这两种形式是等价的。

3.2.1 可选练习:选择学习率

    在这部分练习中,你将尝试为数据集尝试不同的学习率,并找到快速收敛的学习率。你可以通过修改ex1_multi.m并更改设置学习率的代码部分来更改学习率。

    然后ex1_multi.m调用你的gradientDescent.m函数并在选定学习率的情况下迭代50次梯度下降。该函数还会在向量J中返回J(θ)历史值。在最后一次迭代之后,ex1_multi.m脚本将绘制J值关于迭代次数的函数图。

    如果你的学习率选在合适的范围内,那么你的图应该如图4所示。如果你的图和图4的差别较大,尤其是J(θ)在增加甚至看起来很离谱,你应该调整学习率再试一次。我们建议在对数刻度上尝试学习率α的值,步长约为前一个值的3倍(即0.3,0.1,0.03,0.01等)。
如果要查看曲线的整体趋势,你可能还需要调整正在运行的迭代次数。


Figure 4: Convergence of gradient descent with an appropriate learning rate

注意:如果你的学习速度太大,J(θ)可能会发散并“爆炸”,从而导致数值太大以至于计算机无法计算。这种情况下,Octave/MATLAB会返回NaN。NaN代表“非数字”,通常由包括-∞和+∞在内的的未定义操作引起。

Octave/MATLAB提示:为了比较不同的学习速率是如何影响收敛的,在同一个图中绘制几个不同学习速率代价函数图是有帮助的。在Octave/MATLAB中,这可以通过在plot函数之间使用“hold on”命令多次进行梯度下降进行实现。具体一点就是说,如果你尝试了三个不同的alpha值(你应该尝试更多的值),并将代价函数存储在J1、J2和J3变量中,那么你可以使用以下命令将它们绘制在同一个图上:

plot(1:50, J1(1:50), ‘b’);
hold on;
plot(1:50, J2(1:50), ‘r’);
plot(1:50, J3(1:50), ‘k’);

最后一个参数‘b’,‘r’,‘k’指定各个图的颜色。

    注意随着学习速率的变化,收敛曲线的变化。
在学习速率较小的情况下,你应该会发现梯度下降需要很长时间才能收敛到最优值。相反,在学习速率较大的情况下,梯度下降可能不会收敛,甚至可能偏离!

    用你找到的最佳学习率运行ex1_multi.m脚本来运行梯度下降,直到收敛到最终的θ值。然后用这个θ值来预测1650平方尺大小、3个卧室的房子的价格。稍后你会用这个值来验证正规方程。在做预测的时候不要忘记特征标准化。

3.3 正规方程

    在课堂视频中,你们学过线性回归的封闭解是

    使用这个公式不需要任何特征缩放,你将在一个计算中得到一个精确值:像梯度下降一样,没有“循环,直到收敛”。

    在normalEqn.中完成代码以使用上面的公式计算θ。记住,我们虽然不需要特征缩放,但是仍然需要在X矩阵中添加值为1的列作为截距项($θ_0$)。ex1.m中的代码会把值为1的列加到X中。

            ==你现在应该提交答案==

    现在你已经通过正规方程得到了θ的值,用它来为1650平方尺、三个卧室的房子进行估值,你会发现和前面用梯度下降预测到的值是完全拟合的。

提交和评分

    在完成任务的各个模块后,请务必使用提交系统向我们的服务器提交你的作业。以下是这个练习的每个部分如何得分的细则。

    你可以多次提交,但我们只考虑最高分。

点个赞呗:程序员虾说 » 吴恩达机器学习作业翻译1——linear regression

赞 (9) 打赏

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

请作者喝杯咖啡~

支付宝扫一扫打赏

微信扫一扫打赏