引入
1. 什么是过拟合?
相当于泛化性差的概念,见知乎https://www.zhihu.com/question/32246256
2.可能是什么导致了过拟合?
(1)建模样本选取有误,如样本数量太少,选样方法错误,样本标签错误等,导致选取的样本数据不足以代表预定的分类规则;
(2)样本噪音干扰过大,使得机器将部分噪音认为是特征从而扰乱了预设的分类规则;
(3)假设的模型无法合理存在,或者说是假设成立的条件实际并不成立;
(4)参数太多,模型复杂度过高;
(5)对于决策树模型,如果我们对于其生长没有合理的限制,其自由生长有可能使节点只包含单纯的事件数据(event)或非事件数据(no event),使其虽然可以完美匹配(拟合)训练数据,但是无法适应其他数据集。
(6)对于神经网络模型:a)对样本数据可能存在分类决策面不唯一,随着学习的进行,,BP算法使权值可能收敛过于复杂的决策面;b)权值学习迭代次数足够多(Overtraining),拟合了训练数据中的噪声和训练样例中没有代表性的特征。
学习曲线:
学习曲线就是通过画出不同训练集大小时训练集和交叉验证的准确率,可以看到模型在新数据上的表现,
进而来判断模型是否方差偏高或偏差过高,以及增大训练集是否可以减小过拟合
例如同样的问题,左图为我们用 naive Bayes 分类器时,效果不太好,分数大约收敛在 0.85,此时增加数据对效果没有帮助。
右图为 SVM(RBF kernel),训练集的准确率很高,验证集的也随着数据量增加而增加,不过因为训练集的还是高于验证集的,有点过拟合,所以还是需要增加数据量,这时增加数据会对效果有帮助。
绘制学习曲线:
在画学习曲线时,横轴为训练样本的数量,纵轴为准确率
首先定义画出学习曲线的方法,
核心就是调用了 sklearn.model_selection 的 learning_curve,
学习曲线返回的是 train_sizes, train_scores, test_scores,
画训练集的曲线时,横轴为 train_sizes, 纵轴为 train_scores_mean,
画测试集的曲线时,横轴为 train_sizes, 纵轴为 test_scores_mean:
代码解释及代码:
在调用 plot_learning_curve 时,首先定义交叉验证 cv 和学习模型 estimator。
1:这里交叉验证用的是 ShuffleSplit, 它首先将样例打散,并随机取 20% 的数据作为测试集,这样取出 100 次,最后返回的是 train_index, test_index,就知道哪些数据是 train,哪些数据是 test。cv
2. 代码参数:cv = ShuffleSplit(n_splits=10, test_size=0.2, random_state=0) estimator = SVC(gamma=0.001) plot_learning_curve(estimator, title, X, y, (0.7, 1.01), cv=cv, n_jobs=4)
代码注释掉的是控制台打印的结果,def里面是学习曲线方法:
from sklearn.model_selection import train_test_split from sklearn.datasets import load_svmlight_file from sklearn.neural_network import MLPRegressor from sklearn.model_selection import learning_curve import matplotlib.pyplot as plt import numpy as np from sklearn.model_selection import ShuffleSplit t_X,t_y=load_svmlight_file("eunite.txt") # x_train, x_test, y_train, y_test = train_test_split(t_X, t_y, test_size=0.3, random_state=0) # # # clf = MLPRegressor(solver='lbfgs', alpha=1e-5, # hidden_layer_sizes=(5, 2), random_state=1) # clf = clf.fit(x_train, y_train) # clf.predict( x_test) # y_pred=clf.predict(x_test) # print("经过模型重新训练得到的输出值:",clf.predict(x_test))#重新预测的值 # # print("数据集本来存在的输出值:",y_test)#本来 # # print("准确率:",clf.score(x_test, y_test)) # 绘制学习曲线,以确定模型的状况 def plot_learning_curve(estimator, title, X, y,ylim=None,cv=None, train_sizes=np.linspace(.1, 1.0, 5)): ''' 画出data在某模型上的learning curve. 参数解释 ---------- estimator : 你用的分类器。 title : 表格的标题。 X : 输入的feature,numpy类型 y : 输入的target vector ylim : tuple格式的(ymin, ymax), 设定图像中纵坐标的最低点和最高点 cv : 做cross-validation的时候,数据分成的份数,其中一份作为cv集,其余n-1份作为training(默认为3份) ''' plt.figure() train_sizes, train_scores, test_scores = learning_curve( estimator, X, y, cv=5, n_jobs=1, train_sizes=train_sizes) 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.fill_between(train_sizes, train_scores_mean - train_scores_std, train_scores_mean + train_scores_std, alpha=0.1, color="r") plt.fill_between(train_sizes, test_scores_mean - test_scores_std, test_scores_mean + test_scores_std, alpha=0.1, color="g") plt.plot(train_sizes, train_scores_mean, 'o-', color="r", label="Training score") plt.plot(train_sizes, test_scores_mean, 'o-', color="g", label="Cross-validation score") plt.xlabel("Training examples") plt.ylabel("Score") plt.legend(loc="best") plt.grid("on") if ylim: plt.ylim(ylim) plt.title(title) plt.show() # 少样本的情况情况下绘出学习曲线 plot_learning_curve(MLPRegressor(solver='lbfgs', alpha=1e-5,hidden_layer_sizes=(5, 2), random_state=1), "Neural Network", t_X, t_y, ylim=(0.1, 1.01), train_sizes=[50, 110, 250],cv = ShuffleSplit(n_splits=10, test_size=0.2, random_state=0))