import torch
import os
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
import random
def set_seed(seed=42, deterministic=True):
random.seed(seed)
os.environ['PYTHONHASHSEED'] = str(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
if deterministic:
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
set_seed(42)
# 设置中文字体支持
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# 检查GPU是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")
# 1. 数据预处理
# 训练集:使用多种数据增强方法提高模型泛化能力
train_transform = transforms.Compose([
# 随机裁剪图像,从原图中随机截取32x32大小的区域
transforms.RandomCrop(32, padding=4),
# 随机水平翻转图像(概率0.5)
transforms.RandomHorizontalFlip(),
# 随机颜色抖动:亮度、对比度、饱和度和色调随机变化
transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),
# 随机旋转图像(最大角度15度)
transforms.RandomRotation(15),
# 将PIL图像或numpy数组转换为张量
transforms.ToTensor(),
# 标准化处理:每个通道的均值和标准差,使数据分布更合理
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])
# 测试集:仅进行必要的标准化,保持数据原始特性,标准化不损失数据信息,可还原
test_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])
# 2. 加载CIFAR-10数据集
train_dataset = datasets.CIFAR10(
root='./data',
train=True,
download=True,
transform=train_transform # 使用增强后的预处理
)
test_dataset = datasets.CIFAR10(
root='./data',
train=False,
transform=test_transform # 测试集不使用增强
)
# 3. 创建数据加载器
batch_size = 64
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
使用设备: cuda
# 4. 定义CNN模型的定义(替代原MLP)
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
# 第一个卷积块保持不变
self.conv1 = nn.Conv2d(3, 32, 3, padding=1)
self.bn1 = nn.BatchNorm2d(32)
self.relu1 = nn.ReLU()
self.pool1 = nn.MaxPool2d(2, 2)
# 第二个卷积块保持不变
self.conv2 = nn.Conv2d(32, 64, 3, padding=1)
self.bn2 = nn.BatchNorm2d(64)
self.relu2 = nn.ReLU()
self.pool2 = nn.MaxPool2d(2)
# 第三个卷积块保持不变
self.conv3 = nn.Conv2d(64, 128, 3, padding=1)
self.bn3 = nn.BatchNorm2d(128)
self.relu3 = nn.ReLU()
self.pool3 = nn.MaxPool2d(2)
# 调整全连接层结构
self.fc1 = nn.Linear(128 * 4 * 4, 512)
self.bn_fc1 = nn.BatchNorm1d(512) # 新增全连接层的BatchNorm
self.dropout = nn.Dropout(p=0.3) # 降低Dropout率从0.5到0.3
self.fc2 = nn.Linear(512, 10)
def forward(self, x):
# 卷积块处理保持不变
x = self.pool1(self.relu1(self.bn1(self.conv1(x))))
x = self.pool2(self.relu2(self.bn2(self.conv2(x))))
x = self.pool3(self.relu3(self.bn3(self.conv3(x))))
# 展平与全连接层调整
x = x.view(-1, 128 * 4 * 4)
x = self.fc1(x)
x = self.bn_fc1(x) # 新增全连接层的BatchNorm
x = self.relu3(x)
x = self.dropout(x)
x = self.fc2(x)
return x
def init_weights(m):
if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
# 初始化模型
model = CNN()
model = model.to(device) # 将模型移至GPU(如果可用)
model.apply(init_weights) # 优化权重初始化
CNN(
(conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu1): ReLU()
(pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu2): ReLU()
(pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(conv3): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn3): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu3): ReLU()
(pool3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(fc1): Linear(in_features=2048, out_features=512, bias=True)
(bn_fc1): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(dropout): Dropout(p=0.3, inplace=False)
(fc2): Linear(in_features=512, out_features=10, bias=True)
)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 替换为CosineAnnealingLR调度器
scheduler = optim.lr_scheduler.CosineAnnealingLR(
optimizer, # 指定要控制的优化器
T_max=10, # 余弦周期长度(epoch数)
eta_min=1e-5 # 最小学习率下限
)
# 5. 训练模型(记录每个 iteration 的损失)
def train(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs):
model.train() # 设置为训练模式
# 记录每个 iteration 的损失
all_iter_losses = [] # 存储所有 batch 的损失
iter_indices = [] # 存储 iteration 序号
# 记录每个 epoch 的准确率和损失
train_acc_history = []
test_acc_history = []
train_loss_history = []
test_loss_history = []
for epoch in range(epochs):
running_loss = 0.0
correct = 0
total = 0
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device) # 移至GPU
optimizer.zero_grad() # 梯度清零
output = model(data) # 前向传播
loss = criterion(output, target) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新参数
# 记录当前 iteration 的损失
iter_loss = loss.item()
all_iter_losses.append(iter_loss)
iter_indices.append(epoch * len(train_loader) + batch_idx + 1)
# 统计准确率和损失
running_loss += iter_loss
_, predicted = output.max(1)
total += target.size(0)
correct += predicted.eq(target).sum().item()
# 每100个批次打印一次训练信息
if (batch_idx + 1) % 100 == 0:
print(f'Epoch: {epoch+1}/{epochs} | Batch: {batch_idx+1}/{len(train_loader)} '
f'| 单Batch损失: {iter_loss:.4f} | 累计平均损失: {running_loss/(batch_idx+1):.4f}')
# 计算当前epoch的平均训练损失和准确率
epoch_train_loss = running_loss / len(train_loader)
epoch_train_acc = 100. * correct / total
train_acc_history.append(epoch_train_acc)
train_loss_history.append(epoch_train_loss)
# 测试阶段
model.eval() # 设置为评估模式
test_loss = 0
correct_test = 0
total_test = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
test_loss += criterion(output, target).item()
_, predicted = output.max(1)
total_test += target.size(0)
correct_test += predicted.eq(target).sum().item()
epoch_test_loss = test_loss / len(test_loader)
epoch_test_acc = 100. * correct_test / total_test
test_acc_history.append(epoch_test_acc)
test_loss_history.append(epoch_test_loss)
# 更新学习率调度器
# scheduler.step(epoch_test_loss)
scheduler.step(epoch_test_acc)
print(f'Epoch {epoch+1}/{epochs} 完成 | 训练准确率: {epoch_train_acc:.2f}% | 测试准确率: {epoch_test_acc:.2f}%')
# 绘制所有 iteration 的损失曲线
plot_iter_losses(all_iter_losses, iter_indices)
# 绘制每个 epoch 的准确率和损失曲线
plot_epoch_metrics(train_acc_history, test_acc_history, train_loss_history, test_loss_history)
return epoch_test_acc # 返回最终测试准确率
# 6. 绘制每个 iteration 的损失曲线
def plot_iter_losses(losses, indices):
plt.figure(figsize=(10, 4))
plt.plot(indices, losses, 'b-', alpha=0.7, label='Iteration Loss')
plt.xlabel('Iteration(Batch序号)')
plt.ylabel('损失值')
plt.title('每个 Iteration 的训练损失')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
# 7. 绘制每个 epoch 的准确率和损失曲线
def plot_epoch_metrics(train_acc, test_acc, train_loss, test_loss):
epochs = range(1, len(train_acc) + 1)
plt.figure(figsize=(12, 4))
# 绘制准确率曲线
plt.subplot(1, 2, 1)
plt.plot(epochs, train_acc, 'b-', label='训练准确率')
plt.plot(epochs, test_acc, 'r-', label='测试准确率')
plt.xlabel('Epoch')
plt.ylabel('准确率 (%)')
plt.title('训练和测试准确率')
plt.legend()
plt.grid(True)
# 绘制损失曲线
plt.subplot(1, 2, 2)
plt.plot(epochs, train_loss, 'b-', label='训练损失')
plt.plot(epochs, test_loss, 'r-', label='测试损失')
plt.xlabel('Epoch')
plt.ylabel('损失值')
plt.title('训练和测试损失')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
# 8. 执行训练和测试
epochs = 20 # 增加训练轮次以获得更好效果
print("开始使用CNN训练模型...")
final_accuracy = train(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs)
print(f"训练完成!最终测试准确率: {final_accuracy:.2f}%")
开始使用CNN训练模型...
Epoch: 1/20 | Batch: 100/782 | 单Batch损失: 1.7976 | 累计平均损失: 2.5908
Epoch: 1/20 | Batch: 200/782 | 单Batch损失: 2.0419 | 累计平均损失: 2.2892
Epoch: 1/20 | Batch: 300/782 | 单Batch损失: 1.2695 | 累计平均损失: 2.1018
Epoch: 1/20 | Batch: 400/782 | 单Batch损失: 1.1262 | 累计平均损失: 1.9935
Epoch: 1/20 | Batch: 500/782 | 单Batch损失: 1.3149 | 累计平均损失: 1.8990
Epoch: 1/20 | Batch: 600/782 | 单Batch损失: 1.1117 | 累计平均损失: 1.8177
Epoch: 1/20 | Batch: 700/782 | 单Batch损失: 1.0790 | 累计平均损失: 1.7563
d:\anaconda3\envs\DL\lib\site-packages\torch\optim\lr_scheduler.py:198: UserWarning: The epoch parameter in `scheduler.step()` was not necessary and is being deprecated where possible. Please use `scheduler.step()` to step the scheduler. During the deprecation, if epoch is different from None, the closed form is used instead of the new chainable form, where available. Please open an issue if you are unable to replicate your use case: https://github.com/pytorch/pytorch/issues/new/choose.
warnings.warn(EPOCH_DEPRECATION_WARNING, UserWarning)
Epoch 1/20 完成 | 训练准确率: 60.36% | 测试准确率: 74.82%
Epoch: 2/20 | Batch: 100/782 | 单Batch损失: 0.7087 | 累计平均损失: 0.8732
Epoch: 2/20 | Batch: 200/782 | 单Batch损失: 0.4138 | 累计平均损失: 0.8194
Epoch: 2/20 | Batch: 300/782 | 单Batch损失: 0.8031 | 累计平均损失: 0.8085
Epoch: 2/20 | Batch: 400/782 | 单Batch损失: 0.7065 | 累计平均损失: 0.8028
Epoch: 2/20 | Batch: 500/782 | 单Batch损失: 0.7783 | 累计平均损失: 0.7852
Epoch: 2/20 | Batch: 600/782 | 单Batch损失: 0.4857 | 累计平均损失: 0.7780
Epoch: 2/20 | Batch: 700/782 | 单Batch损失: 0.6721 | 累计平均损失: 0.7709
Epoch 2/20 完成 | 训练准确率: 73.66% | 测试准确率: 78.83%
Epoch: 3/20 | Batch: 100/782 | 单Batch损失: 0.6852 | 累计平均损失: 0.7622
Epoch: 3/20 | Batch: 200/782 | 单Batch损失: 0.7237 | 累计平均损失: 0.7482
Epoch: 3/20 | Batch: 300/782 | 单Batch损失: 0.7806 | 累计平均损失: 0.7586
Epoch: 3/20 | Batch: 400/782 | 单Batch损失: 0.6751 | 累计平均损失: 0.7457
Epoch: 3/20 | Batch: 500/782 | 单Batch损失: 0.7248 | 累计平均损失: 0.7408
Epoch: 3/20 | Batch: 600/782 | 单Batch损失: 0.7479 | 累计平均损失: 0.7372
Epoch: 3/20 | Batch: 700/782 | 单Batch损失: 0.8106 | 累计平均损失: 0.7351
Epoch 3/20 完成 | 训练准确率: 74.58% | 测试准确率: 79.26%
Epoch: 4/20 | Batch: 100/782 | 单Batch损失: 0.5943 | 累计平均损失: 0.7012
Epoch: 4/20 | Batch: 200/782 | 单Batch损失: 0.8560 | 累计平均损失: 0.6932
Epoch: 4/20 | Batch: 300/782 | 单Batch损失: 0.8743 | 累计平均损失: 0.6850
Epoch: 4/20 | Batch: 400/782 | 单Batch损失: 0.7913 | 累计平均损失: 0.6830
Epoch: 4/20 | Batch: 500/782 | 单Batch损失: 0.5610 | 累计平均损失: 0.6756
Epoch: 4/20 | Batch: 600/782 | 单Batch损失: 0.5693 | 累计平均损失: 0.6760
Epoch: 4/20 | Batch: 700/782 | 单Batch损失: 0.9094 | 累计平均损失: 0.6740
Epoch 4/20 完成 | 训练准确率: 76.52% | 测试准确率: 79.84%
Epoch: 5/20 | Batch: 100/782 | 单Batch损失: 0.9593 | 累计平均损失: 0.6725
Epoch: 5/20 | Batch: 200/782 | 单Batch损失: 0.4907 | 累计平均损失: 0.6475
Epoch: 5/20 | Batch: 300/782 | 单Batch损失: 0.6721 | 累计平均损失: 0.6581
Epoch: 5/20 | Batch: 400/782 | 单Batch损失: 0.7083 | 累计平均损失: 0.6571
Epoch: 5/20 | Batch: 500/782 | 单Batch损失: 0.7124 | 累计平均损失: 0.6545
Epoch: 5/20 | Batch: 600/782 | 单Batch损失: 0.5440 | 累计平均损失: 0.6516
Epoch: 5/20 | Batch: 700/782 | 单Batch损失: 0.6414 | 累计平均损失: 0.6508
Epoch 5/20 完成 | 训练准确率: 77.36% | 测试准确率: 79.43%
Epoch: 6/20 | Batch: 100/782 | 单Batch损失: 0.5179 | 累计平均损失: 0.6232
Epoch: 6/20 | Batch: 200/782 | 单Batch损失: 0.8351 | 累计平均损失: 0.6266
Epoch: 6/20 | Batch: 300/782 | 单Batch损失: 0.6568 | 累计平均损失: 0.6192
Epoch: 6/20 | Batch: 400/782 | 单Batch损失: 0.7664 | 累计平均损失: 0.6201
Epoch: 6/20 | Batch: 500/782 | 单Batch损失: 0.6261 | 累计平均损失: 0.6265
Epoch: 6/20 | Batch: 600/782 | 单Batch损失: 0.4503 | 累计平均损失: 0.6252
Epoch: 6/20 | Batch: 700/782 | 单Batch损失: 0.7143 | 累计平均损失: 0.6253
Epoch 6/20 完成 | 训练准确率: 78.10% | 测试准确率: 79.20%
Epoch: 7/20 | Batch: 100/782 | 单Batch损失: 0.5741 | 累计平均损失: 0.6233
Epoch: 7/20 | Batch: 200/782 | 单Batch损失: 0.6013 | 累计平均损失: 0.6200
Epoch: 7/20 | Batch: 300/782 | 单Batch损失: 0.6022 | 累计平均损失: 0.6108
Epoch: 7/20 | Batch: 400/782 | 单Batch损失: 0.4207 | 累计平均损失: 0.6095
Epoch: 7/20 | Batch: 500/782 | 单Batch损失: 0.7383 | 累计平均损失: 0.6087
Epoch: 7/20 | Batch: 600/782 | 单Batch损失: 0.6828 | 累计平均损失: 0.6061
Epoch: 7/20 | Batch: 700/782 | 单Batch损失: 0.6047 | 累计平均损失: 0.6076
Epoch 7/20 完成 | 训练准确率: 78.84% | 测试准确率: 80.22%
Epoch: 8/20 | Batch: 100/782 | 单Batch损失: 0.4462 | 累计平均损失: 0.5984
Epoch: 8/20 | Batch: 200/782 | 单Batch损失: 0.7262 | 累计平均损失: 0.6004
Epoch: 8/20 | Batch: 300/782 | 单Batch损失: 0.6540 | 累计平均损失: 0.5978
Epoch: 8/20 | Batch: 400/782 | 单Batch损失: 0.3996 | 累计平均损失: 0.5934
Epoch: 8/20 | Batch: 500/782 | 单Batch损失: 0.4733 | 累计平均损失: 0.5955
Epoch: 8/20 | Batch: 600/782 | 单Batch损失: 0.5828 | 累计平均损失: 0.5946
Epoch: 8/20 | Batch: 700/782 | 单Batch损失: 0.4615 | 累计平均损失: 0.5982
Epoch 8/20 完成 | 训练准确率: 79.14% | 测试准确率: 81.45%
Epoch: 9/20 | Batch: 100/782 | 单Batch损失: 0.3901 | 累计平均损失: 0.5885
Epoch: 9/20 | Batch: 200/782 | 单Batch损失: 0.8645 | 累计平均损失: 0.5754
Epoch: 9/20 | Batch: 300/782 | 单Batch损失: 0.6056 | 累计平均损失: 0.5721
Epoch: 9/20 | Batch: 400/782 | 单Batch损失: 0.5055 | 累计平均损失: 0.5720
Epoch: 9/20 | Batch: 500/782 | 单Batch损失: 0.6439 | 累计平均损失: 0.5726
Epoch: 9/20 | Batch: 600/782 | 单Batch损失: 0.5289 | 累计平均损失: 0.5774
Epoch: 9/20 | Batch: 700/782 | 单Batch损失: 0.7739 | 累计平均损失: 0.5790
Epoch 9/20 完成 | 训练准确率: 79.52% | 测试准确率: 80.72%
Epoch: 10/20 | Batch: 100/782 | 单Batch损失: 0.4442 | 累计平均损失: 0.5829
Epoch: 10/20 | Batch: 200/782 | 单Batch损失: 0.5318 | 累计平均损失: 0.5834
Epoch: 10/20 | Batch: 300/782 | 单Batch损失: 0.5636 | 累计平均损失: 0.5752
Epoch: 10/20 | Batch: 400/782 | 单Batch损失: 0.7698 | 累计平均损失: 0.5774
Epoch: 10/20 | Batch: 500/782 | 单Batch损失: 0.7159 | 累计平均损失: 0.5774
Epoch: 10/20 | Batch: 600/782 | 单Batch损失: 0.5720 | 累计平均损失: 0.5794
Epoch: 10/20 | Batch: 700/782 | 单Batch损失: 0.7295 | 累计平均损失: 0.5756
Epoch 10/20 完成 | 训练准确率: 79.68% | 测试准确率: 82.06%
Epoch: 11/20 | Batch: 100/782 | 单Batch损失: 0.6633 | 累计平均损失: 0.5518
Epoch: 11/20 | Batch: 200/782 | 单Batch损失: 0.6666 | 累计平均损失: 0.5541
Epoch: 11/20 | Batch: 300/782 | 单Batch损失: 0.3432 | 累计平均损失: 0.5528
Epoch: 11/20 | Batch: 400/782 | 单Batch损失: 0.6008 | 累计平均损失: 0.5499
Epoch: 11/20 | Batch: 500/782 | 单Batch损失: 0.8425 | 累计平均损失: 0.5591
Epoch: 11/20 | Batch: 600/782 | 单Batch损失: 0.5723 | 累计平均损失: 0.5601
Epoch: 11/20 | Batch: 700/782 | 单Batch损失: 0.5080 | 累计平均损失: 0.5559
Epoch 11/20 完成 | 训练准确率: 80.48% | 测试准确率: 82.02%
Epoch: 12/20 | Batch: 100/782 | 单Batch损失: 0.4334 | 累计平均损失: 0.5690
Epoch: 12/20 | Batch: 200/782 | 单Batch损失: 0.4173 | 累计平均损失: 0.5486
Epoch: 12/20 | Batch: 300/782 | 单Batch损失: 0.4506 | 累计平均损失: 0.5487
Epoch: 12/20 | Batch: 400/782 | 单Batch损失: 0.6125 | 累计平均损失: 0.5507
Epoch: 12/20 | Batch: 500/782 | 单Batch损失: 0.4057 | 累计平均损失: 0.5470
Epoch: 12/20 | Batch: 600/782 | 单Batch损失: 0.6385 | 累计平均损失: 0.5494
Epoch: 12/20 | Batch: 700/782 | 单Batch损失: 0.5861 | 累计平均损失: 0.5505
Epoch 12/20 完成 | 训练准确率: 80.72% | 测试准确率: 83.08%
Epoch: 13/20 | Batch: 100/782 | 单Batch损失: 0.7643 | 累计平均损失: 0.5124
Epoch: 13/20 | Batch: 200/782 | 单Batch损失: 0.5779 | 累计平均损失: 0.5191
Epoch: 13/20 | Batch: 300/782 | 单Batch损失: 0.5409 | 累计平均损失: 0.5222
Epoch: 13/20 | Batch: 400/782 | 单Batch损失: 0.4922 | 累计平均损失: 0.5257
Epoch: 13/20 | Batch: 500/782 | 单Batch损失: 0.6287 | 累计平均损失: 0.5243
Epoch: 13/20 | Batch: 600/782 | 单Batch损失: 0.4896 | 累计平均损失: 0.5247
Epoch: 13/20 | Batch: 700/782 | 单Batch损失: 0.3443 | 累计平均损失: 0.5226
Epoch 13/20 完成 | 训练准确率: 81.49% | 测试准确率: 82.47%
Epoch: 14/20 | Batch: 100/782 | 单Batch损失: 0.5201 | 累计平均损失: 0.5186
Epoch: 14/20 | Batch: 200/782 | 单Batch损失: 0.3799 | 累计平均损失: 0.5088
Epoch: 14/20 | Batch: 300/782 | 单Batch损失: 0.5359 | 累计平均损失: 0.5198
Epoch: 14/20 | Batch: 400/782 | 单Batch损失: 0.4176 | 累计平均损失: 0.5223
Epoch: 14/20 | Batch: 500/782 | 单Batch损失: 0.5129 | 累计平均损失: 0.5251
Epoch: 14/20 | Batch: 600/782 | 单Batch损失: 0.4319 | 累计平均损失: 0.5251
Epoch: 14/20 | Batch: 700/782 | 单Batch损失: 0.4897 | 累计平均损失: 0.5250
Epoch 14/20 完成 | 训练准确率: 81.63% | 测试准确率: 82.81%
Epoch: 15/20 | Batch: 100/782 | 单Batch损失: 0.4316 | 累计平均损失: 0.5007
Epoch: 15/20 | Batch: 200/782 | 单Batch损失: 0.5886 | 累计平均损失: 0.5024
Epoch: 15/20 | Batch: 300/782 | 单Batch损失: 0.5915 | 累计平均损失: 0.5116
Epoch: 15/20 | Batch: 400/782 | 单Batch损失: 0.6233 | 累计平均损失: 0.5145
Epoch: 15/20 | Batch: 500/782 | 单Batch损失: 0.4326 | 累计平均损失: 0.5115
Epoch: 15/20 | Batch: 600/782 | 单Batch损失: 0.5434 | 累计平均损失: 0.5093
Epoch: 15/20 | Batch: 700/782 | 单Batch损失: 0.4614 | 累计平均损失: 0.5092
Epoch 15/20 完成 | 训练准确率: 82.10% | 测试准确率: 82.63%
Epoch: 16/20 | Batch: 100/782 | 单Batch损失: 0.4750 | 累计平均损失: 0.4958
Epoch: 16/20 | Batch: 200/782 | 单Batch损失: 0.6557 | 累计平均损失: 0.5018
Epoch: 16/20 | Batch: 300/782 | 单Batch损失: 0.6435 | 累计平均损失: 0.5020
Epoch: 16/20 | Batch: 400/782 | 单Batch损失: 0.5078 | 累计平均损失: 0.4966
Epoch: 16/20 | Batch: 500/782 | 单Batch损失: 0.5369 | 累计平均损失: 0.4989
Epoch: 16/20 | Batch: 600/782 | 单Batch损失: 0.4544 | 累计平均损失: 0.5024
Epoch: 16/20 | Batch: 700/782 | 单Batch损失: 0.5159 | 累计平均损失: 0.5042
Epoch 16/20 完成 | 训练准确率: 82.20% | 测试准确率: 82.68%
Epoch: 17/20 | Batch: 100/782 | 单Batch损失: 0.6908 | 累计平均损失: 0.5076
Epoch: 17/20 | Batch: 200/782 | 单Batch损失: 0.4145 | 累计平均损失: 0.4972
Epoch: 17/20 | Batch: 300/782 | 单Batch损失: 0.4537 | 累计平均损失: 0.4999
Epoch: 17/20 | Batch: 400/782 | 单Batch损失: 0.4317 | 累计平均损失: 0.4952
Epoch: 17/20 | Batch: 500/782 | 单Batch损失: 0.6683 | 累计平均损失: 0.4945
Epoch: 17/20 | Batch: 600/782 | 单Batch损失: 0.6604 | 累计平均损失: 0.4967
Epoch: 17/20 | Batch: 700/782 | 单Batch损失: 0.3883 | 累计平均损失: 0.4941
Epoch 17/20 完成 | 训练准确率: 82.58% | 测试准确率: 82.96%
Epoch: 18/20 | Batch: 100/782 | 单Batch损失: 0.3227 | 累计平均损失: 0.4826
Epoch: 18/20 | Batch: 200/782 | 单Batch损失: 0.7680 | 累计平均损失: 0.4810
Epoch: 18/20 | Batch: 300/782 | 单Batch损失: 0.5058 | 累计平均损失: 0.4872
Epoch: 18/20 | Batch: 400/782 | 单Batch损失: 0.3086 | 累计平均损失: 0.4869
Epoch: 18/20 | Batch: 500/782 | 单Batch损失: 0.6193 | 累计平均损失: 0.4867
Epoch: 18/20 | Batch: 600/782 | 单Batch损失: 0.3597 | 累计平均损失: 0.4870
Epoch: 18/20 | Batch: 700/782 | 单Batch损失: 0.5449 | 累计平均损失: 0.4885
Epoch 18/20 完成 | 训练准确率: 82.84% | 测试准确率: 83.40%
Epoch: 19/20 | Batch: 100/782 | 单Batch损失: 0.5982 | 累计平均损失: 0.4632
Epoch: 19/20 | Batch: 200/782 | 单Batch损失: 0.3836 | 累计平均损失: 0.4728
Epoch: 19/20 | Batch: 300/782 | 单Batch损失: 0.3048 | 累计平均损失: 0.4715
Epoch: 19/20 | Batch: 400/782 | 单Batch损失: 0.6162 | 累计平均损失: 0.4662
Epoch: 19/20 | Batch: 500/782 | 单Batch损失: 0.4655 | 累计平均损失: 0.4684
Epoch: 19/20 | Batch: 600/782 | 单Batch损失: 0.5672 | 累计平均损失: 0.4718
Epoch: 19/20 | Batch: 700/782 | 单Batch损失: 0.5672 | 累计平均损失: 0.4723
Epoch 19/20 完成 | 训练准确率: 83.55% | 测试准确率: 83.49%
Epoch: 20/20 | Batch: 100/782 | 单Batch损失: 0.4989 | 累计平均损失: 0.4724
Epoch: 20/20 | Batch: 200/782 | 单Batch损失: 0.6199 | 累计平均损失: 0.4666
Epoch: 20/20 | Batch: 300/782 | 单Batch损失: 0.3568 | 累计平均损失: 0.4633
Epoch: 20/20 | Batch: 400/782 | 单Batch损失: 0.5342 | 累计平均损失: 0.4668
Epoch: 20/20 | Batch: 500/782 | 单Batch损失: 0.2849 | 累计平均损失: 0.4654
Epoch: 20/20 | Batch: 600/782 | 单Batch损失: 0.4448 | 累计平均损失: 0.4679
Epoch: 20/20 | Batch: 700/782 | 单Batch损失: 0.5371 | 累计平均损失: 0.4692
Epoch 20/20 完成 | 训练准确率: 83.54% | 测试准确率: 83.68%
训练完成!最终测试准确率: 83.68%