- 本文为365天深度学习训练营 中的学习记录博客
- 原作者:K同学啊 | 接辅导、项目定制
本文将采用pytorch框架创建CNN网络,实现运动鞋识别。讲述实现代码与执行结果,并浅谈涉及知识点。
关键字:torch动态学习率
import torch
import torch.nn as nn
from torchvision import transforms, datasets
import time
from pathlib import Path
from PIL import Image
from torchinfo import summary
import torch.nn.functional as F
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.rcParams['figure.dpi'] = 100 # 分辨率
import warnings
warnings.filterwarnings('ignore') # 忽略一些warning内容,无需打印
"""前期准备-设置GPU"""
# 如果设备上支持GPU就使用GPU,否则使用CPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print("Using {} device".format(device))
输出
Using cuda device
'''前期工作-导入数据'''
data_dir = r"D:\DeepLearning\data\monkeypox_recognition"
data_dir = Path(data_dir)
data_paths = list(data_dir.glob('./train/*'))
classeNames = [str(path).split("\\")[-1] for path in data_paths]
print(classeNames)
输出
['adidas', 'nike']
'''前期工作-可视化数据'''
subfolder = Path(data_dir)/"train"/"nike"
image_files = list(p.resolve() for p in subfolder.glob('*') if p.suffix in [".jpg", ".png", ".jpeg"])
plt.figure(figsize=(10, 6))
for i in range(len(image_files[:12])):
image_file = image_files[i]
ax = plt.subplot(3, 4, i + 1)
img = Image.open(str(image_file))
plt.imshow(img)
plt.axis("off")
# 显示图片
plt.tight_layout()
plt.show()
'''前期工作-图像数据变换'''
# 关于transforms.Compose的更多介绍可以参考:https://blog.csdn.net/qq_38251616/article/details/124878863
train_transforms = transforms.Compose([
transforms.Resize([224, 224]), # 将输入图片resize成统一尺寸
# transforms.RandomHorizontalFlip(), # 随机水平翻转
transforms.ToTensor(), # 将PIL Image或numpy.ndarray转换为tensor,并归一化到[0,1]之间
transforms.Normalize( # 标准化处理-->转换为标准正太分布(高斯分布),使模型更容易收敛
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]) # 其中 mean=[0.485,0.456,0.406]与std=[0.229,0.224,0.225] 从数据集中随机抽样计算得到的。
])
test_transform = transforms.Compose([
transforms.Resize([224, 224]), # 将输入图片resize成统一尺寸
transforms.ToTensor(), # 将PIL Image或numpy.ndarray转换为tensor,并归一化到[0,1]之间
transforms.Normalize( # 标准化处理-->转换为标准正太分布(高斯分布),使模型更容易收敛
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]) # 其中 mean=[0.485,0.456,0.406]与std=[0.229,0.224,0.225] 从数据集中随机抽样计算得到的。
])
train_dataset = datasets.ImageFolder(Path(data_dir)/"train", transform=train_transforms)
test_dataset = datasets.ImageFolder(Path(data_dir)/"test", transform=train_transforms)
print(train_dataset.class_to_idx)
输出
{'adidas': 0, 'nike': 1}
'''前期工作-加载数据'''
batch_size = 32
train_dl = torch.utils.data.DataLoader(train_dataset,
batch_size=batch_size,
shuffle=True,
num_workers=1)
test_dl = torch.utils.data.DataLoader(test_dataset,
batch_size=batch_size,
shuffle=True,
num_workers=1)
'''前期工作-查看数据'''
for X, y in test_dl:
print("Shape of X [N, C, H, W]: ", X.shape)
print("Shape of y: ", y.shape, y.dtype)
break
输出
Shape of X [N, C, H, W]: torch.Size([32, 3, 224, 224])
Shape of y: torch.Size([32]) torch.int64
"""构建CNN网络"""
class Network_bn(nn.Module):
def __init__(self):
super(Network_bn, self).__init__()
"""
nn.Conv2d()函数:
第一个参数(in_channels)是输入的channel数量
第二个参数(out_channels)是输出的channel数量
第三个参数(kernel_size)是卷积核大小
第四个参数(stride)是步长,默认为1
第五个参数(padding)是填充大小,默认为0
"""
self.conv1 = nn.Conv2d(in_channels=3, out_channels=12, kernel_size=5, stride=1, padding=0)
self.bn1 = nn.BatchNorm2d(12)
self.conv2 = nn.Conv2d(in_channels=12, out_channels=12, kernel_size=5, stride=1, padding=0)
self.bn2 = nn.BatchNorm2d(12)
self.pool = nn.MaxPool2d(2, 2)
self.conv4 = nn.Conv2d(in_channels=12, out_channels=24, kernel_size=5, stride=1, padding=0)
self.bn4 = nn.BatchNorm2d(24)
self.conv5 = nn.Conv2d(in_channels=24, out_channels=24, kernel_size=5, stride=1, padding=0)
self.bn5 = nn.BatchNorm2d(24)
self.fc1 = nn.Linear(24 * 50 * 50, len(classeNames))
def forward(self, x):
x = F.relu(self.bn1(self.conv1(x)))
x = F.relu(self.bn2(self.conv2(x)))
x = self.pool(x)
x = F.relu(self.bn4(self.conv4(x)))
x = F.relu(self.bn5(self.conv5(x)))
x = self.pool(x)
x = x.view(-1, 24 * 50 * 50)
x = self.fc1(x)
return x
model = Network_bn().to(device)
print(model)
输出
Network_bn(
(conv1): Conv2d(3, 12, kernel_size=(5, 5), stride=(1, 1))
(bn1): BatchNorm2d(12, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv2): Conv2d(12, 12, kernel_size=(5, 5), stride=(1, 1))
(bn2): BatchNorm2d(12, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(conv4): Conv2d(12, 24, kernel_size=(5, 5), stride=(1, 1))
(bn4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv5): Conv2d(24, 24, kernel_size=(5, 5), stride=(1, 1))
(bn5): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(fc1): Linear(in_features=60000, out_features=2, bias=True)
)
"""训练模型--设置超参数"""
loss_fn = nn.CrossEntropyLoss() # 创建损失函数,计算实际输出和真实相差多少,交叉熵损失函数,事实上,它就是做图片分类任务时常用的损失函数
learn_rate = 1e-4 # 学习率
optimizer1 = torch.optim.SGD(model.parameters(), lr=learn_rate)# 作用是定义优化器,用来训练时候优化模型参数;其中,SGD表示随机梯度下降,用于控制实际输出y与真实y之间的相差有多大
optimizer2 = torch.optim.Adam(model.parameters(), lr=learn_rate)
#测试集acc 84.2%
lr_opt = optimizer1
model_opt = optimizer1
"""训练模型--编写训练函数"""
# 训练循环
def train(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset) # 训练集的大小,一共60000张图片
num_batches = len(dataloader) # 批次数目,1875(60000/32)
train_loss, train_acc = 0, 0 # 初始化训练损失和正确率
for X, y in dataloader: # 加载数据加载器,得到里面的 X(图片数据)和 y(真实标签)
X, y = X.to(device), y.to(device) # 用于将数据存到显卡
# 计算预测误差
pred = model(X) # 网络输出
loss = loss_fn(pred, y) # 计算网络输出和真实值之间的差距,targets为真实值,计算二者差值即为损失
# 反向传播
optimizer.zero_grad() # 清空过往梯度
loss.backward() # 反向传播,计算当前梯度
optimizer.step() # 根据梯度更新网络参数
# 记录acc与loss
train_acc += (pred.argmax(1) == y).type(torch.float).sum().item()
train_loss += loss.item()
train_acc /= size
train_loss /= num_batches
return train_acc, train_loss
"""训练模型--编写测试函数"""
# 测试函数和训练函数大致相同,但是由于不进行梯度下降对网络权重进行更新,所以不需要传入优化器
def test(dataloader, model, loss_fn):
size = len(dataloader.dataset) # 测试集的大小,一共10000张图片
num_batches = len(dataloader) # 批次数目,313(10000/32=312.5,向上取整)
test_loss, test_acc = 0, 0
# 当不进行训练时,停止梯度更新,节省计算内存消耗
with torch.no_grad(): # 测试时模型参数不用更新,所以 no_grad,整个模型参数正向推就ok,不反向更新参数
for imgs, target in dataloader:
imgs, target = imgs.to(device), target.to(device)
# 计算loss
target_pred = model(imgs)
loss = loss_fn(target_pred, target)
test_loss += loss.item()
test_acc += (target_pred.argmax(1) == target).type(torch.float).sum().item()#统计预测正确的个数
test_acc /= size
test_loss /= num_batches
return test_acc, test_loss
"""训练模型--正式训练"""
epochs = 40
train_loss = []
train_acc = []
test_loss = []
test_acc = []
best_test_acc=0
PATH = './model.pth' # 保存的参数文件名
for epoch in range(epochs):
milliseconds_t1 = int(time.time() * 1000)
# 更新学习率(使用自定义学习率时使用)
adjust_learning_rate(lr_opt, epoch, learn_rate)
model.train()
epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, model_opt)
# scheduler.step() # 更新学习率(调用官方动态学习率接口时使用)
model.eval()
epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)
train_acc.append(epoch_train_acc)
train_loss.append(epoch_train_loss)
test_acc.append(epoch_test_acc)
test_loss.append(epoch_test_loss)
# 获取当前的学习率
lr = lr_opt.state_dict()['param_groups'][0]['lr']
milliseconds_t2 = int(time.time() * 1000)
template = ('Epoch:{:2d}, duration:{}ms, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%,Test_loss:{:.3f}, Lr:{:.2E}')
if best_test_acc < epoch_test_acc:
best_test_acc = epoch_test_acc
# 模型保存
torch.save(model.state_dict(), PATH)
template = (
'Epoch:{:2d}, duration:{}ms, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%,Test_loss:{:.3f}, Lr:{:.2E},save model.pth')
print(
template.format(epoch + 1, milliseconds_t2-milliseconds_t1, epoch_train_acc * 100, epoch_train_loss, epoch_test_acc * 100, epoch_test_loss, lr))
print('Done')
输出
Epoch: 1, duration:5323ms, Train_acc:52.2%, Train_loss:0.745, Test_acc:50.0%,Test_loss:0.700, Lr:1.00E-04,save model.pth
Epoch: 2, duration:3125ms, Train_acc:62.9%, Train_loss:0.651, Test_acc:57.9%,Test_loss:0.667, Lr:1.00E-04,save model.pth
Epoch: 3, duration:3130ms, Train_acc:66.9%, Train_loss:0.614, Test_acc:67.1%,Test_loss:0.584, Lr:9.20E-05,save model.pth
Epoch: 4, duration:3136ms, Train_acc:70.5%, Train_loss:0.567, Test_acc:72.4%,Test_loss:0.568, Lr:9.20E-05,save model.pth
Epoch: 5, duration:3346ms, Train_acc:76.1%, Train_loss:0.531, Test_acc:72.4%,Test_loss:0.537, Lr:8.46E-05
Epoch: 6, duration:3087ms, Train_acc:77.5%, Train_loss:0.510, Test_acc:72.4%,Test_loss:0.531, Lr:8.46E-05
Epoch: 7, duration:3215ms, Train_acc:77.7%, Train_loss:0.492, Test_acc:78.9%,Test_loss:0.511, Lr:7.79E-05,save model.pth
Epoch: 8, duration:3520ms, Train_acc:82.3%, Train_loss:0.467, Test_acc:77.6%,Test_loss:0.504, Lr:7.79E-05
Epoch: 9, duration:3662ms, Train_acc:83.1%, Train_loss:0.442, Test_acc:81.6%,Test_loss:0.494, Lr:7.16E-05,save model.pth
Epoch:10, duration:3410ms, Train_acc:85.7%, Train_loss:0.427, Test_acc:80.3%,Test_loss:0.464, Lr:7.16E-05
Epoch:11, duration:3486ms, Train_acc:86.3%, Train_loss:0.413, Test_acc:81.6%,Test_loss:0.469, Lr:6.59E-05
Epoch:12, duration:3356ms, Train_acc:87.6%, Train_loss:0.394, Test_acc:78.9%,Test_loss:0.452, Lr:6.59E-05
Epoch:13, duration:3453ms, Train_acc:87.6%, Train_loss:0.391, Test_acc:81.6%,Test_loss:0.494, Lr:6.06E-05
Epoch:14, duration:3226ms, Train_acc:87.8%, Train_loss:0.385, Test_acc:80.3%,Test_loss:0.450, Lr:6.06E-05
Epoch:15, duration:3290ms, Train_acc:89.0%, Train_loss:0.368, Test_acc:82.9%,Test_loss:0.486, Lr:5.58E-05,save model.pth
Epoch:16, duration:3247ms, Train_acc:90.4%, Train_loss:0.359, Test_acc:81.6%,Test_loss:0.443, Lr:5.58E-05
Epoch:17, duration:3195ms, Train_acc:90.6%, Train_loss:0.358, Test_acc:81.6%,Test_loss:0.452, Lr:5.13E-05
Epoch:18, duration:3294ms, Train_acc:90.6%, Train_loss:0.342, Test_acc:82.9%,Test_loss:0.436, Lr:5.13E-05
Epoch:19, duration:3305ms, Train_acc:91.2%, Train_loss:0.338, Test_acc:81.6%,Test_loss:0.452, Lr:4.72E-05
Epoch:20, duration:3241ms, Train_acc:91.8%, Train_loss:0.332, Test_acc:81.6%,Test_loss:0.418, Lr:4.72E-05
Epoch:21, duration:3371ms, Train_acc:93.0%, Train_loss:0.320, Test_acc:81.6%,Test_loss:0.459, Lr:4.34E-05
Epoch:22, duration:3279ms, Train_acc:92.8%, Train_loss:0.317, Test_acc:81.6%,Test_loss:0.475, Lr:4.34E-05
Epoch:23, duration:3279ms, Train_acc:93.4%, Train_loss:0.310, Test_acc:82.9%,Test_loss:0.438, Lr:4.00E-05
Epoch:24, duration:3225ms, Train_acc:93.0%, Train_loss:0.313, Test_acc:81.6%,Test_loss:0.437, Lr:4.00E-05
Epoch:25, duration:3293ms, Train_acc:94.0%, Train_loss:0.304, Test_acc:81.6%,Test_loss:0.439, Lr:3.68E-05
Epoch:26, duration:3273ms, Train_acc:94.0%, Train_loss:0.297, Test_acc:81.6%,Test_loss:0.414, Lr:3.68E-05
Epoch:27, duration:3249ms, Train_acc:94.2%, Train_loss:0.296, Test_acc:80.3%,Test_loss:0.413, Lr:3.38E-05
Epoch:28, duration:3266ms, Train_acc:94.8%, Train_loss:0.288, Test_acc:84.2%,Test_loss:0.425, Lr:3.38E-05,save model.pth
Epoch:29, duration:3248ms, Train_acc:94.4%, Train_loss:0.288, Test_acc:81.6%,Test_loss:0.400, Lr:3.11E-05
Epoch:30, duration:3243ms, Train_acc:94.6%, Train_loss:0.291, Test_acc:81.6%,Test_loss:0.445, Lr:3.11E-05
Epoch:31, duration:3250ms, Train_acc:96.4%, Train_loss:0.278, Test_acc:81.6%,Test_loss:0.465, Lr:2.86E-05
Epoch:32, duration:3193ms, Train_acc:95.2%, Train_loss:0.275, Test_acc:81.6%,Test_loss:0.438, Lr:2.86E-05
Epoch:33, duration:3283ms, Train_acc:95.2%, Train_loss:0.270, Test_acc:81.6%,Test_loss:0.402, Lr:2.63E-05
Epoch:34, duration:3542ms, Train_acc:94.8%, Train_loss:0.280, Test_acc:81.6%,Test_loss:0.407, Lr:2.63E-05
Epoch:35, duration:3592ms, Train_acc:95.8%, Train_loss:0.269, Test_acc:81.6%,Test_loss:0.442, Lr:2.42E-05
Epoch:36, duration:3592ms, Train_acc:95.4%, Train_loss:0.267, Test_acc:80.3%,Test_loss:0.413, Lr:2.42E-05
Epoch:37, duration:3588ms, Train_acc:95.0%, Train_loss:0.265, Test_acc:81.6%,Test_loss:0.432, Lr:2.23E-05
Epoch:38, duration:3736ms, Train_acc:95.0%, Train_loss:0.267, Test_acc:81.6%,Test_loss:0.438, Lr:2.23E-05
Epoch:39, duration:3431ms, Train_acc:95.2%, Train_loss:0.265, Test_acc:82.9%,Test_loss:0.400, Lr:2.05E-05
Epoch:40, duration:3417ms, Train_acc:95.8%, Train_loss:0.270, Test_acc:81.6%,Test_loss:0.379, Lr:2.05E-05
Done
"""训练模型--结果可视化"""
epochs_range = range(epochs)
plt.figure(figsize=(12, 3))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, train_acc, label='Training Accuracy')
plt.plot(epochs_range, test_acc, label='Test Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1, 2, 2)
plt.plot(epochs_range, train_loss, label='Training Loss')
plt.plot(epochs_range, test_loss, label='Test Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
def predict_one_image(image_path, model, transform, classes):
test_img = Image.open(image_path).convert('RGB')
plt.imshow(test_img) # 展示预测的图片
plt.show()
test_img = transform(test_img)
img = test_img.to(device).unsqueeze(0)
model.eval()
output = model(img)
_, pred = torch.max(output, 1)
pred_class = classes[pred]
print(f'预测结果是:{pred_class}')
"""指定图片进行预测"""
classes = list(total_data.class_to_idx)
# 预测训练集中的某张照片
predict_one_image(image_path=str(Path(data_dir)/"test/adidas/1.jpg"),
model=model,
transform=train_transforms,
classes=classes)
如果使用效果最好的模型,就先加载保存好的模型,再调用预测代码
# 将参数加载到model当中
model.load_state_dict(torch.load(PATH, map_location=device))
输出
预测结果是:adidas
"""保存并加载模型"""
# 模型保存
PATH = './model.pth' # 保存的参数文件名
torch.save(model.state_dict(), PATH)
# 将参数加载到model当中
model.load_state_dict(torch.load(PATH, map_location=device))
函数原型:
torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)
关键参数详解:
用法示例:
optimizer = torch.optim.SGD(net.parameters(), lr=0.001 )
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)
根据自己定义的函数更新学习率。
函数原型:
torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1, verbose=False)
关键参数详解:
lambda1 = lambda epoch: (0.92 ** (epoch // 2) # 第二组参数的调整方法
optimizer = torch.optim.SGD(model.parameters(), lr=learn_rate)
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda1) #选定调整方法
在特定的 epoch 中调整学习率
函数原型:
torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1, verbose=False)
关键参数详解:
optimizer = torch.optim.SGD(net.parameters(), lr=0.001 )
scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer,
milestones=[2,6,15], #调整学习率的epoch数
gamma=0.1)
更多的官方动态学习率设置方式可参考:https://pytorch.org/docs/stable/optim.html
调用官方接口示例:
model = [Parameter(torch.randn(2, 2, requires_grad=True))]
optimizer = SGD(model, 0.1)
scheduler = ExponentialLR(optimizer, gamma=0.9)
for epoch in range(20):
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
scheduler.step()
尝试变更dropout失活比例为0.5,测试集acc提升至86.8%,实际上也不能确定是因为变更比例导致的效果提升,因为每次运行效果都有不同,有好有坏。
Epoch: 1, duration:4820ms, Train_acc:53.6%, Train_loss:1.133, Test_acc:52.6%,Test_loss:0.712, Lr:1.00E-04,save model.pth
Epoch: 2, duration:3271ms, Train_acc:73.5%, Train_loss:0.547, Test_acc:59.2%,Test_loss:0.697, Lr:1.00E-04,save model.pth
Epoch: 3, duration:3566ms, Train_acc:81.5%, Train_loss:0.396, Test_acc:77.6%,Test_loss:0.485, Lr:9.20E-05,save model.pth
Epoch: 4, duration:3309ms, Train_acc:89.4%, Train_loss:0.287, Test_acc:77.6%,Test_loss:0.470, Lr:9.20E-05
Epoch: 5, duration:3411ms, Train_acc:94.2%, Train_loss:0.219, Test_acc:82.9%,Test_loss:0.418, Lr:8.46E-05,save model.pth
Epoch: 6, duration:3239ms, Train_acc:98.2%, Train_loss:0.172, Test_acc:81.6%,Test_loss:0.385, Lr:8.46E-05
Epoch: 7, duration:3282ms, Train_acc:98.8%, Train_loss:0.127, Test_acc:85.5%,Test_loss:0.374, Lr:7.79E-05,save model.pth
Epoch: 8, duration:3277ms, Train_acc:99.2%, Train_loss:0.115, Test_acc:82.9%,Test_loss:0.332, Lr:7.79E-05
Epoch: 9, duration:3440ms, Train_acc:99.6%, Train_loss:0.091, Test_acc:86.8%,Test_loss:0.356, Lr:7.16E-05,save model.pth
Epoch:10, duration:3570ms, Train_acc:100.0%, Train_loss:0.078, Test_acc:81.6%,Test_loss:0.411, Lr:7.16E-05
Epoch:11, duration:3418ms, Train_acc:99.6%, Train_loss:0.072, Test_acc:84.2%,Test_loss:0.370, Lr:6.59E-05
Epoch:12, duration:3291ms, Train_acc:100.0%, Train_loss:0.064, Test_acc:85.5%,Test_loss:0.339, Lr:6.59E-05
Epoch:13, duration:3273ms, Train_acc:100.0%, Train_loss:0.054, Test_acc:85.5%,Test_loss:0.321, Lr:6.06E-05
Epoch:14, duration:3365ms, Train_acc:100.0%, Train_loss:0.049, Test_acc:85.5%,Test_loss:0.336, Lr:6.06E-05
Epoch:15, duration:3321ms, Train_acc:100.0%, Train_loss:0.046, Test_acc:84.2%,Test_loss:0.311, Lr:5.58E-05
Epoch:16, duration:3273ms, Train_acc:100.0%, Train_loss:0.041, Test_acc:84.2%,Test_loss:0.336, Lr:5.58E-05
Epoch:17, duration:3315ms, Train_acc:100.0%, Train_loss:0.038, Test_acc:85.5%,Test_loss:0.350, Lr:5.13E-05
Epoch:18, duration:3380ms, Train_acc:100.0%, Train_loss:0.034, Test_acc:82.9%,Test_loss:0.314, Lr:5.13E-05
Epoch:19, duration:3275ms, Train_acc:100.0%, Train_loss:0.034, Test_acc:84.2%,Test_loss:0.378, Lr:4.72E-05
Epoch:20, duration:3264ms, Train_acc:100.0%, Train_loss:0.031, Test_acc:82.9%,Test_loss:0.342, Lr:4.72E-05
Epoch:21, duration:3267ms, Train_acc:100.0%, Train_loss:0.029, Test_acc:84.2%,Test_loss:0.299, Lr:4.34E-05
Epoch:22, duration:3243ms, Train_acc:100.0%, Train_loss:0.028, Test_acc:84.2%,Test_loss:0.320, Lr:4.34E-05
Epoch:23, duration:3319ms, Train_acc:100.0%, Train_loss:0.025, Test_acc:82.9%,Test_loss:0.335, Lr:4.00E-05
Epoch:24, duration:3230ms, Train_acc:100.0%, Train_loss:0.025, Test_acc:84.2%,Test_loss:0.351, Lr:4.00E-05
Epoch:25, duration:3251ms, Train_acc:100.0%, Train_loss:0.025, Test_acc:84.2%,Test_loss:0.329, Lr:3.68E-05
Epoch:26, duration:3275ms, Train_acc:100.0%, Train_loss:0.023, Test_acc:84.2%,Test_loss:0.304, Lr:3.68E-05
Epoch:27, duration:3244ms, Train_acc:100.0%, Train_loss:0.022, Test_acc:82.9%,Test_loss:0.324, Lr:3.38E-05
Epoch:28, duration:3319ms, Train_acc:100.0%, Train_loss:0.022, Test_acc:85.5%,Test_loss:0.308, Lr:3.38E-05
Epoch:29, duration:3287ms, Train_acc:100.0%, Train_loss:0.020, Test_acc:85.5%,Test_loss:0.353, Lr:3.11E-05
Epoch:30, duration:3230ms, Train_acc:100.0%, Train_loss:0.019, Test_acc:85.5%,Test_loss:0.346, Lr:3.11E-05
Epoch:31, duration:3285ms, Train_acc:100.0%, Train_loss:0.019, Test_acc:85.5%,Test_loss:0.335, Lr:2.86E-05
Epoch:32, duration:3255ms, Train_acc:100.0%, Train_loss:0.019, Test_acc:85.5%,Test_loss:0.337, Lr:2.86E-05
Epoch:33, duration:3307ms, Train_acc:100.0%, Train_loss:0.018, Test_acc:85.5%,Test_loss:0.334, Lr:2.63E-05
Epoch:34, duration:3281ms, Train_acc:100.0%, Train_loss:0.017, Test_acc:85.5%,Test_loss:0.323, Lr:2.63E-05
Epoch:35, duration:3249ms, Train_acc:100.0%, Train_loss:0.016, Test_acc:85.5%,Test_loss:0.314, Lr:2.42E-05
Epoch:36, duration:3287ms, Train_acc:100.0%, Train_loss:0.017, Test_acc:84.2%,Test_loss:0.368, Lr:2.42E-05
Epoch:37, duration:3337ms, Train_acc:100.0%, Train_loss:0.016, Test_acc:85.5%,Test_loss:0.328, Lr:2.23E-05
Epoch:38, duration:3367ms, Train_acc:100.0%, Train_loss:0.016, Test_acc:84.2%,Test_loss:0.375, Lr:2.23E-05
Epoch:39, duration:3244ms, Train_acc:100.0%, Train_loss:0.015, Test_acc:84.2%,Test_loss:0.329, Lr:2.05E-05
Epoch:40, duration:3277ms, Train_acc:100.0%, Train_loss:0.015, Test_acc:85.5%,Test_loss:0.295, Lr:2.05E-05
尝试变更学习率优化器及模型优化器为(SGD和Adam的四种组合),测试集acc几乎无变化
尝试变更初始学习率,尝试变更学习率不动态更新,测试集acc无提升
通过本文学习到几种动态学习率的设置与调用,要想得到一个比较好的模型效果,对模型相关参数进行不同的尝试,获取一个相对适配该案例的参数。