DM10-偏差-方差-验证曲线-学习曲线
一直在匆忙学习各种模型,很少静下心来思考过,模型学习的一些方法根源于哪里;对于所提出的模型是否合适,参数是否合适。从而了验证的相关方法,验证模型:验证曲线与学习曲线
确定一个模型后,想验证哪个参数比较好,我们可以采用验证曲线去完成这个问题。
来自http://sklearn.apachecn.org/cn/0.19.0/modules/learning_curve.html的关于“偏差”与“方差”的说明:每种估计器都有其优势和缺陷。它的泛化误差可以用偏差、方差和噪声来分解。估计值的“偏差”是不同训练集的平均误差。估计值的“方差”用来表示它对训练集的 变化有多敏感。噪声是数据的一个属性。
什么是偏差与方差
作者:刑无刀 链接:http://www.zhihu.com/question/20448464/answer/24397161 来源:知乎
著作权归作者所有,转载请联系作者获得授权。
想象你开着一架黑鹰直升机,得到命令攻击地面上一只敌军部队,于是你连打数十梭子,结果有一下几种情况:
1.子弹基本上都打在队伍经过的一棵树上了,连在那棵树旁边等兔子的人都毫发无损,这就是方差小(子弹打得很集中),偏差大(跟目的相距甚远)。
2.子弹打在了树上,石头上,树旁边等兔子的人身上,花花草草也都中弹,但是敌军安然无恙,这就是方差大(子弹到处都是),偏差大(同1)。
3.子弹打死了一部分敌军,但是也打偏了些打到花花草草了,这就是方差大(子弹不集中),偏差小(已经在目标周围了)。
4.子弹一颗没浪费,每一颗都打死一个敌军,跟抗战剧里的八路军一样,这就是方差小(子弹全部都集中在一个位置),偏差小(子弹集中的位置正是它应该射向的位置)。
方差,是形容数据分散程度的,算是“无监督的”,客观的指标,偏差,形容数据跟我们期望的中心差得有多远,算是“有监督的”,有人的知识参与的指标。引用来自链接:http://blog.csdn.net/simple_the_best/article/details/71167786,以下为一个感性认识:
对泛化误差进行推导:
偏差. 偏差度量了学习算法的期望预测与真实结果的偏离程序, 即 刻画了学习算法本身的拟合能力 . 方差.
方差度量了同样大小的训练集的变动所导致的学习性能的变化, 即 刻画了数据扰动所造成的影响 . 噪声.
噪声表达了在当前任务上任何学习算法所能达到的期望泛化误差的下界, 即 刻画了学习问题本身的难度 . 巧妇难为无米之炊, 给一堆很差的食材,
要想做出一顿美味, 肯定是很有难度的.
偏差-方差窘境
想当然—-我们希望偏差与方差越小越好。可是这是有冲突的:
通常来说,方差与偏差是冲突的,这个称之为偏差-方差窘境。我们可以知道当我们的模型训练不足的时候,模型的方差是比较小的,但是偏差是比较大的,方差小的原因是此时的模型拟合能力不够强,因此数据的扰动还不足以是模型产生足够的变化,但是此时预测数据与真实label相差很大,故偏差很大;但是当模型训练过头,即过拟合的时候,此时偏差很小,几乎为0,但是方差很大,因为过拟合,所以数据只需要轻微的扰动,就可能导致预测结果很不确定。
引自:http://blog.csdn.net/batuwuhanpei/article/details/51891110
这个东西可以用来调整超参,查看模型的训练情况,拟合的情况程度,可以指导模型的选择等。。
验证曲线[需要一个评分函数来验证一个模型]
如果训练得分和验证得分都很低,则估计器是不合适的。如果训练得分高,验证得分低,则估计器过拟合, 否则估计会拟合得很好。通常不可能有较低的训练得分和较高的验证得分。有助于观察该模型在相应的超参数取值时,是否有过拟合或欠拟合的情况发生。
一个例子:
http://sklearn.lzjqsdd.com/auto_examples/model_selection/plot_validation_curve.html#example-model-selection-plot-validation-curve-py
# coding=utf-8
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import load_digits
from sklearn.model_selection import validation_curve
from sklearn.svm import SVC
# 显示中文
# matplotlib.rcParams['font.sans-serif'] = ['SimHei']
# 用来正常显示负号
# matplotlib.rcParams['axes.unicode_minus']=False
# 加载数据
digits = load_digits()
X, y = digits.data, digits.target
# 验证曲线
param_range = np.logspace(-6, -1, 5)
train_scores, test_scores = validation_curve(
SVC(), X, y, param_name="gamma", param_range=param_range,
cv=10, scoring="accuracy", n_jobs=1)
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.title("SVM VC")
plt.xlabel("$\gamma$")
plt.ylabel("Score")
plt.ylim(0.0, 1.1)
# 训练数据
plt.semilogx(param_range, train_scores_mean, label="train score", color="r")
plt.fill_between(param_range, train_scores_mean - train_scores_std,
train_scores_mean + train_scores_std, alpha=0.2, color="r")
# 测试数据
plt.semilogx(param_range, test_scores_mean, label="test score",
color="g")
plt.fill_between(param_range, test_scores_mean - test_scores_std,
test_scores_mean + test_scores_std, alpha=0.2, color="g")
plt.legend(loc="best")
plt.show()
gamma 很小时,训练分数和验证分数都很低,为欠拟合。
gamma 逐渐增加,两个分数都较高,此时模型相对不错。
gamma 太高时,训练分数高,验证分数低,学习器会过拟合。
另外一个在选择imbalance的例子:
http://contrib.scikit-learn.org/imbalanced-learn/stable/auto_examples/model_selection/plot_validation_curve.html#sphx-glr-auto-examples-model-selection-plot-validation-curve-py
# coding=utf-8
import matplotlib.pyplot as plt
import numpy as np
from sklearn import model_selection as ms
from sklearn import datasets, metrics, tree
from imblearn import over_sampling as os
from imblearn import pipeline as pl
RANDOM_STATE = 42
# 评价分类
scorer = metrics.make_scorer(metrics.cohen_kappa_score)
# 生成数据集
X, y = datasets.make_classification(n_classes=2, class_sep=2,
weights=[0.1, 0.9], n_informative=10,
n_redundant=1, flip_y=0, n_features=20,
n_clusters_per_class=4, n_samples=5000,
random_state=RANDOM_STATE)
# 非平衡数据处理方法
smote = os.SMOTE(random_state=RANDOM_STATE)
# 分类器
cart = tree.DecisionTreeClassifier(random_state=RANDOM_STATE)
# 流程
pipeline = pl.make_pipeline(smote, cart)
# 参数选择[主要是smote的k_neighbors参数上]
param_range = range(1, 11)
# 模型选择
train_scores, test_scores = ms.validation_curve(
pipeline, X, y, param_name="smote__k_neighbors", param_range=param_range,
cv=3, scoring=scorer, n_jobs=1)
# 各参数后的指标计算
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)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
# 显示测试分数结果
plt.plot(param_range, test_scores_mean, label='SMOTE')
# 显示测试分类的波动情况
ax.fill_between(param_range, test_scores_mean + test_scores_std,
test_scores_mean - test_scores_std, alpha=0.2)
# 找最大平均值下标
idx_max = np.argmax(test_scores_mean)
# 标志最值
plt.scatter(param_range[idx_max], test_scores_mean[idx_max],
label=r'Cohen Kappa: ${0:.2f}\pm{1:.2f}$'.format(
test_scores_mean[idx_max], test_scores_std[idx_max]))
# 标题
plt.title("Validation Curve with SMOTE-CART")
plt.xlabel("k_neighbors")
plt.ylabel("Cohen's kappa")
# 其它的绘图设置
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.get_xaxis().tick_bottom()
ax.get_yaxis().tick_left()
ax.spines['left'].set_position(('outward', 10))
ax.spines['bottom'].set_position(('outward', 10))
plt.xlim([1, 10])
plt.ylim([0.4, 0.8])
plt.legend(loc="best")
plt.show()
通过这个方法可以找到最近邻的K值。
学习曲线
验证曲线是估计器或流程中参数取不同值的评分。
学习曲线显示了对于不同数量的训练样本的估计器的验证和训练评分。它可以帮助我们发现从增加更多的训 练数据中能获益多少,以及估计是否受到更多来自方差误差或偏差误差的影响。如果在增加训练集大小时,验证分数和训练 分数都收敛到一个很低的值,那么我们将不会从更多的训练数据中获益。
http://sklearn.apachecn.org/cn/0.19.0/auto_examples/model_selection/plot_learning_curve.html
# coding=utf-8
import numpy as np
import matplotlib.pyplot as plt
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
from sklearn.datasets import load_digits
from sklearn.model_selection import learning_curve
from sklearn.model_selection import ShuffleSplit
def plot_learning_curve(estimator, title, X, y, ylim=None, cv=None, train_sizes=np.linspace(.1, 1.0, 5)):
plt.figure()
plt.title(title)
if ylim is not None:
plt.ylim(*ylim)
plt.xlabel("Training examples")
plt.ylabel("Score")
train_sizes, train_scores, test_scores = learning_curve(
estimator, X, y, cv=cv, 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.grid()
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.legend(loc="best")
return plt
digits = load_digits()
X, y = digits.data, digits.target
title = "Learning Curves (Naive Bayes)"
cv = ShuffleSplit(n_splits=100, test_size=0.2, random_state=0)
estimator = GaussianNB()
plot_learning_curve(estimator, title, X, y, ylim=(0.7, 1.01), cv=cv)
title = "Learning Curves (SVM, RBF kernel, $\gamma=0.001$)"
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)
plt.show()
运行结果:
附:模型分数估计
http://sklearn.apachecn.org/cn/0.19.0/modules/model_evaluation.html
推荐阅读