训练集和测试集
train set
用来训练模型,估计参数
test set
用来测试和评估训练出来的模型好坏,不能用于训练模型
我们将所有数据分成训练集和测试集两部分,我们用训练集进行模型训练,得到的模型再用测试集来衡量模型的预测表现能力
train_test_split(x,y, test_size , random_state)
将数据随机分成训练集和测试集
-
x,y 需要分割的 feature 和 target 数据
-
test_size
一个(0,1) 的数,代表多大比例的数据会被分成测试集
-
random_state
根据不同的随机种子,分割的结果也不一样
用训练集进行评估
holdout
将训练集中的一部分作为 验证集,训练集其余部分训练完模型后,用验证集验证模型的好坏
Cross Validation 交叉验证
背景
最先我们用全部数据进行训练和测试的accuracy_score
,来衡量模型的表现,
但是这种方法
-
不能维持训练集的独立性,就不能评估模型的性能。
-
测试
accuracy_score
的一个缺点是其样本准确度是一个高方差估计(high variance estimate),所以该样本准确度会依赖不同的测试集,其表现效果不尽相同。 -
模型过拟合
模型为训练集的数据妥协的太厉害,忽略了未使用的数据的特点。导致虽然模型在训练集里表现的很好,在对新的数据估计时表现不好。
有的人采取题海战术,把每道题都背下来。但是题目稍微一遍,就不会做了。因为他记住了每道题复杂解法但是没有抽象出通用的规则。有的人采取题海战术,把每道题都背下来。但是题目稍微一遍,就不会做了。因为他记住了每道题复杂解法但是没有抽象出通用的规则。
from sklearn.datasets import load_iris
from sklearn.cross_validation import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics
In [2]:
# read in the iris data
iris = load_iris()
X = iris.data
y = iris.target
In [3]:
for i in xrange(1,5):
print "random_state is ", i,", and accuracy score is:"
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=i)
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
print metrics.accuracy_score(y_test, y_pred)
random_state is 1 , and accuracy score is:
1.0
random_state is 2 , and accuracy score is:
1.0
random_state is 3 , and accuracy score is:
0.947368421053
random_state is 4 , and accuracy score is:
0.973684210526</pre>
# simulate splitting a dataset of 25 observations into 5 folds
from sklearn.cross_validation import KFold
kf = KFold(25, n_folds=5, shuffle=False)
# print the contents of each training and testing set
print( '{} {:^61} {}'.format('Iteration', 'Training set observations', 'Testing set observations') )
for iteration, data in enumerate(kf, start=1):
print('{:^9} {} {:^25}'.format(iteration, str(data[0]), str(data[1])))</pre>
Error反映的是整个模型的准确度(好坏),
Bias反映的是模型在样本上的输出与真实值之间的误差,即模型本身的精准度,
Variance反映的是模型每一次输出结果与模型输出期望之间的误差,即模型的稳定性。
Bias 和 Variance 理解
打个比方:
一次打靶实验,目标是为了打到10环,但是实际上只打到了7环,那么这里面的Error就是3。具体分析打到7环的原因,可能有两方面:一是瞄准出了问题,比如实际上射击瞄准的是9环而不是10环;二是枪本身的稳定性有问题,虽然瞄准的是9环,但是只打到了7环。那么在上面一次射击实验中,Bias就是1,反应的是模型期望与真实目标的差距,而在这次试验中,由于Variance所带来的误差就是2,即虽然瞄准的是9环,但由于本身模型缺乏稳定性,造成了实际结果与模型期望之间的差距。
[图片上传失败...(image-3427b-1563778769660)]
如何得到最佳的模型
最好的模型应该是什么样的?
目标
Error( test ) 最小
但是我们建模时不能对 测试集 进行任何操作。
步骤
1.Error( train ) 尽可能小
2.Error( train ) 尽可能等于 Error( test )
这样Error( test ) 最小
进一步说:
Error( train ) 尽可能小
-
模型复杂化,使用更多的参数,这样模型和数据 拟合程度高,减少 bias
-
但是拟合程度太高,会导致一旦数据有细微差异,模拟结果会剧烈变化,缺少泛化能力
比如 low bias high variance 的情况
Error( train ) 尽可能等于 Error( test )
-
模型简单化,使用较少的参数,这样模型对数据就不会敏感,减少 Variance
-
但是如果模型过于简单就会造成什么数据模拟出来的结果都差不多,欠拟合。
比如 low variance high bias 的情况
矛盾
模型想减少 bias 就需要用更多的参数,想减少 Variance 就需要更少的参数
解决办法
-
选定算法
-
调整算法的超参数;
-
以某种指标选择最合适的超参数组合。
考虑到,模型误差是偏差与方差的加和,有图像
[图片上传失败...(image-c0a74a-1563778769660)
图中的最优位置,实际上是 total error 曲线的拐点。
我们知道,连续函数的拐点意味着此处一阶导数的值为 0。考虑到 total error 是偏差与方差的加和,
在拐点处:
若模型复杂度大于平衡点,则模型的方差会偏高,模型倾向于过拟合;
若模型复杂度小于平衡点,则模型的偏差会偏高,模型倾向于过拟合
判断是过拟合还是欠拟合(Variance 大还是Bias大 )
当观察到 很大时,可能处在途中蓝色圆圈中的两个位置,虽然观察到的现象很相似都很大),但这两个位置的状态是非常不同的,处理方法也完全不同。
-
当cross validation error () 跟training error()差不多,且Jtrain较大时,即图中标出的bias,此时 high bias low variance,当前模型更可能存在欠拟合。
-
当Jcv >> 较且较小时,即图中标出的variance时,此时 low bias high variance,当前模型更可能存在过拟合。
Noise
这里指的是为了避免模型过拟合,人为添加的噪声
过拟合
模型为训练集的数据妥协的太厉害,忽略了未使用的数据的特点。导致虽然模型在训练集里表现的很好,在对新的数据估计时表现不好。泛化能力差
解决办法
获得更多数据
在数据在输入中加入高斯噪声(正态分布)
sigma2 = 0.3
x_train = np.random.uniform(-1, 1, m)
y_train = calc_polynomial(x_train) + np.random.normal(0, np.sqrt(sigma2), m)
x_validation = np.random.uniform(-1, 1, m)
y_validation = calc_polynomial(x_validation) + np.random.normal(0, np.sqrt(sigma2), m)</pre>
a = np.arange(6).reshape(2,3)
print(a)
>>> array([[0, 1, 2],
[3, 4, 5]])
print(np.argmax(a))
>>>5
print(np.argmax(a, axis=0))
>>>array([1, 1, 1])
print(np.argmax(a, axis=1))
>>>array([2, 2])</pre>
>>> X = np.arange(6).reshape(3, 2)
>>> X
array([[0, 1],
[2, 3],
[4, 5]])
>>> poly = PolynomialFeatures(2)
>>> poly.fit_transform(X)
array([[ 1., 0., 1., 0., 0., 1.],
[ 1., 2., 3., 4., 6., 9.],
[ 1., 4., 5., 16., 20., 25.]])
>>> poly = PolynomialFeatures(interaction_only=True)
>>> poly.fit_transform(X)
array([[ 1., 0., 1., 0.],
[ 1., 2., 3., 6.],
[ 1., 4., 5., 20.]])</pre>
生成结果里每一行是一个list。输入矩阵比如[0,1] 类似与上面的[a,b]。多项式输出矩阵是[1,a,b,a2,ab,b2]。所以就是下面对应的[1,0,1,0,0,1]。现在将interaction_only=True。这时就是只找交互作用的多项式输出矩阵。例如[a,b]的多项式交互式输出[1,a,b,ab]。不存在自己与自己交互的情况如;a2或者a*b2之类的。
传入的训练集和 测试集
fit_transform(x,y)
方法:
-
degree 多项式级数
-
interaction_only : boolean, default = False,如果值为true(默认是false),则会产生相互影响的特征集
专门生成多项式特征
sklearn.preprocessing.PolynomialFeatures(degree=2, interaction_only=False, include_bias=True)
- param_grid 参数网格,dict 类型
列出参数网格对应的所有参数排列组合
sklearn.model_selection.ParameterGrid(param_grid)
返回选择结果表格。
cv_results_
通过Grid Search选择的分数最高的参数
best_params_
通过Grid Search选择的估计器,即分数最高(或如果指定的最小损失)的估计器。
best_estimator_
属性:
根据 数据集 X,Y 运行Grid Search。
fit(X, y)
方法:
-
estimator 哪种拟合方式
-
param_grid 参数矩阵, 字典类型
-
scoring 何种评分方式,默认是 estimator 的 score 函数返回的值
-
return_train_score 是否计算训练分数
当前默认值为“警告”,除了在查找训练分数时发出警告外,其表现为True。 该默认值将在0.21中更改为False。 计算训练分数用于深入了解不同参数设置如何影响过度拟合/欠拟合权衡。 然而,计算训练集上的分数可能在计算上是昂贵的,并且不是严格要求选择产生最佳泛化性能的参数。
sklearn.model_selection.GridSearchCV(estimator, param_grid, scoring=None,return_train_score=’warn’,cv = 5)
GridSearchCV方法,自动对输入的参数进行排列组合,并一一测试,从中选出最优的一组参数。
Grid Search
-
a 原矩阵
-
newshape : tuple 类型,确定重组矩阵形状
-
如果是单独一个整数,则结果将是该长度的1-D数组。
-
如果是-1。 从阵列的长度和剩余尺寸推断出数组的另外一个shape属性值。
-
按照某种形状重组矩阵,原有数据不变
numpy.reshape(a, newshape)
返回沿轴的最大值的索引。
numpy.argmax(a, axis)
-
estimator 何种模型
-
x,y 数据集
-
CV k-fold 里的 K 值, 或者是 cross-validation generator
-
scoring : 何种评分方式,默认是 estimator 的 score 函数返回的值, KNN 的是R^2值,越高越好
-
返回每次交叉验证运行的估算器scoring数组。
交叉验证模型分数
sklearn.model_selection.cross_val_score(estimator, X, Y,CV,scoring )
用 CV 选择 Hype 参数
在无监督学习中,数据集的特征是不知道的,没有任何训练样本。
监督学习的特点是训练集已给出,通过已有的训练样本(即已知数据以及对应的输出)去训练得到一个最优模型(这个模型属于某个函数的集合,最优则表示在某个评价标准下是最佳的),再利用这个模型将所有的输入映射为相应的输出,从而实现分类的目的,也就是有了对未知数据进行分类的能力.
监督学习其实就是我们对输入样本经过模型训练后有明确的预期输出,非监督学习就是我们对输入样本经过模型训练后得到什么输出完全没有预期。
有监督学习和无监督学习的区别
返回 num 个符合期望值为 loc , 标准差为 scale 的正态分布随机数。
np.random.normal(loc = 0.0, scale = 1.0 ,num)
简化下,忽略随机误差(其实随机误差很重要)
所以 Error误差 是由随机误差,预测模型与真实模型的误差以及预测模型本身的变异三部分组成的。
等式右边依次是Irreducible Error, Bias^2 和 Variance。
其中,Y是真实值,Y 由 Y = f + e产生, f-hat是预测值 。
[图片上传失败...(image-d7cac4-1563778769660)]
使用平方误差函数表示 Error 的计算
Error 的组成
最后提下 noise
TUT 里讨论的应该是评估模型好坏的语境下的Bias(偏差)和 Variance,这就要再提 Error
Bias(偏差),Error(误差),和Variance(方差),Noise(噪声)
3.最后根据测试集,用调整好 Hype参数的那一个模型,评估模型表现
2.经过 Hype 参数调整的每种模型用训练集的交叉验证通过比较平均accuracy_score
,选择哪种模型最适合这批数据
1.对于每种模型,用训练集的交叉验证通过比较平均accuracy_score
选择合适的 Hype 参数
过程:
-
用哪个模型
-
每个模型里的最佳的超参数
要确定
如果我们需要对一组数据建立模型,
模型选择以及 调节 Hype 参数
-
将训练集平均分割成K个等份
-
使用1份数据作为验证数据,其余作为训练数据
-
计算测试
accuracy_score
-
使用不同的测试集,重复2、3步骤
-
对测试
accuracy_score
做平均,作为对未知数据预测准确率的估计
步骤
可以交叉验证估计该模型的 hype 参数的最佳值。
-
学习率
深层神经网络隐藏层数
树的数量或树的深度
一些模型中的某个参数在模型训练前就要被设置:
什么是 Hype 参数
调整 Hype 参数
-
调整 Hype 参数
-
选择模型
-
特征选择
用处
-
TUT 使用的是 K-fold 交叉验证法,K 有多大,就有多少种训练集划分方式。
-
一般来说 K = 10 用的比较多。
-
在保留交叉验证(hand-out cross validation)中,随机将训练样本集分成训练集(training set)和交叉验证集(cross validation set),比如分别占70%,30%。然后使用模型在训练集上学习得到假设。最后使用交叉
留一法(leave one out, LOO)就是m-fold cross validation,m是样本集的大小,就是只留下一个样本来验证模型的准确性。
补充
演示 K-fold 方式分解训练集
就是把样本集S分成k份,分别使用其中的(k-1)份作为训练集,剩下的1份作为交叉验证集,最后取最后的平均误差,来评估这个模型。
K-fold 方式
将数据集进行一系列分割,生成一组不同的训练测试集,然后分别训练模型并计算测试accuracy_score
,最后对结果进行平均处理。这样来有效降低测试accuracy_score
的差异。
基本思想
Holdout 方法往往因为验证集太小而效果不佳,即验证集数据太少无法完全显示数据的原貌
用全部数据进行训练和测试的accuracy_score
分析导致数据过拟合以及测试集缺少独立性。
问题
这里不同的训练集、验证集分割的方法导致其准确率不同。
2.模型复杂,但是样本量不足。(对的,样本数足够就不用着 CV 了)
1.训练集和测试集特征分布不一样
过拟合有两种可能:
image
网友评论