linearRegCostFunction.m
这个文件主要的功能是计算正则化线性回归的代价函数和梯度,其实在之间的正则化的练习过程中就有过实现。作为温习,先放出对应的参考。
代价函数的计算公式正如上图中所示,这里需要注意的是标黄的部分文字。其意思是不需要正则化theta0,这与视频中一致,同时在MATLAB中,theta0代表的是theta1。
梯度的计算主要是区别j = 0和j ≥ 1。在程序中体现出来,其中j = 0时,对于公式中的
,j的值只能为0,也就是说只能取第1列。(
的上标i代表的是行数,j代表的是列数)。同样的,对于j大于等于1时的程序实现需要注意的是
只能取第2列往后的数据。下面贴出实现代码。
%这里只需要注意下正则化时并未包括theta0
h = X * theta;
J = sum((h - y) .^2) / (2 * m) + lambda * sum(theta(2:end,:) .^2) / (2 * m);
%主要grad(1)和grad(2:end)计算是不同的 主要区别是theta0的计算
grad(1,:) = sum((h - y) .* X(:,1)) / m;
grad(2:end,:) = X(:,2:end)' * (h - y) / m + lambda .* theta(2:end,:) / m;
learningCurve.m
这个文件的主要功能是绘制线性回归的学习曲线。该函数能够返回训练集误差和交叉验证误差的向量。其公式类似于代价函数的计算,如下。
这里需要注意的是在计算训练集的误差时是使用的其子集而非整个集合,计算交叉验证集误差的时候使用的是整个集合。正如下图中标记的文字所说的一样。同时,在计算代价函数时使用的theta,这里需要通过trainLinearReg函数得到,这个函数的其实就是使用fminuc寻找最优的theta。这在之前的学习中已经使用过了。
其实根据学习曲线的定义,其x轴是训练集的数量,y轴是误差,其中绘制了两条曲线分别是训练集的学习曲线和交叉验证集的曲线。因此,不难写出如下的代码 ,下面贴出该文件的主要代码实现
%需要注意的是这里lambda的值是0
for i = 1:m;
theta = trainLinearReg(X(1:i,:),y(1:i),lambda);
error_train(i) = linearRegCostFunction(X(1:i,:),y(1:i), theta, lambda);
error_val(i) = linearRegCostFunction(Xval,yval, theta, lambda);
end
polyFeatures.m
这个函数的实现很简单,就是返回一个m*p的多项式。直接给出实现代码
for i = 1 : p;
X_poly(:,i) = power(X,i);
end
validationCurve.m
这个函数的目的是使用交叉验证集合选择合适的lambda的值。为什么要选择一个合适的lambda参数,这里贴出吴恩达作业中的解释。
In particular, a model without regularization (λ = 0) fits the training set well, but does not generalize. Conversely,a model with too much regularization (λ = 100) does not fit the training set and testing set well.
也就是说如果一个训练模型没有lambda参数,虽然对于训练集的拟合会很好,但是其 泛化能力很弱,运用到其它集合时的效果就不会很好。相反,如果lambda过大,那么对于训练集的拟合就不会很好。
这个函数的实现并不难,其主要思想是通过不同的lambda的值利用trainLinearReg训练得到合适的theta值,并通过得到的theta值利用linearRegCostFunction分别得到训练集误差和交叉验证集的误差。下面贴出关键代码。
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