跟我一起学scikit-learn11:学习曲线

我们可以把{J}_{train}(\theta){J}_{cv}(\theta)作为纵坐标,画出与训练数据集m的大小关系,这就是学习曲线。通过学习曲线,可以直观地观察到模型的准确性与训练数据集大小的关系。

如果数据集的大小为m,则通过下面的流程即可画出学习曲线:

  • 把数据集分成训练数据集和交叉验证数据集。
  • 取训练数据集的20%作为训练样本,训练出模型参数。
  • 使用交叉验证数据集来计算训练出来的模型的准确性。
  • 以训练数据集的准确性,交叉验证的准确性作为纵坐标,训练数据集个数作为横坐标,在坐标轴上画出上述步骤计算出来的模型准确性。
  • 训练数据集增加10%,跳到步骤3继续执行,直到训练数据集大小为100%为止。

学习曲线要表达的内容是,当训练数据集增加时,模型对训练数据集拟合的准确性以及对交叉验证数据集预测的准确性的变化规律。

1.实例:画出学习曲线

通过一个例子来看看在scikit-learn里如何画出模型的学习曲线,从而判断模型的准确性及优化方向。

我们还使用之前举过的例子,生成一个在y=\sqrt{x}附近波动的点来作为训练样本,不过这次要多生成一些点,因为要考虑当训练样本数据增加的时候,模型的准确性是怎么变化的。

import numpy as np
n_dots = 200
X = np.linspace(0,1,n_dots)
y = np.sqrt(X)+0.2*np.random.rand(n_dots)-0.1
# 因为sklearn的接口里,需要用到 n_sample x n_feature 的矩阵
# 所以需要转化为 200 x 1 的矩阵
X = X.reshape(-1,1)
y = y.reshape(-1,1)

(1)需要构造一个多项式模型。在scikit-learn里,需要使用Pipeline来构造多项式模型,Pipeline的意思是流水线,即这个流水线里可以包含多个数据处理模型,前一个模型处理完,转到下一个模型处理。

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
def polynomial_model(degree=1):
    polynomial_features = PolynomialFeatures(degree=degree,include_bias=False)
    linear_regression = LinearRegression()
    # 这是一个流水线,先增加多项式阶数,然后在用线性回归算法来拟合数据
    pipeline = Pipeline([("polynomial_features",polynomial_features),
                         ("linear_regression",linear_regression)])
    return pipeline

polynomial_model()函数生成一个多项式模型,其中参数degree表示多项式的阶数,比如polynomial_model(3)将生成一个3阶多项式的模型。

在scikit-learn里面,我们不用自己去实现学习曲线算法,直接使用sklearn.model_selection.learning_curve()函数来画出学习曲线,它会自动把训练样本的数量按照预定的规则逐渐增加,然后画出不同训练样本数量的变化规则,比如train_sizes=np.linspace(0.1,1.0,5)表示把训练样本数量从0.1~1分成五等分,生成[0.1,0.325,0.55,0.775,1]的序列,从序列中取出训练样本数量百分比,逐个计算在当前训练样本数量情况下训练出来的模型准确性。

from sklearn.model_selection import learning_curve
def plot_learning_curve(estimator, title, X, y, ylim=None, cv=None,
                        n_jobs=1, train_sizes=np.linspace(.1, 1.0, 5)):
    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, n_jobs=n_jobs, 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

这个函数实现的功能就是画出模型的学习曲线。其中有个细节需要注意,当计算模型的准确性时,是随机从数据集中分配出训练样本和交叉验证样本,这样会导致数据分布不均匀。即同样训练样本数量的模型,由于随机分配,导致每次计算出来的准确性都不一样。为了解决这个问题,我们在计算模型准确性时,多次计算,并求准确性的平均值和方差。上述代码中plt.fill_between()函数会把模型准确性的平均值的上下方差的空间里用颜色填充。然后用plt.plot()函数画出模型准确性的平均值。上述函数画出了训练样本的准确性,也画出来交叉验证样本的准确性。
(2)使用polynomial_model()函数构造出3个模型,分别是一阶多项式、三姐多项式和十阶多项式,分别画出这3个模型的学习曲线。

# 为了让学习曲线更平滑,交叉验证数据集的得分计算 10 次,每次都重新选中 20% 的数据计算一遍
cv = ShuffleSplit(n_splits=10, test_size=0.2, random_state=0)
titles = ['Learning Curves (Under Fitting)',
          'Learning Curves',
          'Learning Curves (Over Fitting)']
degrees = [1, 3, 10]
plt.figure(figsize=(18, 4))
for i in range(len(degrees)):
    plt.subplot(1, 3, i + 1)
    plot_learning_curve(polynomial_model(degrees[i]), titles[i], X, y, ylim=(0.75, 1.01), cv=cv)
plt.show()

最终得到的学习曲线如下图所示:


figure3_3.png

左图:一阶多项式,欠拟合;中图:三阶多项式,较好地拟合了数据集;右图:十阶多项式,过拟合。虚线:针对训练数据集计算出来的分数,即针对训练数据集拟合的准确性,实线:针对交叉验证数据集计算出来的分数,即针对交叉验证数据集预测的准确性。

从左图我们可以观察到,当模型欠拟合(High Bias,Under Fitting)时,随着训练数据集的增加,交叉验证数据集的准确性(实线)逐渐增大,逐渐和训练数据集的准确性(虚线)靠近,但其总体水平比较低,收敛在0.88左右。其训练数据集的准确性也比较低,收敛在0.90左右。这就是欠拟合的表现。从这个关系可以看出来,当发生高偏差时,增加训练样本数量不会对算法准确性有较大的改善。

从右图我们可以观察到,当模型过拟合(High Variance,Over Fitting)时,随着训练数据集的增加,交叉验证数据集的准确性(实线)也在增加,逐渐和训练数据集的准确性(虚线)靠近,但两者之间的间隙比较大。训练数据集的准确性很高,收敛在0.95左右,是三者中最高的,但交叉验证数据集的准确性值却较低,最终收敛在0.91左右。

中图,我们选择的三阶多项式较好地拟合了数据,最终训练数据集的准确性(虚线)和交叉验证数据集的准确性(实线)靠得很近,最终交叉验证数据集收敛在0.93附近,训练数据集的准确性收敛在0.94附近。3个模型对比,这个模型的准确性最好。

当需要改进学习算法时,可以画出学习曲线,以便判断算法是高偏差还是高方差问题。我们可以修改一些参数,观察学习曲线的变化规则。学习曲线是诊断模型算法准确性的一个非常重要的工具。

2.过拟合和欠拟合的特征

到此,我们可以总结过拟合和欠拟合的特点如下:

  • 过拟合:模型对训练数据集的准确性比较高,其成本{J}_{train}(\theta)比较低;对交叉验证数据集的准确性比较低,其成本{J}_{cv}(\theta)比较高。
  • 欠拟合:模型对训练数据集的准确性比较低,其成本{J}_{train}(\theta)比较高;对交叉验证数据集的准确性也比较低,其成本{J}_{cv}(\theta)比较高。
    一个好的机器学习算法应该是对训练数据集准确性高、成本低,即较准确地拟合数据,同时对交叉验证数据集准确性高、成本低、误差小,即对未知数据有良好的预测性。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容