(8-4 -2)模型验证和调优:交叉验证优化

8.4.2  交叉验证优化

交叉验证(Cross-Validation)是一种用于评估模型性能的技术,它在有限的数据集上更准确地估计模型的性能,并帮助选择最佳的模型和超参数。交叉验证通过将数据集划分为多个子集,轮流使用其中一个子集作为验证集,其余子集作为训练集,从而多次训练和验证模型。

最常见的交叉验证方法是 K 折交叉验证(K-Fold Cross-Validation)。在 K-Fold 交叉验证中,数据集被均匀地划分为 K 个子集,每次使用其中一个子集作为验证集,其他 K-1 个子集作为训练集,重复进行 K 次。每次训练和验证都会得到一个性能评价指标,例如准确率或均方误差。最终,将 K 次评价指标的平均值作为模型在整个数据集上的性能估计。例如下面是一个使用 K-Fold 实现交叉验证的例子,演示了在 TensorFlow 中使用交叉验证创建和训练模型的过程。

实例8-3:TensorFlow使用交叉验证创建和训练模型(源码路径:daima/8/jiao.py)

实例文件jiao.py的主要实现代码如下所示。

import numpy as np
from sklearn.model_selection import KFold
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

# 生成示例数据
num_samples = 1000
input_dim = 10
output_dim = 1

X = np.random.rand(num_samples, input_dim)
y = np.random.randint(2, size=(num_samples, output_dim))  # 模拟二分类标签

# 设置 K-Fold 参数
num_folds = 5
kf = KFold(n_splits=num_folds, shuffle=True, random_state=42)

# 创建神经网络模型
def create_model():
    model = Sequential([
        Dense(32, activation='relu', input_shape=(input_dim,)),
        Dense(16, activation='relu'),
        Dense(output_dim, activation='sigmoid')
    ])
    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
    return model

# 进行 K-Fold 交叉验证
fold = 1
for train_idx, val_idx in kf.split(X):
    print(f"Fold {fold}")
    X_train, X_val = X[train_idx], X[val_idx]
    y_train, y_val = y[train_idx], y[val_idx]

    model = create_model()
    model.fit(X_train, y_train, batch_size=32, epochs=50, validation_data=(X_val, y_val))
    
    val_loss, val_accuracy = model.evaluate(X_val, y_val)
    print(f"Validation Loss: {val_loss:.4f}, Validation Accuracy: {val_accuracy:.4f}")
    
    fold += 1

对上述代码的具体说明如下:

  1. 生成示例数据。
  2. 使用 KFold 类进行 K-Fold 交叉验证的设置,其中 n_splits 参数表示将数据集分成几个子集。
  3. 创建一个函数 create_model 来构建神经网络模型。
  4. 使用交叉验证迭代进行训练和验证。在每个折叠中,我们根据训练索引和验证索引划分数据集,创建模型并进行训练和验证。同时,我们还计算了每个折叠的验证集性能指标。

注意:这个例子展示了如何使用 K-Fold 交叉验证来评估神经网络模型的性能,并且对每个折叠的性能进行了输出。这样的交叉验证可以更好地了解模型的性能稳定性和泛化能力。但是大家需要注意,虽然交叉验证可以更好地评估模型的性能,并提供对模型的稳定性和泛化能力的更准确估计。然而,交叉验证需要多次训练和验证模型,因此在计算资源有限的情况下,可能会消耗大量的时间和计算资源。另外,在大规模数据集上执行交叉验证可能会变得非常耗时,并且可能并不是必要的。在这些情况下,使用单独的验证集和测试集进行评估可能更实际。

在PyTorch中,可以使用库Scikit-learn中的类KFold来实现交叉验证功能。例如下面是一个例子,展示了使用交叉验证创建、训练和优化模型的过程。

实例8-4PyTorch使用交叉验证创建、训练、优化模型(源码路径:daima/8/pyjiao1.py)

实例文件pyjiao1.py的主要实现代码如下所示。

import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.model_selection import KFold
from torchvision import transforms, datasets
from torch.utils.data import DataLoader, Subset

# 数据预处理
transform = transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))  # 图像归一化
])

# 加载CIFAR-10数据集
dataset = datasets.CIFAR10(root='./data', train=True, transform=transform, download=True)

# 定义模型
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
        self.fc1 = nn.Linear(64 * 16 * 16, 256)
        self.fc2 = nn.Linear(256, 10)

    def forward(self, x):
        x = self.pool(nn.functional.relu(self.conv1(x)))
        x = x.view(x.size(0), -1)
        x = nn.functional.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# 定义交叉验证
num_splits = 5
kf = KFold(n_splits=num_splits, shuffle=True)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()  # 交叉熵损失函数

# 执行交叉验证
for fold, (train_indices, val_indices) in enumerate(kf.split(dataset)):
    print(f"Fold {fold+1}/{num_splits}")
    
    # 划分训练集和验证集
    train_subset = Subset(dataset, train_indices)
    val_subset = Subset(dataset, val_indices)
    
    # 定义数据加载器
    batch_size = 32
    train_loader = DataLoader(train_subset, batch_size=batch_size, shuffle=True)
    val_loader = DataLoader(val_subset, batch_size=batch_size, shuffle=False)
    
    # 创建模型实例
    model = Net()
    
    # 定义优化器
    optimizer = optim.Adam(model.parameters(), lr=0.001)  # Adam优化算法
    
    # 训练模型
    num_epochs = 10
    for epoch in range(num_epochs):
        model.train()  # 设置为训练模式
        for inputs, labels in train_loader:
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
    
    # 在验证集上评估模型
    model.eval()  # 设置为评估模式
    val_loss = 0.0
    correct = 0
    total = 0
    with torch.no_grad():
        for inputs, labels in val_loader:
            outputs = model(inputs)
            val_loss += criterion(outputs, labels).item()
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    
    print(f"Validation Loss: {val_loss/len(val_loader):.4f} - Validation Accuracy: {100*correct/total:.2f}%")

在这个例子中,我们使用KFold类进行交叉验证。在每个交叉验证折叠中,分别划分了训练集和验证集,并在训练集上训练模型,然后在验证集上评估模型性能。在完成所有折叠后,得到了模型在不同验证集上的性能评估结果,从而更全面地了解模型的表现。

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农三叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值