评估一个机器学习算法
01.Evaluating a Hypothesis
- 给定一个数据集,一般将其分为训练集(70%)和测试集(30%)。
- 得到theta参数和最小化代价函数用训练集
- 计算测试集的误差
- 测试集的误差
-
线性回归:
-
分类问题的误差
02. 模型选择
- 机器学习有时候能很好的拟合训练集的时候,并不一定代表他能很好的预测。因为可能过度拟合或者测试的数据太少。一个比较常用的模型选择方法是将数据分为三种:训练集(Training set: 60%)、交叉验证集(Cross validation set: 20%)、测试集(Test set: 20%),具体实现步骤如下:
- 对于每个不同级数d的多项式,利用训练集选择出最优化参数theta
- 利用交叉验证集找到使得误差最小的多项式的级数d
- 用测试集评估最终平均误差
Bias vs. Variance(偏差 vs. 方差)
01. 诊断偏差
-
训练误差和交叉验证误差随着多项式的次数增加会发生一定规律的变化。
高偏差出现在d较小时,此时underfitting;
高方差出现在d较大时,此时overfitting.
02. 正规化的偏差和误差
-
正规化的lamda取值变化对训练偏差和验证误差的关系如图所示:
当lamda取值变大,训练误差变大,此时验证误差也很大(因为训练误差都不准确);太小又过拟合,验证误差变大,只有取值在一个不大不小的值验证误差才比较准确。
找Lamada的过程(双迭代):
- 创造lamda集合
- 用不同次数的多项式创造训练模型
- 循环迭代lamda和不同次数多项式找出theta
- 找到使得验证误差最小的lamda和theta的值
03. 学习曲线
- 学习曲线是训练误差和验证误差随着样本数量的走势图,当我们尝试画出学习曲线的时候,就可以根据走势判断出此时学习算法是高误差还是高方差,以此来修正我们的算法。
-
高偏差:
由于欠拟合,增大训练样本会使得误差变大;验证误差开始因为不能很好拟合所以一开始会很大,但是样本增多,他总能找到一条相对于靠近点的直线、(在增加训练样本的时候实际也是在调整参数),所以偏差会变小,最终和训练偏差差不多。但误差还是较大,此时增加训练样本并不能使训练函数性能提升。
-
高方差:
由于过拟合,样本增加的时候调整参数也不能很好的拟合所有点,所以误差会变大;验证误差一开始就会很大,随着样本增多,会逐渐找到一个较为合适的参数使得误差变小。此时增加训练样本能使函数性能提升。
04. 下一步如何做
- 当发现机器学习算法不能对数据进行很好的预测时,我们下一步可以按照具体情况这么做(在由上画出学习曲线之后做出是偏差还是方差过高问题之后):
- 训练更多样本(解决高方差)
- 尝试更少的特征(解决高方差)
- 增加特征(解决高偏差,高偏差往往是由函数过于简单造成)
- 增加多项式特征(解决高偏差)
- 降低lamda(解决高偏差)
- 增加lamda(解决高方差)
-
神经网络调整
结构简单的神经网络往往计算简单但是偏差较大;
结构复杂的神经网络往往计算复杂,但是更好的拟合训练样本。
要选择复杂度合适的神经网络。
编程作业
01
- 要求利用水面的涨势来预测堤坝被冲毁的程度,要使用规则化求代价函数和梯度,以及实现数据曲线对函数性能进行判断,最后调整训练数据的个数调整合适的lamda。
02. LinearRegCostFunction.m
function [J, grad] = linearRegCostFunction(X, y, theta, lambda)
m = length(y); % number of training examples
% You need to return the following variables correctly
J = 0;
grad = zeros(size(theta));
% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost and gradient of regularized linear
% regression for a particular choice of theta.
%
% You should set J to the cost and grad to the gradient.
%
J = 1/(2m) * sum((Xtheta-y).^2) + lambda/(2m) * sum(theta.^2); % 计算包含惩罚项的误差函数
J = J - lambda/(2m) * theta(1)^2; % 减去theta0的平方,不需要惩罚theta0
grad(1) = 1/m * sum((Xtheta-y)); % theta0的偏导
for i = 2:size(theta,1)
grad(i) = 1/m * sum((Xtheta-y).*X(:,i)) + lambda/m * theta(i); % theta1-thetan的偏导
end
% =========================================================================
grad = grad(:);
end
03. LearningCurve.m
function [error_train, error_val] = ...
learningCurve(X, y, Xval, yval, lambda)
% error_train :训练误差向量
% error_val:验证误差向量
% X :样本数据矩阵,根据所需选择训练数据个数不等
% Xval:验证数据矩阵,固定个数
% ybal: 验证结果向量,固定个数
%
% 训练样本个数
m = size(X, 1);
error_train = zeros(m, 1);
error_val = zeros(m, 1);
% ====================== YOUR CODE HERE ======================
% Instructions: Fill in this function to return training errors in
% error_train and the cross validation errors in error_val.
% i.e., error_train(i) and
% error_val(i) should give you the errors
% obtained after training on i examples.
%
% Note: You should evaluate the training error on the first i training
% examples (i.e., X(1:i, :) and y(1:i)).
%
% For the cross-validation error, you should instead evaluate on
% the entire cross validation set (Xval and yval).
%
% Note: If you are using your cost function (linearRegCostFunction)
% to compute the training and cross validation error, you should
% call the function with the lambda argument set to 0.
% Do note that you will still need to use lambda when running
% the training to obtain the theta parameters.
%
% 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 ----------------------
n = size(Xval,1); % 验证样本个数
for i = 1:m
theta = trainLinearReg(X(1:i,:), y(1:i,:), lambda);
error_train(i) = 1/(2i) * sum((X(1:i,:)theta - y(1:i,:)).^2); % i个训练样本个数
error_val(i) = 1/(2n) * sum((Xvaltheta - yval).^2); % 验证样本个数
end
% -------------------------------------------------------------
% =========================================================================
end
04. validationCurve.m
function [lambda_vec, error_train, error_val] = ...
validationCurve(X, y, Xval, yval)
%选择不同lamda所得到的训练误差和验证误差
%
% Selected values of lambda (you should not change this)
lambda_vec = [0 0.001 0.003 0.01 0.03 0.1 0.3 1 3 10]';
% You need to return these variables correctly.
error_train = zeros(length(lambda_vec), 1);
error_val = zeros(length(lambda_vec), 1);
% ====================== YOUR CODE HERE ======================
% Instructions: Fill in this function to return training errors in
% error_train and the validation errors in error_val. The
% vector lambda_vec contains the different lambda parameters
% to use for each calculation of the errors, i.e,
% error_train(i), and error_val(i) should give
% you the errors obtained after training with
% lambda = lambda_vec(i)
%
% Note: You can loop over lambda_vec with the following:
%
% for i = 1:length(lambda_vec)
% lambda = lambda_vec(i);
% % Compute train / val errors when training linear
% % regression with regularization parameter lambda
% % You should store the result in error_train(i)
% % and error_val(i)
% ....
%
% end
%
%
m=size(X,1); %训练样本个数
n=size(Xval,1) %验证样本个数
for i=1:length(lambda_vec)
lambda=lambda_vec(i)
theta=trainLinearReg(X,y,lambda);
error_train(i)=1/(2m)sum((Xtheta-y).^2);
error_val(i)=1/(2m)sum((Xvaltheta-yval).^2);
end
% =========================================================================
end