本文来自之前在Udacity上自学机器学习的系列笔记。这是第3篇,介绍了模型的误差类型、误差的由来、找到模型适合的参数、以及避免欠拟合和过拟合的方法。
1.诊断误差
1.1.误差类型
我们的预测或者分类的结果与实际结果相比较,会存在一定的误差,误差越小,表示结果越好。一般有两种误差来源,欠拟合和过拟合。将问题看得过于简单导致了欠拟合(Underfitting),将问题看得过于复杂导致了过拟合(Overfitting)。
欠拟合的一个特点是在训练集表现得不够好,我们称之为偏差引起的误差(Error due to bias)。过拟合的一个特点是在训练集表现得过于好,已倾向于记住而不是学习数据,导致在测试集表现不好,又称为泛化能力差,我们称之为方差引起的误差(Error due to variance)。
1.2.复杂度曲线
复杂度曲线可以帮助我们找出模型合适的参数。我们可以将误差作为纵坐标,模型的具体特定参数为横坐标,查看不同参数下模型的表现。另外,我们需要遵循“测试集不能用于训练的原则”,所以一般会从训练集中划分一部分数据集作为“验证集”。
如下图所示,我们可以看到在参数为2的时候,模型刚刚好。
复杂度曲线
1.3.K折交叉验证法(K-fold cross validation)
K折交叉验证法将训练集均分为K份,每次验证时取其中1份作为验证集,其余K-1份为训练集,作为一次验证的结果。依次对K份子数据集进行验证,可以得到K个结果,对这K个结果取平均值作为最终的结果。
from sklearn.model_selection import KFold
kf = KFold(12, 3, shuffle = True)
for train_indices, test_indices in kf:
print train_indices, test_indices
1.4.学习曲线
学习曲线可以帮助我们判断过拟合、欠拟合和好的模型的方法。如下图所示,横坐标是训练集的数量,纵坐标是误差。随着训练集的数量增加,训练集的误差和验证集的误差在不同参数模型下有不同表现。第一个是趋于同一个数,且误差较大,这个是高偏差,表示欠拟合;第二个也是趋于同一个数,但误差较小,表示模型刚刚好;第三个训练集误差很小,但验证集误差较大,这个是高方差,表示过拟合。
学习度曲线from sklearn.model_selection import learning_curve
# It is good to randomize the data before drawing Learning Curves
def randomize(X, Y):
permutation = np.random.permutation(Y.shape[0])
X2 = X[permutation,:]
Y2 = Y[permutation]
return X2, Y2
X2, y2 = randomize(X, y)
def draw_learning_curves(X, y, estimator, num_trainings):
train_sizes, train_scores, test_scores = learning_curve(
estimator, X2, y2, cv=None, n_jobs=1, train_sizes=np.linspace(.1, 1.0, num_trainings))
train_scores_mean = np.mean(train_scores, axis=1)
train_scores_std = np.std(train_scores, axis=1)
test_scores_mean = np.mean(test_scores, axis=1)
test_scores_std = np.std(test_scores, axis=1)
plt.grid()
plt.title("Learning Curves")
plt.xlabel("Training examples")
plt.ylabel("Score")
plt.plot(train_scores_mean, 'o-', color="g",
label="Training score")
plt.plot(test_scores_mean, 'o-', color="y",
label="Cross-validation score")
plt.legend(loc="best")
plt.show()
1.5.网格搜索法(Grid Search)
网格搜索法是一种寻找最佳模型参数组合的方法。它通过遍历多种参数组合,并通过交叉验证来确定最佳性能的参数组合。一般来说,它会遍历用户提前给定的参数组合。
sklearn库的GridSearchCV模块,首先给定一个参数字典以及它们可以取的值,不同参数值组成的一个网格,对于网格中的每一种组合都会被用来训练,然后用交叉验证来完成确定最佳的参数组合。网格搜索时不使用交叉验证时,就不能确定最优的参数组合结果。比如说,如果数据量不大,随机性也不够好,特征数据分布有顺序性,那么分出来的验证集有可能只包含数据集中一种特点的数据,这时候在验证集上得到的分数可能是不准确的。有可能是模型拟合得比较好的数据,得到的成绩优于真实表现;有可能是模型拟合得比较差的数据,得到的成绩差于真实表现。通过使用交叉验证,那么就会取多次不同的验证集分数的平均值,多次取平均值能够减少对模型表现评分的误差,这样就可以更准确地找到最优参数。
GridSearchCV中的'cv_results_'属性cv_result返回一个字典,包含模型参数、模型的性能、模型运行的时间。
例如scikit-learn.org上的例子:
from sklearn import svm, datasets
from sklearn.model_selection import GridSearchCV
iris = datasets.load_iris()
parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]}
svc = svm.SVC()
clf = GridSearchCV(svc, parameters)
clf.fit(iris.data, iris.target)
sorted(clf.cv_results_.keys())
网友评论