动手学深度学习V2每日笔记(权重衰退+Dropout)

本文主要参考沐神的视频教程 https://www.bilibili.com/video/BV1UK4y1o7dy/vd_source=c7bfc6ce0ea0cbe43aa288ba2713e56d
文档教程 https://zh-v2.d2l.ai/

本文的主要内容对沐神提供的代码中个人不太理解的内容进行笔记记录,内容不会特别严谨仅供参考。

1.函数目录

1.1 python

python位置
Lambda 函数3.1

1.2 torch

python位置
torch.utils.data.TensorDataset3.1
torch.optim.SGD3.6
torch.nn.MSELoss3.6
torch.Tensor.uniform_4.1
torch.nn.Dropout4.2

2. 权重衰退

控制模型的容量的主要方法:

  1. 模型参数比较少
  2. 每个参数值选择的范围比较小
    权重衰退就是控制参数值的大小。

2.1 使用均方范数作为硬性限制

  • 通过限制参数值的选择范围来控制模型容量
    m i n l ( w , b ) s u b j e c t t o ∣ ∣ w ∣ ∣ 2 ≤ θ min\ l(w,b) \quad subject\ to\ ||w||^2≤\theta min l(w,b)subject to ∣∣w2θ
  • 通常不限制偏移b(限不限制都差不多)
  • 小的 θ \theta θ意味着更强的正则化
  • 正则化是用来防止模型过拟合而采取的手段

2.2 使用均方范数作为柔性限制

  • 对于每个 θ \theta θ,都可以找到 λ \lambda λ使得之前的目标函数等价于下面
    m i n l ( w , b ) + λ 2 ∣ ∣ w ∣ ∣ 2 min\ l(w,b) + \frac{\lambda}{2}||w||^2 min l(w,b)+2λ∣∣w2
  • 超参数 λ \lambda λ控制了正则项的重要程度
  • λ = 0 : \lambda=0: λ=0:无作用
  • λ → + ∞ , w ∗ → 0 \lambda\to +\infty,\ w^*\to0 λ+, w0
    在这里插入图片描述

2.3 参数更新法则

  • 计算梯度
    d d w ( l ( w , b ) + λ 2 ∣ ∣ w ∣ ∣ 2 ) = d l ( w , b ) d w + λ w \frac{d}{dw}(l(w,b)+\frac{\lambda}{2}||w||^2)=\frac{dl(w,b)}{dw}+\lambda w dwd(l(w,b)+2λ∣∣w2)=dwdl(w,b)+λw
    w t + 1 = w t − η λ w t − η d l ( w , b ) d w w_{t+1}=w_t-\eta \lambda w_t-\eta \frac{dl(w,b)}{dw} wt+1=wtηλwtηdwdl(w,b)
  • 通常 η λ < 1 \eta \lambda<1 ηλ1,在深度学习中通常叫做权重衰退

3 代码实现

3.1 高维线性回归

3.1.1 Lambda 函数

Lambda 函数,也叫匿名函数,是 Python 中用于创建小型、临时函数的一种方法。Lambda 函数没有名字,是一次性使用的,通常用于简化代码。它们可以作为参数传递给其他函数,或在需要一个短小的函数时使用。

lambda arguments: expression
  • lambda 关键字用于定义匿名函数。
  • arguments 是输入参数,可以有多个,参数之间用逗号分隔。
  • expression 是一个单一的表达式,计算并返回结果。
# 定义一个 lambda 函数,计算两个数的和
sum = lambda x, y: x + y
print(sum(3, 5))  # 输出 8
  • 产生线性数据
#true_w.shape=[200,1]
def synthetic_data(true_w, true_b, n_train):"""Generate y = Xw + b + noise."""X = torch.normal(0, 1, size=(n_train, len(true_w)))#X.shape=[20, 200]y = torch.matmul(X, true_w) + true_by += torch.normal(0, 0.01, y.shape)return X, d2l.reshape(y, (-1, 1))

3.1.2 torch.utils.data.TensorDataset

torch.utils.data.TensorDataset 是 PyTorch 中的数据工具类,用于将多个张量包装成一个数据集对象。这个数据集对象可以与 DataLoader 一起使用,以方便地进行批量数据加载和迭代。
每个样本将通过沿第一个维度索引张量来检索。第一个维度索引是指在张量的第 0 维度上进行索引操作。

import torch
from torch.utils.data import TensorDataset, DataLoader
# 示例数据
x = torch.tensor([[1, 2], [3, 4], [5, 6]])
y = torch.tensor([1, 2, 3])# 创建 TensorDataset
dataset = TensorDataset(x, y)
# 创建 DataLoader
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)
# 迭代数据
for batch in dataloader:features, labels = batchprint(features, labels)

在这里插入图片描述

  • 加载数据
def load_array(data_arrays, batch_size, is_train=True):"""Construct a PyTorch data iterator."""dataset = torch.utils.data.TensorDataset(*data_arrays)return torch.utils.data.DataLoader(dataset, batch_size, shuffle=is_train)
def synthetic_data(true_w, true_b, n_train):"""Generate y = Xw + b + noise."""X = torch.normal(0, 1, size=(n_train, len(true_w)))#X.shape=[20, 200]y = torch.matmul(X, true_w) + true_by += torch.normal(0, 0.01, y.shape)return X, d2l.reshape(y, (-1, 1))def load_array(data_arrays, batch_size, is_train=True):"""Construct a PyTorch data iterator."""dataset = torch.utils.data.TensorDataset(*data_arrays)return torch.utils.data.DataLoader(dataset, batch_size, shuffle=is_train)n_train, n_test, num_inputs, batch_size = 20, 100, 200, 5
true_w, true_b = torch.ones((num_inputs, 1)) * 0.01, 0.05
#true_w.shape=[200,1]
train_data = synthetic_data(true_w, true_b, n_train)
train_iter = load_array(train_data, batch_size)
test_data = synthetic_data(true_w,true_b, n_test)
test_iter = load_array(test_data, batch_size)
X,y = next(iter(test_iter))
print(X.shape, y.shape)

3.2 初始化参数模型

def init_params():w = torch.normal(0, 1, size=(num_inputs, 1), requires_grad=True)b = torch.zeros(1, requires_grad=True)return [w, b]

3.3 定义 l 2 l_2 l2范数惩罚

实现这一惩罚最方便的方法是对所有项求平方后并将它们求和

# 定义L2范数惩罚
def l2_penalty(w):return torch.sum(w.pow(2))/2
a = torch.tensor([1, 2, 3])
print(l2_penalty(a)) #输出为tensor(7.)

3.4 训练

def train(lambd):w, b = init_params()net, loss = lambda X:linreg(X, w, b), d2l.squared_lossnum_epochs, lr = 100, 0.003# 训练集损失列表train_loss_all = []# 验证集损失列表val_loss_all = []for epoch in range(num_epochs):for X,y in train_iter:l = loss(net(X), y) + lambd * l2_penalty(w)l.sum().backward()d2l.sgd([w, b], lr, batch_size)train_loss = d2l.evaluate_loss(net, train_iter, loss)val_loss = d2l.evaluate_loss(net, test_iter, loss)train_loss_all.append(train_loss)val_loss_all.append(val_loss)train_process = pd.DataFrame(data={"epoch": range(num_epochs),"train_loss_all": train_loss_all,"val_loss_all": val_loss_all,})return train_process

3.5 完整代码

import pandas as pd
import torch
import matplotlib.pyplot as plt
from torch import nn
from d2l import torch as d2ldef synthetic_data(true_w, true_b, n_train):"""Generate y = Xw + b + noise."""X = torch.normal(0, 1, size=(n_train, len(true_w)))#X.shape=[20, 200]y = torch.matmul(X, true_w) + true_by += torch.normal(0, 0.01, y.shape)return X, d2l.reshape(y, (-1, 1))def load_array(data_arrays, batch_size, is_train=True):"""Construct a PyTorch data iterator."""dataset = torch.utils.data.TensorDataset(*data_arrays)return torch.utils.data.DataLoader(dataset, batch_size, shuffle=is_train)def matplot_acc_loss(train_process):# 显示每一次迭代后的训练集和验证集的损失函数和准确率plt.figure(figsize=(12, 4))plt.subplot(1, 1, 1)plt.plot(train_process['epoch'], train_process.train_loss_all, "ro-", label="Train loss")plt.plot(train_process['epoch'], train_process.val_loss_all, "bs-", label="Val loss")plt.legend()plt.xlabel("epoch")plt.ylabel("Loss")plt.show()def linreg(X, w, b):"""The linear regression model.Defined in :numref:`sec_utils`"""return torch.matmul(X, w)+bn_train, n_test, num_inputs, batch_size = 20, 100, 200, 5
true_w, true_b = torch.ones((num_inputs, 1)) * 0.01, 0.05
#true_w.shape=[200,1]
train_data = synthetic_data(true_w, true_b, n_train)
train_iter = load_array(train_data, batch_size)
test_data = synthetic_data(true_w,true_b, n_test)
test_iter = load_array(test_data, batch_size)
X,y = next(iter(test_iter))
print(X.shape, y.shape)
# 初始化参数模型
def init_params():w = torch.normal(0, 1, size=(num_inputs, 1), requires_grad=True)b = torch.zeros(1, requires_grad=True)return [w, b]
# 定义L2范数惩罚
def l2_penalty(w):return torch.sum(w.pow(2))/2
# a = torch.tensor([1, 2, 3])
# print(l2_penalty(a))
# 训练
def train(lambd):w, b = init_params()net, loss = lambda X:linreg(X, w, b), d2l.squared_lossnum_epochs, lr = 100, 0.003# 训练集损失列表train_loss_all = []# 验证集损失列表val_loss_all = []for epoch in range(num_epochs):for X,y in train_iter:l = loss(net(X), y) + lambd * l2_penalty(w)l.sum().backward()d2l.sgd([w, b], lr, batch_size)train_loss = d2l.evaluate_loss(net, train_iter, loss)val_loss = d2l.evaluate_loss(net, test_iter, loss)train_loss_all.append(train_loss)val_loss_all.append(val_loss)train_process = pd.DataFrame(data={"epoch": range(num_epochs),"train_loss_all": train_loss_all,"val_loss_all": val_loss_all,})return train_processtrain_process = train(3)
matplot_acc_loss(train_process)

3.6 简洁实现

3.6.1 torch.optim.SGD

torch.optim.SGD 是 PyTorch 提供的标准随机梯度下降优化器(Stochastic Gradient Descent)。它适用于大多数深度学习模型的优化过程,可以通过添加动量、权重衰减(L2正则化)和 Nesterov 加速梯度来增强其性能。

torch.optim.SGD(params, lr=<required parameter>, momentum=0, dampening=0, weight_decay=0, nesterov=False)
  • 参数说明
  • params:待优化的模型参数,一般通过 model.parameters() 传递。
  • lr (float):学习率,是控制参数更新步伐的关键超参数。
  • momentum (float, 可选):动量因子,用于加速收敛并减少振荡(默认:0)。
  • dampening (float, 可选):动量抑制因子,用于控制动量的累积(默认:0)。
  • weight_decay (float, 可选):权重衰减(L2正则化)因子,用于防止过拟合(默认:0)。
  • nesterov (bool, 可选):是否使用 Nesterov 加速梯度(默认:False)。

3.6.2 torch.nn.MSELoss

nn.MSELoss 是 PyTorch 中的一个损失函数类,用于计算均方误差(Mean Squared Error, MSE)。该损失函数通常用于回归任务中,评估预测值与实际值之间的差异。通过设置 reduction 参数,可以控制损失值的计算方式。

torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')
  • 参数说明
  • reduction (string, 可选):指定损失值的聚合方式。可以取以下值:
  • ‘none’:不进行任何聚合,返回每个样本的损失值。
  • ‘mean’:返回所有样本损失值的平均值(默认)。
  • ‘sum’:返回所有样本损失值的总和。
import torch
import torch.nn as nn# 定义均方误差损失函数,不进行聚合
loss_fn = nn.MSELoss(reduction='none')# 假设有一些预测值和目标值
predictions = torch.tensor([[2.5, 0.0], [1.5, -0.5], [3.0, 2.0]], requires_grad=True)
targets = torch.tensor([[3.0, -0.5], [1.0, 0.0], [2.0, 2.0]])# 计算损失值
loss = loss_fn(predictions, targets)print(loss)  # 打印每个样本的损失值# 如果需要,可以手动计算损失值的平均值或总和
mean_loss = loss.mean()
sum_loss = loss.sum()print(mean_loss)  # 打印损失值的平均值
print(sum_loss)   # 打印损失值的总和

在这里插入图片描述

def train_concise(wd):net = nn.Sequential(nn.Linear(num_inputs, 1))for param in net.parameters():param.data.normal_()loss = nn.MSELoss(reduction='none')num_epochs, lr = 100, 0.003# 将 weight_decay 应用于 net[0].weight,而不应用于 net[0].bias。trainer = torch.optim.SGD([{"params": net[0].weight, "weight_decay":wd},{"params": net[0].bias}], lr=lr)train_loss_all = []val_loss_all = []for epoch in range(num_epochs):for X,y in train_iter:trainer.zero_grad()l = loss(net(X), y)l.mean().backward()trainer.step()train_loss = d2l.evaluate_loss(net, train_iter, loss)val_loss = d2l.evaluate_loss(net, test_iter, loss)train_loss_all.append(train_loss)val_loss_all.append(val_loss)train_process = pd.DataFrame(data={'epoch':range(num_epochs),"train_loss_all":train_loss_all,"val_loss_all":val_loss_all})return train_process

4. 丢弃法

一个好的模型需要对输入数据的扰动鲁棒

  • 使用有噪音的数据等价于Tikhonov正则
  • 丢弃法:在层之间加入噪声
    无偏差的加入噪声
  • 对x加入噪声得到x’,我们希望
    E [ x ′ ] = x E[x']=x E[x]=x
  • 丢弃法对每个元素进行如下扰动:
    x i ′ = { 0 w i t h p r o b a b l i t y p x i 1 − p o t h e r i s e x'_i=\left\{ \begin{array}{c} 0 \ with\ probablity\ p \\ \frac{x_i}{1-p} \ otherise \\ \end{array} \right. xi={0 with probablity p1pxi otherise
    通常将丢弃法作用在隐藏全连接层的输出上
    在这里插入图片描述
  • 丢弃法将一些输出项随机置0来控制模型复杂度
  • 常作用在多层感知机的隐藏层输出上
  • 丢弃概率是控制模型复杂度的超参数

4.1 dropout实现

4.1.1 torch.Tensor.uniform_()

torch.Tensor.uniform_() 是一个用于填充张量的内置方法。它将张量的元素用来自均匀分布的随机数替换。通常用于初始化模型参数。

uniform_(from=0, to=1) → Tensor

参数

  • from:均匀分布的下界(默认值为0)。
  • to:均匀分布的上界(默认值为1)。
import torch# 创建一个形状为(3, 3)的张量
tensor = torch.empty(3, 3)# 使用uniform_方法将张量的元素初始化为均匀分布[0, 1)范围内的随机数
tensor.uniform_(0, 1)
print(tensor)# 使用uniform_方法将张量的元素初始化为均匀分布[-1, 1)范围内的随机数
tensor.uniform_(-1, 1)
print(tensor)

在这里插入图片描述

def dropout_layer(X, dropout):assert 0 <= dropout <= 1if dropout == 0:return torch.zeros_like(X)if dropout == 1:return Xmask = (torch.Tensor(X.shape).uniform_(0, 1) > dropout).float()return mask * X / (1.0 - dropout)
x = torch.arange(16, dtype=torch.float32).reshape((2,8))
print(x)
print(dropout_layer(x, 0))
print(dropout_layer(x, 0.5))
print(dropout_layer(x, 1.0))

4.2 定义模型

4.2.1 nn.Dropout

nn.Dropout 是 PyTorch 中的一种正则化技术,用于防止神经网络中的过拟合。它通过在训练过程中随机将一部分神经元的输出设为 0 来实现这一点。这种做法可以迫使网络的其余部分学习更稳健的特征,因为它不能依赖于某些特定的神经元。

import torch.nn as nn
dropout = nn.Dropout(p=0.5)
  • p:指定每个神经元在训练时被丢弃的概率。取值范围是 [0, 1),通常设为 0.5。
    训练和评估模式
    Dropout 层在训练和评估(推理)模式下表现不同:

训练模式:在训练模式下,Dropout 会按照指定的概率 p 随机丢弃神经元的输出。
评估模式:在评估模式下,Dropout 不会丢弃任何神经元的输出。即使在训练过程中应Dropout,在评估时网络的所有神经元都会参与计算。
可以通过 model.train() 和 model.eval() 来切换这两种模式。

net = nn.Sequential(nn.Flatten(),nn.Linear(784, 256),nn.ReLU(),# 在第一个全连接层之后添加一个dropout层nn.Dropout(0.5),nn.Linear(256, 256),nn.ReLU(),# 在第二个全连接层之后添加一个dropout层nn.Dropout(0.2),nn.Linear(256, 10))
num_inputs, num_outputs, num_hiddens1, num_hiddens2 = 28*28, 10, 256, 256
dropout1, dropout2 = 0.2, 0.5
class Net(nn.Module):def __init__(self, num_inputs, num_outputs, num_hiddens1, num_hiddens2, is_training = True):super(Net, self).__init__()self.training = is_trainingself.h1 = nn.Linear(num_inputs, num_hiddens1)self.h2 = nn.Linear(num_hiddens1, num_hiddens2)self.h3 = nn.Linear(num_hiddens2, num_outputs)self.Relu = nn.ReLU()def forward(self, x):x = x.view(-1, num_inputs)  # 将输入形状调整为 [batch_size, num_inputs]H1 = self.Relu(self.h1(x))if self.training == True:H1 = dropout_layer(H1, dropout1)H2 = self.Relu(self.h2(H1))if self.training == True:H2 = dropout_layer(H2, dropout2)out = self.h3(H2)return outnet = Net(num_inputs, num_outputs, num_hiddens1, num_hiddens2)
x = torch.rand(size=(1,28*28),dtype=torch.float32)
def print_layer_outputs(net, x):for name, layer in net.named_children():x = layer(x)print(f"{name} output shape: {x.shape}")print_layer_outputs(net, x)

4.3 训练和测试

def train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer):argmax = lambda x, *args, **kwargs: x.argmax(*args, **kwargs)astype = lambda x, *args, **kwargs: x.type(*args, **kwargs) #转换数据类型reduce_sum = lambda x, *args, **kwargs: x.sum(*args, **kwargs) #求和# 对n个变量求和class Accumulator:"""For accumulating sums over `n` variables."""def __init__(self, n):"""Defined in :numref:`sec_utils`"""self.data = [0.0] * ndef add(self, *args):self.data = [a + float(b) for a, b in zip(self.data, args)]def reset(self):self.data = [0.0] * len(self.data)def __getitem__(self, idx):return self.data[idx]# 计算正确预测的数量def accuracy(y_hat, y):"""Compute the number of correct predictions.Defined in :numref:`sec_utils`"""if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:y_hat = argmax(y_hat, axis=1)cmp = astype(y_hat, y.dtype) == yreturn float(reduce_sum(astype(cmp, y.dtype)))# 单轮训练def train_epoch(net, train_iter, loss, trainer):if isinstance(net, nn.Module):net.train()metric_train = Accumulator(3)for X, y in train_iter:y_hat = net(X)l = loss(y_hat, y)if isinstance(trainer, torch.optim.Optimizer):trainer.zero_grad()l.mean().backward()trainer.step()else:l.sum().backward()trainer(X.shape[0])metric_train.add(float(l.sum()), accuracy(y_hat, y), y.numel())#返回训练损失和训练精度return metric_train[0]/metric_train[2], metric_train[1]/metric_train[2]# 用于计算验证集上的准确率def evalution_loss_accuracy(net, loss, data_iter):if isinstance(net, torch.nn.Module):net.eval()meteric = Accumulator(3)with torch.no_grad():for X, y in data_iter:l = loss(net(X), y)meteric.add(float(l.sum()), accuracy(net(X), y), y.numel())return meteric[0]/meteric[2], meteric[1]/meteric[2],# 训练集损失列表train_loss_all = []# 验证集损失列表val_loss_all = []# 训练集准确度列表train_acc_all = []# 验证集准确度列表val_acc_all = []for epoch in range(num_epochs):print("Epoch {}/{}".format(epoch, num_epochs - 1))print("-" * 10)train_metrics = train_epoch(net, train_iter, loss, trainer)print("{} train loss:{:.4f} train acc: {:.4f}".format(epoch, train_metrics[0], train_metrics[1]))# print(train_metrics)test_metrics = evalution_loss_accuracy(net, loss, test_iter)print("{} train loss:{:.4f} train acc: {:.4f}".format(epoch, test_metrics[0], test_metrics[1]))train_loss_all.append(train_metrics[0])train_acc_all.append(train_metrics[1])val_loss_all.append(test_metrics[0])val_acc_all.append(test_metrics[1])train_process = pd.DataFrame(data={"epoch": range(num_epochs),"train_loss_all": train_loss_all,"val_loss_all": val_loss_all,"train_acc_all": train_acc_all,"val_acc_all": val_acc_all})return train_processdef matplot_acc_loss(train_process):# 显示每一次迭代后的训练集和验证集的损失函数和准确率plt.figure(figsize=(12, 4))plt.subplot(1, 2, 1)plt.plot(train_process['epoch'], train_process.train_loss_all, "ro-", label="Train loss")plt.plot(train_process['epoch'], train_process.val_loss_all, "bs-", label="Val loss")plt.legend()plt.xlabel("epoch")plt.ylabel("Loss")plt.subplot(1, 2, 2)plt.plot(train_process['epoch'], train_process.train_acc_all, "ro-", label="Train acc")plt.plot(train_process['epoch'], train_process.val_acc_all, "bs-", label="Val acc")plt.xlabel("epoch")plt.ylabel("acc")plt.legend()plt.show()

4.4 完整代码

import pandas as pd
import torch
import matplotlib.pyplot as plt
from torch import nn
from d2l import torch as d2ldef dropout_layer(X, dropout):assert 0 <= dropout <= 1if dropout == 0:return torch.zeros_like(X)if dropout == 1:return Xmask = (torch.Tensor(X.shape).uniform_(0, 1) > dropout).float()return mask * X / (1.0 - dropout)
x = torch.arange(16, dtype=torch.float32).reshape((2,8))
# print(x)
# print(dropout_layer(x, 0))
# print(dropout_layer(x, 0.5))
# print(dropout_layer(x, 1.0))num_inputs, num_outputs, num_hiddens1, num_hiddens2 = 28*28, 10, 256, 256
dropout1, dropout2 = 0.2, 0.5
class Net(nn.Module):def __init__(self, num_inputs, num_outputs, num_hiddens1, num_hiddens2, is_training = True):super(Net, self).__init__()self.training = is_trainingself.h1 = nn.Linear(num_inputs, num_hiddens1)self.h2 = nn.Linear(num_hiddens1, num_hiddens2)self.h3 = nn.Linear(num_hiddens2, num_outputs)self.Relu = nn.ReLU()def forward(self, x):x = x.view(-1, num_inputs)  # 将输入形状调整为 [batch_size, num_inputs]H1 = self.Relu(self.h1(x))if self.training == True:H1 = dropout_layer(H1, dropout1)H2 = self.Relu(self.h2(H1))if self.training == True:H2 = dropout_layer(H2, dropout2)out = self.h3(H2)return out
# x = torch.rand(size=(1,28*28),dtype=torch.float32)
# def print_layer_outputs(net, x):
#     for name, layer in net.named_children():
#         x = layer(x)
#         print(f"{name} output shape: {x.shape}")
#
# print_layer_outputs(net, x)
def train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer):argmax = lambda x, *args, **kwargs: x.argmax(*args, **kwargs)astype = lambda x, *args, **kwargs: x.type(*args, **kwargs) #转换数据类型reduce_sum = lambda x, *args, **kwargs: x.sum(*args, **kwargs) #求和# 对n个变量求和class Accumulator:"""For accumulating sums over `n` variables."""def __init__(self, n):"""Defined in :numref:`sec_utils`"""self.data = [0.0] * ndef add(self, *args):self.data = [a + float(b) for a, b in zip(self.data, args)]def reset(self):self.data = [0.0] * len(self.data)def __getitem__(self, idx):return self.data[idx]# 计算正确预测的数量def accuracy(y_hat, y):"""Compute the number of correct predictions.Defined in :numref:`sec_utils`"""if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:y_hat = argmax(y_hat, axis=1)cmp = astype(y_hat, y.dtype) == yreturn float(reduce_sum(astype(cmp, y.dtype)))# 单轮训练def train_epoch(net, train_iter, loss, trainer):if isinstance(net, nn.Module):net.train()metric_train = Accumulator(3)for X, y in train_iter:y_hat = net(X)l = loss(y_hat, y)if isinstance(trainer, torch.optim.Optimizer):trainer.zero_grad()l.mean().backward()trainer.step()else:l.sum().backward()trainer(X.shape[0])metric_train.add(float(l.sum()), accuracy(y_hat, y), y.numel())#返回训练损失和训练精度return metric_train[0]/metric_train[2], metric_train[1]/metric_train[2]# 用于计算验证集上的准确率def evalution_loss_accuracy(net, loss, data_iter):if isinstance(net, torch.nn.Module):net.eval()meteric = Accumulator(3)with torch.no_grad():for X, y in data_iter:l = loss(net(X), y)meteric.add(float(l.sum()), accuracy(net(X), y), y.numel())return meteric[0]/meteric[2], meteric[1]/meteric[2]# 训练集损失列表train_loss_all = []# 验证集损失列表val_loss_all = []# 训练集准确度列表train_acc_all = []# 验证集准确度列表val_acc_all = []for epoch in range(num_epochs):print("Epoch {}/{}".format(epoch, num_epochs - 1))print("-" * 10)train_metrics = train_epoch(net, train_iter, loss, trainer)print("{} train loss:{:.4f} train acc: {:.4f}".format(epoch, train_metrics[0], train_metrics[1]))# print(train_metrics)test_metrics = evalution_loss_accuracy(net, loss, test_iter)print("{} train loss:{:.4f} train acc: {:.4f}".format(epoch, test_metrics[0], test_metrics[1]))train_loss_all.append(train_metrics[0])train_acc_all.append(train_metrics[1])val_loss_all.append(test_metrics[0])val_acc_all.append(test_metrics[1])train_process = pd.DataFrame(data={"epoch": range(num_epochs),"train_loss_all": train_loss_all,"val_loss_all": val_loss_all,"train_acc_all": train_acc_all,"val_acc_all": val_acc_all})return train_processdef matplot_acc_loss(train_process):# 显示每一次迭代后的训练集和验证集的损失函数和准确率plt.figure(figsize=(12, 4))plt.subplot(1, 2, 1)plt.plot(train_process['epoch'], train_process.train_loss_all, "ro-", label="Train loss")plt.plot(train_process['epoch'], train_process.val_loss_all, "bs-", label="Val loss")plt.legend()plt.xlabel("epoch")plt.ylabel("Loss")plt.subplot(1, 2, 2)plt.plot(train_process['epoch'], train_process.train_acc_all, "ro-", label="Train acc")plt.plot(train_process['epoch'], train_process.val_acc_all, "bs-", label="Val acc")plt.xlabel("epoch")plt.ylabel("acc")plt.legend()plt.show()if __name__ == '__main__':net = Net(num_inputs, num_outputs, num_hiddens1, num_hiddens2)num_eporch, lr, batch_size = 10, 0.5, 256train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size)loss = nn.CrossEntropyLoss(reduction='none')trainer = torch.optim.SGD(net.parameters(), lr)train_process = train_ch3(net, train_iter, test_iter, loss, num_eporch, trainer)matplot_acc_loss(train_process)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/51395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

科普文:万字详解Kafka基本原理和应用

一、Kafka 简介 1. 消息引擎系统ABC Apache Kafka是一款开源的消息引擎系统&#xff0c;也是一个分布式流处理平台。除此之外&#xff0c;Kafka还能够被用作分布式存储系统&#xff08;极少&#xff09;。 A. 常见的两种消息引擎系统传输协议&#xff08;即用什么方式把消息…

【机器学习】探索图神经网络 (GNNs): 揭秘图结构数据处理的未来

&#x1f48e; 欢迎大家互三&#xff1a;2的n次方_ ​ &#x1f48e;1. 引言 图结构数据在现实世界中无处不在&#xff0c;从社交网络中的用户关系&#xff0c;到推荐系统中的用户-物品交互&#xff0c;再到生物信息学中的分子结构。传统的机器学习模型在处理这些数据时常常力…

【Unity插件】Editor Console Pro:提升开发效率的神器

在 Unity 开发过程中&#xff0c;控制台&#xff08;Console&#xff09;是我们排查错误、获取信息的重要窗口。而 Editor Console Pro 则是 Unity 编辑器控制台的强大替代品&#xff0c;为 Unity 的控制台带来了更多实用的功能和改进&#xff0c;极大地提升了开发效率。 一、…

力扣刷题----42. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图&#xf…

TCP程序设计

TCP概述 建立连接 客户端和服务器端在建立连接时&#xff1a; 服务端是典型的监听接受连接的模式&#xff0c;就是ListenAccept 客户端是主动建立连接的模式&#xff0c;就是Dial Go语言中使用 net包实现网络的相关操作&#xff0c;包括我们TCP的操作。 用于建立连接的典型…

【JavaEE】阻塞队列

目录 一.阻塞队列(Blocking Queue) 1.什么是阻塞队列 2.特性 二.生产者消费者模型 1.什么是生产者消费者模型&#xff1f; 2.生产者消费模型的好处 2.1解耦合 2.2削峰填谷 三.如何在java中使用阻塞队列 四.模拟实现阻塞队列 1.加锁 2.阻塞等待实现 3.解决interru…

学习c语言第十三天(结构体)

一.结构体声明 结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。 描述复杂对象。 结构体成员可以是标量、数组、指针、结构体。 定义和初始化&#xff1a; struct peo {char namer[20];char tele[12];char sex[5];int high; }; s…

git 迁移仓库的方法

git Git是一个开源的分布式版本控制系统&#xff0c;由Linus Torvalds在2005年创建&#xff0c;用于有效、高速地处理从小到大的项目管理。它最初是为Linux内核开发而设计的&#xff0c;但很快被广泛用于各种项目。 以下是Git的一些主要特性&#xff1a; 分布式架构&#xff…

Python设计模式 - 工厂方法模式

定义 工厂方法模式是一种创建型设计模式&#xff0c;它定义一个创建对象的接口&#xff0c;让其子类来处理对象的创建&#xff0c;而不是直接实例化对象。 结构 抽象工厂&#xff08;Factory&#xff09;&#xff1a;声明工厂方法&#xff0c;返回一个产品对象。具体工厂类都…

4.JAVA-运算符

算数运算符 隐式类型转换 强制转换 字符串操作 字符相加 小结 自增自减运算符 赋值运算符 关系运算符 逻辑运算符 短路逻辑运算 三元运算符 运算符优先级 这里小括号优先于所有&#xff0c;所以想要哪一个优先运算&#xff0c;就可以将哪一个用小括号扩起来&#xff0c;比较方便…

酒店押金原路退回系统开通方法,手机查看报表

一、酒店押金管理有哪些&#xff1f; 1.渠道有银行预授权 2.微信押金支付 3.酒店押金系统 4.支付押金管理 二、专业酒店押金管理VS银行 序号功能专业押金系统银行预授权1收款方式支持微信、支付宝、银联app、信用卡、花呗需要带银行卡刷卡2资金安全区分房费和押金&#x…

PermissionError: [Errno 13] Permission denied

PermissionError: [Errno 13] Permission denied 目录 PermissionError: [Errno 13] Permission denied 【常见模块错误】 【错误原因】 【解决方案】 检查文件或目录的权限 确保文件路径正确 关闭其他占用文件的程序 运行程序时提升权限 更改 Python 的工作目录 示例代…

什么是职场?如何在职场中提升自己的情商?

职场这一概念&#xff0c;实质上是指在工作场所中&#xff0c;员工与员工之间、员工与组织之间相互发生作用和影响的一个特定环境。它不仅仅局限于办公室&#xff0c;还延展到会议室、休息室、餐厅等场所&#xff0c;这些场所交织成了一个错综复杂的职场生态系统。在这个系统中…

哪里可以查找短视频素材?6个素材查找下载渠道分享!

在短视频的风靡浪潮中&#xff0c;不少创作者纷纷投身于这一领域&#xff0c;无论是分享生活点滴还是进行商业宣传&#xff0c;高质量的短视频内容总能吸引众多观众的目光。然而&#xff0c;精良的短视频制作离不开优质的素材支持。本文将为大家介绍6个优秀的高质量短视频素材下…

POJ2739.Sum of Consecutive Prime Numbers

欧拉筛处理2-1e4的质数&#xff0c;再用尺取法即可 // Problem: Sum of Consecutive Prime Numbers // Contest: POJ - Japan 2005 // URL: http://poj.org/problem?id2739 // Memory Limit: 65 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.or…

[240727] Qt Creator 14 发布 | AMD 推迟 Ryzen 9000芯片发布

目录 Qt Creator 14 发布Qt Creator 14 版本发布&#xff0c;带来一系列新功能和改进终端用户可通过命令行方式查看此新闻终端用户可通过命令行方式安装软件&#xff1a; AMD 推迟 Ryzen 9000芯片发布 Qt Creator 14 发布 Qt Creator 14 版本发布&#xff0c;带来一系列新功能…

高速板开源项目学习(二)

一定要找一个高速板写的详细的等长规范&#xff1a; 看的出来&#xff0c;这位小哥也是卡着嘉立创最小免费钻孔大小来打孔的&#xff1a; 这里的天线&#xff0c;他做了禁止铺铜和走线处理&#xff0c;模拟信号在这里容易遇到干扰&#xff0c;这样是正确的&#xff0c;值得去学…

《知识点扫盲 · 线程池基础篇》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

【node】Linux下安装node和npm

Linux下安装node和npm 下面的版本虽然安装失败了&#xff0c;第一次尝试不容易&#xff0c;只需要更换一下node的版本为v16.20.2即可安装成功&#xff0c;20这样的高版本对大部分linux服务器来讲还是版本太高了&#xff0c;GLIBC动态库不支持&#xff0c;升级颇为麻烦&#xff…

她是军统美女特工,色诱汉奸一把好手!一件事之后竟......

一.前言 我们在上一篇里简单了解了什么是树&#xff0c;以及树的一种特殊结构——二叉树。而我们对二叉树息息相关的堆进行了简单的介绍。我们知道了堆是借助二叉树中完全二叉树来实现的。它实现了二叉树的顺序存储。但对于普通的二叉树来说&#xff0c;顺序存储会造成空间浪费…