深度学习每周学习总结R5(LSTM-实现糖尿病探索与预测-模型优化)
- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客R7中的内容,为了便于自己整理总结起名为R5
- 🍖 原作者:K同学啊 | 接辅导、项目定制
目录
- 0. 总结
- 优化细节(目前只采用了1、2两种方式)
- 1. L2 正则化(权重衰减)
- 2. Dropout
- 3. Early Stopping(早停)
- 4. Batch Normalization
- 总结
- 其他可行的方法(待测试)
- 1. LSTM介绍
- LSTM的基本组成部分
- 如何理解与应用LSTM
- 2. 数据预处理
- 3. 数据集构建
- 4. 定义模型
- 5. 初始化模型及优化器
- 6. 训练函数
- 7. 测试函数
- 8. 训练过程
- 9. 模型评估
0. 总结
数据导入及处理部分:在 PyTorch 中,我们通常先将 NumPy 数组转换为 torch.Tensor,再封装到 TensorDataset 或自定义的 Dataset 里,然后用 DataLoader 按批次加载。
模型构建部分:LSTM
设置超参数:在这之前需要定义损失函数,学习率(动态学习率),以及根据学习率定义优化器(例如SGD随机梯度下降),用来在训练中更新参数,最小化损失函数。
定义训练函数:函数的传入的参数有四个,分别是设置好的DataLoader(),定义好的模型,损失函数,优化器。函数内部初始化损失准确率为0,接着开始循环,使用DataLoader()获取一个批次的数据,对这个批次的数据带入模型得到预测值,然后使用损失函数计算得到损失值。接下来就是进行反向传播以及使用优化器优化参数,梯度清零放在反向传播之前或者是使用优化器优化之后都是可以的,一般是默认放在反向传播之前。
定义测试函数:函数传入的参数相比训练函数少了优化器,只需传入设置好的DataLoader(),定义好的模型,损失函数。此外除了处理批次数据时无需再设置梯度清零、返向传播以及优化器优化参数,其余部分均和训练函数保持一致。
训练过程:定义训练次数,有几次就使用整个数据集进行几次训练,初始化四个空list分别存储每次训练及测试的准确率及损失。使用model.train()开启训练模式,调用训练函数得到准确率及损失。使用model.eval()将模型设置为评估模式,调用测试函数得到准确率及损失。接着就是将得到的训练及测试的准确率及损失存储到相应list中并合并打印出来,得到每一次整体训练后的准确率及损失。
结果可视化
模型的保存,调取及使用。在PyTorch中,通常使用 torch.save(model.state_dict(), ‘model.pth’) 保存模型的参数,使用 model.load_state_dict(torch.load(‘model.pth’)) 加载参数。
需要改进优化的地方:确保模型和数据的一致性,都存到GPU或者CPU;注意numclasses不要直接用默认的1000,需要根据实际数据集改进;实例化模型也要注意numclasses这个参数;此外注意测试模型需要用(3,224,224)3表示通道数,这和tensorflow定义的顺序是不用的(224,224,3),做代码转换时需要注意。
关于优化:
目前的尝试: 采用了L2正则化及dropout 测试集准确率目前可以达到 78%
优化细节(目前只采用了1、2两种方式)
1. L2 正则化(权重衰减)
在 Adam
优化器中添加 weight_decay
参数,这相当于在损失函数中添加了L2正则化项。L2正则化有助于限制模型的权重过大,从而减少过拟合。
你只需要在优化器的定义中添加 weight_decay
参数:
optimizer = torch.optim.Adam(model.parameters(), lr=learn_rate, weight_decay=1e-4)
其中 1e-4
是L2正则化的强度,你可以根据需要调整这个值。一般来说,较小的值(如1e-5到1e-4)就可以起到一定的正则化作用。
2. Dropout
Dropout 是一种非常有效的正则化技术,通过随机丢弃神经网络中的一部分神经元,减少模型的复杂度。你可以在LSTM层和全连接层之间加入 Dropout
层。
在你的 model_lstm
类中,可以在每个LSTM层后加入 Dropout
层。例如,在forward
函数中插入Dropout操作:
class model_lstm(nn.Module):
def __init__(self):
super(model_lstm, self).__init__()
self.lstm0 = nn.LSTM(input_size=13, hidden_size=200,
num_layers=1, batch_first=True)
self.lstm1 = nn.LSTM(input_size=200, hidden_size=200,
num_layers=1, batch_first=True)
self.dropout = nn.Dropout(0.5) # 设置Dropout比率为0.5
self.fc0 = nn.Linear(200, 2)
def forward(self, x):
out, hidden1 = self.lstm0(x)
out, _ = self.lstm1(out, hidden1)
out = self.dropout(out) # 在LSTM后加Dropout
out = self.fc0(out)
return out
这里,0.5
表示每次训练时会随机丢弃50%的神经元。你可以调整这个比例,通常0.3到0.5是常见的选择。
3. Early Stopping(早停)
你可以在训练过程中监控验证集准确率,若验证集的准确率在若干个epoch内没有提升,可以提前停止训练。这可以避免模型在训练集上过拟合,减少不必要的训练。
# 假设best_acc为最优验证集准确率,patience为耐心值,即允许多少个epoch验证集准确率不提升
patience = 5
trigger_times = 0
best_acc = 0.0
for epoch in range(epochs):
model.train()
epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, optimizer)
model.eval()
epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)
# 如果验证集准确率没有提升,增加trigger_times
if epoch_test_acc > best_acc:
best_acc = epoch_test_acc
trigger_times = 0
else:
trigger_times += 1
if trigger_times >= patience:
print(f"Early stopping at epoch {epoch + 1}")
break
4. Batch Normalization
BatchNormalization
是另一种正则化技术,通过对每一层的输出进行标准化来加速训练并减少过拟合。对于LSTM等循环神经网络模型,BatchNormalization的使用可能不是很直接,通常建议在全连接层或卷积层后使用。如果要在LSTM中使用,可以尝试在LSTM之后添加BatchNormalization层:
class model_lstm(nn.Module):
def __init__(self):
super(model_lstm, self).__init__()
self.lstm0 = nn.LSTM(input_size=13, hidden_size=200,
num_layers=1, batch_first=True)
self.lstm1 = nn.LSTM(input_size=200, hidden_size=200,
num_layers=1, batch_first=True)
self.bn = nn.BatchNorm1d(200) # BatchNorm层
self.fc0 = nn.Linear(200, 2)
def forward(self, x):
out, hidden1 = self.lstm0(x)
out, _ = self.lstm1(out, hidden1)
out = self.bn(out[:, -1, :]) # 对LSTM的输出进行Batch Normalization
out = self.fc0(out)
return out
总结
你可以根据需求选择一种或多种正则化方法:
- 在优化器中添加L2正则化(
weight_decay
)。 - 在LSTM后加入Dropout层。
- 采用Early Stopping技术来避免过拟合。
- 如果适用的话,考虑Batch Normalization。
你可以根据实验结果逐步调整这些方法,看看哪种最适合你的数据和任务。
其他可行的方法(待测试)
进一步调整学习率
网络机构调整
增加训练集数据等
1. LSTM介绍
LSTM(Long Short-Term Memory)是一种特殊类型的循环神经网络(RNN),主要用于处理和预测基于时间序列的数据。它解决了传统RNN在处理长时间依赖问题时的局限性,比如“梯度消失”问题。
LSTM的基本组成部分
LSTM通过“记忆单元”来决定哪些信息需要记住,哪些需要遗忘。它的核心是一个“门控”机制,主要有三个“门”:
- 遗忘门(Forget Gate):决定上一时刻的状态需要遗忘多少。
- 输入门(Input Gate):决定当前输入信息中有多少被存储到“记忆单元”。
- 输出门(Output Gate):决定“记忆单元”中的信息有多少会传递到下一时刻的状态。
如何理解与应用LSTM
-
理解LSTM的优势:LSTM能捕捉长时间序列中的依赖关系,适合处理那些长序列的数据,如文本、语音、金融数据等。相比于传统的RNN,LSTM能够有效解决“梯度消失”问题,使得模型能够学习长期的依赖关系。
-
应用场景:LSTM广泛应用于自然语言处理(如文本生成、机器翻译、情感分析)、语音识别、时间序列预测(如股市预测)等领域。
-
如何使用LSTM:在初学者阶段,可以从以下几个步骤入手:
- 数据预处理:将数据转换成适合时间序列建模的格式,比如文本序列或连续的时间戳数据。
- 选择框架:使用像TensorFlow或PyTorch这样的深度学习框架来实现LSTM。你可以从简单的LSTM网络开始,逐渐增加网络复杂性。
- 调试与优化:调整LSTM的超参数(如隐藏单元数、学习率、批量大小等)来提升模型性能。
你可以从一个简单的文本生成模型或者时间序列预测模型开始,逐步理解LSTM的细节和优势。
import torch.nn as nn
import torch.nn.functional as F
import torchvision,torch
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
plt.rcParams['savefig.dpi'] = 500 #图片像素
plt.rcParams['figure.dpi'] = 500 #分辨率
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
import warnings
warnings.filterwarnings("ignore")
# 设置硬件设备,如果有GPU则使用,没有则使用cpu
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
device
device(type='cuda')
2. 数据预处理
DataFrame=pd.read_excel('./data/dia.xlsx')
DataFrame.head()
卡号 | 性别 | 年龄 | 高密度脂蛋白胆固醇 | 低密度脂蛋白胆固醇 | 极低密度脂蛋白胆固醇 | 甘油三酯 | 总胆固醇 | 脉搏 | 舒张压 | 高血压史 | 尿素氮 | 尿酸 | 肌酐 | 体重检查结果 | 是否糖尿病 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 18054421 | 0 | 38 | 1.25 | 2.99 | 1.07 | 0.64 | 5.31 | 83 | 83 | 0 | 4.99 | 243.3 | 50 | 1 | 0 |
1 | 18054422 | 0 | 31 | 1.15 | 1.99 | 0.84 | 0.50 | 3.98 | 85 | 63 | 0 | 4.72 | 391.0 | 47 | 1 | 0 |
2 | 18054423 | 0 | 27 | 1.29 | 2.21 | 0.69 | 0.60 | 4.19 | 73 | 61 | 0 | 5.87 | 325.7 | 51 | 1 | 0 |
3 | 18054424 | 0 | 33 | 0.93 | 2.01 | 0.66 | 0.84 | 3.60 | 83 | 60 | 0 | 2.40 | 203.2 | 40 | 2 | 0 |
4 | 18054425 | 0 | 36 | 1.17 | 2.83 | 0.83 | 0.73 | 4.83 | 85 | 67 | 0 | 4.09 | 236.8 | 43 | 0 | 0 |
# 查看数据是否有缺失值
print('数据缺失值---------------------------------')
print(DataFrame.isnull().sum())
数据缺失值---------------------------------
卡号 0
性别 0
年龄 0
高密度脂蛋白胆固醇 0
低密度脂蛋白胆固醇 0
极低密度脂蛋白胆固醇 0
甘油三酯 0
总胆固醇 0
脉搏 0
舒张压 0
高血压史 0
尿素氮 0
尿酸 0
肌酐 0
体重检查结果 0
是否糖尿病 0
dtype: int64
# 数据分布分析
feature_map = {
'年龄': '年龄',
'高密度脂蛋白胆固醇': '高密度脂蛋白胆固醇',
'低密度脂蛋白胆固醇': '低密度脂蛋白胆固醇',
'极低密度脂蛋白胆固醇': '极低密度脂蛋白胆固醇',
'甘油三酯': '甘油三酯',
'总胆固醇': '总胆固醇',
'脉搏': '脉搏',
'舒张压':'舒张压',
'高血压史':'高血压史',
'尿素氮':'尿素氮',
'尿酸':'尿酸',
'肌酐':'肌酐',
'体重检查结果':'体重检查结果'
}
plt.figure(figsize=(15, 10))
for i, (col, col_name) in enumerate(feature_map.items(), 1):
plt.subplot(3, 5, i)
sns.boxplot(x=DataFrame['是否糖尿病'], y=DataFrame[col])
plt.title(f'{col_name}的箱线图', fontsize=14)
plt.ylabel('数值', fontsize=12)
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
在这里插入图片描述
# # 相关性分析
# import plotly
# import plotly.express as px
# # 删除列 '卡号'
# DataFrame.drop(columns=['卡号'], inplace=True)
# # 计算各列之间的相关系数
# df_corr = DataFrame.corr()
# # 相关矩阵生成函数
# def corr_generate(df):
# fig = px.imshow(df,text_auto=True,aspect="auto",color_continuous_scale='RdBu_r')
# fig.show()
# # 生成相关矩阵
# corr_generate(df_corr)
3. 数据集构建
from sklearn.preprocessing import StandardScaler
# '高密度脂蛋白胆固醇'字段与糖尿病负相关,故而在 X 中去掉该字段
X = DataFrame.drop(['是否糖尿病','高密度脂蛋白胆固醇'],axis=1)
y = DataFrame['是否糖尿病']
sc_X = StandardScaler()
X = sc_X.fit_transform(X)
X = torch.tensor(np.array(X), dtype=torch.float32)
y = torch.tensor(np.array(y), dtype=torch.int64)
train_X, test_X, train_y, test_y = train_test_split(X, y,
test_size=0.2,
random_state=1)
train_X.shape, train_y.shape
(torch.Size([804, 13]), torch.Size([804]))
from torch.utils.data import TensorDataset, DataLoader
train_dl = DataLoader(TensorDataset(train_X, train_y),
batch_size=64,
shuffle=False)
test_dl = DataLoader(TensorDataset(test_X, test_y),
batch_size=64,
shuffle=False)
4. 定义模型
class model_lstm(nn.Module):
def __init__(self):
super(model_lstm, self).__init__()
self.lstm0 = nn.LSTM(input_size=13 ,hidden_size=200,
num_layers=1, batch_first=True)
self.lstm1 = nn.LSTM(input_size=200 ,hidden_size=200,
num_layers=1, batch_first=True)
self.dropout = nn.Dropout(0.5) # 尝试设置Dropout比率为0.5;0.5 表示每次训练时会随机丢弃50%的神经元。你可以调整这个比例,通常0.3到0.5是常见的选择。
self.fc0 = nn.Linear(200, 2)
def forward(self, x):
out, hidden1 = self.lstm0(x)
out, _ = self.lstm1(out, hidden1)
out = self.dropout(out) # 尝试在LSTM后加Dropout
out = self.fc0(out)
return out
5. 初始化模型及优化器
model = model_lstm().to(device)
print(model)
loss_fn = nn.CrossEntropyLoss() # 创建损失函数
weight_decay = 1e-4 # 尝试加入权重衰减;一般来说,较小的值(如1e-5到1e-4)就可以起到一定的正则化作用。
# weight_decay = 1e-3
learn_rate = 1e-3 # 学习率
# learn_rate = 3e-4 # 学习率
lambda1 = lambda epoch:(0.92**(epoch//2))
optimizer = torch.optim.Adam(model.parameters(),lr = learn_rate, weight_decay = 1e-4)
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer,lr_lambda=lambda1) # 选定调整方法
epochs = 50
model_lstm(
(lstm0): LSTM(13, 200, batch_first=True)
(lstm1): LSTM(200, 200, batch_first=True)
(dropout): Dropout(p=0.5, inplace=False)
(fc0): Linear(in_features=200, out_features=2, bias=True)
)
6. 训练函数
# 训练循环
def train(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset) # 训练集的大小
num_batches = len(dataloader) # 批次数目, (size/batch_size,向上取整)
train_loss, train_acc = 0, 0 # 初始化训练损失和正确率
for X, y in dataloader: # 获取图片及其标签
X, y = X.to(device), y.to(device)
# 计算预测误差
pred = model(X) # 网络输出
loss = loss_fn(pred, y) # 计算网络输出和真实值之间的差距,targets为真实值,计算二者差值即为损失
# 反向传播
optimizer.zero_grad() # 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
7. 测试函数
def test (dataloader, model, loss_fn):
size = len(dataloader.dataset) # 测试集的大小
num_batches = len(dataloader) # 批次数目, (size/batch_size,向上取整)
test_loss, test_acc = 0, 0
# 当不进行训练时,停止梯度更新,节省计算内存消耗
with torch.no_grad():
for X, y in dataloader:
X, y = X.to(device), y.to(device)
# 计算loss
target_pred = model(X)
loss = loss_fn(target_pred, y)
test_loss += loss.item()
test_acc += (target_pred.argmax(1) == y).type(torch.float).sum().item()
test_acc /= size
test_loss /= num_batches
return test_acc, test_loss
8. 训练过程
import copy
train_loss = []
train_acc = []
test_loss = []
test_acc = []
best_acc = 0.0
for epoch in range(epochs):
model.train()
epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, optimizer)
# 更新学习率
scheduler.step() # 更新学习率——调用官方动态学习率时使用
model.eval()
epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)
# 保存最佳模型
if epoch_test_acc > best_acc:
best_acc = epoch_test_acc
best_model = copy.deepcopy(model)
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 = optimizer.state_dict()['param_groups'][0]['lr']
template = ('Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%, Test_loss:{:.3f}, Lr:{:.2E}')
print(template.format(epoch+1, epoch_train_acc*100, epoch_train_loss,
epoch_test_acc*100, epoch_test_loss, lr))
print('Done. Best test acc: ', best_acc)
Epoch: 1, Train_acc:53.5%, Train_loss:0.683, Test_acc:55.9%, Test_loss:0.681, Lr:1.00E-03
Epoch: 2, Train_acc:65.0%, Train_loss:0.636, Test_acc:68.8%, Test_loss:0.623, Lr:9.20E-04
Epoch: 3, Train_acc:73.0%, Train_loss:0.536, Test_acc:75.2%, Test_loss:0.542, Lr:9.20E-04
Epoch: 4, Train_acc:76.7%, Train_loss:0.473, Test_acc:78.2%, Test_loss:0.510, Lr:8.46E-04
Epoch: 5, Train_acc:78.7%, Train_loss:0.444, Test_acc:75.7%, Test_loss:0.498, Lr:8.46E-04
Epoch: 6, Train_acc:79.0%, Train_loss:0.425, Test_acc:77.2%, Test_loss:0.485, Lr:7.79E-04
Epoch: 7, Train_acc:80.5%, Train_loss:0.408, Test_acc:76.2%, Test_loss:0.482, Lr:7.79E-04
Epoch: 8, Train_acc:80.8%, Train_loss:0.407, Test_acc:77.7%, Test_loss:0.476, Lr:7.16E-04
Epoch: 9, Train_acc:81.0%, Train_loss:0.392, Test_acc:76.7%, Test_loss:0.483, Lr:7.16E-04
Epoch:10, Train_acc:82.5%, Train_loss:0.391, Test_acc:76.2%, Test_loss:0.481, Lr:6.59E-04
Epoch:11, Train_acc:81.1%, Train_loss:0.380, Test_acc:77.2%, Test_loss:0.481, Lr:6.59E-04
Epoch:12, Train_acc:82.2%, Train_loss:0.361, Test_acc:77.7%, Test_loss:0.494, Lr:6.06E-04
Epoch:13, Train_acc:82.5%, Train_loss:0.355, Test_acc:75.2%, Test_loss:0.500, Lr:6.06E-04
Epoch:14, Train_acc:83.3%, Train_loss:0.341, Test_acc:74.3%, Test_loss:0.507, Lr:5.58E-04
Epoch:15, Train_acc:83.6%, Train_loss:0.333, Test_acc:74.3%, Test_loss:0.514, Lr:5.58E-04
Epoch:16, Train_acc:85.0%, Train_loss:0.321, Test_acc:74.8%, Test_loss:0.527, Lr:5.13E-04
Epoch:17, Train_acc:84.8%, Train_loss:0.303, Test_acc:73.8%, Test_loss:0.542, Lr:5.13E-04
Epoch:18, Train_acc:86.6%, Train_loss:0.289, Test_acc:73.8%, Test_loss:0.554, Lr:4.72E-04
Epoch:19, Train_acc:85.8%, Train_loss:0.300, Test_acc:73.8%, Test_loss:0.499, Lr:4.72E-04
Epoch:20, Train_acc:87.1%, Train_loss:0.282, Test_acc:74.3%, Test_loss:0.525, Lr:4.34E-04
Epoch:21, Train_acc:88.2%, Train_loss:0.255, Test_acc:73.8%, Test_loss:0.610, Lr:4.34E-04
Epoch:22, Train_acc:89.2%, Train_loss:0.239, Test_acc:72.3%, Test_loss:0.604, Lr:4.00E-04
Epoch:23, Train_acc:88.4%, Train_loss:0.231, Test_acc:70.3%, Test_loss:0.601, Lr:4.00E-04
Epoch:24, Train_acc:89.7%, Train_loss:0.218, Test_acc:72.3%, Test_loss:0.632, Lr:3.68E-04
Epoch:25, Train_acc:90.3%, Train_loss:0.214, Test_acc:73.3%, Test_loss:0.682, Lr:3.68E-04
Epoch:26, Train_acc:91.5%, Train_loss:0.200, Test_acc:72.8%, Test_loss:0.712, Lr:3.38E-04
Epoch:27, Train_acc:92.3%, Train_loss:0.176, Test_acc:72.3%, Test_loss:0.743, Lr:3.38E-04
Epoch:28, Train_acc:92.5%, Train_loss:0.166, Test_acc:71.8%, Test_loss:0.771, Lr:3.11E-04
Epoch:29, Train_acc:92.4%, Train_loss:0.164, Test_acc:71.3%, Test_loss:0.778, Lr:3.11E-04
Epoch:30, Train_acc:92.9%, Train_loss:0.162, Test_acc:71.8%, Test_loss:0.832, Lr:2.86E-04
Epoch:31, Train_acc:93.3%, Train_loss:0.143, Test_acc:71.3%, Test_loss:0.906, Lr:2.86E-04
Epoch:32, Train_acc:94.3%, Train_loss:0.131, Test_acc:71.8%, Test_loss:0.976, Lr:2.63E-04
Epoch:33, Train_acc:95.1%, Train_loss:0.122, Test_acc:74.3%, Test_loss:0.955, Lr:2.63E-04
Epoch:34, Train_acc:94.4%, Train_loss:0.119, Test_acc:71.3%, Test_loss:0.927, Lr:2.42E-04
Epoch:35, Train_acc:94.3%, Train_loss:0.126, Test_acc:71.8%, Test_loss:0.896, Lr:2.42E-04
Epoch:36, Train_acc:95.5%, Train_loss:0.115, Test_acc:70.8%, Test_loss:1.024, Lr:2.23E-04
Epoch:37, Train_acc:95.1%, Train_loss:0.108, Test_acc:70.8%, Test_loss:1.005, Lr:2.23E-04
Epoch:38, Train_acc:96.3%, Train_loss:0.092, Test_acc:71.3%, Test_loss:1.140, Lr:2.05E-04
Epoch:39, Train_acc:96.5%, Train_loss:0.085, Test_acc:70.3%, Test_loss:1.137, Lr:2.05E-04
Epoch:40, Train_acc:97.0%, Train_loss:0.079, Test_acc:71.8%, Test_loss:1.148, Lr:1.89E-04
Epoch:41, Train_acc:96.4%, Train_loss:0.081, Test_acc:71.8%, Test_loss:1.153, Lr:1.89E-04
Epoch:42, Train_acc:97.0%, Train_loss:0.079, Test_acc:69.3%, Test_loss:1.119, Lr:1.74E-04
Epoch:43, Train_acc:96.0%, Train_loss:0.082, Test_acc:71.8%, Test_loss:1.161, Lr:1.74E-04
Epoch:44, Train_acc:96.8%, Train_loss:0.080, Test_acc:72.3%, Test_loss:1.126, Lr:1.60E-04
Epoch:45, Train_acc:97.9%, Train_loss:0.068, Test_acc:70.8%, Test_loss:1.235, Lr:1.60E-04
Epoch:46, Train_acc:98.0%, Train_loss:0.058, Test_acc:71.8%, Test_loss:1.281, Lr:1.47E-04
Epoch:47, Train_acc:97.6%, Train_loss:0.057, Test_acc:70.3%, Test_loss:1.271, Lr:1.47E-04
Epoch:48, Train_acc:98.5%, Train_loss:0.052, Test_acc:71.3%, Test_loss:1.259, Lr:1.35E-04
Epoch:49, Train_acc:98.6%, Train_loss:0.054, Test_acc:70.3%, Test_loss:1.405, Lr:1.35E-04
Epoch:50, Train_acc:98.1%, Train_loss:0.046, Test_acc:71.3%, Test_loss:1.315, Lr:1.24E-04
Done. Best test acc: 0.7821782178217822
9. 模型评估
import matplotlib.pyplot as plt
#隐藏警告
import warnings
warnings.filterwarnings("ignore") #忽略警告信息
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.rcParams['figure.dpi'] = 100 #分辨率
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()