一、 留一交叉验证(Leave-one-out Cross Validation)
留一交叉验证(LOO CV)指的是使用数据集X中的(n-1)个样本数据作为训练集(train),然后剩下的1条数据作为测试集(test)。每次只使用一个数据作为测试集,剩下的全部作为训练集。
假设数据集X中数据个数为n,通过LOO交叉验证训练模型,一共需要训练n次。由于得到了充分的训练,这种方法得出的结果与训练整个测试集的期望值最为接近,但是时间成本过于庞大。
因此留一交叉验证常用于小样本数据集的模型训练中。
二、随机森林(RandomForest)
本文使用随机森林二分类问题作为模型训练的示例,故不再详细阐述随机森林的原理。
各位实战中可以把这一步换成任何的二分类模型。
三、F1分数(F1-score)
是常见的用于衡量机器学习模型效果的评估指标,F1分数同时考虑精确率和召回率,让两者同时达到最高,取得平衡。F1 分数计算式为 2*精确率*召回率/(精确率+召回率)。
但我们需要得到分类模型的混淆矩阵才能计算这些指标。
混淆矩阵 | 预测为正类 | 预测为负类 |
实际为正类 | TP | FN |
实际为负类 | FP |
TN |
【LOO实战】
【数据集声明】:本文代码中生成一个小数据集以便于直接理解和运行
1.导入程序包+数据准备:
import pandas as pd
import numpy as np
from sklearn.model_selection import LeaveOneOut#导入留一交叉验证的包
from sklearn.ensemble import RandomForestClassifier
#sklearn里面有很多分类器模型,这里以随机森林作为示例
nums = [[i for i in range(4)] for _ in range(10)]
colu = [f'col_{i}' for i in range(4)] # 用来做列名
inde = [f'row_{i}' for i in range(10)] # 用来做索引
data=pd.DataFrame(data=nums,index=inde,columns=colu)
data['col_2']=[0,1,0,1,0,1,1,1,0,0]
data['col_3']=[0,1,0,1,0,1,1,1,0,0]#col_3作为带预测的二分类变量,我们手动随便生成一个
data
生成的数据集一共有10条数据,前三列是变量(X),col_3是待预测的二分类标签(y)
X=data[['col_0','col_1','col_2']]
y=data['col_3']
数据集生成成功
2.留一交叉验证+训练模型:
先生成LOO的实例化对象
LOO = LeaveOneOut() # 实例化LOO对象
.split函数会直接生成每一次训练过程中训练集和测试集在原数据集中所对应的索引,用train_idx记录每次训练的训练集索引,test_idx记录每次训练的测试集索引
这个函数每循环一次,就是进行了一次训练,本数据集一共要循环10次
#如果有10个样本,需要做10次模型训练,每一次测试集只有一个样本
# 取LOO训练、测试集数据值
predicty=[]#predicty记录下每次预测的结果
for train_idx, test_idx in LOO.split(y):
# train_idx 是指训练数据在总数据集上的索引位置
# test_idx 是指测试数据在总数据集上的索引位置
trainx,trainy = X.iloc[train_idx],y.iloc[train_idx]#按照索引拿出训练集
testx,testy=X.iloc[test_idx],y.iloc[test_idx]#按照索引拿出测试集
RF = RandomForestClassifier(random_state = 88)#定义随机森林模型
#训练随机森林模型
RF.fit(trainx, trainy)
predicty.append(RF.predict(testx))#将每次预测的结果保存到predicty中
3.手动计算模型的F1分数值:
再回顾一下计算混淆矩阵的规则:
矩阵 | 预测为正类 | 预测为负类 |
实际为正类 | TP | FN |
实际为负类 | FP |
TN |
初始化四个值之后,手动写循环统计
#初始化需要记录的值,详细含义见我写的混淆矩阵
TP=0
FP=0
TN=0
FN=0
#写一个简单的循环实现统计四个值
for i in range(1,len(y)):
if y[i]==1:
if predicty[i]==1:
TP=TP+1
else: FN=FN+1
else:
if predicty[i]==1:
FP=FP+1
else: TN=TN+1
Acc=TP/(TP+FP)#精确率Acc
Rec=TP/(TP+FN)#召回率Rec
#F1值=2*精确率*召回率/精确率+召回率
F1score=2*Acc*Rec/(Acc+Rec)
F1score#输出查看F1分数的值