当前位置: 首页 > news >正文

深度学习-全连接神经网络(过拟合,欠拟合。批量标准化)

七、过拟合与欠拟合

在训练深层神经网络时,由于模型参数较多,在数据量不足时很容易过拟合。而正则化技术主要就是用于防止过拟合,提升模型的泛化能力(对新数据表现良好)和鲁棒性(对异常数据表现良好)。

1. 概念认知

这里我们简单的回顾下过拟合和欠拟合的基本概念~

1.1 过拟合

过拟合是指模型对训练数据拟合能力很强并表现很好,但在测试数据上表现较差。

过拟合常见原因有:

  1. 数据量不足:当训练数据较少时,模型可能会过度学习数据中的噪声和细节。

  2. 模型太复杂:如果模型很复杂,也会过度学习训练数据中的细节和噪声。

  3. 正则化强度不足:如果正则化强度不足,可能会导致模型过度学习训练数据中的细节和噪声。

举个例子:

1.2 欠拟合

欠拟合是由于模型学习能力不足,无法充分捕捉数据中的复杂关系。

1.3 如何判断

那如何判断一个错误的结果是过拟合还是欠拟合呢?

过拟合

训练误差低,但验证时误差高。模型在训练数据上表现很好,但在验证数据上表现不佳,说明模型可能过度拟合了训练数据中的噪声或特定模式。

欠拟合

训练误差和测试误差都高。模型在训练数据和测试数据上的表现都不好,说明模型可能太简单,无法捕捉到数据中的复杂模式。

2. 解决欠拟合

欠拟合的解决思路比较直接:

  1. 增加模型复杂度:引入更多的参数、增加神经网络的层数或节点数量,使模型能够捕捉到数据中的复杂模式。

  2. 增加特征:通过特征工程添加更多有意义的特征,使模型能够更好地理解数据。

  3. 减少正则化强度:适当减小 L1、L2 正则化强度,允许模型有更多自由度来拟合数据。

  4. 训练更长时间:如果是因为训练不足导致的欠拟合,可以增加训练的轮数或时间.

3. 解决过拟合

避免模型参数过大是防止过拟合的关键步骤之一。

模型的复杂度主要由权重w决定,而不是偏置b。偏置只是对模型输出的平移,不会导致模型过度拟合数据。

怎么控制权重w,使w在比较小的范围内?

考虑损失函数,损失函数的目的是使预测值与真实值无限接近,如果在原来的损失函数上添加一个非0的变量

其中是关于权重w的函数,​

要使L1变小,就要使L变小的同时,也要使变小。从而控制权重w在较小的范围内。

3.1 L2正则化

L2 正则化通过在损失函数中添加权重参数的平方和来实现,目标是惩罚过大的参数值。

3.1.1 数学表示

设损失函数为 ,其中 表示权重参数,加入L2正则化后的损失函数表示为:

其中:

  • 是原始损失函数(比如均方误差、交叉熵等)。

  • 是正则化强度,控制正则化的力度。

  • 是模型的第 ​ 个权重参数。

  • 是所有权重参数的平方和,称为 L2 正则化项。

L2 正则化会惩罚权重参数过大的情况,通过参数平方值对损失函数进行约束。

为什么是?

假设没有1/2,则对L2 正则化项的梯度为:,会引入一个额外的系数 2,使梯度计算和更新公式变得复杂。

添加1/2后,对的梯度为:。

3.1.2 梯度更新

在 L2 正则化下,梯度更新时,不仅要考虑原始损失函数的梯度,还要考虑正则化项的影响。更新规则为:

其中:

  • 是学习率。

  • 是损失函数关于参数 的梯度。

  • 是 L2 正则化项的梯度,对应的是参数值本身的衰减。

很明显,参数越大惩罚力度就越大,从而让参数逐渐趋向于较小值,避免出现过大的参数。

3.1.3 作用
  1. 防止过拟合:当模型过于复杂、参数较多时,模型会倾向于记住训练数据中的噪声,导致过拟合。L2 正则化通过抑制参数的过大值,使得模型更加平滑,降低模型对训练数据噪声的敏感性。

  2. 限制模型复杂度:L2 正则化项强制权重参数尽量接近 0,避免模型中某些参数过大,从而限制模型的复杂度。通过引入平方和项,L2 正则化鼓励模型的权重均匀分布,避免单个权重的值过大。

  3. 提高模型的泛化能力:正则化项的存在使得模型在测试集上的表现更加稳健,避免在训练集上取得极高精度但在测试集上表现不佳。

  4. 平滑权重分布:L2 正则化不会将权重直接变为 0,而是将权重值缩小。这样模型就更加平滑的拟合数据,同时保留足够的表达能力。

3.1.4 代码实现

代码实现如下:

import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
​
# 设置随机种子以保证可重复性
torch.manual_seed(42)
​
# 生成随机数据
n_samples = 100
n_features = 20
X = torch.randn(n_samples, n_features)  # 输入数据
y = torch.randn(n_samples, 1)  # 目标值
​
​
# 定义一个简单的全连接神经网络
class SimpleNet(nn.Module):def __init__(self):super(SimpleNet, self).__init__()self.fc1 = nn.Linear(n_features, 50)self.fc2 = nn.Linear(50, 1)
​def forward(self, x):x = torch.relu(self.fc1(x))return self.fc2(x)
​
​
# 训练函数
def train_model(use_l2=False, weight_decay=0.01, n_epochs=100):# 初始化模型model = SimpleNet()criterion = nn.MSELoss()  # 损失函数(均方误差)
​# 选择优化器if use_l2:optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=weight_decay)  # 使用 L2 正则化else:optimizer = optim.SGD(model.parameters(), lr=0.01)  # 不使用 L2 正则化
​# 记录训练损失train_losses = []
​# 训练过程for epoch in range(n_epochs):optimizer.zero_grad()  # 清空梯度outputs = model(X)  # 前向传播loss = criterion(outputs, y)  # 计算损失loss.backward()  # 反向传播optimizer.step()  # 更新参数
​train_losses.append(loss.item())  # 记录损失
​if (epoch + 1) % 10 == 0:print(f'Epoch [{epoch + 1}/{n_epochs}], Loss: {loss.item():.4f}')
​return train_losses
​
​
# 训练并比较两种模型
train_losses_no_l2 = train_model(use_l2=False)  # 不使用 L2 正则化
train_losses_with_l2 = train_model(use_l2=True, weight_decay=0.01)  # 使用 L2 正则化
​
# 绘制训练损失曲线
plt.plot(train_losses_no_l2, label='Without L2 Regularization')
plt.plot(train_losses_with_l2, label='With L2 Regularization')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss: L2 Regularization vs No Regularization')
plt.legend()
plt.show()

3.2 L1正则化

L1 正则化通过在损失函数中添加权重参数的绝对值之和来约束模型的复杂度。

3.2.1 数学表示

设模型的原始损失函数为 ,其中 表示模型权重参数,则加入 L1 正则化后的损失函数表示为:

其中:

  • 是原始损失函数。

  • 是正则化强度,控制正则化的力度。

  • 是模型第 个参数的绝对值。

  • 是所有权重参数的绝对值之和,这个项即为 L1 正则化项。

3.2.2 梯度更新

在 L1 正则化下,梯度更新时的公式是:

其中:

  • 是学习率。

  • 是损失函数关于参数 的梯度。

  • 是参数 的符号函数,表示当 为正时取值为 ,为负时取值为 ,等于 0 时为 。

因为 L1 正则化依赖于参数的绝对值,其梯度更新时不是简单的线性缩小,而是通过符号函数来直接调整参数的方向。这就是为什么 L1 正则化能促使某些参数完全变为 0。

3.2.3 作用
  1. 稀疏性:L1 正则化的一个显著特性是它会促使许多权重参数变为 。这是因为 L1 正则化倾向于将权重绝对值缩小到零,使得模型只保留对结果最重要的特征,而将其他不相关的特征权重设为零,从而实现 特征选择 的功能。

  2. 防止过拟合:通过限制权重的绝对值,L1 正则化减少了模型的复杂度,使其不容易过拟合训练数据。相比于 L2 正则化,L1 正则化更倾向于将某些权重完全移除,而不是减小它们的值。

  3. 简化模型:由于 L1 正则化会将一些权重变为零,因此模型最终会变得更加简单,仅依赖于少数重要特征。这对于高维度数据特别有用,尤其是在特征数量远多于样本数量的情况下。

  4. 特征选择:因为 L1 正则化会将部分权重置零,因此它天然具有特征选择的能力,有助于自动筛选出对模型预测最重要的特征。

3.2.4 与L2对比
  • L1 正则化 更适合用于产生稀疏模型,会让部分权重完全为零,适合做特征选择。

  • L2 正则化 更适合平滑模型的参数,避免过大参数,但不会使权重变为零,适合处理高维特征较为密集的场景。

3.2.5 代码实现

代码需要自己实现:

l1_lambda = 0.001
# 计算 L1 正则化项并将其加入到总损失中
l1_norm = sum(p.abs().sum() for p in model.parameters())
loss = loss + l1_lambda * l1_norm

3.3 Dropout

Dropout 的工作流程如下:

  1. 在每次训练迭代中,随机选择一部分神经元(通常以概率 p丢弃,比如 p=0.5)。

  2. 被选中的神经元在当前迭代中不参与前向传播和反向传播。

  3. 在测试阶段,所有神经元都参与计算,但需要对权重进行缩放(通常乘以 1−p),以保持输出的期望值一致。

Dropout 是一种在训练过程中随机丢弃部分神经元的技术。它通过减少神经元之间的依赖来防止模型过于复杂,从而避免过拟合。

3.3.1 基本实现
import torch
import torch.nn as nn
​
​
def dropout():dropout = nn.Dropout(p=0.5)x = torch.randint(0, 10, (5, 6), dtype=torch.float)print(x)# 开始dropoutprint(dropout(x))
​
​
if __name__ == "__main__":dropout()
​

Dropout过程:

  1. 按照指定的概率把部分神经元的值设置为0;

  2. 为了规避该操作带来的影响,需对非 0 的元素使用缩放因子进行强化。

假设某个神经元的输出为 x,Dropout 的操作可以表示为:

  • 在训练阶段:

    以概率保留神经元以概率丢弃神经元

  • 在测试阶段:

为什么要使用缩放因子?

在训练阶段,Dropout 会以概率 p随机将某些神经元的输出设置为 0,而以概率 1−p 保留这些神经元。

假设某个神经元的原始输出是 x,那么在训练阶段,它的期望输出值为:

通过这种缩放,训练阶段的期望输出值仍然是 x,与没有 Dropout 时一致。

3.3.2 权重影响
import torch
import torch.nn as nn
​
​
def test001():torch.manual_seed(0)w = torch.randn(12, 1, requires_grad=True)x = torch.randint(0, 8, (3, 12)).float()output = x @ woutput = output.sum()output.backward()print(w.grad.flatten())
​
​
def test002():torch.manual_seed(0)dropout = nn.Dropout(0.8)w = torch.randn(12, 1, requires_grad=True)x = torch.randint(0, 8, (3, 12)).float()# 随机抛点x = dropout(x)print(x)output = x @ woutput = output.sum()output.backward()print(w.grad.flatten())
​
​
if __name__ == "__main__":test001()test002()
​

输出结果:如果所有的数据的对应特征都为0,则参数梯度为0

tensor([12., 15., 12.,  2.,  8.,  4.,  8.,  5., 13.,  7., 10., 15.])
tensor([[ 0.,  5., 25.,  0.,  0.,  0.,  0.,  0., 15.,  0., 15.,  0.],[ 0.,  0.,  0.,  0.,  0., 15.,  0.,  0.,  0.,  0.,  0.,  0.],[30.,  0.,  0.,  0.,  5.,  5.,  0.,  0.,  0.,  0.,  0.,  0.]])
tensor([30.,  5., 25.,  0.,  5., 20.,  0.,  0., 15.,  0., 15.,  0.])

示例:对图片进行随机丢弃

import torch
from torch import nn
from PIL import Image
from torchvision import transforms
import os
​
from matplotlib import pyplot as plt
​
torch.manual_seed(42)
​
​
def load_img(path, resize=(224, 224)):pil_img = Image.open(path).convert('RGB')print("Original image size:", pil_img.size)  # 打印原始尺寸transform = transforms.Compose([transforms.Resize(resize),transforms.ToTensor()  # 转换为Tensor并自动归一化到[0,1]])return transform(pil_img)  # 返回[C,H,W]格式的tensor
​
​
if __name__ == '__main__':dirpath = os.path.dirname(__file__)path = os.path.join(dirpath, 'img', '100.jpg')  # 使用os.path.join更安全
​# 加载图像 (已经是[0,1]范围的Tensor)trans_img = load_img(path)
​# 添加batch维度 [1, C, H, W],因为Dropout默认需要4D输入trans_img = trans_img.unsqueeze(0)
​# 创建Dropout层dropout = nn.Dropout2d(p=0.2)
​drop_img = dropout(trans_img)
​# 移除batch维度并转换为[H,W,C]格式供matplotlib显示trans_img = trans_img.squeeze(0).permute(1, 2, 0).numpy()drop_img = drop_img.squeeze(0).permute(1, 2, 0).numpy()
​# 确保数据在[0,1]范围内drop_img = drop_img.clip(0, 1)
​# 显示图像fig = plt.figure(figsize=(10, 5))
​ax1 = fig.add_subplot(1, 2, 1)ax1.imshow(trans_img)
​ax2 = fig.add_subplot(1, 2, 2)ax2.imshow(drop_img)
​plt.show()

效果:

说明:

nn.Dropout2d(p):Dropout2d 是针对二维数据设计的 Dropout 层,它在训练过程中随机将输入张量的某些通道(二维平面)置为零。

参数要求格式示例形状说明
输入(N, C, H, W)(16, 64, 32, 32)批大小×通道×高×宽
输出(N, C, H, W)(16, 64, 32, 32)与输入同形,部分通道归零

3.4 简化模型

  • 减少网络层数和参数: 通过减少网络的层数、每层的神经元数量或减少卷积层的滤波器数量,可以降低模型的复杂度,减少过拟合的风险。

  • 使用更简单的模型: 对于复杂问题,使用更简单的模型或较小的网络架构可以减少参数数量,从而降低过拟合的可能性。

3.5 数据增强

样本数量不足(即训练数据过少)是导致过拟合(Overfitting)的常见原因之一,可以从以下角度理解:

  • 当训练数据过少时,模型容易“记住”有限的样本(包括噪声和无关细节),而非学习通用的规律。

  • 简单模型更可能捕捉真实规律,但数据不足时,复杂模型会倾向于拟合训练集中的偶然性模式(噪声)。

  • 样本不足时,训练集的分布可能与真实分布偏差较大,导致模型学到错误的规律。

  • 小数据集中,个别样本的噪声(如标注错误、异常值)会被放大,模型可能将噪声误认为规律。

数据增强(Data Augmentation)是一种通过人工生成或修改训练数据来增加数据集多样性的技术,常用于解决过拟合问题。数据增强通过“模拟”更多训练数据,迫使模型学习泛化性更强的规律,而非训练集中的偶然性模式。其本质是一种低成本的正则化手段,尤其在数据稀缺时效果显著。

在了解计算机如何处理图像之前,需要先了解图像的构成元素。

图像是由像素点组成的,每个像素点的值范围为: [0, 255], 像素值越大意味着较亮。比如一张 200x200 的图像, 则是由 40000 个像素点组成, 如果每个像素点都是 0 的话, 意味着这是一张全黑的图像。

我们看到的彩色图一般都是多通道的图像, 所谓多通道可以理解为图像由多个不同的图像层叠加而成, 例如我们看到的彩色图像一般都是由 RGB 三个通道组成的,还有一些图像具有 RGBA 四个通道,最后一个通道为透明通道,该值越小,则图像越透明。

数据增强是提高模型泛化能力(鲁棒性)的一种有效方法,尤其在图像分类、目标检测等任务中。数据增强可以模拟更多的训练样本,从而减少过拟合风险。数据增强通过torchvision.transforms模块来实现。

数据增强的好处

大幅度降低数据采集和标注成本;

模型过拟合风险降低,提高模型泛化能力;

官方地址:

transforms:Transforming and augmenting images — Torchvision 0.21 documentation

transforms:

常用变换类

  • transforms.Compose:将多个变换操作组合成一个流水线。

  • transforms.ToTensor:将 PIL 图像或 NumPy 数组转换为 PyTorch 张量,将图像数据从 uint8 类型 (0-255) 转换为 float32 类型 (0.0-1.0)。

  • transforms.Normalize:对张量进行标准化。

  • transforms.Resize:调整图像大小。

  • transforms.CenterCrop:从图像中心裁剪指定大小的区域。

  • transforms.RandomCrop:随机裁剪图像。

  • transforms.RandomHorizontalFlip:随机水平翻转图像。

  • transforms.RandomVerticalFlip:随机垂直翻转图像。

  • transforms.RandomRotation:随机旋转图像。

  • transforms.ColorJitter:随机调整图像的亮度、对比度、饱和度和色调。

  • transforms.RandomGrayscale:随机将图像转换为灰度图像。

  • transforms.RandomResizedCrop:随机裁剪图像并调整大小。

3.5.1 图片缩放

具体参考官方文档:Illustration of transforms — Torchvision 0.21 documentation

参考代码:

from PIL import Image
​
def test03():img1 = plt.imread('./img/100.jpg')plt.imshow(img1)plt.show()
​img = Image.open('./img/100.jpg')transform = transforms.Compose([transforms.Resize((224, 224)), transforms.ToTensor()])r_img = transform(img)print(r_img.shape)
​r_img = r_img.permute(1, 2, 0)
​plt.imshow(r_img)plt.show()
​
3.5.2 随机裁剪
    img = Image.open('./img/100.jpg')transform = transforms.Compose([transforms.RandomCrop(size=(224, 224)), transforms.ToTensor()])r_img = transform(img)print(r_img.shape)
​r_img = r_img.permute(1, 2, 0)
​plt.imshow(r_img)plt.show()
3.5.3 随机水平翻转

RandomHorizontalFlip(p):随机水平翻转图像,参数p表示翻转概率(0 ≤ p ≤ 1),p=1 表示必定翻转,p=0 表示不翻转

    img = Image.open('./img/100.jpg')transform = transforms.Compose([transforms.RandomHorizontalFlip(p=1), transforms.ToTensor()])r_img = transform(img)print(r_img.shape)
​r_img = r_img.permute(1, 2, 0)
​plt.imshow(r_img)plt.show()
3.5.4 调整图片颜色
transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0)

brightness:

  • 亮度调整的范围。

  • 可以float(min, max) 元组:

    • 如果是 float(如 brightness=0.2),则亮度在 [max(0, 1 - 0.2), 1 + 0.2] = [0.8, 1.2] 范围内随机缩放。

    • 如果是 (min, max)(如 brightness=(0.5, 1.5)),则亮度在 [0.5, 1.5] 范围内随机缩放。

contrast:

  • 对比度调整的范围。

  • 格式与 brightness 相同。

saturation:

  • 饱和度调整的范围。

  • 格式与 brightness 相同。

hue:

  • 色调调整的范围。

  • 可以是一个浮点数(表示相对范围)或一个元组 (min, max)。

  • 取值范围必须为 [-0.5, 0.5](因为色相在 HSV 色彩空间中是循环的,超出范围会导致颜色异常)。

  • 例如,hue=0.1 表示色调在 [-0.1, 0.1] 之间随机调整。

    img = Image.open('./img/100.jpg')transform = transforms.Compose([transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.2), transforms.ToTensor()])r_img = transform(img)print(r_img.shape)
​r_img = r_img.permute(1, 2, 0)
​plt.imshow(r_img)plt.show()
3.5.5 随机旋转

RandomRotation用于对图像进行随机旋转。

transforms.RandomRotation(degrees, interpolation=InterpolationMode.NEAREST, expand=False, center=None, fill=0
)

degrees:

  • 旋转角度的范围,可以是一个浮点数或元组 (min_degree, max_degree)。

  • 例如,degrees=30 表示旋转角度在 [-30, 30] 之间随机选择。

  • 例如,degrees=(30, 60) 表示旋转角度在 [30, 60] 之间随机选择。

interpolation:

  • 插值方法,用于旋转图像。

  • 默认是 InterpolationMode.NEAREST(最近邻插值)。

  • 其他选项包括 InterpolationMode.BILINEAR(双线性插值)、InterpolationMode.BICUBIC(双三次插值)等。

expand:

  • 是否扩展图像大小以适应旋转后的图像。如:当需要保留完整旋转后的图像时(如医学影像、文档扫描)

  • 如果为 True,旋转后的图像可能会比原始图像大。

  • 如果为 False,旋转后的图像大小与原始图像相同。

center:

  • 旋转中心点的坐标,默认为图像中心。

  • 可以是一个元组 (x, y),表示旋转中心的坐标。

fill:

  • 旋转后图像边缘的填充值。

  • 可以是一个浮点数(用于灰度图像)或一个元组(用于 RGB 图像)。默认填充0(黑色)

    # 加载图像image = Image.open('./img/100.jpg')
​# 定义 RandomRotation 变换transform = transforms.RandomRotation(degrees=30)  # 旋转角度在 [-30, 30] 之间随机选择
​# 应用变换rotated_image = transform(image)
​# 显示图像plt.imshow(rotated_image)plt.axis('off')plt.show()
3.5.6 归一化
  • 标准化:将图像的像素值从原始范围(如 [0, 255] 或 [0, 1])转换为均值为 0、标准差为 1 的分布。

  • 加速训练:标准化后的数据分布更均匀,有助于加速模型训练。

  • 提高模型性能:标准化可以使模型更容易学习到数据的特征,提高模型的收敛性和稳定性。

    img = Image.open('./img/100.jpg')transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])r_img = transform(img)print(r_img.shape)
​r_img = r_img.permute(1, 2, 0)
​plt.imshow(r_img)plt.show()

mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])]

均值(Mean):数据集中所有图像在每个通道上的像素值的平均值。

标准差(Std):数据集中所有图像在每个通道上的像素值的标准差。

RGB 三个通道的均值和标准差 不是随便定义的,而是需要根据具体的数据集进行统计计算。这些值是 ImageNet 数据集的统计结果,已成为计算机视觉任务的默认标准。

3.5.7 数据增强整合

使用transforms.Compose()把要增强的操作整合到一起:

from PIL import Image
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
import torch
from torchvision import transforms, datasets, utils
​
​
def test01():# 定义数据增强和归一化transform = transforms.Compose([transforms.RandomHorizontalFlip(),  # 随机水平翻转transforms.RandomRotation(10),  # 随机旋转 ±10 度transforms.RandomResizedCrop(32, scale=(0.8, 1.0)),  # 随机裁剪到 32x32,缩放比例在0.8到1.0之间transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),  # 随机调整亮度、对比度、饱和度、色调transforms.ToTensor(),  # 转换为 Tensortransforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),  # 归一化,这是一种常见的经验设置,适用于数据范围 [0, 1],使其映射到 [-1, 1]])
​# 加载 CIFAR-10 数据集,并应用数据增强trainset = datasets.CIFAR10(root="./cifar10_data", train=True, download=True, transform=transform)dataloader = DataLoader(trainset, batch_size=4, shuffle=False)
​# 获取一个批次的数据images, labels = next(iter(dataloader))
​# 还原图片并显示plt.figure(figsize=(10, 5))for i in range(4):# 反归一化:将像素值从 [-1, 1] 还原到 [0, 1]img = images[i] / 2 + 0.5
​# 转换为 PIL 图像img_pil = transforms.ToPILImage()(img)
​# 显示图片plt.subplot(1, 4, i + 1)plt.imshow(img_pil)plt.axis('off')plt.title(f'Label: {labels[i]}')
​plt.show()
​
​
if __name__ == "__main__":test01()
​

代码解释:

transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])

若数据分布与ImageNet差异较大(如医学影像、卫星图、MNIST等),或均值和标准差未知时,可用此简化设置。

将图片进行归一化,使数据更符合正态分布,归一化公式:

img = img / 2 + 0.5

表示反归一化,是归一化的逆运算:

数据集计算均值和标准差

以CIFAR10数据集为例:

# 获取数据集
train_data = datasets.CIFAR10(root='./cifar10',train=True,download=True,transform=transforms.ToTensor()  # 自动将PIL图像转为[0,1]范围的张量
)
​
​
def compute_mean_std(dataset):# 初始化累加器mean = torch.zeros(3)std = torch.zeros(3)num_samples = len(dataset)
​# 遍历数据集计算均值for img, _ in dataset:mean += img.mean(dim=(1, 2))  # 对每个通道的H,W维度求均值mean /= num_samplesprint(mean)
​# 遍历数据集计算标准差for img, _ in dataset:# 原始mean 是一个形状为 [3] 的张量,表示每个通道的均值。# 使用 view(3, 1, 1) 将 mean 的形状从 [3] 改变为 [3, 1, 1]。# 这样,mean 的形状变为 [3, 1, 1],其中 3 表示通道数,1 和 1 分别表示高度和宽度的维度。# 当执行 img - mean.view(3, 1, 1) 时,PyTorch 会利用广播机制将 mean 自动扩展到与 img 相同的形状 [3, H, W]。# 然后利用方差公式计算:var=E(x-E(x))^2std += (img - mean.view(3, 1, 1)).pow(2).mean(dim=(1, 2))# 计算出所有图片的方差后,计算平均方差,然后求标准差std = torch.sqrt(std / num_samples)
​return mean, std
​
​
mean, std = compute_mean_std(train_data)
print(f"Mean: {mean}")  # 输出类似 [0.4914, 0.4822, 0.4465]
print(f"Std: {std}")  # 输出类似 [0.2470, 0.2435, 0.2616]

3.6 早停

早停是一种在训练过程中监控模型在验证集上的表现,并在验证误差不再改善时停止训练的技术。这样可避免训练过度,防止模型过拟合。pytorch没有现成的API,需要自己写代码实现。

早停法的实现步骤

  1. 将数据集分为训练集和验证集。

  2. 在训练过程中,定期(例如每个 epoch)在验证集上评估模型的性能(如损失或准确率)。

  3. 记录验证集的最佳性能(如最低损失或最高准确率)。

  4. 如果验证集的性能在连续若干次评估中没有改善(即达到预设的“耐心值”),则停止训练。

  5. 返回验证集性能最佳时的模型参数。

早停法的关键参数

  1. 耐心值(Patience):

    • 允许验证集性能不提升的连续次数。

    • 例如,如果耐心值为 5,则当验证集损失连续 5 次没有下降时,停止训练。

  2. 最小改善值(Min Delta):

    • 定义“性能提升”的最小阈值。

    • 例如,如果验证集损失的变化小于该值,则认为性能没有提升。

  3. 恢复最佳权重(Restore Best Weights):

    • 是否在早停时恢复验证集性能最佳时的模型权重。

示例(AI生成):

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
from sklearn.model_selection import train_test_split
import numpy as np
​
# 1. 定义一个简单的神经网络
class SimpleNet(nn.Module):def __init__(self):super(SimpleNet, self).__init__()self.fc1 = nn.Linear(20, 64)self.fc2 = nn.Linear(64, 1)self.relu = nn.ReLU()
​def forward(self, x):x = self.relu(self.fc1(x))x = self.fc2(x)return x
​
# 2. 早停法类
class EarlyStopping:def __init__(self, patience=5, min_delta=0):"""Args:patience (int): 允许验证集损失不提升的连续次数。min_delta (float): 定义“提升”的最小阈值。"""self.patience = patienceself.min_delta = min_deltaself.counter = 0self.best_loss = Noneself.early_stop = False
​def __call__(self, val_loss):if self.best_loss is None:self.best_loss = val_losselif val_loss > self.best_loss - self.min_delta:self.counter += 1if self.counter >= self.patience:self.early_stop = Trueelse:self.best_loss = val_lossself.counter = 0
​
# 3. 生成一些随机数据
np.random.seed(42)
torch.manual_seed(42)
​
X = np.random.rand(1000, 20)  # 1000 个样本,每个样本 20 个特征
y = np.random.rand(1000, 1)   # 1000 个目标值
​
# 划分训练集和验证集
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
​
# 转换为 PyTorch 张量
X_train = torch.tensor(X_train, dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.float32)
X_val = torch.tensor(X_val, dtype=torch.float32)
y_val = torch.tensor(y_val, dtype=torch.float32)
​
# 创建 DataLoader
train_dataset = TensorDataset(X_train, y_train)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_dataset = TensorDataset(X_val, y_val)
val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)
​
# 4. 初始化模型、损失函数和优化器
model = SimpleNet()
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
​
# 5. 初始化早停法
early_stopping = EarlyStopping(patience=5, min_delta=0.001)
​
# 6. 训练循环
num_epochs = 100
train_losses, val_losses = [], []
​
for epoch in range(num_epochs):model.train()epoch_train_loss = 0for X_batch, y_batch in train_loader:optimizer.zero_grad()outputs = model(X_batch)loss = criterion(outputs, y_batch)loss.backward()optimizer.step()epoch_train_loss += loss.item()train_losses.append(epoch_train_loss / len(train_loader))
​# 验证阶段model.eval()epoch_val_loss = 0with torch.no_grad():for X_batch, y_batch in val_loader:outputs = model(X_batch)loss = criterion(outputs, y_batch)epoch_val_loss += loss.item()val_losses.append(epoch_val_loss / len(val_loader))
​print(f"Epoch {epoch+1}/{num_epochs}, Train Loss: {train_losses[-1]:.4f}, Val Loss: {val_losses[-1]:.4f}")
​# 早停法检查early_stopping(val_losses[-1])if early_stopping.early_stop:print("Early stopping triggered!")break
​
# 7. 训练完成
print("Training complete!")

3.7 交叉验证

使用交叉验证技术可以帮助评估模型的泛化能力,并调整模型超参数,以防止模型在训练数据上过拟合。

这些方法可以单独使用,也可以结合使用,以有效地防止参数过大和过拟合。根据具体问题和数据集的特点,选择合适的策略来优化模型的性能。

八、批量标准化

批量标准化(Batch Normalization, BN)是一种广泛使用的神经网络正则化技术,核心思想是对每一层的输入进行标准化,然后进行缩放和平移,旨在加速训练、提高模型的稳定性和泛化能力。批量标准化通常在全连接层卷积层之后、激活函数之前应用。

核心思想

Batch Normalization(BN)通过对每一批(batch)数据的每个特征通道进行标准化,解决内部协变量偏移(Internal Covariate Shift)问题,从而:

  • 加速网络训练

  • 允许使用更大的学习率

  • 减少对初始化的依赖

  • 提供轻微的正则化效果

批量标准化的基本思路是在每一层的输入上执行标准化操作,并学习两个可训练的参数:缩放因子 和偏移量 ​。

在深度学习中,批量标准化(Batch Normalization)在训练阶段测试阶段的行为是不同的。在测试阶段,由于没有 mini-batch 数据,无法直接计算当前 batch 的均值和方差,因此需要使用训练阶段计算的全局统计量(均值和方差)来进行标准化。

官网地址:torch.nn — PyTorch 2.6 documentation

1. 训练阶段的批量标准化

1.1 计算均值和方差

对于给定的神经网络层,假设输入数据为 ,其中 是批次大小。我们首先计算该批次数据的均值和方差。

  • 均值(Mean)

  • 方差

1.2 标准化

使用计算得到的均值和方差对数据进行标准化,使得每个特征的均值为0,方差为1。

  • 标准化后的值

    其中, 是一个很小的常数,防止除以零的情况。

1.3 缩放和平移

标准化后的数据通常会通过可训练的参数进行缩放和平移,以恢复模型的表达能力。

  • 缩放(Gamma)

  • 平移(Beta)

    其中, 和 是在训练过程中学习到的参数。它们会随着网络的训练过程通过反向传播进行更新。

1.4 更新全局统计量

通过指数移动平均(Exponential Moving Average, EMA)更新全局均值和方差:

其中,momentum 是一个超参数,控制当前 mini-batch 统计量对全局统计量的贡献。

momentum 是一个介于 0 和 1 之间的值,控制当前 mini-batch 统计量的权重。PyTorch 中 momentum 的默认值是 0.1。

与优化器中的 momentum 的区别

  • 批量标准化中的 momentum:

    • 用于更新全局统计量(均值和方差)。

    • 控制当前 mini-batch 统计量对全局统计量的贡献。

  • 优化器中的 momentum:

    • 用于加速梯度下降过程,帮助跳出局部最优。

    • 例如,SGD 优化器中的 momentum 参数。

两者虽然名字相同,但作用完全不同,不要混淆。

2. 测试阶段的批量标准化

在测试阶段,由于没有 mini-batch 数据,无法直接计算当前 batch 的均值和方差。因此,使用训练阶段通过 EMA 计算的全局统计量(均值和方差)来进行标准化。

在测试阶段,使用全局统计量对输入数据进行标准化:

然后对标准化后的数据进行缩放和平移:

为什么使用全局统计量?

一致性

  • 在测试阶段,输入数据通常是单个样本或少量样本,无法准确计算均值和方差。

  • 使用全局统计量可以确保测试阶段的行为与训练阶段一致。

稳定性

  • 全局统计量是通过训练阶段的大量 mini-batch 数据计算得到的,能够更好地反映数据的整体分布。

  • 使用全局统计量可以减少测试阶段的随机性,使模型的输出更加稳定。

效率

  • 在测试阶段,使用预先计算的全局统计量可以避免重复计算,提高效率。

3. 作用

批量标准化(Batch Normalization, BN)通过以下几个方面来提高神经网络的训练稳定性、加速训练过程并减少过拟合:

3.1 缓解梯度问题

标准化处理可以防止激活值过大或过小,避免了激活函数(如 Sigmoid 或 Tanh)饱和的问题,从而缓解梯度消失或爆炸的问题。

3.2 加速训练

由于 BN 使得每层的输入数据分布更为稳定,因此模型可以使用更高的学习率进行训练。这可以加快收敛速度,并减少训练所需的时间。

3.3 减少过拟合

  • 类似于正则化:虽然 BN 不是一种传统的正则化方法,但它通过对每个批次的数据进行标准化,可以起到一定的正则化作用。它通过在训练过程中引入了噪声(由于批量均值和方差的估计不完全准确),这有助于提高模型的泛化能力。

  • 避免对单一数据点的过度拟合:BN 强制模型在每个批次上进行标准化处理,减少了模型对单个训练样本的依赖。这有助于模型更好地学习到数据的整体特征,而不是对特定样本的噪声进行过度拟合。

4.函数说明

torch.nn.BatchNorm1d 是 PyTorch 中用于一维数据的批量标准化(Batch Normalization)模块。

torch.nn.BatchNorm1d(num_features,         # 输入数据的特征维度eps=1e-05,           # 用于数值稳定性的小常数momentum=0.1,        # 用于计算全局统计量的动量affine=True,         # 是否启用可学习的缩放和平移参数track_running_stats=True,  # 是否跟踪全局统计量device=None,         # 设备类型(如 CPU 或 GPU)dtype=None           # 数据类型
)

参数说明:

eps:用于数值稳定性的小常数,添加到方差的分母中,防止除零错误。默认值:1e-05

momentum:用于计算全局统计量(均值和方差)的动量。默认值:0.1,参考本节1.4

affine:是否启用可学习的缩放和平移参数(γ和 β)。如果 affine=True,则模块会学习两个参数;如果 affine=False,则不学习参数,直接输出标准化后的值 。默认值:True

track_running_stats:是否跟踪全局统计量(均值和方差)。如果 track_running_stats=True,则在训练过程中计算并更新全局统计量,并在测试阶段使用这些统计量。如果 track_running_stats=False,则不跟踪全局统计量,每次标准化都使用当前 mini-batch 的统计量。默认值:True

4. 代码实现

import torch
from torch import nn
from matplotlib import pyplot as plt
​
from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_split
from torch.nn import functional as F
from torch import optim
​
# 数据准备
# 生成非线性可分数据(同心圆)
# n_samples int 总样本数(默认100),内外圆各占一半
# noise float   添加到数据中的高斯噪声标准差(默认0.0)
# factor    float   内圆与外圆的半径比(默认0.8)
# random_state  int 随机数种子,保证可重复性
​
# 输出数据
# X: 二维坐标数组,形状 (n_samples, 2)
# 每行是一个数据点的 [x, y] 坐标
# y: 类别标签 0(外圆)或 1(内圆),形状 (n_samples,)
x, y = make_circles(n_samples=2000, noise=0.1, factor=0.4, random_state=42)
x = torch.tensor(x, dtype=torch.float)
y = torch.tensor(y, dtype=torch.long)
​
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42)
​
# 可视化原始训练数据和测试数据
plt.scatter(x[:, 0], x[:, 1], c=y, cmap='coolwarm', edgecolors='k')
plt.show()
​
​
# 定义BN模型
class NetWithBN(nn.Module):def __init__(self):super().__init__()self.fc1 = nn.Linear(2, 64)self.bn1 = nn.BatchNorm1d(64)self.fc2 = nn.Linear(64, 32)self.bn2 = nn.BatchNorm1d(32)self.fc3 = nn.Linear(32, 2)
​def forward(self, x):x = F.relu(self.bn1(self.fc1(x)))x = F.relu(self.bn2(self.fc2(x)))x = self.fc3(x)return x
​
​
# 定义无BN模型
class NetWithoutBN(nn.Module):def __init__(self):super().__init__()self.fc1 = nn.Linear(2, 64)self.fc2 = nn.Linear(64, 32)self.fc3 = nn.Linear(32, 2)
​def forward(self, x):x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))x = self.fc3(x)return x
​
​
# 定义训练函数
def train(model, x_train, y_train, x_test, y_test, name, lr=0.1, epochs=500):criterion = nn.CrossEntropyLoss()optimizer = optim.SGD(model.parameters(), lr=lr)
​train_loss = []test_acc = []
​for epoch in range(epochs):model.train()y_pred = model(x_train)loss = criterion(y_pred, y_train)optimizer.zero_grad()loss.backward()optimizer.step()train_loss.append(loss.item())
​model.eval()with torch.no_grad():y_test_pred = model(x_test)_, pred = torch.max(y_test_pred, dim=1)correct = (pred == y_test).sum().item()test_acc.append(correct / len(y_test))
​if epoch % 100 == 0:print(f'{name}|Epoch:{epoch},loss:{loss.item():.4f},acc:{test_acc[-1]:.4f}')return train_loss, test_acc
​
​
model_bn = NetWithBN()
model_nobn = NetWithoutBN()
​
bn_train_loss, bn_test_acc = train(model_bn, x_train, y_train, x_test, y_test, name='BN')
nobn_train_loss, nobn_test_acc = train(model_nobn, x_train, y_train, x_test, y_test, name='NoBN')
​
​
def plot(bn_train_loss, nobn_train_loss, bn_test_acc, nobn_test_acc):fig = plt.figure(figsize=(12, 5))ax1 = fig.add_subplot(1, 2, 1)ax1.plot(bn_train_loss, 'b', label='BN')ax1.plot(nobn_train_loss, 'r', label='NoBN')ax1.legend()
​ax2 = fig.add_subplot(1, 2, 2)ax2.plot(bn_test_acc, 'b', label='BN')ax2.plot(nobn_test_acc, 'r', label='NoBN')ax2.legend()plt.show()
​
​
plot(bn_train_loss, nobn_train_loss, bn_test_acc, nobn_test_acc)

相关文章:

深度学习-全连接神经网络(过拟合,欠拟合。批量标准化)

七、过拟合与欠拟合 在训练深层神经网络时,由于模型参数较多,在数据量不足时很容易过拟合。而正则化技术主要就是用于防止过拟合,提升模型的泛化能力(对新数据表现良好)和鲁棒性(对异常数据表现良好)。 1. 概念认知 …...

访问Maven私服的教程

1.首先准备好maven私服的启动器,到bin目录下启动: 2.等待加载,加载过程比较长: 3.访问端口号: 4.仓库简介: 5.在maven的setting中 servers配置信息(设置私服访问的密码): 6.配置私服仓库地址: 7.配置上传地址(私服地址): 8.在自己的副项…...

Linux系统编程 day9 SIGCHLD and 线程

SIGCHLD信号 只要子进程信号发生改变&#xff0c;就会产生SIGCHLD信号。 借助SIGCHLD信号回收子进程 回收子进程只跟父进程有关。如果不使用循环回收多个子进程&#xff0c;会产生多个僵尸进程&#xff0c;原因是因为这个信号不会循环等待。 #include<stdio.h> #incl…...

Linux 内核中 cgroup 子系统 cpuset 是什么?

cpuset 是 Linux 内核中 cgroup&#xff08;控制组&#xff09; 的一个子系统&#xff0c;用于将一组进程&#xff08;或任务&#xff09;绑定到特定的 CPU 核心和 内存节点&#xff08;NUMA 节点&#xff09;上运行。它通过限制进程的 CPU 和内存资源的使用范围&#xff0c;优…...

乐视系列玩机---乐视2 x520 x528等系列线刷救砖以及刷写第三方twrp 卡刷第三方固件步骤解析

乐视2 x520 x528 x526等,搭载了高通骁龙652处理器,骁龙652的GPU性能甚至优于前一年的骁龙810,配备了3GB RAM和32GB ROM的存储空间, 通过博文了解💝💝💝 1💝💝💝-----详细解析乐视2 x520系列黑砖线刷救砖的步骤 2💝💝💝----官方两种更新卡刷步骤以及刷…...

电容加速电路!

大家好&#xff0c;我是记得诚。 今天分享一个小电路&#xff1a;电容加速电路。 下面是一个普通的三极管开关电路&#xff0c;区别是多了一个C1&#xff0c;C1被称为加速电容。作用是&#xff1a;加速三极管VT1的开通和截止&#xff0c;做到快开快关。 工作原理&#xff1a;…...

MCP Host、MCP Client、MCP Server全流程实战

目录 准备工作 MCP Server 实现 调试工作 MCP Client 实现 MCP Host 配置 第一步:配置支持 function calling的 LLM 第二步:添加MCP Server 一般有两种方式,第一种json配置,第二种直接是Command形式,我这里采用Command形式 第三步:使用MCP Server 准备工作 安装…...

Win10一体机(MES电脑设置上电自动开机)

找个键盘&#xff0c;带线的那种&#xff0c;插到电脑上&#xff0c;电脑开机&#xff1b;连续点按F11&#xff1b;通过↑↓键选择Enter Setup 然后回车&#xff1b; 选择 smart settings &#xff1b; 选择 Restore AC Power Loss By IO 回车&#xff1b; 将prower off 改为…...

强化学习和微调 区别如下

强化学习和微调 区别如下 定义与概念 强化学习**:是一种机器学习范式,强调智能体(agent)如何在环境中采取一系列行动,以最大化累积奖励**。智能体通过与环境进行交互,根据环境反馈的奖励信号来学习最优的行为策略。例如,机器人通过不断尝试不同的动作来学习如何在复杂环…...

【EasyPan】文件上传、文件秒传、文件转码、文件合并、异步转码、视频切割分析

【EasyPan】项目常见问题解答&#xff08;自用&持续更新中…&#xff09;汇总版 文件上传方法解析 一、方法总览 Transactional(rollbackFor Exception.class) public UploadResultDto uploadFile(...)核心能力&#xff1a; 秒传验证&#xff1a;通过MD5文件大小实现文…...

React18+ 项目搭建-从初始化、技术选型到开发部署的全流程规划

搭建一个 React 项目需要从项目初始化、技术选型到开发部署的全流程规划。以下是详细步骤和推荐的技术栈&#xff1a; 一、项目初始化 1. 选择脚手架工具 推荐工具&#xff1a; Vite&#xff08;现代轻量级工具&#xff0c;支持 React 模板&#xff0c;速度快&#xff09;&am…...

day3 打卡训练营

循环语句和判断语句之前已经会了&#xff0c;把列表的方法练一练 浙大疏锦行 python训练营介绍...

MySQL VS SQL Server:优缺点全解析

数据库选型、企业协作、技术生态、云数据库 1.1 MySQL优缺点分析 优点 开源免费 社区版完全免费&#xff0c;适合预算有限的企业 允许修改源码定制功能&#xff08;需遵守GPL协议&#xff09; 跨平台兼容性 支持Windows/Linux/macOS&#xff0c;适配混合环境部署 云服务商…...

【CPP】固定大小内存池

程序运行时&#xff0c;通常会频繁地进行内存的分配和释放操作。传统的内存分配方式&#xff08;如使用new和delete运算符&#xff09;可能会导致内存碎片的产生&#xff0c;并且每次分配和释放内存都有一定的时间开销。内存池通过在程序启动时一次性分配一大块内存或一次性分配…...

[数据结构]树和二叉树

概念 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次关系的集合。 树形结构中&#xff0c;子树之间不能有交集&#xff0c;否则就不是树形结构 双亲结点或父结点 &#xff1a;若一个结点含有子结点&#xff0c;则…...

监控页面卡顿PerformanceObserver

监控页面卡顿PerformanceObserver 性能观察器掘金 const observer new PerformanceObserver((list) > {}); observer.observe({entryTypes: [longtask], })...

Web开发-JavaEE应用JNDI注入RMI服务LDAP服务DNS服务高版本限制绕过

知识点&#xff1a; 1、安全开发-JavaEE-JNDI注入-LADP&RMI&DNS等 2、安全开发-JavaEE-JNDI注入-项目工具&手工原理等 演示案例-WEB开发-JavaEE-JNDI注入&LDAP&RMI服务&DNS服务&高版本限制绕过 JNDI全称为 Java Naming and DirectoryInterface&am…...

深度学习训练中的显存溢出问题分析与优化:以UNet图像去噪为例

最近在训练一个基于 Tiny-UNet 的图像去噪模型时&#xff0c;我遇到了经典但棘手的错误&#xff1a; RuntimeError: CUDA out of memory。本文记录了我如何从复现、分析&#xff0c;到逐步优化并成功解决该问题的全过程&#xff0c;希望对深度学习开发者有所借鉴。 训练数据&am…...

【Spring】单例模式的创建方式(Bean解析)

在Java中&#xff0c;单例模式&#xff08;Singleton Pattern&#xff09;确保一个类只有一个实例&#xff0c;并提供全局访问点。以下是实现单例的五种常见方式&#xff1a;懒汉式、饿汉式、双重检查锁、静态内部类和枚举&#xff0c;包括代码示例和优缺点分析。 1. 懒汉式&am…...

小小矩阵设计

在电气设计图中&#xff0c;矩阵设计的接线方法是通过结构化布局实现多灵活链接的技术&#xff0c;常用于信号切换、配电调压或更加复杂的控制场景。 今天聊一种在电气图纸中用到的一种简单矩阵接法&#xff0c;一眼就看明白&#xff0c;很大程度简化了程序控制点和继电器的使用…...

IOT项目——双轴追光系统

双轴太阳能追光系统 - ESP32实现 系统概述 这个系统使用&#xff1a; ESP32开发板2个舵机&#xff08;水平方向和垂直方向&#xff09;4个光敏电阻&#xff08;用于检测光照方向&#xff09;适当的电阻&#xff08;用于光敏电阻分压&#xff09; 接线示意图 --------------…...

深度学习基石:神经网络核心知识全解析(一)

神经网络核心知识全解析 一、神经网络概述 神经网络作为机器学习领域的关键算法&#xff0c;在现代生活中发挥着重要作用&#xff0c;广泛应用于图像识别、语音处理、智能推荐等诸多领域&#xff0c;深刻影响着人们的日常生活。它通过模拟人类大脑神经系统的结构和功能&#…...

什么是 金字塔缩放(Multi-scale Input)

金字塔缩放 什么是金字塔缩放(Multi-scale Input)什么场景下会用到金字塔缩放?图像识别目标跟踪图像压缩视频处理如何在计算机程序中实现金字塔缩放?准备数据缩小数据(构建金字塔的上层)存储数据使用数据(在程序中应用金字塔缩放)金字塔缩放的记忆卡片什么是金字塔缩放(M…...

从零开始配置 Zabbix 数据库监控:MySQL 实战指南

Zabbix作为一款开源的分布式监控工具&#xff0c;在监控MySQL数据库方面具有显著优势&#xff0c;能够为数据库的稳定运行、性能优化和故障排查提供全面支持。以下是使用Zabbix监控MySQL数据库的配置。 一、安装 Zabbix Agent 和 MySQL 1. 安装 Zabbix Agent services:zabbix…...

机器学习超参数优化全解析

机器学习超参数优化全解析 摘要 本文全面深入地剖析了机器学习模型中的超参数优化策略&#xff0c;涵盖了从参数与超参数的本质区别&#xff0c;到核心超参数&#xff08;如学习率、批量大小、训练周期&#xff09;的动态调整方法&#xff1b;从自动化超参数优化技术&#xf…...

【算法】双指针8道速通(C++)

1. 移动零 思路&#xff1a; 拿示例1的数据来举例&#xff0c;定义两个指针&#xff0c;cur和dest&#xff0c;cur表示当前遍历的元素&#xff0c;dest以及之前表示非零元素 先用cur去找非零元素&#xff0c;每找到一个非零元素&#xff0c;就让dest的下一个元素与之交换 单个…...

synchronized锁

在了解锁之前我们要先了解对象布局 什么是java对象布局 在JVM中&#xff0c;对象在内存中存储的布局可以分为三块区域&#xff0c;即实例化之后的对象 对象头&#xff1a;分配的空间是固定的12Byte&#xff0c;由Mark Word&#xff08;标记字段&#xff09;和Class Pointer&…...

实训Day-2 流量分析与安全杂项

目录 实训Day-2-1流量分析实战 实训目的 实训任务1 SYN半链接攻击流量分析 实训任务2 SQL注入攻击流量分析一 实训任务3 SQL注入攻击流量分析二 实训任务4 Web入侵溯源一 实训任务5 Web入侵溯源二 ​编辑 实训Day-2-1安全杂项实战 实训目的 实训任务1 流量分析 FTP…...

LOH 怎么进行深度标准化?

The panel of normals is applied by replacing the germline read depth of the sample with the median read depth of samples with the same genotype in our panel. 1.解释: panel of normal 正常组织&#xff0c;用于识别技术噪音 germline read depth: 胚系测序深度。根…...

[预备知识]3. 自动求导机制

自动求导机制 本章节介绍 PyTorch 的自动求导机制&#xff0c;包括计算图、反向传播和梯度计算的原理及实现。 1. 计算图原理 计算图是深度学习框架中的一个核心概念&#xff0c;它描述了计算过程中各个操作之间的依赖关系。 计算图由节点&#xff08;节点&#xff09;和边…...

蓝桥杯中的知识点

总结&#xff1a; 这次考的并不理想 比赛前好多知识点遗漏 但到此为止已经结束了 mod 是 模运算&#xff08;Modulo Operation&#xff09;的缩写&#xff0c;表示求两个数相除后的 余数 10mod31 (a % b) &#xff08;7%21&#xff09; 1e9代表1乘以10的9次方&#xff0c…...

2023蓝帽杯初赛内存取证-6

这里需要用到pslist模块&#xff0c;结合一下查找关键词&#xff1a; vol.py -f memdump.mem --profile Win7SP1x64 pslist | grep -E "VeraCrypt" 将2023-06-20 16:47:41 UTC0000世界标准时间转换成北京时间&#xff1a; 答案&#xff1a;2023-06-21 00:47:41...

《MySQL 核心技能:SQL 查询与数据库概述》

MySQL 核心技能&#xff1a;SQL 查询与数据库概述 一、数据库概述1. 什么是数据库2.为什么要使用数据库3.数据库的相关概念3.1 数据库&#xff08;DB&#xff09;&#xff1a;数据的“仓库”3.2 数据库管理系统&#xff08;DBMS&#xff09;&#xff1a;数据库的“管家”3.3 SQ…...

三维几何变换

一、学习目的 了解几何变换的意义 掌握三维基本几何变换的算法 二、学习内容 在本次试验中&#xff0c;我们实现透视投影和三维几何变换。我们首先定义一个立方体作为我们要进行变换的三维物体。 三、具体代码 &#xff08;1&#xff09;算法实现 // 获取Canvas元素 con…...

TDengine 查询引擎设计

简介 TDengine 作为一个高性能的时序大数据平台&#xff0c;其查询与计算功能是核心组件之一。该平台提供了丰富的查询处理功能&#xff0c;不仅包括常规的聚合查询&#xff0c;还涵盖了时序数据的窗口查询、统计聚合等高级功能。这些查询计算任务需要 taosc、vnode、qnode 和…...

15.第二阶段x64游戏实战-分析怪物血量(遍历周围)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 上一个内容&#xff1a;14.第二阶段x64游戏实战-分析人物的名字 如果想实现自动打怪&#xff0c;那肯定…...

vue浅试(1)

先安装了vue nvm安装详细教程&#xff08;安装nvm、node、npm、cnpm、yarn及环境变量配置&#xff09; 稍微了解了一下cursor ​ cursor的使用 请出我们的老师&#xff1a; 提示词&#xff1a; 你是我的好朋友也是一个前端专家&#xff0c;你能向我传授前端知识&#xff0c…...

VSCode连服务器一直处于Downloading

使用vscode的remote插件连接远程服务器时&#xff0c;部分服务器可能会出现一直处于Downloading VS Code Server的情况 早期的一些教程&#xff0c;如https://blog.csdn.net/chongbin007/article/details/126958840, https://zhuanlan.zhihu.com/p/671718415给出的方法是手动下…...

QGIS实用功能:加载天地图与下载指定区域遥感影像

QGIS 实用功能&#xff1a;加载天地图与下载指定区域遥感影像 目录标题 QGIS 实用功能&#xff1a;加载天地图与下载指定区域遥感影像一、安装天地图插件&#xff0c;开启地图加载之旅二、获取天地图密钥&#xff0c;获取使用权限三、加载天地图服务&#xff0c;查看地图数据四…...

mybatis-plus开发orm

1、mybatis 使用mybatis-generator自动生成代码 这个也是有系统在使用 2、mybatis-plus开发orm--有的系统在使用 MybatisPlus超详细讲解_mybatis-plus-CSDN博客...

ubuntu 交叉编译 macOS 库, 使用 osxcross 搭建 docker 编译 OS X 库

1. ubuntu 交叉编译 macOS 库, 使用 osxcross 搭建 docker 编译 OS X 库 1. ubuntu 交叉编译 macOS 库, 使用 osxcross 搭建 docker 编译 OS X 库 1.1. 安装依赖1.2. 安装 osxcross 及 macOS SDK 1.2.1. 可能错误 1.3. 编译 cmake 类工程1.4. 编译 configure 类工程1.5. 单文件…...

抱佛脚之学SSM四

MyBatis基础 一个接口对应一个映射文件 在映射文件中指定对应接口指定的位置 sql语句中id对应方法名par..参数的类型&#xff0c;resul..返回值的类型 WEB-INF下的文件是受保护的&#xff0c;不能直接访问&#xff0c;只能通过请求转发的方式访问 SqlSessionFactory&#xff1…...

2.5 函数的拓展

1.匿名函数&#xff08;简化代码&#xff09; python中没有这个概念&#xff0c;通过lambda关键字可以简化函数的代码写法 2.lambda表达式 arguments lambda 参数列表 &#xff1a; 函数体 print(aarguments(参数)) #测试lambda #原本代码def sum1(x,y):return xyprint(sum1…...

深度学习--卷积神经网络数据增强

文章目录 一、数据增强1、什么是数据增强&#xff1f;2、为什么需要数据增强&#xff1f; 二、常见的数据增强方法1、图像旋转2、图像翻转3、图像缩放4、图像平移5、图像剪切6、图像亮度、对比度、饱和度调整7、噪声添加8、随机扰动 三、代码实现1、预处理2、使用数据增强增加训…...

Buffer of Thoughts: Thought-Augmented Reasoningwith Large Language Models

CODE: NeurIPS 2024 https://github.com/YangLing0818/buffer-of-thought-llm Abstract 我们介绍了思想缓冲(BoT)&#xff0c;一种新颖而通用的思想增强推理方法&#xff0c;用于提高大型语言模型(大型语言模型)的准确性、效率和鲁棒性。具体来说&#xff0c;我们提出了元缓冲…...

mybatisX动态切换数据源直接执行传入sql

代码 mapper接口中方法定义如下&#xff0c;其中#dbName代表传入的数据源变量&#xff08;取值可参考application.properties中spring.datasource.dynamic.datasource指定的数据源&#xff09; DS("#dbName")List<LinkedHashMap<String, Object>> execu…...

N8N MACOS本地部署流程避坑指南

最近n8n很火&#xff0c;就想在本地部署一个&#xff0c;尝尝鲜&#xff0c;看说明n8n是开源软件&#xff0c;可以在本地部署&#xff0c;于是就尝试部署了下&#xff0c;大概用了1个多小时&#xff0c;把相关的过程记录一下&#xff1a; 1、基础软件包 abcXu-MacBook-m2-Air…...

搜索策略的基本概念

搜索是人工智能中的一个基本问题&#xff0c;是推理不可分割的一部分&#xff0c;它直接关系到智能系统的性能与运行效率&#xff0c;因而尼尔逊把它列为人工智能研究中的四个核心问题之一。在过去40多年中&#xff0c;人工智能界已对搜索技术开展了大量研究&#xff0c;取得了…...

云原生--CNCF-1-云原生计算基金会介绍(云原生生态的发展目标和未来)

1、CNCF定义与背景 云原生计算基金会&#xff08;Cloud Native Computing Foundation&#xff0c;CNCF&#xff09;是由Linux基金会于2015年12月发起成立的非营利组织&#xff0c;旨在推动云原生技术的标准化、开源生态建设和行业协作。其核心目标是通过开源项目和社区协作&am…...

【Chrome插件开发】某视频网站的m4s视频/音频下载方案,及其Chrome插件实现-v250415

文章目录 引言效果v1.0.0 TODO让AI写初稿两条路&#xff1a;在content.js里&#xff0c;还是popup.js里发请求&#xff1f;World in content.js新建项目如何打包background.js&#xff1a;在鼠标右键菜单添加一个选项&#xff0c;点击后通知content.js第一次创建弹窗eslint 9如…...