PyTorch深度学习实战(37)——CycleGAN详解与实现

PyTorch深度学习实战(37)——CycleGAN详解与实现

    • 0. 前言
    • 1. CycleGAN 基本原理
    • 2. CycleGAN 模型分析
    • 3. 实现 CycleGAN
    • 小结
    • 系列链接

0. 前言

CycleGAN 是一种用于图像转换的生成对抗网络(Generative Adversarial Network, GAN),可以在不需要配对数据的情况下将一种风格的图像转换成另一种风格,而无需为每一对输入-输出图像配对训练数据。CycleGAN 的核心思想是利用两个生成器和两个判别器,它们共同学习两个域之间的映射关系。例如,将马的图像转换成斑马的图像,或者将夏天的风景转换成冬天的风景。在本节中,我们将学习 CycleGAN 的基本原理,并实现该模型用于将苹果图像转换为橙子图像,或反之将橙子图像转换为苹果图像。

1. CycleGAN 基本原理

CycleGAN 是一种无需配对的图像转换技术,它可以将一个图像域中的图像转换为另一个图像域中的图像,而不需要匹配这两个域中的图像。它使用两个生成器和两个判别器,其中一个生成器将一个域中的图像转换为另一个域中的图像,而第二个生成器将其转换回来。这个过程被称为循环一致性,转换过程是可逆的。
CycleGAN 可以用于执行从一个类别到另一个类别的图像转换,而无需提供相匹配的输入-输出图像对来训练模型,只需要在两个不同的文件夹中提供这两个类别的图像。在本节中,我们将学习如何训练 CycleGAN 将苹果图像转换为橙子图像,或反之将橙子图像转换为苹果图像,CycleGAN 中的 Cycle 是指将图像从一个类别转换到另一个类别,然后再转换回原始类别的过程。
CycleGAN 中,需要使用三种不同的损失值:

  • 鉴别器损失:用于区分真实图像和伪造图像
  • 循环一致性损失:由于 CycleGAN 使用了两个生成器,因此需要确保转换是可逆的,循环一致性损失通过将转换过的图像再次传递到原始的生成器中,并将生成的图像与原始图像进行比较来实现
  • 恒等损失 (Identity loss):确保生成器在不进行转换的情况下仍然能够生成与原始图像相似的图像,通过将原始图像传递到生成器中,并计算生成图像与原始图像之间的差异

2. CycleGAN 模型分析

CycleGAN 模型构建策略如下:

  1. 导入数据集并进行预处理
  2. 定义 UNet 架构用于构建生成器和判别器网络
  3. 定义两个生成器:
    • G_AB:将类别 A 图像转换为类别 B 图像的生成器
    • G_BA:将类别 B 图像转换为类别 A 图像的生成器
  4. 定义恒等损失:
    • 如果将一张橘子的图像输入到橙子生成器,理想情况下,如果生成器完全理解橙子的所有信息,它不应该改变图像,而应该“生成”完全相同的图像,据此,我们可以创建一个恒等变换
    • 当类别 A (real_A) 的图像通过 G_BA 并与 real_A 进行比较时,恒等损失应该是最小的
    • 当类别 B (real_B) 的图像通过 G_AB 并与 real_B 进行比较时,恒等损失应该是最小的
  5. 定义GAN损失:
    • real_Afake_A 的判别器和生成器损失(当 real_B 图像通过 G_BA 时得到 fake_A)
    • real_Bfake_B 的判别器和生成器损失(当 real_A 图像通过 G_AB 时得到 fake_B)
  6. 定义循环一致性损失:
    • 一张苹果图像需要通过橙子生成网络进行转换,生成伪造的橘子图像,然后再通过苹果生成网络将伪造的橙子图像转换回苹果图像
    • fake_Breal_A 通过 G_AB 时的输出,当 fake_B 通过 G_BA 时应该重新生成 real_A
    • fake_Areal_B 通过 G_BA 时的输出,当 fake_A 通过 G_AB 时应该重新生成 real_B
  7. 优化三个损失函数的加权和

3. 实现 CycleGAN

接下来,我们使用 PyTorch 实现 CycleGAN 模型,用以将苹果图像转换为橙子图像,或反之将橙子图像转换为苹果图像。

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

首先下载并解压数据集,可以自行构建数据集,也可以下载本文所用数据集,下载地址:https://pan.baidu.com/s/1iTOt2NsUQ1a3taUHjvkjfA,提取码:iuqf

可视化示例图像如下:
数据集

与 Pix2Pix 训练数据集不同,苹果和橙色图像之间不存在一一对应的关系。

导入所需的库:

import torch
from torch import nn
from torch import optim
from matplotlib import pyplot as plt
import numpy as np
from torchvision.utils import make_grid
from torch.utils.data import DataLoader, Dataset
import cv2
import random
from glob import glob
from PIL import Image
import itertools
from torchvision import transforms
device = "cuda" if torch.cuda.is_available() else "cpu"

(2) 定义图像转换管道 transform

IMAGE_SIZE = 256
device = 'cuda' if torch.cuda.is_available() else 'cpu'
transform = transforms.Compose([
    transforms.Resize(int(IMAGE_SIZE*1.33)),
    transforms.RandomCrop((IMAGE_SIZE,IMAGE_SIZE)),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
])

(3) 定义数据集类 CycleGANDataset,以苹果图像 apple 和橙子图像 orange 文件夹为输入,提供批数据:

class CycleGANDataset(Dataset):
    def __init__(self, apples, oranges):
        self.apples = glob(apples)
        self.oranges = glob(oranges)

    def __getitem__(self, ix):
        apple = self.apples[ix % len(self.apples)]
        orange = random.choice(self.oranges)
        apple = Image.open(apple).convert('RGB')
        orange = Image.open(orange).convert('RGB')
        return apple, orange

    def __len__(self):
        return max(len(self.apples), len(self.oranges))
    def choose(self):
        return self[random.randint(len(self))]

    def collate_fn(self, batch):
        srcs, trgs = list(zip(*batch))
        srcs = torch.cat([transform(img)[None] for img in srcs], 0).to(device).float()
        trgs = torch.cat([transform(img)[None] for img in trgs], 0).to(device).float()
        return srcs.to(device), trgs.to(device)

(4) 定义训练、验证数据集和数据加载器:

trn_ds = CycleGANDataset('apples_oranges/apples_train/*.jpg', 'apples_oranges/oranges_train/*.jpg')
val_ds = CycleGANDataset('apples_oranges/apples_test/*.jpg', 'apples_oranges/oranges_test/*.jpg')

trn_dl = DataLoader(trn_ds, batch_size=1, shuffle=True, collate_fn=trn_ds.collate_fn)
val_dl = DataLoader(val_ds, batch_size=5, shuffle=True, collate_fn=val_ds.collate_fn)

(5) 定义网络的权重初始化方法 weights_init_normal

def weights_init_normal(m):
    classname = m.__class__.__name__
    if classname.find("Conv") != -1:
        torch.nn.init.normal_(m.weight.data, 0.0, 0.02)
        if hasattr(m, "bias") and m.bias is not None:
            torch.nn.init.constant_(m.bias.data, 0.0)
    elif classname.find("BatchNorm2d") != -1:
        torch.nn.init.normal_(m.weight.data, 1.0, 0.02)
        torch.nn.init.constant_(m.bias.data, 0.0)

(6) 定义残差块 ResidualBlock

class ResidualBlock(nn.Module):
    def __init__(self, in_features):
        super(ResidualBlock, self).__init__()

        self.block = nn.Sequential(
            nn.ReflectionPad2d(1),
            nn.Conv2d(in_features, in_features, 3),
            nn.InstanceNorm2d(in_features),
            nn.ReLU(inplace=True),
            nn.ReflectionPad2d(1),
            nn.Conv2d(in_features, in_features, 3),
            nn.InstanceNorm2d(in_features),
        )

    def forward(self, x):
        return x + self.block(x)

(7) 定义生成器 GeneratorResNet

class GeneratorResNet(nn.Module):
    def __init__(self, num_residual_blocks=9):
        super(GeneratorResNet, self).__init__()
        out_features = 64
        channels = 3
        model = [
            nn.ReflectionPad2d(3),
            nn.Conv2d(channels, out_features, 7),
            nn.InstanceNorm2d(out_features),
            nn.ReLU(inplace=True),
        ]
        in_features = out_features
        # Downsampling
        for _ in range(2):
            out_features *= 2
            model += [
                nn.Conv2d(in_features, out_features, 3, stride=2, padding=1),
                nn.InstanceNorm2d(out_features),
                nn.ReLU(inplace=True),
            ]
            in_features = out_features

        # Residual blocks
        for _ in range(num_residual_blocks):
            model += [ResidualBlock(out_features)]

        # Upsampling
        for _ in range(2):
            out_features //= 2
            model += [
                nn.Upsample(scale_factor=2),
                nn.Conv2d(in_features, out_features, 3, stride=1, padding=1),
                nn.InstanceNorm2d(out_features),
                nn.ReLU(inplace=True),
            ]
            in_features = out_features

        # Output layer
        model += [nn.ReflectionPad2d(channels), nn.Conv2d(out_features, channels, 7), nn.Tanh()]
        self.model = nn.Sequential(*model)
        self.apply(weights_init_normal)
    def forward(self, x):
        return self.model(x)

(8) 定义判别器 Discriminator

class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()

        channels, height, width = 3, IMAGE_SIZE, IMAGE_SIZE

        def discriminator_block(in_filters, out_filters, normalize=True):
            """Returns downsampling layers of each discriminator block"""
            layers = [nn.Conv2d(in_filters, out_filters, 4, stride=2, padding=1)]
            if normalize:
                layers.append(nn.InstanceNorm2d(out_filters))
            layers.append(nn.LeakyReLU(0.2, inplace=True))
            return layers

        self.model = nn.Sequential(
            *discriminator_block(channels, 64, normalize=False),
            *discriminator_block(64, 128),
            *discriminator_block(128, 256),
            *discriminator_block(256, 512),
            nn.ZeroPad2d((1, 0, 1, 0)),
            nn.Conv2d(512, 1, 4, padding=1)
        )
        self.apply(weights_init_normal)

    def forward(self, img):
        return self.model(img)

(9) 定义图像样本生成函数 generate_sample

@torch.no_grad()
def generate_sample(G_AB, G_BA):
    data = next(iter(val_dl))
    G_AB.eval()
    G_BA.eval()
    
    real_A, real_B = data
    fake_B = G_AB(real_A)
    fake_A = G_BA(real_B)
    # Arange images along x-axis
    real_A = make_grid(real_A, nrow=5, normalize=True)
    real_B = make_grid(real_B, nrow=5, normalize=True)
    fake_A = make_grid(fake_A, nrow=5, normalize=True)
    fake_B = make_grid(fake_B, nrow=5, normalize=True)
    # Arange images along y-axis
    image_grid = torch.cat((real_A, fake_B, real_B, fake_A), 1)
    plt.imshow(image_grid.detach().cpu().permute(1,2,0).numpy())
    plt.show()

(10) 定义生成器训练函数 generator_train_step

该函数将两个生成器( G_ABG_BA)、优化器和两个类别的真实图像( real_Areal_B )作为输入:

def generator_train_step(Gs, optimizer, real_A, real_B, D_A, D_B, criterion_identity, criterion_cycle, criterion_GAN, lambda_cyc, lambda_id):

指定生成器:

    G_AB, G_BA = Gs

将优化器的梯度设置为零:

    optimizer.zero_grad()

计算类别 A (苹果)和类别 B (橙子)图像的恒等损失 (loss_identity):

    loss_id_A = criterion_identity(G_BA(real_A), real_A)
    loss_id_B = criterion_identity(G_AB(real_B), real_B)

    loss_identity = (loss_id_A + loss_id_B) / 2

计算图像通过生成器时的 GAN 损失,此时生成的图像应尽可能接近另一类别,使用 np.ones 作为训练生成器的判别网络目标输出,因为我们将生成的伪造图像传递给相同类别的判别器:

    fake_B = G_AB(real_A)
    loss_GAN_AB = criterion_GAN(D_B(fake_B), torch.Tensor(np.ones((len(real_A), 1, 16, 16))).to(device))
    fake_A = G_BA(real_B)
    loss_GAN_BA = criterion_GAN(D_A(fake_A), torch.Tensor(np.ones((len(real_A), 1, 16, 16))).to(device))
    loss_GAN = (loss_GAN_AB + loss_GAN_BA) / 2

计算循环一致性损失。假设,一张苹果图像被橙子生成器转换为一张伪造橙子图像,然后伪造橙子图像通过苹果生成器转换回一张苹果图像,理想情况下,经过该过程后应该返回原始图像,即循环一致性损失应该为零:

    recov_A = G_BA(fake_B)
    loss_cycle_A = criterion_cycle(recov_A, real_A)
    recov_B = G_AB(fake_A)
    loss_cycle_B = criterion_cycle(recov_B, real_B)

    loss_cycle = (loss_cycle_A + loss_cycle_B) / 2

计算总损失并执行反向传播:

    loss_G = loss_GAN + lambda_cyc * loss_cycle + lambda_id * loss_identity
    loss_G.backward()
    optimizer.step()
    return loss_G, loss_identity, loss_GAN, loss_cycle, loss_G, fake_A, fake_B

(11) 定义判别器训练函数 discriminator_train_step

def discriminator_train_step(D, real_data, fake_data, optimizer, criterion_GAN):
    optimizer.zero_grad()
    loss_real = criterion_GAN(D(real_data), torch.Tensor(np.ones((len(real_data), 1, 16, 16))).to(device))
    loss_fake = criterion_GAN(D(fake_data.detach()), torch.Tensor(np.zeros((len(real_data), 1, 16, 16))).to(device))
    loss_D = (loss_real + loss_fake) / 2
    loss_D.backward()
    optimizer.step()
    return loss_D

(12) 定义生成器、判别器对象、优化器和损失函数:

G_AB = GeneratorResNet().to(device)
G_BA = GeneratorResNet().to(device)
D_A = Discriminator().to(device)
D_B = Discriminator().to(device)

criterion_GAN = torch.nn.MSELoss()
criterion_cycle = torch.nn.L1Loss()
criterion_identity = torch.nn.L1Loss()

optimizer_G = torch.optim.Adam(
    itertools.chain(G_AB.parameters(), G_BA.parameters()), lr=0.0002, betas=(0.5, 0.999)
)
optimizer_D_A = torch.optim.Adam(D_A.parameters(), lr=0.0002, betas=(0.5, 0.999))
optimizer_D_B = torch.optim.Adam(D_B.parameters(), lr=0.0002, betas=(0.5, 0.999))

lambda_cyc, lambda_id = 10.0, 5.0

(13) 训练网络:

n_epochs = 50
# log = Report(n_epochs)
loss_D_epochs = []
loss_G_epochs = []
loss_GAN_epochs = []
loss_cycle_epochs = []
loss_identity_epochs = []
for epoch in range(n_epochs):
    N = len(trn_dl)
    loss_D_items = []
    loss_G_items = []
    loss_GAN_items = []
    loss_cycle_items = []
    loss_identity_items = []
    for bx, batch in enumerate(trn_dl):
        real_A, real_B = batch

        loss_G, loss_identity, loss_GAN, loss_cycle, loss_G, fake_A, fake_B = generator_train_step((G_AB,G_BA), optimizer_G, real_A, real_B, D_A, D_B, criterion_identity, criterion_cycle, criterion_GAN, lambda_cyc, lambda_id)
        loss_D_A = discriminator_train_step(D_A, real_A, fake_A, optimizer_D_A, criterion_GAN)
        loss_D_B = discriminator_train_step(D_B, real_B, fake_B, optimizer_D_B, criterion_GAN)
        loss_D = (loss_D_A + loss_D_B) / 2
        loss_D_items.append(loss_D.item())
        loss_G_items.append(loss_G.item())
        loss_GAN_items.append(loss_GAN.item())
        loss_cycle_items.append(loss_cycle.item())
        loss_identity_items.append(loss_identity.item())
    loss_D_epochs.append(np.average(loss_D_items))
    loss_G_epochs.append(np.average(loss_G_items))
    loss_GAN_epochs.append(np.average(loss_GAN_items))
    loss_cycle_epochs.append(np.average(loss_cycle_items))
    loss_identity_epochs.append(np.average(loss_cycle_items))

(14) 训练模型后,测试模型生成图像:

generate_sample(G_AB, G_BA)

模型生成结果
从上图可以看出,CycleGAN 可以成功地将苹果转换为橙子(前两行),将橙子转换为苹果(后两行)。

小结

CycleGAN 是一种用于无监督图像转换的深度学习模型,它通过两个生成器和两个判别器的组合来学习两个不同域之间的映射关系。生成器负责将一个域的图像转换成另一个域的图像,而判别器则用于区分生成的图像和真实的图像。CycleGAN 引入循环一致性损失,确保图像转换是可逆的,从而提高生成图像的质量。通过对抗训练和循环一致性损失,CycleGAN 可以实现在没有配对标签的情况下进行图像域转换。

系列链接

PyTorch深度学习实战(1)——神经网络与模型训练过程详解
PyTorch深度学习实战(2)——PyTorch基础
PyTorch深度学习实战(3)——使用PyTorch构建神经网络
PyTorch深度学习实战(4)——常用激活函数和损失函数详解
PyTorch深度学习实战(5)——计算机视觉基础
PyTorch深度学习实战(6)——神经网络性能优化技术
PyTorch深度学习实战(7)——批大小对神经网络训练的影响
PyTorch深度学习实战(8)——批归一化
PyTorch深度学习实战(9)——学习率优化
PyTorch深度学习实战(10)——过拟合及其解决方法
PyTorch深度学习实战(11)——卷积神经网络
PyTorch深度学习实战(12)——数据增强
PyTorch深度学习实战(13)——可视化神经网络中间层输出
PyTorch深度学习实战(14)——类激活图
PyTorch深度学习实战(15)——迁移学习
PyTorch深度学习实战(16)——面部关键点检测
PyTorch深度学习实战(17)——多任务学习
PyTorch深度学习实战(18)——目标检测基础
PyTorch深度学习实战(19)——从零开始实现R-CNN目标检测
PyTorch深度学习实战(20)——从零开始实现Fast R-CNN目标检测
PyTorch深度学习实战(21)——从零开始实现Faster R-CNN目标检测
PyTorch深度学习实战(22)——从零开始实现YOLO目标检测
PyTorch深度学习实战(23)——从零开始实现SSD目标检测
PyTorch深度学习实战(24)——使用U-Net架构进行图像分割
PyTorch深度学习实战(25)——从零开始实现Mask R-CNN实例分割
PyTorch深度学习实战(26)——多对象实例分割
PyTorch深度学习实战(27)——自编码器(Autoencoder)
PyTorch深度学习实战(28)——卷积自编码器(Convolutional Autoencoder)
PyTorch深度学习实战(29)——变分自编码器(Variational Autoencoder, VAE)
PyTorch深度学习实战(30)——对抗攻击(Adversarial Attack)
PyTorch深度学习实战(31)——神经风格迁移
PyTorch深度学习实战(32)——Deepfakes
PyTorch深度学习实战(33)——生成对抗网络(Generative Adversarial Network, GAN)
PyTorch深度学习实战(34)——DCGAN详解与实现
PyTorch深度学习实战(35)——条件生成对抗网络(Conditional Generative Adversarial Network, CGAN)
PyTorch深度学习实战(36)——Pix2Pix详解与实现

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

windows server设置桌面显示此电脑

我开发的chatgpt网站: https://chat.xutongbao.top

LeetCode 热题 100 | 二叉树(下)

目录 1 114. 二叉树展开为链表 2 105. 从前序与中序遍历序列构造二叉树 3 437. 路径总和 III 菜鸟做题(即将返校版),语言是 C 1 114. 二叉树展开为链表 题眼:展开后的单链表应该与二叉树 先序遍历 顺序相同。 而先序遍历就…

day08-实战-今日指数

今日指数-day08 1. 个股最新分时行情数据 1.1 个股最新分时行情功能说明 1)个股最新分时行情功能原型 2)个股最新分时行情数据接口分析 功能描述:获取个股最新分时行情数据,主要包含:开盘价、前收盘价、最新价、最…

机试笔记-划拳

想复杂了,没有体现代码的简洁优雅之美 可以在for循环的过程中一边接受一边进行failA的统计,fail属于全局变量,可以在一次一次的接受中改变自身的数值 然后还要统计两种情况: 甲win 乙fail和相反的情况,剩下同赢同输的情…

Chrome关闭时出现弹窗runtime error c++R6052,且无法关闭

环境: Chrome 版本121 Win10专业版 问题描述: Chrome关闭时出现弹窗runtime error cR6052,且无法关闭 解决方案: 1.任务管理器打开,强制结束进程 2.再次打开谷歌浏览器,打开设置关于Chrome&#xff0…

云上业务一键性能调优,应用程序性能诊断工具 Btune 上线

- 01 - 终于等来了预算,这就把服务迁移到最新的 CPU 平台上去,这样前端的同事立马就能感受我们带来的速度提升了。可是…… 这些性能指标怎么回事?不仅没有全面提升,有些反而下降了。不应该这样啊,这可怎么办&#xf…

为什么在MOS管开关电路设计中使用三极管容易烧坏?

MOS管作为一种常用的开关元件,具有低导通电阻、高开关速度和低功耗等优点,因此在许多电子设备中广泛应用。然而,在一些特殊情况下,我们需要在MOS管控制电路中加入三极管来实现一些特殊功能。然而,不同于MOS管&#xff…

猫咪不喝水是什么原因?这些方法远离缺水小猫

有经验的铲屎官都知道,家里的猫似乎不太喜欢喝水。只看到一只或两只猫不喝水,那可能是例外情况。但绝大部分的猫都不咋爱喝水,这是为什么呢? 一、猫咪不喝水是什么原因? 如果你已经尝试了各种方法来让猫咪多喝水&…

springboot整合mybatisPlus超级详细

springboot整合mybatis-plus超级详细 一、环境二、springboot整合myBatisPlus2.1新建2.2 添加Mybatis-plus和mysql依赖2.3 修改配置文件2.4 新建包和文件2.5 新建表2.6 创建实体类2.7 创建Mapper接口2.8 创建Service接口2.9 创建Service实现类2.10 增删改查 MyBatis-Plus&#…

IDEA左侧启动图标消失

一、问题如图 二、解决方式

水经注下载注记地图, mars3d加载底图

使用 水经微图 (公司提供的,需付费,我也没有这个东西)下载注记地图; 1、选择下载 选择区域: 根据需求进行选择,两边都可以选择,看个人喜欢;这里以澳门为演示 选择地图…

渗透测试—信息收集

渗透测试—信息收集 1. 收集域名信息1.1. 域名注册信息1.2. SEO信息收集1.3. 子域名收集1.3.1. 在线子域名收集1.3.2. 子域名收集工具 1.4. 域名备案信息1.5. ICP备案号查询1.6. SSL证书查询 2. 收集真实IP2.1. 超级ping2.2. Ping2.3. CDN绕过 3. 收集旁站或C段IP3.1. 旁站或C段…

瑞_Redis_初识Redis(含安装教程)

文章目录 1 初识Redis1.1 认识NoSQL1.1.1 结构化与非结构化1.1.2 关联和非关联1.1.3 查询方式1.1.4 事务1.1.5 总结 1.2 认识Redis1.2.1 介绍1.2.2 特征1.2.3 优势 1.3 安装Redis ★★★1.3.1 Linux安装Redis1.3.1.1 安装Redis依赖 1.3.2 Windows安装Redis1.3.2.1 安装步骤1.3.…

挖掘机生产装配线无线通讯应用

一、应用背景 山东某挖掘机机械有限公司主要产品有装载机、挖掘机、道路机械及核心关键零部件等系列工程机械产品。为加速新旧动能转换,全新挖掘机整机装配线配合劳动组合的调整,提高装配水平和生产效率;可集中、合理地使用工装、专用工具&a…

【深度学习】Pytorch教程(八):PyTorch数据结构:2、张量的数学运算(6):高维张量:乘法、卷积(conv2d~四维张量;conv3d~五维张量)

文章目录 一、前言二、实验环境三、PyTorch数据结构1、Tensor(张量)1. 维度(Dimensions)2. 数据类型(Data Types)3. GPU加速(GPU Acceleration) 2、张量的数学运算1. 向量运算2. 矩阵…

【rust】8、连接数据库:sqlx

sqlx 是 rust 的数据库访问工具, 本身并不是 orm,但常见的 orm 都是基于它实现的。其有如下特点: 支持异步,适合高并发编译时检查:cargo build 时检查执行 sql,校验响应值支持多数据库:mysql、…

Leo赠书活动-17期 《基础软件之路:企业级实践及开源之路》

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 赠书活动专栏 ✨特色专栏:…

学习笔记-Git

Git 问题一描述解决方法注意事项 问题一 描述 在commit和push的时候因为网络太慢了中途强行关闭了进程,而push的内容因为文件过大导致无法正常push 按照原本的流程在push的时候会提示失败,并且需要在解决了大文件之后重新push 而因为中途中断了&#x…

Autosar-Mcal配置详解-MCU

3.6.1创建、配置RAM 1)创建RAM配置 2)配置RAM 以F1KM R7F7016533ABG为例,它的local RAM有512K, global RAM 192K,Retention RAM 64K. Local RAM: local RAM就是程序平常使用的RAM,在DeepStop模式下内容会丢失。 Global RAM:主要用于DMA的源地址和目的地址使用,在Dee…

win电脑截屏的图片在哪里?电脑截屏的图片删了怎么找回来

在使用Windows操作系统的电脑时,截屏功能是我们经常使用的工具之一。然而,有时我们可能会遇到找不到截屏图片或误删截屏图片的情况。那么,Win电脑截屏的图片究竟存放在哪里?如果误删了截屏图片,我们又该如何找回呢&…
最新文章