You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

交叉验证下模型训练准确率与损失可视化的代码实现方法

交叉验证下可视化训练准确率与损失变化的解决方案

这个问题在Keras交叉验证训练中很常见——你猜的没错,核心问题就是没有在fit()中传入验证数据集,导致history里没有val_acc和val_loss这些关键指标。下面是具体的调整方案和代码示例:

步骤1:修改训练代码,传入验证数据并收集历史记录

首先,我们需要在每一轮K折交叉验证的训练中,把当前fold的测试集作为验证数据传入fit(),同时把每一轮的训练历史保存下来:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import StratifiedKFold
from tensorflow.keras.models import Sequential
from tensorflow.keras import layers

seed = 42
kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=seed)
cvscores = []
all_histories = []  # 用来保存每一轮fold的训练历史

for train, test in kfold.split(x_train, y_train):
    model = Sequential()
    model.add(layers.Conv2D(32,(4,4), activation = 'relu', input_shape = (224,224,3)))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(64, (4,4), activation = 'relu'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Flatten())
    model.add(layers.Dense(64, activation = 'relu'))
    model.add(layers.Dropout(0.5))
    model.add(layers.Dense(1, activation = 'sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    
    # 关键修改:传入validation_data,使用当前fold的测试集作为验证集
    history = model.fit(x_train[train], y_train[train], 
                        epochs=15, batch_size=64,
                        validation_data=(x_train[test], y_train[test]))
    all_histories.append(history)
    
    scores = model.evaluate(x_train[test], y_train[test], verbose=0)
    print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
    cvscores.append(scores[1] * 100)

print("%.2f%% (+/- %.2f%%)" % (np.mean(cvscores), np.std(cvscores)))

步骤2:可视化训练过程

现在我们有了每一轮fold的训练历史,可以用两种方式可视化:

方式一:绘制每折的单独曲线

这种方式能直观看到不同fold之间的训练差异:

# 绘制准确率曲线
plt.figure(figsize=(12, 6))
for i, history in enumerate(all_histories):
    plt.plot(history.history['accuracy'], label=f'Train Fold {i+1}')
    plt.plot(history.history['val_accuracy'], label=f'Val Fold {i+1}')
plt.title('Model Accuracy Across Folds')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.grid(True)
plt.show()

# 绘制损失曲线
plt.figure(figsize=(12, 6))
for i, history in enumerate(all_histories):
    plt.plot(history.history['loss'], label=f'Train Fold {i+1}')
    plt.plot(history.history['val_loss'], label=f'Val Fold {i+1}')
plt.title('Model Loss Across Folds')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.grid(True)
plt.show()

方式二:绘制平均后的趋势曲线

如果想看到整体的训练趋势,可以计算所有fold在每个epoch的指标平均值:

# 提取所有fold的指标数据
num_epochs = 15
avg_acc = np.zeros(num_epochs)
avg_val_acc = np.zeros(num_epochs)
avg_loss = np.zeros(num_epochs)
avg_val_loss = np.zeros(num_epochs)

for history in all_histories:
    avg_acc += np.array(history.history['accuracy'])
    avg_val_acc += np.array(history.history['val_accuracy'])
    avg_loss += np.array(history.history['loss'])
    avg_val_loss += np.array(history.history['val_loss'])

# 计算平均值
avg_acc /= len(all_histories)
avg_val_acc /= len(all_histories)
avg_loss /= len(all_histories)
avg_val_loss /= len(all_histories)

# 绘制平均准确率曲线
plt.figure(figsize=(10, 5))
plt.plot(avg_acc, label='Train Accuracy (Avg)')
plt.plot(avg_val_acc, label='Val Accuracy (Avg)')
plt.title('Average Model Accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(loc='upper left')
plt.grid(True)
plt.show()

# 绘制平均损失曲线
plt.figure(figsize=(10, 5))
plt.plot(avg_loss, label='Train Loss (Avg)')
plt.plot(avg_val_loss, label='Val Loss (Avg)')
plt.title('Average Model Loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(loc='upper left')
plt.grid(True)
plt.show()

补充说明

  • 这里用当前fold的测试集作为验证数据,完全符合交叉验证的逻辑——每一轮训练时,我们用未见过的当前fold测试集来评估泛化能力。
  • 如果你的数据集很大,也可以考虑在训练集内部再划分一个小验证集,但这样会减少训练数据量;用fold的测试集作为验证是更标准的交叉验证做法。

内容的提问来源于stack exchange,提问作者Janne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:41:17