机器学习 学习曲线 Python实现学习曲线及案例解析

机器学习 学习曲线 Python实现学习曲线及案例解析

学习曲线

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

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

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

实例:画出学习曲线

生成一个在 y = x y=\sqrt{x} y=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)
需要构造一个多项式模型

在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 表示多项式的阶数
,比如polynomail_model(3)将生成一个三阶多项式的模型。

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

from sklearn.model_selection import learning_curve
from sklearn.model_selection import ShuffleSplit
import matplotlib.pyplot as plt

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, 's--', 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()函数画出模型准确性的平均值。上诉函数画出了训练样本的的准确性,也画出了交叉验证样本的准确性。

使用ploynomial_model()函数构造出3个模型,分别是一阶多项式、三阶多项式、十阶多项式,分别画出这3个模型的学习曲线。
# 为了让学习曲线更平滑,计算10次交叉验证数据集的分数
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), dpi=200)
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()

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

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

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

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

当需要改进学习算法时,可以画出学习曲线,以便判断算法时处在高偏差还是高分差问题。
学习曲线是诊断模型算法准确性的一个非常重要的工具。

过拟合和欠拟合的特征

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

  • 过拟合:模型对训练数据集的准确性比较高,其成本 J t r a i n ( θ ) J_{train}(\theta) Jtrain(θ)比较低,对交叉验证数据集的准确性比较低,其成本 J c v ( θ ) J_{cv}(\theta) Jcv(θ) 比较高。
  • 欠拟合:模型对训练数据集的准确性比较低,其成本 J t r a i n ( θ ) J_{train}(\theta) Jtrain(θ)比较高,对交叉验证数据集的准确性夜比较低,其成本 J c v ( θ ) J_{cv}(\theta) Jcv(θ) 也比较高。

一个好的机器学习算法应该是对训练数据集准确性高、成本低,即较准确地拟合数据,同时对交叉验证数据集准确性高、成本低、误差小,即对未知数据有良好的预测性。

  • 3
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值