【Pytorch项目实战】之生成式网络:编码器-解码器、自编码器AE、变分自编码器VAE、生成式对抗网络GAN

news2024/9/21 12:46:21

文章目录

  • 生成式网络 - 生成合成图像
    • 算法一:编码器-解码器
    • 算法二:自编码器(Auto-Encoder,AE)
    • 算法三:变分自编码器(Variational Auto Encoder,VAE)
    • 算法四:生成式对抗网络(Generative Adversarial Nets,GAN)
    • (十四)实战:基于VAE变分自编码器生成图像(数据集:MNIST)
    • (十五)实战:基于GAN生成式对抗网络生成图像(数据集:MNIST)

生成式网络 - 生成合成图像

概念区分:
判别模型:利用训练样本图像训练模型,然后对新样本图像进行预测。
生成模型:根据一些规则,在原图像的基础上,生成新图像。

算法一:编码器-解码器

编码器解码器在不同领域的应用(图形化)
(1.1)通俗理解

假设你有一本菜谱,这本菜谱有很多章节,每个章节都是文字描写如何烹饪不同的菜。现在我们将所有文字输入到网络中,对于网络来说,其接收到的只是文字信息,它并不知道这本菜谱的构成。Encoder使得网络能理解这本菜谱的结构,对其中的内容进行抽象,形成一些高阶的信息(如:描述做了什么菜),并将这些信息对应到一个简化的空间里。Decoder对这些简化的高阶信息进行理解,对相同语义相近的文字进行分类,并对应到具体的菜式上面(比如:凉菜,面食,鱼,肉等)。

备注0:可以彼此独立使用,但一起使用性能表现良好。
备注1:CNN编码器与RNN解码器可以混合搭配使用,反之亦然;可以根据给定任务任意组合。
备注2:编码器和解码器可以由好多个编码器解码器组成,即由多层组成。
备注3:编码器可以是各种网络。如:线性网络,CNN,RNN,Transformer;
备注4:解码器与编码器可以是相同的网络,也可以是不同的网络。


(1.2)编码器解码器架构

  • 编码器处理输入
  • 解码器生成输出
    当RNN是多层时,解码器每一个时间步的输入是编码器最后一个时间步的输出与解码器上一时间输出的合并。编码器-解码器(seq2seq)
    在这里插入图片描述

(CNN/RNN)Encoder编码器、Decoder解码器
(CNN/RNN)什么是编码器、解码器?


(1.2.1)CNN架构定义

在CNN中,编码器 - 解码器网络通常看起来像这样(CNN编码器和CNN解码器),这是执行图像的语义分割的网络。
网络的左半部分Encoder将原始图像的像素映射到特征向量集合的高阶信息(如:汽车,马路,行人)。
网络的右半部分Decoder基于高阶信息,最后生成一张分割图像。并将输出一一映射回"原始"格式(在本例中为图像像素)。

  • 编码器:将输入编程成中间表达特征。
  • 解码器:将中间表示特征解码成输出。
    在这里插入图片描述
    如图所示:Encoder和Decoder中都存在卷积层,但作用不同。
    Encoder阶段(卷积层主要用于提取特征):卷积层获取图像的局部信息,然后输入2x2最大池化层,最后输入到下一层卷积。
    Decoder阶段(卷积层主要用于补全特征):将特征图进行上采样,然后交给卷积层进行处理。由于上采样后的2x2区域只有一个前一层传来的1x1特征点,其余区域都是空值,因此这些空值需要被填补成适当的特征值,来让这个区域变得完整并且平滑。这个工作就是由卷基层担任的。

(1.2.2)RNN架构定义
在RNN中,编码器 - 解码器网络通常看起来像这样(RNN编码器和RNN解码器),这是预测传入电子邮件响应的网络。
网络的左半部分Encoder将电子邮件编码为特征向量。
网络的右半部分Decoder对特征向量进行解码,最后生成字预测。

  • 编码器:将文本表示成向量。
  • 解码器:将向量表示成输出。
    在这里插入图片描述

算法二:自编码器(Auto-Encoder,AE)

自动编码器是一种特殊的神经网络,用于特征提取和数据降维。
在这里插入图片描述
组成:最简单的自动编码器由一个输入层,一个隐含层,一个输出层组成
隐含层的映射充当编码器。训练时编码器对输入向量进行映射,得到编码后的向量;
输出层的映射充当解码器。训练时解码器对编码向量进行映射,得到重构后的向量。
训练:编码器和解码器(神经网络)同时训练模型,使得重构向量与输入向量之间的误差最小。因此样本X的标签值就是样本自身。
预测:训练完成之后,在预测时只使用编码器而不再需要解码器,将编码器的输出结果进行分类,回归等任务。
在这里插入图片描述

算法三:变分自编码器(Variational Auto Encoder,VAE)

VAE的设计原理+损失函数推导

题目:假设有两张训练图像:全月图、半月图。经过训练后,自编码器模型已经能够无损地还原这两张图像。
问题:然而当我们想要生成一张清晰的且类似于3/4全月的图像时,结果确是模糊且无法辨认的乱码图。原因是由于深度神经网络DNN是非线性的变换过程,所以在点与点之间的迁移是没有规律的。
解决方法:**变分自编码器(VAE)**引入噪声,使得图像的编码区域扩大,从而可以有效地覆盖失真区域。在训练过程中,解码器会尽可能还原与原图相似的图像,又会针对噪声的失真点区域使其尽可能同时与全月图、半月图相似。
优点:该方法将参与训练的所有图像的编码方式由离散(图像之间特征相互独立)变为连续(图像之间特征有所关联)。

背景:由于自编码器的潜在变量Z都是从原始图像中产生,导致无法产生新的内容(如:3/4全月的图像)。
创新:VAE对自编码器的潜在变量Z增加正态分布约束(如:噪声);并通过(编码器)神经网络确定参数:均值(原图)和标准差(噪声)。使得可以生成清晰的原图像的同时,生成合成图像。
理论模型:对于生成模型而言,主流的理论模型分为隐马尔科夫模型HMM、朴素贝叶斯模型NB和高斯混合模型GMM。VAE基于高斯混合模型,即任何一个数据的分布,都可以看做是若干高斯分布的叠加。理论证明:当拆分的数量达到512时,其叠加的分布与原始分布的误差非常非常小,此时可以认为两者等同。
在这里插入图片描述
前向传播
(1)将输入样本X通过编码器(神经网络)输出:mu、log_var(相当于均值和方差)
(2)在标准正态分布N(0,1)中,随机采样一个ε,通过ε完成对潜在空间Z的约束。
(3)带入Z计算公式:Z = mu + ε * exp(log_var)。
(4)Z通过解码器生成输出样本X~。
反向传播的损失函数由下面两个度量的和构成:
(1)生成的新图像与原图像的相似度(采用交叉熵损失函数。如:nn.BCELoss)
(2)隐含空间的分布与正态分布的相似度(采用KL散度:Kullback-Leibler divergence)
在这里插入图片描述

算法四:生成式对抗网络(Generative Adversarial Nets,GAN)

生成对抗网络(GAN)是一种无监督机器学习算法。

背景:VAE利用潜在空间,能够捕捉到图像的结构变化(倾斜角度、形态变化、表情变化等),可以生成连续的新图像。但训练的损失函数采用均方误差MSE之类的粗略误差衡量,导致生成的图像较为模糊。
优缺点GAN生成的图像效果优于VAE,但更难训练。 原因:生成器和判别器之间需要很好的同步,但是在实际训练中判别器很容易收敛,而使得传递给生成器的信息变少,导致生成器无法训练自己的损失。
直观理解伪造者与技术鉴赏者的故事。(1)一个名画伪造者想要伪造一副达芬奇的画作。开始时,伪造者技术不精,但他将自己的一些赝品和达芬奇的真品混在一起,请一个艺术商人对每一幅画进行真实性评估,并向伪造者反馈。告诉他哪些看起来像真迹、哪些看起来不像真迹。(2)伪造者根据这些反馈,改进自己的赝品。随着时间的推移,伪造者技能越来越高,艺术商人也变得越来越擅长找出赝品。最后,他们手上都拥有了一些可以假以乱真的赝品。

在这里插入图片描述> 网络组成
(1)生成器(Generator)网络:将潜在空间的随机向量作为输入,并将其解码为一张合成图像。最终目的是使生成的合成图像骗过判别器。
(2)判别器(Discriminator)网络:将图像(真实图像或合成图像)作为输入,并预测该图像是真实的还是合成的。最终目的是找出生成器合成的假图像。
 
对抗网络:生成网络不断优化自己生成的数据让判别网络判断不出来,判别网络也要不断优化自己让自己判断得更准确。二者关系形成对抗,因此叫对抗网络。

GAN如何提升判别器的明辨是非能力?如何使生成的图像越来越逼近真实图像?
核心生成器与判别器的损失函数

######################################################################
# 11、定义判断器对【真图片】的损失函数
outputs = D(images)                                 # 前向传播(判别器)
d_loss_real = criterion(outputs, real_labels)       # 判别器的损失loss
real_score = outputs
# 22、定义判别器对【假图片】的损失函数
z = torch.randn(batch_size, latent_size).to(device)
fake_images = G(z)                                  # 前向传播(生成器)
outputs = D(fake_images)                            # 前向传播(判别器)
d_loss_fake = criterion(outputs, fake_labels)       # 判别器的损失loss
fake_score = outputs
# 33、判别器的总损失loss
d_loss = d_loss_real + d_loss_fake
######################################################################
# 定义生成器对假图片的损失函数。
z = torch.randn(batch_size, latent_size).to(device)
fake_images = G(z)                              # 前向传播(生成器)
outputs = D(fake_images)                        # 前向传播(判别器)
g_loss = criterion(outputs, real_labels)        # 生成器的损失loss
# 要求判别器生成的图片越来越像真图片,故损失函数中的标签改为真图片的标签,即希望生成的假图片,越来越靠近真图片。
######################################################################

10大典型的GAN算法 + GAN 的13种实际应用
GAN 的变种 :DCGAN、CGAN、CycleGAN、CoGAN、ProGAN、WGAN、SAGAN、BigGAN
GAN 的13种实际应用
(1)生成图像数据集。人工智能的训练是需要大量的数据集的,如果全部靠人工收集和标注,成本是很高的。GAN 可以自动的生成一些数据集,提供低成本的训练数据。
(2)生成人脸照片
(3)漫画人物
(4)自动生成人体模特 - 并且使用新的姿势
(5)给出多个不同角度的2D图像 - 自动生成3D模型
(6)图像到图像的转换
(7)文字到图像的转换
(8)语意 – 图像 – 照片 的转换
(9)根据人脸自动生成对应的表情
(10)可以生成特定的照片,例如:更换头发颜色、更改面部表情、甚至是改变性别。
(11)预测不同年龄阶段,你会长成什么样。
(12)提高图像分辨率。
(13)修复图像缺失区域。


(十四)实战:基于VAE变分自编码器生成图像(数据集:MNIST)

链接:https://pan.baidu.com/s/1X62pFmLRx7LDKwxG624KgA?pwd=5zf0
提取码:5zf0

在这里插入图片描述

import os
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision
from torchvision import transforms
from torchvision.utils import save_image
import matplotlib.pyplot as plt

os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'     # "OMP: Error #15: Initializing libiomp5md.dll"
#################################################################
class VAE(nn.Module):
    """VAE模型"""
    def __init__(self, image_size=784, h_dim=400, z_dim=20):
        super(VAE, self).__init__()
        self.fc1 = nn.Linear(image_size, h_dim)
        self.fc2 = nn.Linear(h_dim, z_dim)
        self.fc3 = nn.Linear(h_dim, z_dim)
        self.fc4 = nn.Linear(z_dim, h_dim)
        self.fc5 = nn.Linear(h_dim, image_size)

    def encode(self, x):
        """Encoder编码器"""
        h = F.relu(self.fc1(x))
        return self.fc2(h), self.fc3(h)

    def reparameterize(self, mu, log_var):
        """标准正态分布约束"""
        std = torch.exp(log_var / 2)
        # 从N(0,1)中随机采样
        eps = torch.randn_like(std)
        return mu + eps * std

    def decode(self, z):
        """Decoder编码器"""
        h = F.relu(self.fc4(z))
        return F.sigmoid(self.fc5(h))

    def forward(self, x):
        """前向传播"""
        mu, log_var = self.encode(x)
        z = self.reparameterize(mu, log_var)
        x_reconst = self.decode(z)
        return x_reconst, mu, log_var


#################################################################
# (1)超参数定义
image_size = 784
h_dim = 400
z_dim = 20
num_epochs = 30
batch_size = 128
learning_rate = 0.001
#################################################################
# (2)数据加载
# 在当前目录,若不存在则新建文件夹:ave_samples(用于存储解码器生成的图像)
sample_dir = 'ave_samples'
if not os.path.exists(sample_dir):
    os.makedirs(sample_dir)

dataset = torchvision.datasets.MNIST(root='data', train=True, transform=transforms.ToTensor(), download=True)   # 下载MNIST数据集
data_loader = torch.utils.data.DataLoader(dataset=dataset, batch_size=batch_size, shuffle=True)                 # 数据加载器
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')       # 是否有可用GPU,否则CPU
model = VAE().to(device)                                                    # 模型实例化
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)          # 优化器(Adam)
#################################################################
# (3)开始训练模型
for epoch in range(num_epochs):
    model.train()       # 模型训练
    for i, (x, _) in enumerate(data_loader):
        model.zero_grad()                           # 模型梯度清零
        x = x.to(device).view(-1, image_size)       # 改变数组形状并传递数据
        x_reconst, mu, log_var = model(x)           # 前向传播
        reconst_loss = F.binary_cross_entropy(x_reconst, x, size_average=False)     # 交叉熵损失函数(度量新图像与原图像的相似度)
        kl_div = - 0.5 * torch.sum(1 + log_var - mu.pow(2) - log_var.exp())         # KL散度(度量隐含空间的分布与正态分布的相似度)
        loss = reconst_loss + kl_div        # 损失值(两者相加的总损失)
        optimizer.zero_grad()               # 梯度清零
        loss.backward()                     # 反向传播
        optimizer.step()                    # 梯度更新

        # 每100个批次,打印结果。
        if (i + 1) % 100 == 0:
            print("Epoch[{}/{}], Step [{}/{}], Reconst Loss: {:.4f}, KL Div: {:.4f}"
                  .format(epoch + 1, num_epochs, i + 1, len(data_loader), reconst_loss.item(), kl_div.item()))

    with torch.no_grad():       # 强制之后的内容不进行计算图构建。
        # (在自定义文件夹中)保存采样图像,即潜在向量Z通过解码器生成的新图像
        z = torch.randn(batch_size, z_dim).to(device)
        out = model.decode(z).view(-1, 1, 28, 28)
        save_image(out, os.path.join(sample_dir, 'sampled-{}.png'.format(epoch + 1)))

        # (在自定义文件夹中)保存重构图像,即原图像通过解码器生成的图像
        out, _, _ = model(x)
        x_concat = torch.cat([x.view(-1, 1, 28, 28), out.view(-1, 1, 28, 28)], dim=3)
        save_image(x_concat, os.path.join(sample_dir, 'reconst-{}.png'.format(epoch + 1)))
#################################################################
# (4)画图
reconsPath = './ave_samples/reconst-30.png'     # (随机选择)重构图像
genPath = './ave_samples/sampled-30.png'        # (随机选择)新生成图像
Reconstruct_Image = plt.imread(reconsPath)
Generate_Image = plt.imread(genPath)

plt.subplot(121), plt.imshow(Reconstruct_Image), plt.title('Reconstruct_Image'), plt.axis('off')
plt.subplot(122), plt.imshow(Generate_Image), plt.title('Generate_Image'), plt.axis('off')
plt.show()

(十五)实战:基于GAN生成式对抗网络生成图像(数据集:MNIST)

链接:https://pan.baidu.com/s/1X62pFmLRx7LDKwxG624KgA?pwd=5zf0
提取码:5zf0

在这里插入图片描述

import os
import torch
import torchvision
import torch.nn as nn
from torchvision import transforms
from torchvision.utils import save_image
import matplotlib.pyplot as plt

os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'     # "OMP: Error #15: Initializing libiomp5md.dll"
###################################################################
# (1)超参数定义
latent_size = 64
hidden_size = 256
image_size = 784
num_epochs = 10
batch_size = 100
###################################################################
# (2)数据加载
# 在当前目录,创建不存在的目录gan_samples
sample_dir = 'gan_samples'
if not os.path.exists(sample_dir):
    os.makedirs(sample_dir)

trans = transforms.Compose([transforms.ToTensor(), transforms.Normalize([0.5], [0.5])])
mnist = torchvision.datasets.MNIST(root='data', train=True, transform=trans, download=False)
data_loader = torch.utils.data.DataLoader(dataset=mnist, batch_size=batch_size, shuffle=True)
###################################################################
# (3)模型定义
# 构建判断器
D = nn.Sequential(
    nn.Linear(image_size, hidden_size),
    nn.LeakyReLU(0.2),
    nn.Linear(hidden_size, hidden_size),
    nn.LeakyReLU(0.2),
    nn.Linear(hidden_size, 1),
    nn.Sigmoid())

# 构建生成器,这个相当于AVE中的解码器
G = nn.Sequential(
    nn.Linear(latent_size, hidden_size),
    nn.ReLU(),
    nn.Linear(hidden_size, hidden_size),
    nn.ReLU(),
    nn.Linear(hidden_size, image_size),
    nn.Tanh())
###################################################################
# (4)加载模型并定义相关函数
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
D = D.to(device)        # 将判别器迁移到设备上
G = G.to(device)        # 将生成器迁移到设备上
criterion = nn.BCELoss()                                        # 判别器的E交叉熵损失函数(BC)
d_optimizer = torch.optim.Adam(D.parameters(), lr=0.0002)       # 判别器的优化器Adam
g_optimizer = torch.optim.Adam(G.parameters(), lr=0.0002)       # 生成器的优化器Adam
###################################################################
# Clamp函数x限制在区间[min, max]内
def denorm(x):
    out = (x + 1) / 2
    return out.clamp(0, 1)


# 开始训练
total_step = len(data_loader)
for epoch in range(num_epochs):
    for i, (images, _) in enumerate(data_loader):
        images = images.reshape(batch_size, -1).to(device)      # 改变数组形状
        real_labels = torch.ones(batch_size, 1).to(device)      # 定义图像的真标签(全1)
        fake_labels = torch.zeros(batch_size, 1).to(device)     # 定义图像的假标签(全0)
        # ================================================================== #
        #                      训练判别器                                      #
        # ================================================================== #
        # 11、定义判断器对【真图片】的损失函数
        outputs = D(images)                                 # 前向传播(判别器)
        d_loss_real = criterion(outputs, real_labels)       # 判别器的损失loss
        real_score = outputs
        # 22、定义判别器对【假图片】的损失函数
        z = torch.randn(batch_size, latent_size).to(device)
        fake_images = G(z)                                  # 前向传播(生成器)
        outputs = D(fake_images)                            # 前向传播(判别器)
        d_loss_fake = criterion(outputs, fake_labels)       # 判别器的损失loss
        fake_score = outputs
        # 33、判别器的总损失loss
        d_loss = d_loss_real + d_loss_fake

        d_optimizer.zero_grad()     # 判别器的梯度清零
        g_optimizer.zero_grad()     # 生成器的梯度清零
        d_loss.backward()           # 判别器的反向传播
        d_optimizer.step()          # 判别器的梯度更新
        # ================================================================== #
        #                        训练生成器                                    #
        # ================================================================== #
        # 定义生成器对假图片的损失函数。
        # 要求判别器生成的图片越来越像真图片,故损失函数中的标签改为真图片的标签,即希望生成的假图片,越来越靠近真图片。
        z = torch.randn(batch_size, latent_size).to(device)
        fake_images = G(z)                              # 前向传播(生成器)
        outputs = D(fake_images)                        # 前向传播(判别器)
        g_loss = criterion(outputs, real_labels)        # 生成器的损失loss

        d_optimizer.zero_grad()     # 判别器的梯度清零
        g_optimizer.zero_grad()     # 生成器的梯度清零
        g_loss.backward()           # 生成器的反向传播
        g_optimizer.step()          # 生成器的梯度更新

        # 每200个批次,打印结果
        if (i + 1) % 200 == 0:
            print('Epoch [{}/{}], Step [{}/{}], d_loss: {:.4f}, g_loss: {:.4f}, D(x): {:.2f}, D(G(z)): {:.2f}'
                  .format(epoch+1, num_epochs, i + 1, total_step, d_loss.item(), g_loss.item(),
                          real_score.mean().item(), fake_score.mean().item()))

    # 保存真图片
    if (epoch + 1) == 1:
        images = images.reshape(images.size(0), 1, 28, 28)
        save_image(denorm(images), os.path.join(sample_dir, 'real_images.png'))
    # 保存假图片
    fake_images = fake_images.reshape(fake_images.size(0), 1, 28, 28)
    save_image(denorm(fake_images), os.path.join(sample_dir, 'fake_images-{}.png'.format(epoch + 1)))

# 保存预训练模型
torch.save(G.state_dict(), 'G.ckpt')
torch.save(D.state_dict(), 'D.ckpt')
###################################################################
for epoch in range(num_epochs):
    fake_images_path = './gan_samples/fake_images-' + str(epoch+1) + '.png'
    fake_image = plt.imread(fake_images_path)
    plt.subplot(int(num_epochs/5), 5, epoch+1), plt.imshow(fake_image), plt.title('fake_images' + str(epoch+1))
plt.show()

reconsPath = './gan_samples/real_images.png'
Image = plt.imread(reconsPath)
plt.imshow(Image), plt.title('real_images'), plt.axis('off')
plt.show()

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

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

相关文章

九型人格是什么?

九型人格是什么? 九型人格学(Enneagram/Ninehouse)是一个有2000多年历史的古老学问,它按照人们习惯性的思维模式,情绪反应和行为习惯等性格特质,将人的性格分为九种,又被称为九柱图,起源于中亚西亚地区,和中国的八卦图有点像,近代的九型是由六十年代智利的一位心理学…

计算机组成原理 | 第四章:存储器 | 存储器与CPU连接 | 存储器的校验 | Cache容量计算

文章目录📚概述🐇存储器分类🐇存储器的层次结构🥕原理🥕主存速度慢的原因🥕存储器三个主要特征的关系🥕缓存-主存层次和主存-辅存层次⭐️📚主存储器🐇概述🥕…

【opencv】Haar分类器及Adaboost算法人脸识别理论讲解

提到opencv,就不得不提其图像识别能力,最近旷世开源的YoloX项目兴起,作为目前Yolo系列中的最强者,本人对其也很感兴趣,但是完全没用机器学习和计算机视觉的基础,知其然,不知其所以然,于是想稍稍入坑一下opencv图像识别,了解一下相关算法,(说不定以后毕设会用到呢)。…

磨金石教育影视干货分享|朋友亲身经历—给新人剪辑师的三个建议

大学的时候有一个同学很喜欢视频剪辑。平时没事就蹲在电脑前,下载一些素材,自学剪辑软件,慢慢的搞一些创意剪辑。那时候自媒体短视频已经很火爆,这位同学剪辑的视频,不管质量如何就往上面发。一开始我们对于新事物的认…

Java---微服务---分布式搜索引擎elasticsearch(2)

分布式搜索引擎elasticsearch(2)1.DSL查询文档1.1.DSL查询分类1.2.全文检索查询1.2.1.使用场景1.2.2.基本语法1.2.3.示例1.2.4.总结1.3.精准查询1.3.1.term查询1.3.2.range查询1.3.3.总结1.4.地理坐标查询1.4.1.矩形范围查询1.4.2.附近查询1.5.复合查询1…

SpringBoot+Vue项目学生读书笔记共享平台

文末获取源码 开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7/8.0 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9 浏…

一起自学SLAM算法:10.3 机器学习与SLAM

连载文章,长期更新,欢迎关注: 前面已经分析过的8种SLAM算法案例(Gmapping、Cartographer、LOAM、ORB-SLAM2、LSD-SLAM、SVO、RTABMAP和VINS)都可以称为传统方法,因为这些算法都是在人为精心设计的特定规则下…

电子技术——MOS放大器基础

电子技术——MOS放大器基础 我们已经学过MOS可以当做一个压控流源,使用栅极电压 vGSv_{GS}vGS​ 控制漏极电流 iDi_DiD​ 。尽管两个量的关系不是线性的,稍后我们将会介绍偏置在线性区的工作方法。 构建压控压源放大器 现在,我们有了一个压…

【Java|golang】1664. 生成平衡数组的方案数---奇数前缀和 + 偶数前缀和

给你一个整数数组 nums 。你需要选择 恰好 一个下标(下标从 0 开始)并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。 比方说,如果 nums [6,1,7,4,1] ,那么: 选择删除下标 1 ,剩下…

[JAVA安全]JACKSON反序列化

前言 ackson是一个开源的Java序列化和反序列化工具&#xff0c;可以将Java对象序列化为XML或JSON格式的字符串&#xff0c;以及将XML或JSON格式的字符串反序列化为Java对象。 依赖 <dependency><groupId>com.fasterxml.jackson.core</groupId><artifact…

中国省际铁路通行时间数据

一、数据简介 本数据来自南京大学长江产业经济研究院《全国统一大市场下的省际铁路交通研究报告》的附录部分。中国的铁路&#xff08;高铁&#xff09;建设取得了辉煌成果。但受铁路时刻众多、历史数据不容易搜集整理的限制&#xff0c;学术与政策研究者一直无法对铁路建设的时…

三、JDBC详解

教程相关资料&#xff1a;https://www.aliyundrive.com/s/wMiqbd4Zws6 1&#xff0c;JDBC概述 在开发中我们使用的是java语言&#xff0c;那么势必要通过java语言操作数据库中的数据。这就是接下来要学习的JDBC。 1.1 JDBC概念 JDBC 就是使用Java语言操作关系型数据库的一套…

Nacos 配置中心 服务端推送变更源码讲解

目录 1. 配置引起变更的两种方式 1.1 后台管理直接操作 1.2 NacosClient 调用 RPC 接口 2. 变更事件处理 AsyncNotifyService 2.1 HTTP 任务 2.2 RPC任务 2.3 NacosServer 其他节点接收到消息后如何处理 3. 客户端推送实现&#xff1a;DumpService.dump 接着上一篇 Nac…

1601_读Dennis M. Ritchie and Ken Thompson的The UNIX TimeSharing System_Unix分时复用系统

全部学习汇总&#xff1a; GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 很久之前就闻听了UNIX的大名&#xff0c;也看过很多相关的故事类文章。其中最让我印象深刻的莫过于Ken发明UNIX的故事以及这个系统对于Linux以及GNU的OS的影响&…

Linux操作系统之线程同步

文章目录一、线程的实现&#xff1a;用户级、内核级、组合二、线程的同步&#xff08;通讯&#xff09;&#xff1a;信号量&#xff0c;互斥锁&#xff0c;条件变量&#xff0c;读写锁1&#xff09;信号量2&#xff09;互斥锁操作&#xff1a;加锁&#xff0c;解锁。3&#xff…

浮躁的当下或许我们更加需要一颗平常心

科技的迅速发展&#xff0c;已经融入我们的生活&#xff1b;曾经的慢生活慢节奏早已离我们远去&#xff0c;取而代之的是伴随科技齿轮快速运转的生活&#xff0c;快节奏更是科技时代下人们普遍生活的真实写照。 然而&#xff0c;科技虽然带给了我们生活的极大的便利&#xff0…

php伪协议

目录 一、伪协议介绍 1、php://协议 2、php://filter伪协议 3.php://input&#xff08;读取POST数据&#xff09; 4、file伪协议 5、phar://伪协议(读取压缩包文件内容) 6、压缩文件伪协议 6.1.zip://[压缩文件绝对路径]%23压缩文件内的子文件名 6.2.compress.bzip2://…

Mybatis 的输出结果封装小细节

resultType 属性可以指定结果集的类型&#xff0c;它支持基本类型和实体类类型。我们在前面的 CRUD 案例中已经对此属性进行过应用了。需要注意的是&#xff0c;它和 parameterType 一样&#xff0c;如果注册过类型别名的&#xff0c;可以直接使用别名。没有注册过的必须使用全…

Markdown基础语法

文章目录Markdown基础语法一、标题使用&#xff1a;2、二级标题3、一次类推二、字体三、引用四、分割线五、插入图片六、超链接七、列表1、有序列表2、无序列表八、表格九、代码十、添加目录九、代码十、添加目录Markdown基础语法 一、标题使用&#xff1a; 格式&#xff1a;…

智能驾驶 车牌检测和识别(二)《YOLOv5实现车牌检测(含车牌检测数据集和训练代码)》

智能驾驶 车牌检测和识别&#xff08;二&#xff09;《YOLOv5实现车牌检测&#xff08;含车牌检测数据集和训练代码&#xff09;》 目录 智能驾驶 车牌检测和识别&#xff08;二&#xff09;《YOLOv5实现车牌检测&#xff08;含车牌检测数据集和训练代码&#xff09;》 1. 前…