编程作业(五)

正则化的线性回归以及偏差VS方差

正则化的线性回归

背景:数据集中包含水位变化的历史记录x和水坝的水量y。

任务一 可视化数据集

我们将数据集分为三部分:

  • 训练集:X,y
  • 交叉验证集:Xval,yval
  • 测试集:Xtest,ytest

因此,本任务只需将训练集可视化即可。在ex5.m文件已将该任务代码准备好了,我们只需运行即可:

% Load from ex5data1: 
% You will have X, y, Xval, yval, Xtest, ytest in your environment
load ('ex5data1.mat');

% m = Number of examples
m = size(X, 1);

% Plot training data
plot(X, y, 'rx', 'MarkerSize', 10, 'LineWidth', 1.5);
xlabel('Change in water level (x)');
ylabel('Water flowing out of the dam (y)');

其运行结果为:

任务二 线性回归的正则化代价函数

我们先将正则化代价函数公式列出:

其向量化后公式为:
 J(θ) = ((Xθ - y)T(Xθ - y) + λθtTθt) / 2m
其中,θt表示将θ的第一列替换为0,即θ0不参与正则化操作。

因此,我们可根据上述公式在linearRegCostFunction.m文件中键入如下代码:

theta_1 = [0; theta(2:end)];
J = ((X * theta - y)' * (X * theta - y)) / (2 * m) + lambda / (2 * m) * theta_1' * theta_1;

任务三 线性回归的正则化下降梯度

同样的,我们先将公式列出:

其向量化后的公式为:
 grad = (XT(Xθ - y) + λθt) / m
其中θt同上。

因此,在linearRegCostFunction.m文件中继续键入如下代码:

grad = (X' * (X * theta - y) + lambda * theta_1) / m;

任务四 拟合线性回归

一旦你的代价函数和下降梯度运行正常,下一步就是在ex5.m文件调用并运行trainLinearReg.m文件中的代码,通过使用fmincg函数计算出使得代价函数最小化的θ。

在该任务中参数θ为2维向量,因此我们将正则化参数λ的值设为0。为何将正则化参数λ的值设为0?这是因为正则化对于低维度的θ没有太大的帮助。

trainLinearReg.m文件中的代码如下:

function [theta] = trainLinearReg(X, y, lambda)
%TRAINLINEARREG Trains linear regression given a dataset (X, y) and a
%regularization parameter lambda
%   [theta] = TRAINLINEARREG (X, y, lambda) trains linear regression using
%   the dataset (X, y) and regularization parameter lambda. Returns the
%   trained parameters theta.
%

% Initialize Theta
initial_theta = zeros(size(X, 2), 1); 

% Create "short hand" for the cost function to be minimized
costFunction = @(t) linearRegCostFunction(X, y, t, lambda);

% Now, costFunction is a function that takes in only one argument
options = optimset('MaxIter', 200, 'GradObj', 'on');

% Minimize using fmincg
theta = fmincg(costFunction, initial_theta, options);

end

ex5.m文件中该部分代码如下:

%  Train linear regression with lambda = 0
lambda = 0;
[theta] = trainLinearReg([ones(m, 1) X], y, lambda);

%  Plot fit over the data
plot(X, y, 'rx', 'MarkerSize', 10, 'LineWidth', 1.5);
xlabel('Change in water level (x)');
ylabel('Water flowing out of the dam (y)');
hold on;
plot(X, [ones(m, 1) X]*theta, '--', 'LineWidth', 2)
hold off;

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

运行结果为:

偏差与方差

高偏差的模型通常对训练集的拟合不太好,即欠拟合问题;高方差的模型通常对训练集的拟合非常完美,但对于交叉验证集或测试集的拟合不太好,即过拟合问题。

因此,该小节将练习绘制学习曲线来诊断偏差与方差的问题。

任务一 学习曲线

为了绘制学习曲线,我们需要计算出Jtrain(θ)和JCV(θ)。

其中Jtrain(θ)的计算公式为:

JCV(θ)的计算公式为:

因此,我们先需要利用trainLinearReg函数计算出使得代价函数最下化的θ的值;然后在使用linearRegCostFunction函数分别计算Jtrain(θ)和JCV(θ)。

注:在使用linearRegCostFunction函数时,要注意将正则化参数λ = 0。

learningCurve.m文件中的具体代码如下:

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

该部分的运行结果为:

多项式回归

在之前的部分,我们的线性模型对数据的拟合不太好,即出现欠拟合问题。在本小节,我们通过增加特征变量来解决欠拟合问题。

对于多项式回归,我们的假设函数hθ(x)为:
hθ(x) = θ0 + θ1 * (waterLevel) + θ2 * (waterLevel)2 + ... + θp * (waterLevel)p

现在,我们需要在数据集中增添高阶幂的特征变量。因此,我们需要在polyFeatures.m文件中键入相关代码,使得数据集X变为一个m*p的矩阵。

polyFeatures.m文件的相关代码如下:

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

任务一 学习多项式回归

对于该部分的练习,我们使用8次幂的多项式回归模型。由于特征变量在多项式回归模型中,其取值范围各不相同。因此,我们需要对特征变量归一化。

featureNormalize.m文件中特征变量归一化代码如下:

function [X_norm, mu, sigma] = featureNormalize(X)
%FEATURENORMALIZE Normalizes the features in X 
%   FEATURENORMALIZE(X) returns a normalized version of X where
%   the mean value of each feature is 0 and the standard deviation
%   is 1. This is often a good preprocessing step to do when
%   working with learning algorithms.

mu = mean(X);
X_norm = bsxfun(@minus, X, mu);

sigma = std(X_norm);
X_norm = bsxfun(@rdivide, X_norm, sigma);


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

end

然后,我们将正则化参数λ = 0,利用trainLinearReg函数计算出使得代价函数最下化的θ的值。

最后,我们利用linearRegCostFunction函数分别计算Jtrain(θ)和JCV(θ),绘制出学习曲线。

该部分代码如下:

%% =========== Part 6: Feature Mapping for Polynomial Regression =============
%  One solution to this is to use polynomial regression. You should now
%  complete polyFeatures to map each example into its powers
%

p = 8;

% Map X onto Polynomial Features and Normalize
X_poly = polyFeatures(X, p);
[X_poly, mu, sigma] = featureNormalize(X_poly);  % Normalize
X_poly = [ones(m, 1), X_poly];                   % Add Ones

% Map X_poly_test and normalize (using mu and sigma)
X_poly_test = polyFeatures(Xtest, p);
X_poly_test = bsxfun(@minus, X_poly_test, mu);
X_poly_test = bsxfun(@rdivide, X_poly_test, sigma);
X_poly_test = [ones(size(X_poly_test, 1), 1), X_poly_test];         % Add Ones

% Map X_poly_val and normalize (using mu and sigma)
X_poly_val = polyFeatures(Xval, p);
X_poly_val = bsxfun(@minus, X_poly_val, mu);
X_poly_val = bsxfun(@rdivide, X_poly_val, sigma);
X_poly_val = [ones(size(X_poly_val, 1), 1), X_poly_val];           % Add Ones

fprintf('Normalized Training Example 1:\n');
fprintf('  %f  \n', X_poly(1, :));

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



%% =========== Part 7: Learning Curve for Polynomial Regression =============
%  Now, you will get to experiment with polynomial regression with multiple
%  values of lambda. The code below runs polynomial regression with 
%  lambda = 0. You should try running the code with different values of
%  lambda to see how the fit and learning curve change.
%

lambda = 0;
[theta] = trainLinearReg(X_poly, y, lambda);

% Plot training data and fit
figure(1);
plot(X, y, 'rx', 'MarkerSize', 10, 'LineWidth', 1.5);
plotFit(min(X), max(X), mu, sigma, theta, p);
xlabel('Change in water level (x)');
ylabel('Water flowing out of the dam (y)');
title (sprintf('Polynomial Regression Fit (lambda = %f)', lambda));

figure(2);
[error_train, error_val] = ...
    learningCurve(X_poly, y, X_poly_val, yval, lambda);
plot(1:m, error_train, 1:m, error_val);

title(sprintf('Polynomial Regression Learning Curve (lambda = %f)', lambda));
xlabel('Number of training examples')
ylabel('Error')
axis([0 13 0 100])
legend('Train', 'Cross Validation')

fprintf('Polynomial Regression (lambda = %f)\n\n', lambda);
fprintf('# Training Examples\tTrain Error\tCross Validation Error\n');
for i = 1:m
    fprintf('  \t%d\t\t%f\t%f\n', i, error_train(i), error_val(i));
end

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

运行结果为:

学习曲线

任务二 调整正则化参数(选做)

当正则化参数λ = 1时,其运行结果为:

学习曲线

当正则化参数λ = 100时,其运行结果为:

学习曲线

任务三 通过交叉验证集选择正则化参数

当正则化参数λ∈{0, 0.001, 0.003, 0.03, 0.1, 0.3, 1, 3, 10}时,分别计算出Jtrain(θ)和JCV(θ)。

在validationCurve.m文件中键入如下代码:

for i = 1 : length(lambda_vec)
    lambda = lambda_vec(i);
    theta = trainLinearReg(X, y, lambda);
    error_train(i) = linearRegCostFunction(X, y, theta, 0);
    error_val(i) = linearRegCostFunction(Xval, yval, theta, 0);
end

然后,ex5.m文件中的相关代码通过Jtrain(θ)和JCV(θ)的值,绘制出相关函数图。

[lambda_vec, error_train, error_val] = ...
    validationCurve(X_poly, y, X_poly_val, yval);

close all;
plot(lambda_vec, error_train, lambda_vec, error_val);
legend('Train', 'Cross Validation');
xlabel('lambda');
ylabel('Error');

fprintf('lambda\t\tTrain Error\tValidation Error\n');
for i = 1:length(lambda_vec)
    fprintf(' %f\t%f\t%f\n', ...
            lambda_vec(i), error_train(i), error_val(i));
end

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

其运行结果为:

任务四 计算测试集误差(选做)

在实际开发中,除了计算Jtrain(θ)和JCV(θ),我们还需计算Jtest(θ)。

参考代码:

for i = 1 : m
    theta = trainLinearReg(X(1:i, :), y(1:i), lambda);
    error_test(i) = linearRegCostFunction(Xtest(1:i, :), ytest(1:i), theta, 0);
end

任务五 绘制随机数据集的学习曲线(选做)

从数据集中随机抽取60%的数据作为训练集,20%的数据作为交叉验证集和20%的数据作为测试集。由于此部分答案不唯一就不过多叙述。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 之前浏览Coursera上机器学习方面的课程,Andrew Ng的《Machine Learning》课程评分一直...
    黑洞王阅读 1,536评论 0 2
  • 偏差和方差的判别 高偏差和高方差本质上为学习模型的欠拟合和过拟合问题。 对于高偏差和高方差问题,即学习模型的欠拟合...
    SmallRookie阅读 478评论 0 0
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,047评论 25 707
  • 过拟合问题(The Problem of Overfitting) 如上图所示,第一个采用单变量线性回归模型来拟合...
    SmallRookie阅读 542评论 0 1
  • 新虎日精进269(11.11): 1.复习一天 2.准备明日主持筛选 Tiger 新虎日精进270(11...
    新虎NewTiger阅读 209评论 0 0