winycg的博客

学习笔记

利用学习和验证曲线评估模型

偏差和方差

参考链接:https://www.zhihu.com/question/20448464
模型误差 = 偏差 + 方差 + 随机误差

E[(yf(x)^)]=Bias[f(x)^]2+Variance[f(x)^]+σ

偏差:预测值的期望与真实值之间的差距。
Bias[f(x)^]2=E[f(x)^f(x)]

方差:刻画了数据扰动所造成的影响。 跟真实值没有直接关系。
Variance[f(x)^]=E[f(x)2^]E[f(x)^]2

这里写图片描述
如图所示为多项式的次数与误差的关系。
高偏差:相当于图中的左侧。
Jtrain(θ)Jtrain(θ)JCV(θ)

高方差:相当于图中的右侧。
Jtrain(θ)Jtrain(θ)JCV(θ)
训练得到的模型太拟合训练数据了。不同的训练数据训练的模型效果波动很大。

学习曲线

参考:http://scikit-learn.org/stable/modules/learning_curve.html#learning-curve
学习曲线即为准确率随训练样本数量的变化曲线。更多的训练样本有助于降低过拟合程度,在实践中,收集更多的数据会带来高昂的成本。通过将模型的训练及验证准确率看作是训练数据集大小的函数,并绘制图像,可以很容易看出收集更多的数据是否有助于解决问题。
使用威斯康星乳腺癌数据集绘制学习曲线:

import matplotlib.pyplot as plt
from sklearn.model_selection import learning_curve
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split

'''
读取乳腺癌数据集
数据集前两列存储样本ID和诊断结果(M代表恶性,B代表良性)
3~32列包含了30个特征
'''
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases'
                 + '/breast-cancer-wisconsin/wdbc.data',
                 header=None)
X = df.loc[:, 2:].values
y = df.loc[:, 1].values
le =LabelEncoder()
# 将类标从字符串(M或B)变为整数的(0,1)
y = le.fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

'''
在流水线中集成标准化操作以及分类器
PipeLine对象采用元组的序列作为输入,每个元组第一个值为字符串,
可以通过字符串访问流水线的元素,第二个值为sklearn中的转换器或评估器
'''
pipe_lr = Pipeline([
    ('scl', StandardScaler()),
    ('clf', LogisticRegression(penalty='l2', random_state=0))
])
'''
learning_curve默认使用分层K折交叉验证
'''
train_sizes, train_scores, valid_scores = \
    learning_curve(estimator=pipe_lr,
                   X=X_train,
                   y=y_train,
                   train_sizes=np.linspace(0.1, 1.0, 10),
                   cv=10)

train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
valid_mean = np.mean(valid_scores, axis=1)
valid_std = np.std(valid_scores, axis=1)

plt.plot(train_sizes, train_mean, c='blue', marker='o', markersize=5,
         label='training accuracy')
plt.fill_between(train_sizes,
                 train_mean - train_std,
                 train_mean + train_std,
                 alpha=0.15, color='blue')

plt.plot(train_sizes, valid_mean, c='green', marker='o', markersize=5,
         linestyle='--', label='validation accuracy')
plt.fill_between(train_sizes,
                 valid_mean - valid_std,
                 valid_mean + valid_std,
                 alpha=0.15, color='green')

plt.grid()
plt.xlabel('Number of training samples')
plt.ylabel('Accuracy')
plt.legend(loc='best')
plt.ylim([0.8, 1.01])
plt.show()

从图中可以看出,数据集样本的数量在300~350之间时,泛化能力最强。模型在数据集较小的情况下,随着样本数量的增多训练准确率下降,说明模型陷入了过拟合。在250样本数量之后,模型趋于饱和和稳定,并具有轻微的过拟合现象。
这里写图片描述

验证曲线

验证曲线是准确率与模型超参数之间的关系,可以从关系中看出超参数在什么时候泛化能力最强,以及什么时候会陷入欠拟合或者过拟合。
使用逻辑斯谛回归中的正则化参数C绘制验证曲线:

import matplotlib.pyplot as plt
from sklearn.model_selection import validation_curve
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split

'''
读取乳腺癌数据集
数据集前两列存储样本ID和诊断结果(M代表恶性,B代表良性)
3~32列包含了30个特征
'''
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases'
                 + '/breast-cancer-wisconsin/wdbc.data',
                 header=None)
X = df.loc[:, 2:].values
y = df.loc[:, 1].values
le =LabelEncoder()
# 将类标从字符串(M或B)变为整数的(0,1)
y = le.fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

'''
在流水线中集成标准化操作以及分类器
PipeLine对象采用元组的序列作为输入,每个元组第一个值为字符串,
可以通过字符串访问流水线的元素,第二个值为sklearn中的转换器或评估器
'''
pipe_lr = Pipeline([
    ('scl', StandardScaler()),
    ('clf', LogisticRegression(penalty='l2', random_state=0))
])


param_range = [0.001, 0.01, 0.1, 1.0, 10.0, 100.0]
train_scores, valid_scores = \
    validation_curve(estimator=pipe_lr,
                     X=X_train,
                     y=y_train,
                     # 可以通过estimator.get_params().keys()获取param索引名
                     param_name='clf__C',
                     param_range=param_range,
                     cv=10)

train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
valid_mean = np.mean(valid_scores, axis=1)
valid_std = np.std(valid_scores, axis=1)

plt.plot(param_range, train_mean, c='blue', marker='o', markersize=5,
         label='training accuracy')
plt.fill_between(param_range,
                 train_mean - train_std,
                 train_mean + train_std,
                 alpha=0.15, color='blue')

plt.plot(param_range, valid_mean, c='green', marker='o', markersize=5,
         label='validation accuracy')
plt.fill_between(param_range,
                 valid_mean - valid_std,
                 valid_mean + valid_std,
                 alpha=0.15, color='green')

plt.grid()
plt.xscale('log')
plt.xlabel('Parameter C')
plt.ylabel('Accuracy')
plt.legend(loc='best')
plt.ylim([0.8, 1.0])
plt.show()

从图中可以看出,最优点在C=0.1附件。C值较小时,随着C值越大,训练准确率和验证准确率逐渐上升,说明模型处于欠拟合;C值较大时,随着C值越大,训练准确率逐渐上升,验证准确率下降,说明模型处于过拟合。
这里写图片描述

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/winycg/article/details/80342038
个人分类: python机器学习
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

利用学习和验证曲线评估模型

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭