模型训练技巧
k-折交叉验证
1:k-fold
将样例划分为K份,若K=样例数,即为留一交叉验证,K-1份作为训练。
2:Stratified k-fold 分层交叉验证
StratifiedKFold()这个函数较常用,比KFold的优势在于将k折数据按照百分比划分数据集,每个类别百分比在训练集和测试集中都是一样,这样能保证不会有某个类别的数据在训练集中而测试集中没有这种情况,同样不会在训练集中没有全在测试集中,这样会导致结果糟糕透顶。
## 加载包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
## 图像在jupyter notebook中显示
%matplotlib inline
## 显示的图片格式(mac中的高清格式),还可以设置为"bmp"等格式
%config InlineBackend.figure_format = "retina"
## 输出图显示中文
from matplotlib.font_manager import FontProperties
fonts = FontProperties(fname = "D:\Desktop\python在机器学习中的应用\旗黑55扩B6字.ttf",size=14)
from sklearn import metrics
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
## 忽略提醒
import warnings
warnings.filterwarnings("ignore")
## 读取鸢尾花数据集
Iris = load_iris()
Iris.data.shape
Iris.target #目标输出
将数据集切分为k个于集,每次采用其中的一个子集用于模型的测试集,余下的k-1个自己用于模型训练,这个过程重复k次,做种将k次测试集的测试结果的均值作为模型的效果评价。k常取10,10折交叉验证
1.随机不放回抽样
即随机地将数据集分为k份,每份没有重复的样本
## k-折交叉验证
## 1:使用k-fold对Iris数据集分类
from sklearn.model_selection import KFold
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
Irkf = KFold(n_splits=10,random_state=42) #random_state参数,设置随机生成器种子。n_splits参数切分子集个数
## 使用 线性判别 分析算法进行数据分类
LDA_clf = LinearDiscriminantAnalysis(n_components=2) #n_components表示希望保留的方差比率
scores = []
for ii,(train_index, test_index) in enumerate(Irkf.split(Iris.data)):
## 训练模型
LDA_clf.fit(Iris.data[train_index],Iris.target[train_index])
## 测试模型效果
prey = LDA_clf.predict(Iris.data[test_index])
acc = metrics.accuracy_score(Iris.target[test_index],prey)
print("Fold:",ii+1,"Acc:",np.round(acc,4))
scores.append(acc)
## 计算准确率的平均值
print("平均Acc:",np.round(np.mean(scores),4))
通过使用10折交叉验证的最终预测精度为0.9667
省略上行代码段可用下面代替
## 同时sklearn还提供了cross_val_score函数直接计算平均得分
from sklearn.model_selection import cross_val_score
scores = cross_val_score(estimator=LDA_clf,cv=10,
X=Iris.data,y = Iris.target,
n_jobs = 4)
print("10折交叉验证的Acc:\n",scores)
print("平均Acc:",np.round(np.mean(scores),4))
2.分层抽样
即按照匪类数据百分比划分数据及,使每个类别百分比在训练集合测试集中都一样
## 2:Stratified k-fold 分层交叉验证
from sklearn.model_selection import StratifiedKFold
Skf_ir = StratifiedKFold(n_splits=3,random_state=2)
scores = []
## 使用Skf_ir.split()时需要同时提供X和Y
for ii,(train_index, test_index) in enumerate(Skf_ir.split(Iris.data,Iris.target)):
## 训练模型
LDA_clf.fit(Iris.data[train_index],Iris.target[train_index])
## 测试模型效果
prey = LDA_clf.predict(Iris.data[test_index])
acc = metrics.accuracy_score(Iris.target[test_index],prey)
print("每个测试集的类别比例:\n",pd.value_counts(Iris.target[test_index]))
scores.append(acc)
## 计算准确率的平均值
print("平均Acc:",np.mean(scores))
参数网格搜索
使用网格搜索为模型寻找更优的参数。结合K近邻判别分析介绍如何使用参数网格搜素方法,找到更优的参数
## 参数网格搜索
## 切分数据集
train_x,test_x,train_y,test_y = train_test_split(Iris.data,Iris.target,
test_size = 0.25,random_state = 42)
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
## 定义模型流程
pipe_KNN = Pipeline([("scale",StandardScaler()),
("KNN",KNeighborsClassifier())])
## 定义需要搜索的参数
n_neighbors = np.arange(1,10)
para_grid = [{"scale__with_mean":[True,False],
# "scale__with_std":[True,False],
"KNN__n_neighbors" : n_neighbors}]
## 应用到数据上
gs_KNN_ir = GridSearchCV(estimator=pipe_KNN,param_grid=para_grid,
cv=10,n_jobs=4)
gs_KNN_ir.fit(train_x,train_y)
## 输出最优的参数
gs_KNN_ir.best_params_
使用*best_estimator_*获取最好的模型并保存,保存后直接用于测试集的预测,不需要重新训练
## 获取最好的模型
Iris_clf = gs_KNN_ir.best_estimator_
## 用来预测
prey = Iris_clf.predict(test_x)
print("Acc:",'{:.2%}'.format(metrics.accuracy_score(test_y,prey)))
正确率100%,所有样本都能预测正确
训练集、验证集、测试集的引入
引入验证集防止模型过拟合,将数据集分为训练集、验证集(验证模型效果,帮助模型优化)、测试集(测试模型的泛化能力,避免模型过拟合)