机器学习基础06DAY
模型检验-交叉验证
一般在进行模型的测试时,我们会将数据分为训练集和测试集。在给定的样本空间中,拿出大部分样本作为训练集来训练模型,剩余的小部分样本使用刚建立的模型进行预测。
训练集与测试集
训练集与测试集的分割可以使用cross_validation中的train_test_split方法,大部分的交叉验证迭代器都内建一个划分数据前进行数据索引打散的选项,train_test_split 方法内部使用的就是交叉验证迭代器。默认不会进行打散,包括设置cv=some_integer(直接)k折叠交叉验证的cross_val_score会返回一个随机的划分。如果数据集具有时间性,千万不要打散数据再划分!
- sklearn.cross_validation.train_test_split
def train_test_split(*arrays,**options)
"""
:param arrays:允许的输入是列表,数字阵列
:param test_size:float,int或None(默认为无),如果浮点数应在0.0和1.0之间,并且表示要包括在测试拆分中的数据集的比例。如果int,表示测试样本的绝对数
:param train_size:float,int或None(默认为无),如果浮点数应在0.0到1.0之间,表示数据集包含在列车拆分中的比例。如果int,表示列车样本的绝对数
:param random_state:int或RandomState,用于随机抽样的伪随机数发生器状态,参数 random_state 默认设置为 None,这意为着每次打散都是不同的。
"""
from sklearn.cross_validation import train_test_split
from sklearn import datasets
iris = datasets.load_iris()
print iris.data.shape,iris.target.shape
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.4, random_state=42)
print X_train.shape,y_train.shape
print X_test.shape,y_test.shape
上面的方式也有局限。因为只进行一次测试,并不一定能代表模型的真实准确率。因为,模型的准确率和数据的切分有关系,在数据量不大的情况下,影响尤其突出。所以还需要一个比较好的解决方案。
模型评估中,除了训练数据和测试数据,还会涉及到验证数据。使用训练数据与测试数据进行了交叉验证,只有这样训练出的模型才具有更可靠的准确率,也才能期望模型在新的、未知的数据集上,能有更好的表现。这便是模型的推广能力,也即泛化能力的保证。
holdout method
评估模型泛化能力的典型方法是holdout交叉验证(holdout cross validation)。holdout方法很简单,我们只需要将原始数据集分割为训练集和测试集,前者用于训练模型,后者用于评估模型的性能。一般来说,Holdout 验证并非一种交叉验证,因为数据并没有交叉使用。 随机从最初的样本中选出部分,形成交叉验证数据,而剩余的就当做训练数据。 一般来说,少于原本样本三分之一的数据被选做验证数据。所以这种方法得到的结果其实并不具有说服性
k-折交叉验证
K折交叉验证,初始采样分割成K个子样本,一个单独的子样本被保留作为验证模型的数据,其他K-1个样本用来训练。交叉验证重复K次,每个子样本验证一次,平均K次的结果或者使用其它结合方式,最终得到一个单一估测。这个方法的优势在于,同时重复运用随机产生的子样本进行训练和验证,每次的结果验证一次,10折交叉验证是最常用的。
例如5折交叉验证,全部可用数据集分成五个集合,每次迭代都选其中的1个集合数据作为验证集,另外4个集合作为训练集,经过5组的迭代过程。交叉验证的好处在于,可以保证所有数据都有被训练和验证的机会,也尽最大可能让优化的模型性能表现的更加可信。
使用交叉验证的最简单的方法是在估计器和数据集上使用cross_val_score函数。
- sklearn.cross_validation.cross_val_score
def cross_val_score(estimator, X, y=None, groups=None, scoring=None, cv=None, n_jobs=1, verbose=0, fit_params=None, pre_dispatch='2*n_jobs')
"""
:param estimator:模型估计器
:param X:特征变量集合
:param y:目标变量
:param cv:int,使用默认的3折交叉验证,整数指定一个(分层)KFold中的折叠数
:return :预估系数
"""
from sklearn.cross_validation import cross_val_score
diabetes = datasets.load_diabetes()
X = diabetes.data[:150]
y = diabetes.target[:150]
lasso = linear_model.Lasso()
print(cross_val_score(lasso, X, y))
使用交叉验证方法的目的主要有2个:
- 从有限的学习数据中获取尽可能多的有效信息;
- 可以在一定程度上避免过拟合问题。
K-邻近算法调优
网格搜索
In [ ]:
from sklearn.datasets import load_wine
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
In [ ]:
# 实例化红酒集
wine = load_wine()
In [ ]:
# 数据划分
x_train, x_test, y_train, y_test = train_test_split(wine.data, wine.target, test_size=0.25)
In [ ]:
# 数据标准化
std = StandardScaler().fit(x_train)
x_train = std.transform(x_train)
x_test = std.transform(x_test)
In [ ]:
# 实例化K-邻近
knn = KNeighborsClassifier()
In [ ]:
# 实例化网格搜索
param = {"n_neighbors": [3, 5, 10]}
grid = GridSearchCV(estimator=knn, param_grid=param, cv=10)
grid.fit(x_train, y_train)
Out[ ]:
In [ ]:
# 预测测试集的准确率
score = grid.score(x_test, y_test)
score
Out[ ]:
0.9777777777777777
In [ ]:
# 在交叉验证中最好的结果
grid.best_score_
Out[ ]:
0.9472527472527472
In [ ]:
# 在交叉验证中最好的参数模型参数
grid.best_estimator_.get_params()
Out[ ]:
{'algorithm': 'auto',
'leaf_size': 30,
'metric': 'minkowski',
'metric_params': None,
'n_jobs': None,
'n_neighbors': 5,
'p': 2,
'weights': 'uniform'}
In [ ]:
# 每个超参数,每次交叉验证的结果
grid.cv_results_
Out[ ]:
{'mean_fit_time': array([0.00060642, 0.00055697, 0.00055516]),
'std_fit_time': array([0.00049536, 0.00057434, 0.00047108]),
'mean_score_time': array([0.0013592 , 0.00115194, 0.00121515]),
'std_score_time': array([0.00044467, 0.00044955, 0.00042784]),
'param_n_neighbors': masked_array(data=[3, 5, 10],
mask=[False, False, False],
fill_value='?',
dtype=object),
'params': [{'n_neighbors': 3}, {'n_neighbors': 5}, {'n_neighbors': 10}],
'split0_test_score': array([1., 1., 1.]),
'split1_test_score': array([1., 1., 1.]),
'split2_test_score': array([0.85714286, 0.85714286, 0.92857143]),
'split3_test_score': array([0.84615385, 1. , 0.84615385]),
'split4_test_score': array([0.84615385, 0.84615385, 0.92307692]),
'split5_test_score': array([1., 1., 1.]),
'split6_test_score': array([0.92307692, 0.92307692, 0.92307692]),
'split7_test_score': array([1., 1., 1.]),
'split8_test_score': array([0.92307692, 0.92307692, 0.92307692]),
'split9_test_score': array([0.92307692, 0.92307692, 0.92307692]),
'mean_test_score': array([0.93186813, 0.94725275, 0.9467033 ]),
'std_test_score': array([0.06251192, 0.05831428, 0.04902442]),
'rank_test_score': array([3, 1, 2])}