斯坦福机器学习Coursera课程:第五次作业--正则多项式回归和误差分析
本次作业主要是实现正则化多项式回归,画出训练误差和交叉测试误差随训练用例数量变化的曲线,分析高偏差和高方差的影响因素,最后画出的取值变化对误差的影响曲线。
主要函数文件如下 ,需要实现最后4个带*文件的函数。
ex5.m - Octave/MATLAB script that steps you through the exercise
ex5data1.mat - Dataset
submit.m - Submission script that sends your solutions to our servers
featureNormalize.m - Feature normalization function
fmincg.m - Function minimization routine (similar to fminunc)
plotFit.m - Plot a polynomial t
trainLinearReg.m - Trains linear regression using your cost function
[*] linearRegCostFunction.m - Regularized linear regression cost func-
tion
[*] learningCurve.m - Generates a learning curve
[*] polyFeatures.m - Maps data into polynomial feature space
[*] validationCurve.m - Generates a cross validation curve
ext5data1文件中的数据集分为三部分:
X表示水库中水位的变化,y表示水坝放水量
Xval,yval表示交叉测试集中对应的量
Xtest, ytest表示测试集中对应的量。
1. 加载和可视化数据后(原程序只画X/y的,我们作了增加),我们可以知道X/y, Xval/yval, Xtest/ytest分别是12*1, 21*1,21*1的向量,图形如下:
2. 正则化线性回归线代价函数并计算梯度
这个比较简单,和前面作业中的基本一样,linearRegCostFunction.m中套用公式即可。
J=(X*theta-y)'*(X*theta-y)/2/m+lambda*(theta(2:end,1)')*theta(2:end,1)/2/m;
grad(1,1)=1/m*X(:,1)'*(X*theta-y);
grad(2:end,1)=1/m*X(:,2:end)'*(X*theta-y)+lambda/m*theta(2:end,1);
结果和预期相当:
Cost at theta = [1 ; 1]: 303.993192
(this value should be about 303.993192)
Program paused. Press enter to continue.
Gradient at theta = [1 ; 1]: [-15.303016; 598.250744]
(this value should be about [-15.303016; 598.250744])
3. 不带正则化的线性拟合,即训练并画出拟合曲线
对2中代价函数和梯度不断迭代得到优化值。图中可以看出,测试集数据不具有线性特征,用线性回归线时出现高偏差,属于欠拟合。
5. 线性回归线的学习曲线 (实现learningCurve.m中的函数)
学习曲线即是训练集和交叉验证集的误差与训练集size关系的函数曲线。
迭代中训练集size逐渐增加,对应的数据为X(1:i, :) and y(1:i) ( i=1:m, m为训练集X的大小),计算误差时也以参加训练的数据来计算;而交叉验证集则以全集来参与和计算。
根据每次计算的theta值,对训练集和交叉验证集分别计算误差并保存在error_train, error_val向量中。
% Hint: You can loop over the examples with the following:
%
% for i = 1:m
% % Compute train/cross validation errors using training examples
% % X(1:i, :) and y(1:i), storing the result in
% % error_train(i) and error_val(i)
% ....
%
% end
%
% ---------------------- Sample Solution ----------------------
for i=1:m
[theta] = trainLinearReg([ones(i, 1) X(1:i,:)], y(1:i,:), lambda);
error_train(i,1)=linearRegCostFunction([ones(i,1) X(1:i,:)],
y(1:i,:), theta,0);
error_val(i,1)=linearRegCostFunction([ones(size(Xval,1),1) Xval],yval, theta,0);
end
e.g. i=3时,[ones(3,1) X(1:3,:)]
ans =
1.0000 -15.9368
1.0000 -29.1530
1.0000 36.1895
曲线中很显示可以看出,本次中线性回归出现的高偏差问题,依靠增加测试集大小对误差的改善没什么效果。结合前篇“机器学习算法的效果评估和优化方法"的结论和建议,此时需要增加特征,增加多项式特征,减小归一化程度参数lambda,本便中数据只能增加多项式特征来改善。
6. 多项式回归线的特征映射
示例中p=8,即8阶多项式回归。需要完成polyFeatures.m 文件中的函数。
X_poly = zeros(numel(X), p);
for i=1:numel(X)
for j=1:p
X_poly(i,j)=X(i).^j;
end
end
numel(X)将返回X中的元素数,zeros(numel(X),p)将构建元素为0、大小为12*8的矩阵。
阶数高后,需要对元素做特征缩放即归一化处理featureNormalize.m中有实现,知道有这步调用即可,不需要额外实现。
归一化后X为:Normalized Training Example All:
1.000000 -0.362141 -0.755087 0.182226 -0.706190 0.306618 -0.590878 0.344516 -0.508481
1.000000 -0.803205 0.001258 -0.247937 -0.327023 0.093396 -0.435818 0.255416 -0.448912
1.000000 1.377467 0.584827 1.249769 0.245312 0.978360 -0.012156 0.756568 -0.170352
1.000000 1.420940 0.706647 1.359846 0.395534 1.106162 0.125637 0.871929 -0.059638
1.000000 -1.434149 1.854000 -2.037163 2.331431 -2.411536 2.602212 -2.645675 2.766085
1.000000 -0.128687 -0.975969 0.251385 -0.739687 0.316953 -0.594997 0.345812 -0.508955
1.000000 0.680582 -0.780029 0.340656 -0.711721 0.326509 -0.591790 0.346830 -0.508613
1.000000 -0.988534 0.451358 -0.601282 0.092917 -0.218473 -0.141608 0.039403 -0.266693
1.000000 0.216076 -1.074993 0.266275 -0.743369 0.317561 -0.595129 0.345835 -0.508960
1.000000 -1.311501 1.422806 -1.548121 1.493396 -1.515908 1.388655 -1.368307 1.224144
1.000000 0.403777 -1.015010 0.273379 -0.741977 0.317742 -0.595098 0.345839 -0.508959
1.000000 0.929375 -0.419808 0.510968 -0.588624 0.382616 -0.559030 0.361832 -0.500665
7. 多项式回归线的学习曲线 (lambda=0)
左图中略有点问题,红x部分应该有蓝线与之完全重合,明显是过拟合了。
同时,通过右图也能看出来,lambda=0时,随着测试集数量的增加,测试集误差一直为0,交叉验证集的误差一直较大,也是过拟合的问题。
8. 选择不同lambda时的验证曲线以确定最佳lambda
validationCurve.m中实现:
lambda_vec = [0 0.001 0.003 0.01 0.03 0.1 0.3 1 3 10]';
for j=1:length(lambda_vec)
lambda=lambda_vec(j);
[theta] = trainLinearReg(X, y, lambda);
error_train(j,1)=linearRegCostFunction(X, y, theta,0);
error_val(j,1)=linearRegCostFunction(Xval,yval, theta,0);
end
明显,lambda=3时交叉验证集的误差最小。因为测试集和验证集的随机性,交叉验证误差可能略小于测试集误差。