吴恩达机器学习笔记(5)对回归的评估检测

这一部分是对吴恩达机器学习检测评估的总结

当我们使用算法对某种样本进行回归的时候,需要某种评价标椎对其优劣进行评估,比如对多项式回归的合理次数,正则项的大小选择,样本数目或者样本特征值的选择等等,这些知识详见笔记,这里仅讨论学习函数的代码实现
在这里插入图片描述

主要分为以下几个部分:

1.正则化的线性回归
2.线性回归的学习曲线分析
3.正则化的多项式回归
4.正则化多项式回归的学习曲线分析
1.正则化的线性回归

首先仍然是数据的加载和可视化

%% =========== Part 1: Loading and Visualizing Data =============
fprintf('Loading and Visualizing Data ...\n')
load ('ex5data1.mat');%加载数据
m = size(X, 1);%样本容量
plot(X, y, 'rx', 'MarkerSize', 10, 'LineWidth', 1.5);
%绘制x,y图像
xlabel('Change in water level (x)');
ylabel('Water flowing out of the dam (y)');
fprintf('Program paused. Press enter to continue.\n');
pause;

然后进行线性回归,且看代码
基于模块化思想,分别定义代价函数、梯度、训练的函数

function [J, grad] = linearRegCostFunction(X, y, theta, lambda)
%计算代价函数和梯度的函数
m = length(y); % 样本容量
J = 0;
grad = zeros(size(theta));
J=(1/(2.0*m))*(sum((X*theta-y).^2))+(lambda/(2.0*m)*(theta(2:end)'*theta(2:end)));%代价函数
grad(1)=(1/m).*sum((X*theta)-y);
grad(2:end)=((1/m)*sum((X*theta-y).*X(:,2:end)))'+(lambda/m)*theta(2:end);
%代价函数
grad = grad(:);
end

以及

function [theta] = trainLinearReg(X, y, lambda)
%训练函数
initial_theta = zeros(size(X, 2), 1); 
costFunction = @(t) linearRegCostFunction(X, y, t, lambda);
options = optimset('MaxIter', 200, 'GradObj', 'on');
theta = fmincg(costFunction, initial_theta, options);
end

再在主程序里面把拟合曲线可视化

lambda = 0;%先不考虑正则化问题
[theta] = trainLinearReg([ones(m, 1) X], y, lambda);
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;

这样我们就有了拟合结果并且可以绘制图像:
在这里插入图片描述

2.线性回归的学习曲线分析

现在我们用学习曲线来评价这个拟合的质量,定义绘制学习曲线的函数:

function [error_train, error_val] = ...
    learningCurve(X, y, Xval, yval, lambda)
m = size(X, 1);
error_train = zeros(m, 1);
error_val   = zeros(m, 1);
%这两个参数一个是训练集的代价函数一个是交叉验证集的验证函数,从m=1时开始计算,一直算到m=m
%接下来实现这个循环
for i = 1:m 	%1开始算到m
    theta = trainLinearReg(X(1:i,:),y(1:i),lambda);
    % X(1:i,:)1到i个样本开始算,每一列就是每个特征都要算
    % y(1:i)这是对应的label
    % lambda是正则项,但是观察当下拟合情况的时候可以不用考虑正则化,即lambda=0
    % 这里直接算出训练集的theta
    [error_train(i), ~] = linearRegCostFunction(X(1:i,:),y(1:i),theta,0);
	%用拟合出的theta加上对应样本计算代价函数,但是样本数是随theta变的
    [error_val(i), ~] = linearRegCostFunction(Xval,yval,theta,0);
    %用刚才的theta算代价函数算交叉训练集,但是这里是不随theta变化的,一直是这些样本
end
end

用刚才得到的结论绘图:

lambda = 0;
[error_train, error_val] = ...
    learningCurve([ones(m, 1) X], y, ...
                  [ones(size(Xval, 1), 1) Xval], yval, ...
                  lambda);
plot(1:m, error_train, 1:m, error_val);
title('Learning curve for linear regression')
legend('Train', 'Cross Validation')
xlabel('Number of training examples')
ylabel('Error')
axis([0 13 0 150])
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;

在这里插入图片描述
这是随着样本数增大的代价函数图,可以看出来,它们的收敛值很高,且它们很接近,且随着样本数目增加,代价函数的变化很小这说明它们欠拟合了

但如果它们的收敛值差距很大,且随着样本数增大它们还会慢慢收敛,就说明是过拟合了

那么如果欠拟合,就要考虑多项式回归

3.正则化的多项式回归

我们来看一下8次多项式拟合的效果
首先还是要将有限的特征展开
定义这样一个函数:

function [X_poly] = polyFeatures(X, p)
X_poly = zeros(numel(X), p);
for i = 1:p
    X_poly(:,i) = X.^i;
    %由于本例中只有一个特征,所以自己和自己乘就行
end
end

由于数据的量级差距很大,所以需要归一化,这里使用的归一化方法比较复杂,其实可以用我们之前的方法,这个方法我只贴代码,不做解释,对了,归一化计算的均值是每一个变量的均值,标准差也是,它们不是总体的

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

以上是归一化训练集的函数
注意,验证集和测试集的均值和标准差使用的是测试集的

% 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

接下来在不考虑正则化的情况下用训练集计算theta

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

接下来可视化一些东西

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));

这里plotFit函数是一个绘制拟合曲线的函数,这里只贴代码:

function plotFit(min_x, max_x, mu, sigma, theta, p)
%PLOTFIT Plots a learned polynomial regression fit over an existing figure.
%Also works with linear regression.
%   PLOTFIT(min_x, max_x, mu, sigma, theta, p) plots the learned polynomial
%   fit with power p and feature normalization (mu, sigma).

% Hold on to the current figure
hold on;

% We plot a range slightly bigger than the min and max values to get
% an idea of how the fit will vary outside the range of the data points
x = (min_x - 15: 0.05 : max_x + 25)';

% Map the X values 
X_poly = polyFeatures(x, p);
X_poly = bsxfun(@minus, X_poly, mu);
X_poly = bsxfun(@rdivide, X_poly, sigma);

% Add ones
X_poly = [ones(size(x, 1), 1) X_poly];

% Plot
plot(x, X_poly * theta, '--', 'LineWidth', 2)

% Hold off to the current figure
hold off

end

接下来用同样的方法看看多项式的拟合效果:

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

拟合效果和误差效果如下:
在这里插入图片描述
在这里插入图片描述
训练集的误差很小说明曲线和点拟合的相当好,但是这并不一定是好事,看验证集,与训练集有gap,而且它甚至是不收敛的,这就说明过拟合了,那么就要调整正则项lambda来改善过拟合的情况

定义一个检测函数:

function [lambda_vec, error_train, error_val] = ...
    validationCurve(X, y, Xval, yval)
%这是一个返回一个lambda集合,训练集代价函数,验证集代价函数的函数    
lambda_vec = [0 0.001 0.003 0.01 0.03 0.1 0.3 1 3 10]';
%定义这样的lambda集,记住把它转置
error_train = zeros(length(lambda_vec), 1);
error_val = zeros(length(lambda_vec), 1);
%初始化训练集代价函数,验证集代价函数,每一个lambda对应两个这样的值
for i=1:length(lambda_vec)
%开始挨个计算
    lambda=lambda_vec(i);
    theta = trainLinearReg(X, y, lambda);
    用训练集计算theta
    error_train(i) = linearRegCostFunction(X, y, theta, 0);
    error_val(i) = linearRegCostFunction(Xval, yval, theta, 0);
    用这样的theta计算两个误差
end

所以主程序:

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

并且将其可视化:

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

如图所示:
在这里插入图片描述

λ要选择交叉验证集误差最小的!

所以从上图来看,λ=3的时候效果最好,把λ改成3,效果如下:
在这里插入图片描述
在这里插入图片描述
收敛值很低,舒服了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值