PyTorch深度学习实战(12)——数据增强

news2024/9/27 23:32:20

PyTorch深度学习实战(12)——数据增强

    • 0. 前言
    • 1. 图像增强
      • 1.1 仿射变换
      • 1.2 亮度修改
      • 1.3 添加噪音
      • 1.4 联合使用多个增强方法
    • 2. 对批图像执行图像增强
    • 3. 利用数据增强训练模型
    • 小结
    • 系列链接

0. 前言

数据增强是指通过对原始数据进行一系列变换和处理,生成更多、更丰富的训练样本的技术方法。数据增强在机器学习和深度学习领域中被广泛应用,它可以有效地解决数据不足的问题,提高模型的泛化能力和鲁棒性。我们已经了解了卷积神经网络 (Convolutional Neural Network, CNN) 有助于解决图像平移问题,但如果平移的范围过大同样可能影响模型的性能。在本节中,我们将学习如何使用数据增强确保模型能够得到正确的预测结果,即使图像移动较大范围。

1. 图像增强

数据增强的目的是通过对原始数据进行合理的变换,生成新的样本,使得这些样本在保持原始类别标签不变的情况下,尽可能涵盖更多的数据特征和变化情况。在计算机视觉领域,对于给定的图像,即使我们平移,旋转或缩放图像,图像的标签也将保持不变。
基于上述原理,数据增强是从给定的图像集中创建更多图像的一种方法,即通过旋转,平移或缩放它们并将它们映射到原始图像的标签,以扩充数据集。通过随机平移输入图像并将它们传递给网络来训练神经网络,相同的图像将在不同批次中作为不同的图像处理,因为在每个批次中具有不同的平移量。我们已经了解了图像平移对模型预测准确性的影响。但是,在现实世界中,我们可能会遇到其他多种图像变换的情况:

  • 图像旋转
  • 图像缩放
  • 图片翻转
  • 图像剪切
  • 图像中存在噪点
  • 图像亮度较低/高

如果不考虑以上情况,训练出的神经网络并不会得到准确的预测结果。图像增强根据给定图像创建更多图像,通过旋转、平移、缩放、添加噪声和亮度等修改原始图像,此外,可以使用不同的参数指定图像的变化程度(例如,某个图像的平移可以是 +10 像素,也可以是 -5 像素)。imgaug 库中的 augmenters 类可以用于实现数据增强,常用的数据增强技术如下:

  • 仿射变换
  • 亮度修改
  • 添加噪音

PyTorch 中同样包含图像增强管道 torchvision.transforms。但是,imgaug 包含更多选项,且易于解释数据增强功能,可以使用 pip 命令安装 imgaug 库:

pip install imgaug

1.1 仿射变换

仿射变换包括平移、旋转、缩放和剪切图像,可以使用 augmenters 类中的 Affine 方法执行仿射变换。Affine 方法中包含以下重要参数:

  • scale:要对图像进行的缩放量
  • translate_percent: 将平移量指定为图像高度和宽度的百分比
  • translate_px:将平移量指定为绝对像素数
  • rotate:要在图像上完成的旋转量
  • shear:要在图像的一部分上完成的旋转量

(1)Fashion-MNIST 数据集中获取随机图像:

import imgaug
import imgaug.augmenters as iaa
print(imgaug.__version__)
# 0.4.0

from torchvision import datasets
import torch
data_folder = './data/FMNIST'
fmnist = datasets.FashionMNIST(data_folder, download=True, train=True)

tr_images = fmnist.data
tr_targets = fmnist.targets

import matplotlib.pyplot as plt
import numpy as np
from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
device = 'cuda' if torch.cuda.is_available() else 'cpu'

def to_numpy(tensor):
    return tensor.cpu().detach().numpy()

plt.imshow(tr_images[0], cmap='gray')
plt.title('Original image')
plt.show()

原始图像
(2) 定义用于执行缩放的对象 aug

aug = iaa.Affine(scale=2)

(3) 指定使用 aug 对象中的 augment_image 方法执行图像增强,并进行绘制:

plt.imshow(aug.augment_image(to_numpy(tr_images[0])))
plt.title('Scaled image')
plt.show()

缩放图像
在以上输出中,图像已被放大,但由于图像的输出形状没有改变,因此会从原始图像中删除一部分像素。

(4) 使用 translate_px 参数执行图像平移:

aug = iaa.Affine(translate_px=10)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Translated image by 10 pixels (right and bottom)')
plt.show()

图像平移
在以上输出中,x 轴和 y 轴都平移了 10 个像素。如果两个轴上平移不同的像素量,则必须指定在每个轴上的平移量:

aug = iaa.Affine(translate_px={'x':10,'y':2})
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Translation of 10 pixels \nacross columns and 2 pixels over rows')
plt.show()

图像平移
在以上输出结果中,在 translate_px 参数中使用字典指定 xy 轴的平移量,图像在 x 轴上平移了更多像素。

(5) 观察旋转和剪切对图像增强的影响:

plt.figure(figsize=(20,20))
plt.subplot(151)
plt.imshow(tr_images[0], cmap='gray')
plt.title('Original image')
plt.subplot(152)
aug = iaa.Affine(scale=2)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Scaled image')
plt.subplot(153)
aug = iaa.Affine(translate_px={'x':10,'y':2})
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Translation of 10 pixels across \ncolumns and 2 pixels over rows')
plt.subplot(154)
aug = iaa.Affine(rotate=30)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Rotation of image \nby 30 degrees')
plt.subplot(155)
aug = iaa.Affine(shear=30)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Shear of image \nby 30 degrees')
plt.show()

旋转和剪切
在以上输出中,可以看到某些像素在转换后从图像中被裁剪掉。接下来,我们利用 Affine 方法中的 fit_output 参数确保图像不因裁剪丢失信息。默认情况下,fit_output 设置为 False,将 fit_output 指定为 True 时,观察在缩放、平移、旋转和剪切图像时,输出图像的变化:

plt.figure(figsize=(20,20))
plt.subplot(151)
plt.imshow(tr_images[0], cmap='gray')
plt.title('Original image')
plt.subplot(152)
aug = iaa.Affine(scale=2, fit_output=True)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Scaled image')
plt.subplot(153)
aug = iaa.Affine(translate_px={'x':10,'y':2}, fit_output=True)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Translation of 10 pixels across \ncolumns and 2 pixels over rows')
plt.subplot(154)
aug = iaa.Affine(rotate=30, fit_output=True)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Rotation of image \nby 30 degrees')
plt.subplot(155)
aug = iaa.Affine(shear=30, fit_output=True)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Shear of image \nby 30 degrees')
plt.show()

旋转和剪切
可以看到原始图像没有被裁剪,并且会增加图像的大小以进行完整显示。当增强图像的大小增加时,我们需要清楚如何填充不属于原始图像的新像素。

fit_outputTrue 时,使用 cval 参数指定创建的新像素的像素值。在以上代码中,cval 填充了默认值 0,即黑色像素,接下来,将 cval 参数改为 255,即白色像素,观察输出结果:

aug = iaa.Affine(rotate=30, fit_output=True, cval=255)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Rotation of image by 30 degrees')
plt.show()

图像填充
此外,可以使用不同的模式来填充新创建的像素的值,mode 参数的可选值如下:

  • constant:使用恒定值填充
  • edge:用输入的边缘值填充
  • symmetric:用沿输入边缘的反射填充
  • reflect:用反射向量填充
  • wrap:用沿轴的向量填充

cval 设置为 0 并使用不同 mode 参数:

plt.figure(figsize=(20,20))
plt.subplot(151)
aug = iaa.Affine(rotate=30, fit_output=True, cval=0, mode='constant')
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Rotation of image by \n30 degrees with constant mode')
plt.subplot(152)
aug = iaa.Affine(rotate=30, fit_output=True, cval=0, mode='edge')
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Rotation of image by 30 degrees \n with edge mode')
plt.subplot(153)
aug = iaa.Affine(rotate=30, fit_output=True, cval=0, mode='symmetric')
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Rotation of image by \n30 degrees with symmetric mode')
plt.subplot(154)
aug = iaa.Affine(rotate=30, fit_output=True, cval=0, mode='reflect')
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Rotation of image by 30 degrees \n with reflect mode')
plt.subplot(155)
aug = iaa.Affine(rotate=30, fit_output=True, cval=0, mode='wrap')
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.title('Rotation of image by \n30 degrees with wrap mode')
plt.show()

图像填充示例
在执行数据增强时,很难指定图像需要旋转的确切角度,通常提供图像将旋转的范围:

plt.figure(figsize=(20,20))
plt.subplot(141)
aug = iaa.Affine(rotate=(-45,45), fit_output=True, cval=0, mode='constant')
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.subplot(142)
aug = iaa.Affine(rotate=(-45,45), fit_output=True, cval=0, mode='constant')
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.subplot(143)
aug = iaa.Affine(rotate=(-45,45), fit_output=True, cval=0, mode='constant')
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.subplot(144)
aug = iaa.Affine(rotate=(-45,45), fit_output=True, cval=0, mode='constant')
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray')
plt.show()

不同旋转角度
在以上输出中,由于根据旋转的上限和下限指定了可能的旋转角度范围,相同的图像在不同的迭代中旋转角度不同。同样,我们可以在平移或缩放图像时引入随机化增强。

1.2 亮度修改

由于图像中的照明条件不同,背景和前景之间的差异有时并不明显。如果在训练模型时背景的像素值始终为 0,前景的像素值始终为 255,而预测图像的背景像素值为 20,前景像素值为 220,则预测很可能并不正确。乘法( Multiply )和线性对比度( Linearcontrast) 是两种不同的增强技术,可以解决照明条件不同的问题。

Multiply 方法将每个像素值乘以指定的值,例如将图像中的每个像素值乘以 0.5 后输出:

aug = iaa.Multiply(0.5)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray',vmin = 0, vmax = 255)
plt.title('Pixels multiplied by 0.5')
plt.show()

Multiply 方法
Linearcontrast 根据以下公式调整每个像素值:

127 + α × ( x i − 127 ) 127+\alpha \times(x_i-127) 127+α×(xi127)

其中, x i x_i xi 表示像素值,当 α α α 等于 1 时,像素值保持不变,当 α α α 小于 1 时,高像素值减少,低像素值增加。观察对输出图像的影响:

aug = iaa.LinearContrast(0.5)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray',vmin = 0, vmax = 255)
plt.title('Pixel contrast by 0.5')
plt.show()

Linearcontrast
可以看到,使用 Linearcontrast 方法,图像中的背景变得更加明亮,而前景像素的强度降低了。

使用 GaussianBlur 方法模糊图像以模拟真实场景(图像可能由于运动而模糊):

aug = iaa.GaussianBlur(sigma=1)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray',vmin = 0, vmax = 255)
plt.title('Gaussian blurring of image\n with a sigma of 1')
plt.show()

GaussianBlur
可以看到图像非常模糊,并且随着 sigma 值的增加,图像也会变得更加模糊。

1.3 添加噪音

在现实世界的场景中,可能会在图像中包含噪点,DropoutSaltAndPepper 是用于模拟图像噪声的两种主要方法:

aug = iaa.Dropout(p=0.2)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray',vmin = 0, vmax = 255)
plt.title('Random 20% pixel dropout')
plt.show()

aug = iaa.SaltAndPepper(0.2)
plt.imshow(aug.augment_image(to_numpy(tr_images[0])), cmap='gray',vmin = 0, vmax = 255)
plt.title('Random 20% salt and pepper noise')
plt.show()

添加噪声
可以看到 Dropout 方法随机丢弃了一定数量的像素,即将它们的像素值转换为 0,而 SaltAndPepper 方法则在图像中随机添加白色和黑色的像素。

1.4 联合使用多个增强方法

在现实世界的场景中,我们必须综合使用尽可能多的增强方法。在本节中,我们将了解图像增强的 Sequential 方式,
Sequential 方法中可以使用需要执行的增强方法来构造图像增强。如果只考虑旋转和 Dropout 来增强图像,Sequential 对象如下所示:

seq = iaa.Sequential([
        iaa.Dropout(p=0.2,),
        iaa.Affine(rotate=(-30,30))], random_order= True)

在以上代码中,指定两种增强方法,并且使用 random_order 参数,指示采用随机顺序执行两种增强方法:

plt.imshow(seq.augment_image(to_numpy(tr_images[0])), cmap='gray',vmin = 0, vmax = 255)
plt.title('Image augmented using a \nrandom orderof the two augmentations')
plt.show()

联合使用多个增强方法

2. 对批图像执行图像增强

为了最大限度的提高模型性能,需要同一图像在不同迭代中执行不同的增强。如果我们在 __init__ 方法中定义了一个增强管道,则只需要对输入图像集执行一次增强,这意味着在不同的迭代中不会有不同的增强;如果增强是在 __getitem__ 方法中,会对每个图像执行一组不同的增强,对每个图像执行一次增强。如果每次对一批图像而不是一次对一个图像执行增强,可以提高算法执行效率,接下来,我们对比以下两种方案:

  • 一次对一张图像执行增强,得到 32 张图像
  • 一次对一批图像执行增强,得到 32 张图像

为了了解在这两种情况下执行图像增强所需的时间,利用 Fashion-MNIST 数据集的训练图像中的前 32 张图像。

(1) 获取训练数据集中的前 32 张图像:

from torchvision import datasets
import torch
device = 'cuda' if torch.cuda.is_available() else 'cpu'
import time

data_folder = './data/FMNIST'
fmnist = datasets.FashionMNIST(data_folder, download=True, train=True)

tr_images = fmnist.data
tr_targets = fmnist.targets

def to_numpy(tensor):
    return tensor.cpu().detach().numpy()

(2) 指定要对图像执行的增强:

from imgaug import augmenters as iaa
aug = iaa.Sequential([
            iaa.Affine(translate_px={'x':(-10,10)}, mode='constant'),
            ])

接下来,介绍如何在 Dataset 类中扩充数据,有两种方法来扩充数据:

  • 每次增强一批数据中的一张图像
  • 一次性增强一批数据中的所有图像

增强批数据中的 32 张图像,一次一张
使用 augment_image 方法,计算增强批数据中的 32 张图像(一次增强一张)所需的时间:

start = time.time()
for i in range(32):
    aug.augment_image(to_numpy(tr_images[i]))
print('total times: ', time.time()-start)

增强 32 张图像大约需要 33 毫秒。

一次性增强批数据中的 32 张图像
使用 augment_images 方法,计算一次性增强 32 张图像所需的时间:

start = time.time()
x = aug.augment_images(to_numpy(tr_images[:32]))
print('total times: ', time.time()-start)

对一批图像执行增强大约需要 12 毫秒。

因此,最佳实践是在一批图像之上执行增强,而不是一次增强一个图像,augment_images 方法的输出是一个 numpy 数组。但是,之前使用的 Dataset 类在 __getitem__ 方法中一次提供一张图像的索引。因此,需要创建一个新函数 collate_fn,使我们能够对一批图像执行操作。

(3) 定义 Dataset 类,将输入图像、类别和增强对象作为初始化器:

class FMNISTDataset(Dataset):
    def __init__(self, x, y, aug=None):
        self.x, self.y = x, y
        self.aug = aug
    def __getitem__(self, ix):
        x, y = self.x[ix], self.y[ix]
        return x, y
    def __len__(self):
        return len(self.x)

(4) 定义 collate_fn 函数,将批数据作为输入:

    def collate_fn(self, batch):

将批图像及其类别分成两个不同的变量:

        ims, classes = list(zip(*batch))

如果提供了增强对象,则执行数据增强,因为我们只需要对训练数据执行增强,而验证数据无需执行增强:

        # transform a batch of images at once
        if self.aug:
            ims=self.aug.augment_images(images=list(map(to_numpy,list(ims))))

在以上代码中,使用 augment_images 方法,以便可以一次性处理一批图像。

创建图像张量,并通过将数据除以 255 来缩放数据:

        ims = torch.tensor(ims)[:,None,:,:].to(device)/255.
        classes = torch.tensor(classes).to(device)
        return ims, classes

一般来说,当我们需要执行复杂计算时,会利用 collate_fn 方法,这是因为一次性对一批图像执行计算比一次执行一个图像要快得多。

(5) 为了利用 collate_fn 方法,在创建 DataLoader 时使用一个新参数。

首先,创建 train 对象:

train = FMNISTDataset(tr_images, tr_targets, aug=aug)

接下来,定义 DataLoader 以及对象的 collate_fn 方法:

trn_dl = DataLoader(train, batch_size=64,
                collate_fn=train.collate_fn, shuffle=True)

最后,训练模型,通过利用 collate_fn 方法,可以更快地训练模型。

3. 利用数据增强训练模型

接下来,我们使用增强数据训练模型,观察数据增强对模型训练的影响。

(1) 导入相关库和数据集:

from torchvision import datasets
import torch
import matplotlib.pyplot as plt
import numpy as np
from torch.utils.data import Dataset, DataLoader
import torch
import torch.nn as nn
device = 'cuda' if torch.cuda.is_available() else 'cpu'

data_folder = './data/FMNIST' 
fmnist = datasets.FashionMNIST(data_folder, download=True, train=True)

tr_images = fmnist.data
tr_targets = fmnist.targets

val_fmnist = datasets.FashionMNIST(data_folder, download=True, train=False)
val_images = val_fmnist.data
val_targets = val_fmnist.targets

(2) 创建数据集类,用于随机平移图像执行数据增强:

定义数据增强管道:

from imgaug import augmenters as iaa
aug = iaa.Sequential([
            iaa.Affine(translate_px={'x':(-10,10)},
            mode='constant'),
        ])

定义数据集类:

def to_numpy(tensor):
    return tensor.numpy()

class FMNISTDataset(Dataset):
    def __init__(self, x, y, aug=None):
        self.x, self.y = x, y
        self.aug = aug
    def __getitem__(self, ix):
        x, y = self.x[ix], self.y[ix]
        return x, y
    def __len__(self):
        return len(self.x)

    def collate_fn(self, batch):
        'logic to modify a batch of images'
        ims, classes = list(zip(*batch))
        # transform a batch of images at once
        if self.aug:
            ims=self.aug.augment_images(images=list(map(to_numpy,list(ims))))
        ims = torch.tensor(ims)[:,None,:,:].to(device)/255.
        classes = torch.tensor(classes).to(device)
        return ims, classes

在以上代码中,利用 collate_fn 方法来指定要对批图像执行增强。

(3) 定义模型架构:

from torch.optim import SGD, Adam
def get_model():
    model = nn.Sequential(
        nn.Conv2d(1, 64, kernel_size=3),
        nn.MaxPool2d(2),
        nn.ReLU(),
        nn.Conv2d(64, 128, kernel_size=3),
        nn.MaxPool2d(2),
        nn.ReLU(),
        nn.Flatten(),
        nn.Linear(3200, 256),
        nn.ReLU(),
        nn.Linear(256, 10)
    ).to(device)
    loss_fn = nn.CrossEntropyLoss()
    optimizer = Adam(model.parameters(), lr=1e-3)
    return model, loss_fn, optimizer

(4) 定义 train_batch 函数以在批数据上训练模型:

def train_batch(x, y, model, optimizer, loss_fn):
    prediction = model(x)
    batch_loss = loss_fn(prediction, y)
    batch_loss.backward()
    optimizer.step()
    optimizer.zero_grad()
    return batch_loss.item()

(5) 定义 get_data 函数获取训练和验证 DataLoaders

def get_data():
    train = FMNISTDataset(tr_images, tr_targets, aug=aug)
    'notice the collate_fn argument'
    trn_dl = DataLoader(train, batch_size=64,
                collate_fn=train.collate_fn, shuffle=True)
    val = FMNISTDataset(val_images, val_targets)
    val_dl = DataLoader(val, batch_size=len(val_images),
                collate_fn=val.collate_fn, shuffle=True)
    return trn_dl, val_dl

(6) 指定训练和验证 DataLoaders 并获取模型对象、损失函数和优化器:

trn_dl, val_dl = get_data()
model, loss_fn, optimizer = get_model()

(7) 训练模型:

for epoch in range(10):
    print(epoch)
    for ix, batch in enumerate(iter(trn_dl)):
        x, y = batch
        batch_loss = train_batch(x, y, model, optimizer, loss_fn)

(8) 在平移图像上测试模型:

preds = []
ix = 24150
for px in range(-5,6):
    img = tr_images[ix]/255.
    img = img.view(28, 28)
    plt.subplot(1, 11, px+6)
    img2 = np.roll(img, px, axis=1)
    img3 = torch.Tensor(img2).view(-1,1,28,28).to(device)
    np_output = model(img3).cpu().detach().numpy()
    pred = np.exp(np_output)/np.sum(np.exp(np_output))
    preds.append(pred)
    plt.imshow(img2)
    plt.title(fmnist.classes[pred[0].argmax()])

plt.show()

图像平移
绘制模型关于平移图形的预测类别变化:

import seaborn as sns
fig, ax = plt.subplots(1,1, figsize=(12,10))
plt.title('Probability of each class for various translations')
sns.heatmap(np.array(preds).reshape(11,10), annot=True, ax=ax, fmt='.2f', xticklabels=fmnist.classes, yticklabels=[str(i)+str(' pixels') for i in range(-5,6)], cmap='gray')
plt.show()

类别预测
可以看到,当我们预测各种平移图像时,模型能够以极高的置信度预测图像的正确类别。

小结

数据增强是一种有效的提升模型性能的方法,通过扩充训练数据集和增加数据的多样性,可以提高模型的泛化能力和鲁棒性。在实际应用中,可以根据需求选择适当的数据增强方法,并进行合理的参数设置,以获得更好的训练效果。imgaug 是一个用于机器学习中图像增强的 Python 库,它支持多种增强技术,能够轻松组合这些技术,且有丰富的文档支持,能满足大多数的数据增强的需求。本节中,介绍了图像增强的基本概念,并使用 imgaug 介绍了常见的图像增强技术,通过实验表明使用图像增强能够显著提高神经网络模型性能。

系列链接

PyTorch深度学习实战(1)——神经网络与模型训练过程详解
PyTorch深度学习实战(2)——PyTorch基础
PyTorch深度学习实战(3)——使用PyTorch构建神经网络
PyTorch深度学习实战(4)——常用激活函数和损失函数详解
PyTorch深度学习实战(5)——计算机视觉基础
PyTorch深度学习实战(6)——神经网络性能优化技术
PyTorch深度学习实战(7)——批大小对神经网络训练的影响
PyTorch深度学习实战(8)——批归一化
PyTorch深度学习实战(9)——学习率优化
PyTorch深度学习实战(10)——过拟合及其解决方法
PyTorch深度学习实战(11)——卷积神经网络

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

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

相关文章

三款远程控制软件对比,5大挑选指标:安全、稳定、易用、兼容、功能

陈老老老板🤴 🧙‍♂️本文专栏:生活(主要讲一下自己生活相关的内容)生活就像海洋,只有意志坚强的人,才能到达彼岸。 🧙‍♂️本文简述:三款远程控制软件对比,5大挑选指标&#xff1…

两款开箱即用的Live2d

目录 背景第一款:开箱即用的Live2d在vue项目中使用html页面使用在线预览依赖文件地址配置相关参数成员属性源码 模型下载 第二款:换装模型超多的Live2d在线预览代码示例源码 模型下载 背景 从第一次使用服务器建站已经三年多了,记得那是在2…

App Tamer for Mac CPU智能控制管理

App Tamer是一款针对 macOS 平台的软件,它可以帮助用户有效地管理和控制正在运行的应用程序。通过优化 CPU 使用率,减少电池消耗和降低系统负载,App Tamer 提供了更加流畅和高效的计算体验。 App Tamer 的主要特点包括: 智能控制&…

HttpRunner接口自动化框架搭建,干货满满!

前言 除了前面讲述的unittest、pytest等等自动化框架外,HttpRunner也是当前流行自动化框架之一。 一、先简单来介绍下httprunner框架 1、它是面向HTTP协议的测试框架,独立于语言之外,无需编写代码脚本,只需要去维护yaml/json文…

【分布式共识】Multi-Paxos 算法思想

上一篇文章主要聊了Basic Paxos算法,而Multi-Paxos并不是一种算法,是一种算法思想。具体就是Basic Paxos解决的是对一个值达成共识。而后者是通过执行多次的Basic Paxos算法就多个值达成一致。具体的落地实现有Raft。 Muti-Paxos的问题 在Basic Paxos中…

为什么要建设校园气象站?

为什么要建设校园气象站?这是因为校园气象站不仅是气象观测工具,也可以作为气象教学仪器。校园气象站是由温度传感器、湿度传感器、大气压力传感器、二氧化碳传感器、风速传感器、风向传感器、雨量计等共同组成,它们会将看不见摸不着的各种气…

pdf太大怎么压缩大小?这样压缩文件很简单

工作和学习中,用到PDF文件的机会还是比较多的,但有时候PDF文件过大会给我们带来困扰,比如上传PDF文件时会因超出系统大小导致无法上传,这时候简单的解决方法就是压缩PDF文件,下面就来看看具体的操作方法吧~ 方法一&…

Codeforces EDU 151 Div.2

文章目录 A. Forbidden IntegerB. Come TogetherC. Strong PasswordD. Rating SystemE. Boxes and Balls A. Forbidden Integer Problem - A - Codeforces 给定整数n,从1~k中选择除了x的数,使这些数之和为n,每个数可以选择无限次 爆搜&…

回溯算法详解

目录 回溯算法详解 回溯VS递归 回溯算法的实现过程 n个结点构造多本节要讨论的是当给定 n(n>0)个结点时,可以构建多少种形态不同的树。 回溯算法详解 回溯算法,又称为“试探法”。解决问题时,每进行一步&#…

港联证券|集合竞价涨停马上又取消什么意思?

【科创板上市公司掀罕见回购潮】近来科创板上市公司董事长、实控人提议回购潮涌。Wind数据显现,今年以来,除掉定向回购,A股共有240家上市公司发表回购方案。其中,8月16日晚至20日晚,共有40家科创板上市公司董事长、实控…

Java 实现证件照底图替换,Java 实现照片头像底图替换

效果图 这里前端用layui实现的案例截图 color底图颜色可以在网页上这样取色 new Color(34, 133, 255) 实现案例下载链接:https://download.csdn.net/download/weixin_43992507/88237432

浅谈中压系统母线弧光保护的必要性-安科瑞黄安南

摘要:本文介绍了中低压开关柜内部发生电弧故障的原因、危害以及弧光保护在中压母线保护中的原理、用途、应用关键点,同时还介绍了弧光保护应用现状,探讨了无线测温在线监测系统在实际工作场景中的应用案例,证明了其在电力监控方面…

了解扩散概率模型 (DPM)

一、介绍 对复杂的概率分布进行建模是机器学习的核心问题。如果这个问题可以出现在不同的形状下,最常见的设置之一如下:给定仅由一些可用样本描述的复杂概率分布,如何生成新样本? 所有生成模型都依赖于相同的基本思想,…

基于PyQt+mysql图书管理系统

1 需求分析 针对图书馆的图书管理系统数据库设计,分别对图书馆的读者、一般工作人员和部门负责人进行详细地分析,总结出如下的需求信息: (1)图书馆中的图书具有书号、书名、作者、馆藏册数、在馆册数、价格、出版社及摘要等必要信…

AMEYA360:芯力特SIT1043Q CAN FD收发器振铃抑制功能实现原理及实际应用

01、SIT1043Q CAN收发器 振铃抑制功能简述 随着新能源汽车与自动驾驶技术的深入发展,CAN通信的速率从基础的125kbps速率提升到目前8Mbps速率的应用,通信速率越高对CAN收发器差分信号的质量要求越来越高。芯力特研发工程师在SIT1043Q芯片中内置振铃抑制电…

PSP - 基于 OpenFold 训练的 Finetuning 模型与推理逻辑评估

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/132410296 AlphaFold2 以其能够以极高的准确度预测蛋白质结构的能力,彻底改变了结构生物学。然而,AlphaFold2 的实现&…

Qt开发环境安装(版本5.14.2)

1.Qt下载 下载地址:https://download.qt.io/archive/qt/ 界面如下: 因为从qt 5.15开始,qt不再提供安装包,需要自行编译。本次我们选择5.14.2进行操作。 我们是在windows下安装,所以选择windows版本进行下载 下载完成…

使用 ChatGPT 的代码解释器进行数据科学的 5 种方法

推荐:使用 NSDT场景编辑器 助你快速搭建可二次编辑的3D应用场景 通过代码解释器集成,ChatGPT 现在可以在沙盒环境中编写和执行 Python 代码,以提供更准确和精确的答案。这允许它通过代码执行(而不仅仅是文本预测)执行复…

sdk manager (ubuntu20.4) 安装

1、首先下载sdk manager 1.9.3 下载链接 https://www.baidu.com/link?urlVXJhUqxxhS3eFK3bOPTzi5LFl6ybeW3JwDY1CwANaPf1gvO3IxQKzY547NIe53x1blJxnAXg7FTRTvs-cnfnVa&wd&eqida22baa7b0004ca980000000664e2d426 当然要登录自己的账号才能成功下载,下载对应…

MyBatis-Plus 详解

文章目录 MyBatisPlus一、入门案例1.1 准备表结构和数据1.2 添加依赖1.3 yml 配置1.4 添加 Factor 实体1.5 创建Mapper接口1.6 创建Mapper.xml 文件1.7 测试操作1.8 日志输出 二、CRUD操作2.1 插入因子2.2 更新因子2.3 删除因子① 根据id删除② 批量删除③ 通过Map删除 2.4 查询…