模型的选择与调优
1 交叉验证
1.1 交叉验证过程
交叉验证:为了让被评估的模型更加准确可信
交叉验证的意义:为了使一部分数据即当成验证集,也做过训练集,更加准确得出准确率,把最后的准确率取平均值。
注意:线上的测试数据才有测试集如果没有测试数据集,怎么知道结果好与不好,那就把训练集分成训练集和验证集(和测试集没关系,抛开测试集)。
交叉验证过程:将拿到的数据分为数据集和验证集。以下图为例:将数据分成5份,其中一份作为验证集。然后经过5次(组)的测试,每次都更换不同的验证集。即得到5组模型的结果,取平均值作为最终结果。又称5折交叉验证。10折交叉验证是最常用的。
1.2 交叉验证目的
使用交叉验证方法的目的主要有2个:
①从有限的学习数据中获取尽可能多的有效信息;
②可以在一定程度上避免过拟合问题。
1.3 交叉验证API
使用交叉验证的最简单的方法是在估计器和数据集上使用cross_val_score函数。
sklearn.model_selection._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')
参数: estimator:模型估计器 X:特征变量集合 y:目标变量
cv:使用默认的3折交叉验证,整数指定一个(分层)KFold中的折叠数 return :预估系数
1.4 案例
from sklearn.model_selection._validation import cross_val_score
from sklearn.datasets import load_digits
from sklearn import linear_model
diabetes = load_digits()
X = diabetes.data[:150]
y = diabetes.target[:150]
lasso = linear_model.Lasso()
print(cross_val_score(lasso, X, y))
2 网格搜索-超参数搜索
通常情况下,有很多参数是需要手动指定的(如k-近邻算法中的K值),这种叫超参数。但是手动过程繁杂,所以需要对模型预设几种超参数组合。每组超参数都采用交叉验证来进行评估。最后选出最优参数组合建立模型。
2.1 网格搜索API
sklearn.model_selection.GridSearchCV
sklearn.model_selection.GridSearchCV(estimator, param_grid=None,cv=None)
常改参数: estimator:估计器对象 param_grid:估计器参数(dict){“n_neighbors”:[2,4,6]}
cv:指定几折交叉验证
常用方法:
fit(X, y=None, groups=None, **fit_params):输入训练数据,与所有参数组合运行
score(X, y=None):准确率
predict(X):调用使用最佳找到的参数对估计量进行预测,X:可索引,长度为n_samples
常用属性
best_score_:在交叉验证中测试的最好结果
best_estimator_:最好的参数模型
cv_results_:每次交叉验证后的测试集准确率结果和训练集准确率结果
2.2 案例
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
#1 读取数据
data = pd.read_csv("./data/train.csv")
#2 处理数据,截取部分数据
data = data.query("x > 1.0 & x < 1.5 & y > 2.5 & y < 3")
timev = pd.to_datetime(data['time'],unit='s')
timev = pd.DatetimeIndex(timev)
#构造新特征
data['day']=timev.day
data['hour'] = timev.hour
data['weekday'] = timev.weekday
#删除时间特性,pandas的列是1,sklearn的列是0
data.drop(['time'],axis=1)
#根据palce_id分组
data_count = data.groupby('palce_id').count()
#调用reset_index,reset_index()的所用是把索引palce_id变成某一列,便于获取
tf = data_count[data_count.row_id>5].reset_index()
#筛选data里面id是tf里面的id,在就保留下来
data[data['place_id'].isin(tf.place_id)]
# 取出数据当中的特征值和将place_id作为目标值,
y = data['place_id']
x = data.drop(['place_id'], axis=1)
# 将数据的分割成训练集合测试集
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25)
#3 特征工程标准化
std = StandardScaler()
x_train = std.fit_transform(x_train)
x_test = std.transform(x_test)
#进行算法流程 使用网格验证超参数在这不加
knn = KNeighborsClassifier()
#构造参数值进行搜索,字典形式
params = {"n_neighbor":[2,4,6,8]}
#进行网格搜索
gsc = GridSearchCV(knn,params,cv=3)
gsc.fit(x_train,y_train)
# 预测准确率
print("在测试集上准确率:", gsc.score(x_test, y_test))
print("在交叉验证当中最好的结果:", gsc.best_score_)
print("选择最好的模型是:", gsc.best_estimator_)
print("每个超参数每次交叉验证的结果:", gsc.cv_results_)