2. 深度学习的项目流程(批量化打包数据、构建模型、训练模型、波士顿房价预测、激活函数、多层感知机)
深度学习流程
原文链接:https://blog.csdn.net/Deadwalk/article/details/139649117?spm=1001.2014.3001.5502
1. 深度学习基本流程
1.1 流程图
- 由于训练的本质就是求loss函数的最小值;所以,我们类比求
y
=
2
x
2
y = 2x^2
y=2x2 最小值的过程,来看一下线性回归训练(也就是求loss最小值)的过程,其流程如下:
1.2 代码实现
import torch
import torch.nn as nn
import torch.optim as optim
# 生成模拟数据
torch.manual_seed(42)
x_train = torch.randn(100, 13) # 100个样本,每个样本有13个特征
y_train = torch.randn(100, 1) # 每个样本对应一个输出值
# 定义模型
model = nn.Linear(13, 1) # 输入特征数为13,输出特征数为1
# 初始化优化器
criterion = nn.MSELoss() # 均方误差损失
optimizer = optim.SGD(model.parameters(), lr=0.01) # 随机梯度下降优化器
# 迭代次数和学习率
epochs = 1000
learning_rate = 1e-2
# 使用 PyTorch 进行梯度下降
for _ in range(epochs):
optimizer.zero_grad() # 梯度清零
outputs = model(x_train) # 正向传播
loss = criterion(outputs, y_train) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新参数
# 输出最终模型参数
print("线性回归模型的权重:", model.weight)
print("线性回归模型的偏置:", model.bias)
1.3 基本概念
- 模型 model
- 前向传播:把特征 X 带入模型 model ,得到预测结果 y_pred
- 训练时:自动在底层构建计算图(把正向传播的流程记录下来,方便进行后续的分布求导/链式求导
- 例如:在导数中,对于一个复合函数 h ( g ( f ( x ) ) ) h( g( f(x))) h(g(f(x))) ,我们需要进行链式求导,即 h ( g ( f ( x ) ) ) = f ′ ∗ g ′ ∗ h ′ h( g( f(x))) = f' * g' * h' h(g(f(x)))=f′∗g′∗h′
- 反向传播:本质是计算每个参数的梯度,是通过损失函数发起的
- 模型的作用:只负责前向传播 forward,不负责后向传播 backward
- 前向传播:把特征 X 带入模型 model ,得到预测结果 y_pred
- 训练流程
- 从训练集中,取一批 batch 样本 (x, y)
- 把样本特征 X 送入模型 model,得到预测结果 y_pred
- 计算损失函数 loss = f(y_pred, y),计算当前的误差 loss
- 通过 loss , 反向传播,计算每个参数 (w, b) 的梯度
- 利用优化器 optimizer ,通过梯度下降法,更新参数
- 利用优化器 optimizer 清空参数的梯度
- 重复1-6 直至迭代结束(各项指标满足要求或是误差很小)
- 预测流程
- 拿到待测样本 X(推理时,没有标签,只有特征)
- 把样本特征 X 送入模型 model ,得到预测结果 y_pred
- 根据 y_pred 解析并返回预测结果即可
2. 深度学习项目流程
- 通过上述内容梳理,我们已经了解深度学习的一个基本流程,包括:定义模型、训练、预测。
- 但是在实际工程使用中,由于训练数据比较庞大,所以我们还需要一些额外的步骤,例如:增加批量化打包流程。
- 为了更好地理解深度学习的整体流程,我们仍然使用机器学习中使用的《波士顿房价预测》案例,来看一下深度学习下应该如何实现。
2.1 批量化打包数据
- 原因:在实际的工程中,深度学习要进行大数据量的训练,批量化打包数据有以下优点:
- 提高训练效率:通过批量化处理数据,可以充分利用GPU的并行计算能力,加快模型训练速度;
- 稳定模型训练:批量化处理可以降低训练过程中的方差,使模型更加稳定;
- 减少内存消耗:批量化处理可以减少在每个迭代中需要存储的数据量,节省内存消耗。
- 原理:使用生成器来打包数据
- 生成器记录了一个规则,每次调用生成器就会返回一个批次数据。
- 实现:
- 先自定义dataset
- 再定义dataloader
from torch.utils.data import DataLoader, TensorDataset # 批量化打包数据示例代码 # 创建数据集和数据加载器 dataset = TensorDataset(x_tensor, y_tensor) data_loader = DataLoader(dataset, batch_size=16, shuffle=True)
2.2 构建模型
- 定义
- 在深度学习中构建模型是指设计神经网络结构,确定网络的层数、每层的神经元数量、激活函数等参数,以实现特定的学习任务。
- 常见方式
- Sequential模型:Sequential模型是一种简单的线性堆叠模型,层按顺序依次堆叠在一起,适用于顺序处理的神经网络结构。
- Class子类化模型:通过继承框架提供的模型基类,用户可以自定义模型的结构和计算逻辑,实现更加灵活和定制化的模型构建。
- 除上述方式之外,还有迁移学习、模型组合、模型集成、自动机器学习(AutoML)、超网络(Hypernetwork) 等方式,由于不是本章内容重点,暂不展开。
2.3 训练模型
(1)筹备训练
- a. 定义损失函数
- 目的:损失函数用于衡量模型预测结果与真实标签之间的差异,是优化算法的目标函数,帮助模型学习正确的参数。
- 常见损失函数:
- 均方误差损失(Mean Squared Error, MSE)
- 交叉熵损失(Cross Entropy Loss)
- b. 定义优化器
- 目的:优化器用于更新模型参数,通过最小化损失函数来提高模型性能,调整模型参数使得损失函数达到最小值。
- 常见优化器:
- 随机梯度下降(SGD)
- Adam
- Adagrad等
- c. 设置训练次数
- 定义:训练次数指的是将整个训练数据集在模型上反复训练的次数,每次完整地遍历整个数据集称为一个训练周期(Epoch)。
- 作用:通过增加训练次数,模型可以更好地学习数据集中的模式和特征,提高模型的泛化能力,减少过拟合的风险。
- d. 设置学习率
- 定义:学习率是优化算法中的一个重要超参数,控制模型参数在每次迭代中更新的步长大小,即参数沿着梯度方向更新的幅度。
- 目的:学习率的选择影响模型训练的速度和性能,合适的学习率能够使模型更快地收敛到最优解,而过大或过小的学习率可能导致训练不稳定或陷入局部最优解。
(2)开始训练
- 训练过程中需要监控模型指标,如:准确率、损失值等
- 训练过程中需要保存模型参数,方便后续推理
- 避免过拟合
2.4 模型推理
- 训练好模型之后,直接使用模型进行推理即可。
3. 深度学习实现波士顿房价预测
3.1 数据读取、切分、预处理
# 数据读取
file_name = './housing.data'
X = []
y = []
with open(file=file_name, mode='r', encoding='utf8') as f:
# f.readline()
for line in f:
line = line.strip()
if line:
sample = [float(ele) for ele in line.split(" ") if ele]
X.append(sample[:-1])
y.append(sample[-1])
# 数据切分
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2,
random_state=0)
# 数据预处理(规范化)
import numpy as np
# 转numpy数组
X_train = np.array(X_train)
X_test = np.array(X_test)
# 提取参数
_mean = X_train.mean(axis=0)
_std = X_train.std(axis=0) + 1e-9 # 为了避免除零,此处加上一个非常小的数
# 执行规范化处理
X_train = (X_train - _mean) / _std
X_test = (X_test - _mean) / _std
3.2 批量化打包数据
- 通过定义一个继承Dataset的数据集类,方便数据的常见操作,如:len()、index()等。
import torch
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
# 1. 继承Dataset 自定义一个数据集类
class HouseDataset(Dataset):
"""
自定义一个房价数据集
"""
def __init__(self, X, y):
"""
接受参数,定义静态属性
"""
self.X = X
self.y = y
def __len__(self):
"""
返回数据集样本的个数
"""
return len(self.X)
def __getitem__(self, idx):
"""
通过索引,读取第idx个样本
"""
x = self.X[idx]
y = self.y[idx]
# 转张量
x = torch.tensor(data=x, dtype=torch.float32)
y = torch.tensor(data=[y], dtype=torch.float32)
return x, y
此处__len__和__getitem__方法是Python的魔法方法,他们是回调(callback)函数,不需要用户自己调用而由系统调用。即:
告诉系统我定义的数据集在取长度和按index取元素调用哪个方法;
当系统触发这两种情况(取长度和按index取元素)时,会自动调用类里的__len__和__getitem__方法。
# 训练集加载器
house_train_dataset = HouseDataset(X=X_train, y=y_train)
house_train_dataloader = DataLoader(dataset=house_train_dataset,
batch_size=12,
shuffle=True)
# 测试集加载器
house_test_dataset = HouseDataset(X=X_test, y=y_test)
house_test_dataloader = DataLoader(dataset=house_test_dataset,
batch_size=32,
shuffle=True)
# 测试代码:查看上述训练集和测试集的数据形状
for X, y in house_train_dataset:
print(X)
print(X.shape)
print(y)
print(y.shape)
break
tensor([-0.3726, -0.4996, -0.7049, 3.6645, -0.4249, 0.9357, 0.6937, -0.4372,
-0.1622, -0.5617, -0.4846, 0.3717, -0.4110])
torch.Size([13])
tensor([26.7000])
torch.Size([1])
3.3 搭建模型
# 模型搭建
from torch import nn
# # 搭建方法1:
# model = nn.Linear(in_features=13, out_features=1)
# # 搭建方法2:
# model = nn.Sequential(
# nn.Linear(in_features=13, out_features=1)
# )
# 搭建方法3:
class Model(nn.Module):
"""
自定义一个类
- 必须继承 nn.Module
"""
def __init__(self, n_features=13):
"""
接收超参
定义处理的层
"""
# 先初始化父类
super(Model, self).__init__()
# 定义一个线性层(做一次矩阵变换)
self.linear = nn.Linear(in_features=n_features, out_features=1)
def forward(self, x):
"""
模型前向传播逻辑
"""
x = self.linear(x)
return x
# 实例化模型
model = Model(n_features=13)
# 测试代码:可以看到模型的运行结果
for X, y in house_train_dataloader:
y_pred = model(X)
print(y_pred)
print(y)
break
tensor([[-0.3277],
[-0.3072],
[ 0.0355],
[-0.0539],
[-0.1478],
[-0.2848],
[ 0.5001],
[ 0.8047],
[ 0.2635],
[-0.2561],
[-0.1742],
[-0.4823]], grad_fn=)
tensor([[33.1000],
[14.5000],
[35.4000],
[39.8000],
[22.5000],
[23.8000],
[36.5000],
[14.6000],
[35.1000],
[25.0000],
[20.3000],
[18.8000]])
3.4 训练模型
(1)筹备训练
- 定义模型(实例化上述自定义模型)、定义损失函数、定义优化器、定义训练次数和定义学习率
# 定义模型
model = Model(n_features=13)
# 定义训练的轮次
epochs = 100
# 定义学习率
learing_rate = 1e-3
# 定义损失函数
loss_fn = nn.MSELoss()
# 定义优化器
optimizer = torch.optim.SGD(params=model.parameters(),
lr=learing_rate)
(2)定义监控指标和方法
- 在训练的过程中,我们需要对训练过程的重要指标加以监控,以避免训练有问题。
# 定义查看损失函数的方法,用于监控训练过程
def get_loss(dataloader):
# 模型设置为评估模式
# (BatchNorm LayNorm Dropout层,在train模式和eval模式下,行为是不一样)
model.eval()
# 收集每个批量的损失
losses = []
# 构建一个无梯度的环境(底层不会默认自动创建计算图,节约资源)
with torch.no_grad():
for X, y in dataloader:
y_pred = model(X)
loss = loss_fn(y_pred, y)
losses.append(loss.item())
# 计算每个批量损失的平均值
final_loss = sum(losses) / len(losses)
# 保留小数点后5位
final_loss = round(final_loss, ndigits=5)
return final_loss
(3)实现训练过程
def train():
# 记录训练过程
train_losses = []
test_losses = []
# 每一轮次
for epoch in range(epochs):
#模型设为训练模式
model.train()
# 每一批量
for X, y in house_train_dataloader:
# 1. 正向传播
y_pred = model(X)
# 2. 损失计算
loss = loss_fn(y_pred, y)
# 3. 反向传播
loss.backward()
# 4. 优化一步
optimizer.step()
# 5. 清空梯度
optimizer.zero_grad()
# 计算模型当前的损失情况
train_loss = get_loss(dataloader=house_train_dataloader)
test_loss = get_loss(dataloader=house_test_dataloader)
train_losses.append(train_loss)
test_losses.append(test_loss)
print(f"当前是第{epoch+1}轮,训练集损失为:{train_loss}, 测试集损失为:{test_loss}")
return train_losses, test_losses
(4)开始训练
train_losses, test_losses = train()
当前是第1轮,训练集损失为:512.23866, 测试集损失为:470.53479
当前是第2轮,训练集损失为:441.68754, 测试集损失为:414.82328
当前是第3轮,训练集损失为:387.13285, 测试集损失为:417.94884
当前是第4轮,训练集损失为:339.7604, 测试集损失为:321.25851
当前是第5轮,训练集损失为:295.34212, 测试集损失为:283.35604
当前是第6轮,训练集损失为:259.63065, 测试集损失为:304.31802
当前是第7轮,训练集损失为:229.71633, 测试集损失为:274.742
当前是第8轮,训练集损失为:201.60888, 测试集损失为:213.39904
当前是第9轮,训练集损失为:179.15055, 测试集损失为:193.0374
当前是第10轮,训练集损失为:158.91308, 测试集损失为:154.98766
当前是第11轮,训练集损失为:140.94878, 测试集损失为:143.02044
当前是第12轮,训练集损失为:125.19098, 测试集损失为:144.65741
当前是第13轮,训练集损失为:112.88125, 测试集损失为:129.76349
当前是第14轮,训练集损失为:100.19187, 测试集损失为:131.55499
当前是第15轮,训练集损失为:90.06036, 测试集损失为:96.69405
当前是第16轮,训练集损失为:81.32993, 测试集损失为:88.38998
当前是第17轮,训练集损失为:73.30434, 测试集损失为:83.43338
当前是第18轮,训练集损失为:66.68453, 测试集损失为:94.52958
当前是第19轮,训练集损失为:60.70854, 测试集损失为:111.13627
当前是第20轮,训练集损失为:55.5599, 测试集损失为:75.72988
当前是第21轮,训练集损失为:51.33824, 测试集损失为:102.07828
当前是第22轮,训练集损失为:47.48327, 测试集损失为:59.70907
当前是第23轮,训练集损失为:44.18092, 测试集损失为:53.83336
当前是第24轮,训练集损失为:41.14358, 测试集损失为:94.82549
当前是第25轮,训练集损失为:38.32627, 测试集损失为:89.27538
当前是第26轮,训练集损失为:36.4985, 测试集损失为:47.11266
当前是第27轮,训练集损失为:33.95471, 测试集损失为:44.56353
当前是第28轮,训练集损失为:32.83847, 测试集损失为:49.46564
当前是第29轮,训练集损失为:30.80773, 测试集损失为:77.49344
当前是第30轮,训练集损失为:29.49684, 测试集损失为:74.35186
当前是第31轮,训练集损失为:29.75533, 测试集损失为:45.33565
当前是第32轮,训练集损失为:27.50819, 测试集损失为:40.49028
当前是第33轮,训练集损失为:26.46446, 测试集损失为:37.61283
当前是第34轮,训练集损失为:25.75421, 测试集损失为:38.15598
当前是第35轮,训练集损失为:25.35517, 测试集损失为:42.44055
当前是第36轮,训练集损失为:24.32058, 测试集损失为:35.23858
当前是第37轮,训练集损失为:23.8545, 测试集损失为:45.60548
当前是第38轮,训练集损失为:23.91668, 测试集损失为:34.84441
当前是第39轮,训练集损失为:23.40606, 测试集损失为:44.46604
当前是第40轮,训练集损失为:22.6011, 测试集损失为:36.04847
当前是第41轮,训练集损失为:22.31131, 测试集损失为:34.43374
当前是第42轮,训练集损失为:22.0708, 测试集损失为:33.82917
当前是第43轮,训练集损失为:22.30289, 测试集损失为:37.85688
当前是第44轮,训练集损失为:21.53935, 测试集损失为:38.87277
当前是第45轮,训练集损失为:21.3713, 测试集损失为:33.417
当前是第46轮,训练集损失为:21.23279, 测试集损失为:31.88459
当前是第47轮,训练集损失为:21.06997, 测试集损失为:40.63353
当前是第48轮,训练集损失为:21.41602, 测试集损失为:36.13148
当前是第49轮,训练集损失为:21.15649, 测试集损失为:36.81873
当前是第50轮,训练集损失为:20.78297, 测试集损失为:70.94823
当前是第51轮,训练集损失为:20.58092, 测试集损失为:33.10058
当前是第52轮,训练集损失为:20.60467, 测试集损失为:35.11913
当前是第53轮,训练集损失为:20.43625, 测试集损失为:33.78005
当前是第54轮,训练集损失为:20.52897, 测试集损失为:34.07798
当前是第55轮,训练集损失为:20.64655, 测试集损失为:39.28524
当前是第56轮,训练集损失为:20.30059, 测试集损失为:33.22317
当前是第57轮,训练集损失为:20.25821, 测试集损失为:36.61137
当前是第58轮,训练集损失为:20.17982, 测试集损失为:31.30995
当前是第59轮,训练集损失为:20.7384, 测试集损失为:61.73834
当前是第60轮,训练集损失为:20.29678, 测试集损失为:31.74056
当前是第61轮,训练集损失为:20.14952, 测试集损失为:36.40789
当前是第62轮,训练集损失为:20.14775, 测试集损失为:34.92755
当前是第63轮,训练集损失为:20.2442, 测试集损失为:35.53998
当前是第64轮,训练集损失为:20.06632, 测试集损失为:64.03114
当前是第65轮,训练集损失为:19.99748, 测试集损失为:33.22721
当前是第66轮,训练集损失为:19.96938, 测试集损失为:30.25136
当前是第67轮,训练集损失为:19.99487, 测试集损失为:31.36242
当前是第68轮,训练集损失为:20.17933, 测试集损失为:58.25826
当前是第69轮,训练集损失为:19.93474, 测试集损失为:38.55068
当前是第70轮,训练集损失为:20.28924, 测试集损失为:40.849
当前是第71轮,训练集损失为:20.0135, 测试集损失为:31.5855
当前是第72轮,训练集损失为:19.83351, 测试集损失为:34.03661
当前是第73轮,训练集损失为:20.40153, 测试集损失为:30.72532
当前是第74轮,训练集损失为:19.93389, 测试集损失为:29.66065
当前是第75轮,训练集损失为:19.84209, 测试集损失为:31.01681
当前是第76轮,训练集损失为:19.76584, 测试集损失为:29.77414
当前是第77轮,训练集损失为:19.99292, 测试集损失为:35.58202
当前是第78轮,训练集损失为:20.03342, 测试集损失为:29.54016
当前是第79轮,训练集损失为:19.84374, 测试集损失为:34.61122
当前是第80轮,训练集损失为:19.78551, 测试集损失为:57.45225
当前是第81轮,训练集损失为:19.99286, 测试集损失为:38.98204
当前是第82轮,训练集损失为:20.83931, 测试集损失为:37.50468
当前是第83轮,训练集损失为:19.8902, 测试集损失为:32.13173
当前是第84轮,训练集损失为:20.81494, 测试集损失为:36.72431
当前是第85轮,训练集损失为:19.76138, 测试集损失为:32.56446
当前是第86轮,训练集损失为:19.93493, 测试集损失为:32.25109
当前是第87轮,训练集损失为:19.87319, 测试集损失为:29.45971
当前是第88轮,训练集损失为:19.76319, 测试集损失为:30.47269
当前是第89轮,训练集损失为:19.66747, 测试集损失为:31.15023
当前是第90轮,训练集损失为:19.99098, 测试集损失为:58.56397
当前是第91轮,训练集损失为:19.69602, 测试集损失为:28.64936
当前是第92轮,训练集损失为:19.76346, 测试集损失为:29.46989
当前是第93轮,训练集损失为:19.72865, 测试集损失为:39.08675
当前是第94轮,训练集损失为:19.64981, 测试集损失为:30.54216
当前是第95轮,训练集损失为:19.74504, 测试集损失为:29.54564
当前是第96轮,训练集损失为:19.93373, 测试集损失为:29.28439
当前是第97轮,训练集损失为:19.62625, 测试集损失为:43.54383
当前是第98轮,训练集损失为:19.64032, 测试集损失为:40.3629
当前是第99轮,训练集损失为:19.62572, 测试集损失为:32.7787
当前是第100轮,训练集损失为:19.59034, 测试集损失为:34.74736
3.5 图形化监控数据
- 为了方便查看训练过程变化情况,可以使用matplotlib绘制损失函数的变化曲线。
from matplotlib import pyplot as plt
plt.plot(train_losses, c="blue", label="train_loss")
plt.plot(test_losses, c="red", label="test_loss")
plt.title("The Losses")
plt.xlabel(xlabel="epoches")
plt.ylabel(ylabel="loss")
plt.legend()
- 由上图可以看到:在一开始的训练中,损失值快速下降;当训练次数到40次左右后,损失值已经下降不明显。
- 我们可以通过加入激活函数,引入非线性因素来优化模型。
3.6 激活函数
- 定义:
- 激活函数是神经网络中的一种非线性函数,通常应用在神经元的输出上,将输入信号转换为输出信号。激活函数引入了非线性因素,使神经网络可以学习和表达复杂的非线性关系。
- 举个例子:
- 想象一下,神经网络就像是一个复杂的拼图游戏,每个神经元就像是拼图中的一个小块。当我们只使用线性函数(比如直线)作为激活函数时,就好比每个小块都是直线,无法拼出复杂的图案,只能表达简单的线性关系。
但是,当我们引入非线性的激活函数时,就好比在每个小块上加入了各种形状和曲线,使得每个小块可以表达更加复杂的形状和关系。这样,当我们把许多这样的小块(神经元)组合在一起时,就可以拼出更加复杂和多样的图案(非线性关系),从而让神经网络能够学习和表达更加复杂的模式和特征。
因此,激活函数的作用就是为神经网络引入了这种非线性因素,使得神经网络可以更好地学习和表达复杂的非线性关系,就像在拼图游戏中加入了各种形状和曲线,让我们能够拼出更加丰富多彩的图案一样。
- 想象一下,神经网络就像是一个复杂的拼图游戏,每个神经元就像是拼图中的一个小块。当我们只使用线性函数(比如直线)作为激活函数时,就好比每个小块都是直线,无法拼出复杂的图案,只能表达简单的线性关系。
- 常见激活函数有:Sigmoid函数、Tanh函数、ReLU函数、Softmax函数,相关内容在补充知识段落展开。
- 使用方法:
class Model(nn.Module):
"""
自定义一个类
- 必须继承 nn.Module
"""
def __init__(self, n_features=13):
"""
接收超参
定义处理的层
"""
# 先初始化父类
super(Model, self).__init__()
# 定义一个线性层(做一次矩阵变换)
self.linear = nn.Linear(in_features=n_features, out_features=1)
def forward(self, x):
"""
模型前向传播逻辑
"""
x = self.linear(x)
x = nn.ReLU()(x) # 添加ReLU激活函数
return x
当前是第495轮,训练集损失为:19.04356, 测试集损失为:38.45236
当前是第496轮,训练集损失为:19.29613, 测试集损失为:31.20161
当前是第497轮,训练集损失为:19.03669, 测试集损失为:30.85609
当前是第498轮,训练集损失为:19.01585, 测试集损失为:29.17376
当前是第499轮,训练集损失为:19.03183, 测试集损失为:28.62275
当前是第500轮,训练集损失为:19.10681, 测试集损失为:32.04256
3.7 多层感知机
-
由于无法模拟诸如异或以及其他复杂函数的功能,使得单层感知机的应用较为单一。一个简单的想法是,如果能在感知机模型中增加若干隐藏层,增强神经网络的非线性表达能力,就会让神经网络具有更强拟合能力。
-
大脑是一个多层感知机,每一层都在学习不同级别的特征。
- 输入层:输入层就像你的眼睛,它接收到动物的各种特征信息,比如颜色、大小等。
- 隐藏层:隐藏层就像你的大脑皮层,它处理输入的特征信息,并尝试从中提取出更加抽象和复杂的特征,比如动物的轮廓、纹理等。
- 输出层:输出层就像你的嘴巴,它根据隐藏层提取的特征信息做出判断,比如判断输入的动物是狗还是猫。
- 通过多次学习和训练,你的大脑(多层感知机)会逐渐调整隐藏层中的神经元(神经元就像大脑中的神经元)的连接权重,从而更好地识别不同类型的动物。
-
实现方法:修改自定义模型的初始化方法,加入一个新的线性层
class Model(nn.Module):
"""
自定义一个类
- 必须继承 nn.Module
"""
def __init__(self, n_features=13):
"""
接收超参
定义处理的层
"""
# 先初始化父类
super(Model, self).__init__()
# 定义两个线性层
self.linear1 = nn.Linear(in_features=n_features, out_features=8)
self.linear2 = nn.Linear(in_features=8, out_features=1)
def forward(self, x):
"""
模型前向传播逻辑
"""
x = self.linear1(x)
x = torch.relu(x) # 添加ReLU激活函数
x = self.linear2(x)
return x
当前是第95轮,训练集损失为:7.32678, 测试集损失为:18.07006
当前是第96轮,训练集损失为:7.16269, 测试集损失为:33.28857
当前是第97轮,训练集损失为:7.33148, 测试集损失为:23.29867
当前是第98轮,训练集损失为:7.24137, 测试集损失为:17.90972
当前是第99轮,训练集损失为:7.30563, 测试集损失为:17.59436
当前是第100轮,训练集损失为:7.21022, 测试集损失为:18.19897
- 由上图可以看到,多层感知机+引入激活函数,损失值已经降到8左右;对比之前未优化的模型,模型的损失值变小,预测准确性得到提升。
原文地址:https://blog.csdn.net/weixin_38566632/article/details/140319602
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!