目录
一、机器学习评估的基本概念
1.1 评估的定义与目标
1.2 常见评估指标
1.3 训练集、验证集与测试集的划分
二、分离数据集
2.1 分离训练数据集和评估数据集
2.2 k折交叉验证分离
2.3 弃一交叉验证分离
2.4 重复随机评估和训练数据集分离
三、交叉验证技术
3.1 K折交叉验证的原理与实现
3.2 留一法交叉验证
3.2.1 留一法交叉验证的优缺点
3.3 分层交叉验证
一、机器学习评估的基本概念
机器学习评估是指通过一系列指标和方法来衡量模型在特定任务上的表现。评估的目的是确保模型不仅在训练数据上表现良好,还能在未见过的数据上保持稳定的性能。
1.1 评估的定义与目标
评估是指通过系统化的方法和指标对模型性能进行量化分析,旨在判断模型在特定任务中的表现是否符合预期。其核心目标包括验证模型的泛化能力(即对未见数据的预测准确性)、识别过拟合或欠拟合问题、比较不同算法的优劣,并为模型优化提供依据。
1.2 常见评估指标
常用的评估指标包括:准确率、精确率、召回率、F1分数、ROC曲线和AUC值等;
- 准确率(Accuracy):模型预测正确的样本占总样本的比例。
- 精确率(Precision):模型预测为正类的样本中,实际为正类的比例。
- 召回率(Recall):实际为正类的样本中,模型预测为正类的比例。
- F1分数(F1 Score):精确率和召回率的调和平均数,用于平衡两者。
- ROC曲线(Receiver Operating Characteristic Curve):通过不同阈值下的真正类率和假正类率绘制的曲线。
- AUC值(Area Under Curve):ROC曲线下的面积,用于衡量分类器的整体性能。
1.3 训练集、验证集与测试集的划分
请点击链接跳转至之前的机器学习的基本知识篇,有详细介绍训练集、验证集与测试集的划分
这里就不做赘述了
https://love-xin.blog.csdn.net/article/details/143162589?spm=1011.2415.3001.5331https://love-xin.blog.csdn.net/article/details/143162589?spm=1011.2415.3001.5331
二、分离数据集
常用的分离数据集方法有:分离训练数据集和评估数据集、k折交叉验证分离、弃一交叉验证分离、重复随机评估和训练数据集分离。
2.1 分离训练数据集和评估数据集
将数据集划分为训练集和评估集是最基础的分离方法。通常采用70%-30%或80%-20%的比例分配。训练集用于模型训练,评估集用于验证模型性能。
这种方法的优势在于简单直接,适用于大规模数据集。但需要注意数据分布的均衡性,避免因随机划分导致评估偏差。
使用scikit-learn
实现分离训练数据集和评估数据集:
from pandas import read_csv
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression# 导入数据
filename = 'Sklearn\pima_data.csv' #(注意自己数据集的路径)
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
data = read_csv(filename, names=names)# 将数据分为输入数据和输出结果
array = data.values
X = array[:, 0:8]
Y = array[:, 8]
test_size = 0.33
seed = 4
X_train, X_test, Y_traing, Y_test = train_test_split(X, Y, test_size=test_size, random_state=seed)
model = LogisticRegression(max_iter=3000)
model.fit(X_train, Y_traing)
result = model.score(X_test, Y_test)
print("算法评估结果:%.3f%%" % (result * 100))
执行结果为:80.315%
2.2 k折交叉验证分离
k折交叉验证将数据集分为k个大小相似的子集。每次使用k-1个子集作为训练集,剩余1个子集作为验证集,重复k次。最终性能取k次验证的平均值。这种方法充分利用数据,适合中小规模数据集。典型k值为5或10,需注意k值过大会增加计算成本。
使用scikit-learn
实现k折交叉验证:
from pandas import read_csv
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold# 导入数据
filename = 'Sklearn\pima_data.csv'
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
data = read_csv(filename, names=names)# 将数据分为输入数据和输出结果
array = data.values
X = array[:, 0:8]
Y = array[:, 8]
n_splits=10
seed=4
kfold=KFold(n_splits=n_splits,random_state=seed,shuffle=True)
model=LogisticRegression(max_iter=3000)
result=cross_val_score(model, X,Y,cv=kfold)
print("结果:%.3f%% (%.3f%%)"%(result.mean()*100, result.std()*100))
执行结果为:77.729% (4.617%)
2.3 弃一交叉验证分离
弃一交叉验证是k折交叉验证的特例,k等于样本数量。每个样本单独作为验证集,其余样本用于训练。这种方法提供无偏估计,但计算复杂度高,仅适用于极小样本量场景。需注意样本代表性,避免异常值影响整体评估。
使用scikit-learn
实现弃一交叉验证:
from pandas import read_csv
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import LeaveOneOut# 导入数据
filename = 'Sklearn\pima_data.csv'
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
data = read_csv(filename, names=names)# 将数据分为输入数据和输出结果
array = data.values
X = array[:, 0:8]
Y = array[:, 8]
loocv = LeaveOneOut()
model = LogisticRegression(max_iter=3000)
result = cross_val_score(model, X, Y, cv=loocv)
print("算法评估结果:%.3f%% (%.3f%%)" % (result.mean() * 100, result.std() * 100))
执行结果为:77.604% (41.689%)
2.4 重复随机评估和训练数据集分离
另外一种对K折交叉验证的用法是随机分离数据成训练数据集和评估数据集,但是重复这个过程多次,就如同交叉验证分离。
下面的例子就是将数据按照67%/33%分离,重复这个过程10次:
from pandas import read_csv
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import ShuffleSplit# 导入数据
filename = 'Sklearn\pima_data.csv'
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
data = read_csv(filename, names=names)# 将数据分为输入数据和输出结果
array = data.values
X = array[:, 0:8]
Y = array[:, 8]
n_splits = 10
test_size = 0.33
seed = 4
kfold = ShuffleSplit(n_splits=n_splits, test_size=test_size, random_state=seed)
model = LogisticRegression(max_iter=3000)
result = cross_val_score(model, X, Y, cv=kfold)
print("结果:%.3f%% (%.3f%%)" % (result.mean() * 100, result.std() * 100))
执行结果为:75.945% (2.626%)
三、交叉验证技术
3.1 K折交叉验证的原理与实现
K折交叉验证(K-Fold Cross Validation)是一种评估机器学习模型性能的统计方法,通过将数据集划分为K个子集(“折”),依次使用其中K-1个子集作为训练数据,剩余1个子集作为验证数据,重复K次并计算平均性能指标。
使用scikit-learn
实现K折交叉验证:
import numpy as np
from sklearn.model_selection import KFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score# 加载数据
data = load_iris()
X, y = data.data, data.target# 初始化模型和K折划分器
model = RandomForestClassifier()
kf = KFold(n_splits=5, shuffle=True, random_state=42)# 存储每轮得分
scores = []for train_index, val_index in kf.split(X):X_train, X_val = X[train_index], X[val_index]y_train, y_val = y[train_index], y[val_index]model.fit(X_train, y_train)y_pred = model.predict(X_val)scores.append(accuracy_score(y_val, y_pred))# 输出平均准确率
print(f"Mean Accuracy: {np.mean(scores):.4f} (±{np.std(scores):.4f})")
执行结果为:Mean Accuracy: 0.9600 (±0.0249)
3.2 留一法交叉验证
留一法交叉验证(Leave-One-Out Cross-Validation, LOOCV)是一种特殊的交叉验证方法,适用于小样本数据集。其核心思想是每次从数据集中留出一个样本作为测试集,其余样本作为训练集,重复这一过程直到所有样本都被作为测试集一次。
3.2.1 留一法交叉验证的优缺点
优点:
- 无偏估计:由于每次训练集几乎包含所有样本(仅少一个),模型的评估结果更接近真实性能;
- 适用小样本:特别适合样本量极少的情况(如N<100)。
缺点:
- 计算成本高:需要训练模型N次,对于大数据集(N较大)时效率极低;
- 方差较高:每次训练集仅相差一个样本,可能导致评估结果波动较大。
使用Python和scikit-learn实现留一法交叉验证的示例:
from sklearn.model_selection import LeaveOneOut, cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_irisdata = load_iris() # 加载数据集
X, y = data.data, data.targetmodel = LogisticRegression(max_iter=200) # 初始化模型
loo = LeaveOneOut() # 初始化留一法交叉验证
scores = cross_val_score(model, X, y, cv=loo, scoring='accuracy') # 计算交叉验证得分
print(f"Mean Accuracy: {scores.mean():.4f}")
执行结果为:Mean Accuracy: 0.9667
3.3 分层交叉验证
分层交叉验证(Stratified Cross-Validation)是一种在交叉验证过程中保持数据集中各类别比例一致的技术。它特别适用于分类问题,尤其是当数据集中的类别分布不均衡时。通过分层交叉验证,可以确保每一折的训练集和验证集中各类别的比例与原始数据集一致,从而提高模型评估的准确性。
使用scikit-learn
库中的StratifiedKFold
类来实现分层交叉验证:
from sklearn.model_selection import StratifiedKFold
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score# 加载数据集
data = load_iris()
X = data.data
y = data.target# 初始化分层交叉验证
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)# 初始化模型
model = LogisticRegression(max_iter=200)# 进行交叉验证
accuracies = []
for train_index, test_index in skf.split(X, y):X_train, X_test = X[train_index], X[test_index]y_train, y_test = y[train_index], y[test_index]model.fit(X_train, y_train)y_pred = model.predict(X_test)accuracies.append(accuracy_score(y_test, y_pred))# 输出平均准确率
print(f"平均准确率: {sum(accuracies) / len(accuracies):.4f}")
执行结果为:0.9667