【人工智能Ⅱ】实验8:生成对抗网络

实验8:生成对抗网络

一:实验目的

1:理解生成对抗网络的基本原理。

2:学会构建改进的生成对抗网络,如DCGAN、WGAN、WGAN-GP等。

3:学习在更为真实的数据集上应用生成对抗网络的方法。

二:实验要求

1:理解生成对抗网络改进算法的改进内容和改进目的。

2:参考课程资源中的2024年春第八次实验代码,完成生成对抗网络改进算法WGAN或DCGAN网络的实现。

3:在Fashion MNIST数据集上验证生成对抗网络改进算法的效果,并对其进行调优。

4:在玉米数据集上验证生成对抗网络改进算法在真实场景下对复杂数据集的生成结果。(选做)

5:撰写实验报告,对结果进行分析。

三:实验环境

本实验所使用的环境条件如下表所示。

操作系统

Ubuntu(Linux)

程序语言

Python(3.11.4)

第三方依赖

torch, torchvision, matplotlib等

四:实验原理

1:GAN

GAN的中文名称为生成对抗网络。GAN是一种深度学习模型,由一个生成器网络和一个判别器网络组成,它们相互竞争地学习生成逼真的数据样本。GAN的核心思想是通过对抗训练来使生成器生成逼真的数据样本,同时训练判别器来区分真实数据样本和生成的数据样本。

【1】生成器网络

生成器网络的目标是接收一个随机噪声向量(通常服从某种先验分布,如均匀分布或正态分布)作为输入,并生成与真实数据样本相似的假数据样本。生成器网络通常由一系列反卷积层(也称为转置卷积层)组成,用于逐渐将输入噪声向量映射到数据空间。生成器网络的输出通常通过某种激活函数(如sigmoid、tanh等)进行转换,以确保生成的数据在合适的范围内。


生成器的训练过程如下图所示。

【2】判别器网络

判别器网络的目标是接收真实数据样本或生成的假数据样本作为输入,并输出一个标量值,表示输入数据是真实数据样本的概率。判别器网络通常由一系列卷积层组成,用于从输入数据中提取特征,并最终将这些特征映射到一个标量输出。判别器的输出通常通过sigmoid激活函数进行转换,将其限制在0到1之间,以表示输入数据是真实数据样本的概率。


判别器的训练过程如下图所示。

【3】对抗训练

在对抗训练中,生成器和判别器网络相互竞争,以改善其性能。生成器试图生成越来越逼真的假数据样本,以欺骗判别器,使其无法区分生成的假数据样本和真实数据样本。而判别器则试图提高其准确性,以尽可能准确地区分真实数据样本和生成的假数据样本。这种竞争的动态最终导致了生成器生成逼真的数据样本。

【4】损失函数

生成对抗网络使用两个损失函数来训练生成器和判别器。对于判别器,损失函数通常是二元交叉熵损失函数,用于衡量判别器在真实数据样本和生成的假数据样本上的分类性能。对于生成器,损失函数通常是判别器在生成的假数据样本上的输出与真实标签(即1)之间的二元交叉熵损失函数。通过最小化生成器和判别器的损失函数,可以实现对抗训练。

2:GAN的变种

目前GAN的变体主要从网络结构、条件生成网络、图像翻译、归一化和限制、损失函数、评价指标等方面进行改进。

变体的发展过程如下图所示。

其中,DCGAN(Deep Convolutional Generative Adversarial Networks)、WGAN(Wasserstein Generative Adversarial Networks)和 WGAN-GP(Wasserstein Generative Adversarial Networks with Gradient Penalty)都是GAN的常见变体,用于生成逼真的图像。

上述三种GAN变种的对比如下:

【1】损失函数

DCGAN:DCGAN使用交叉熵损失函数来训练生成器和判别器。

WGAN:WGAN引入了Wasserstein距离作为生成器和判别器之间的损失函数。Wasserstein距离能够更好地衡量生成分布和真实分布之间的差异,从而提高了训练的稳定性。

WGAN-GP:WGAN-GP在WGAN的基础上引入了梯度惩罚项,用于限制判别器的梯度,从而进一步提高了训练的稳定性和生成图像的质量。

【2】训练稳定性

DCGAN:DCGAN在训练过程中可能会出现训练不稳定的问题,例如模式崩溃(mode collapse)和梯度消失等。

WGAN:WGAN的损失函数设计使其更加稳定,可以缓解训练过程中出现的模式崩溃和梯度消失等问题,有助于生成更加高质量和多样化的图像。

WGAN-GP:WGAN-GP进一步改进了WGAN的稳定性,通过梯度惩罚项有效地限制了判别器的梯度,减轻了训练过程中的梯度爆炸和梯度消失问题。

五:算法流程

  1. 数据准备。准备训练所需的Fashion MNIST数据集。
  2. 网络构建。利用PyTorch框架搭建不同GAN的判别器和生成器。
  3. 可视化数据。导出生成器和判别器随着迭代次数所变化的损失曲线图像,同时利用生成器生成图像。

六:实验展示

1:DCGAN在Fashion MNIST数据集上的应用

DCGAN的生成器网络构建,如下图所示。

DCGAN的判别器网络构建,如下图所示。

DCGAN使用的损失函数为BCE损失函数,优化器使用Adam,优化器的学习率为0.0002,训练迭代次数为30次。

DCGAN中判别器和生成器的损失曲线,如下图所示。其中,橘色部分为生成器、蓝色部分为判别器。

DCGAN的生成效果,如下图所示。

2:WGAN在Fashion MNIST数据集上的应用

    WGAN的生成器网络构建,如下图所示。

WGAN的判别器网络构建,如下图所示。

WGAN使用的损失函数为Wasserstein距离损失函数,优化器使用RMSprop,优化器的学习率为0.00005,训练迭代次数为30次。

WGAN中判别器和生成器的损失曲线,如下图所示。其中,橘色部分为生成器、蓝色部分为判别器。

WGAN的生成效果,如下图所示。

3:DCGAN在大米数据集上的应用

DCGAN的超参数和训练过程与第1部分类似,但是迭代次数变为了500,加载数据集时将图像尺寸压缩为了28*28。


DCGAN中判别器和生成器的损失曲线,如下图所示。其中,橘色部分为生成器、蓝色部分为判别器。


DCGAN的生成效果,如下图所示。生成的图像中包含4粒大米。


源数据集的图像样本如下。

4:DCGAN在玉米数据集上的应用

DCGAN的超参数和训练过程与第1部分类似,但是迭代次数变为了500,加载数据集时将图像尺寸压缩为了28*28。


DCGAN中判别器和生成器的损失曲线,如下图所示。其中,橘色部分为生成器、蓝色部分为判别器。


DCGAN的生成效果,如下图所示。生成的图像中包含4个玉米。


源数据集的图像样本如下。

七:实验结论与心得

1:生成对抗网络利用生成器和判别器之间的对抗训练机制,能够有效地生成逼真的数据样本,在图像生成、文本生成、图像转换等领域广泛应用。

2:GAN的性能很大程度上受到超参数的影响,如学习率、潜在空间维度、网络结构等。

3:GAN相比较其他生成模型(玻尔兹曼机等),只用到了反向传播,不需要复杂的马尔科夫链,且可以产生更加清晰、真实的样本。

4:GAN采用无监督的学习方式训练,可以被广泛用在无监督学习和半监督学习领域。

5:如果生成器生成的样本,判别器判定为真实的,则说明生成器的效果是较好的,因而可以用判别器来评价生成器,即判别的性能越差,说明生成器的性能越好。

八:主要代码

1:DCGAN源代码

import torch

from torch import nn, optim

from torchvision import datasets, transforms, utils

from torch.utils.data import DataLoader

import matplotlib.pyplot as plt

# 设备配置

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 数据预处理

transform = transforms.Compose([

    transforms.ToTensor(),

    transforms.Normalize((0.5,), (0.5,))

])

# 加载数据集

train_data = datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)

train_loader = DataLoader(train_data, batch_size=128, shuffle=True)

# 生成器

class Generator(nn.Module):

    def __init__(self):

        super(Generator, self).__init__()

        self.main = nn.Sequential(

            # 输入是一个 100 维的噪声向量,我们将其投射并reshape 1x1x128 的大小

            nn.Linear(100, 128*7*7),

            nn.BatchNorm1d(128*7*7),

            nn.ReLU(True),

            nn.Unflatten(1, (128, 7, 7)),

            nn.ConvTranspose2d(128, 64, 4, stride=2, padding=1),

            nn.BatchNorm2d(64),

            nn.ReLU(True),

            nn.ConvTranspose2d(64, 1, 4, stride=2, padding=1),

            nn.Tanh()

        )

    def forward(self, x):

        return self.main(x)

# 判别器

class Discriminator(nn.Module):

    def __init__(self):

        super(Discriminator, self).__init__()

        self.main = nn.Sequential(

            nn.Conv2d(1, 64, 4, stride=2, padding=1),

            nn.LeakyReLU(0.2, inplace=True),

            nn.Conv2d(64, 128, 4, stride=2, padding=1),

            nn.BatchNorm2d(128),

            nn.LeakyReLU(0.2, inplace=True),

            nn.Flatten(),

            nn.Linear(128*7*7, 1),

            nn.Sigmoid()

        )

    def forward(self, x):

        return self.main(x)

# 实例化模型

netG = Generator().to(device)

netD = Discriminator().to(device)

# 损失函数和优化器

criterion = nn.BCELoss()

optimizerD = optim.Adam(netD.parameters(), lr=0.0002, betas=(0.5, 0.999))

optimizerG = optim.Adam(netG.parameters(), lr=0.0002, betas=(0.5, 0.999))

# 训练

num_epochs = 30

lossD = []

lossG = []

for epoch in range(num_epochs):

    for i, (images, _) in enumerate(train_loader):

        # 更新判别器:maximize log(D(x)) + log(1 - D(G(z)))

        netD.zero_grad()

        real_data = images.to(device)

        batch_size = real_data.size(0)

        labels = torch.full((batch_size,), 1, dtype=torch.float, device=device)

        output = netD(real_data)

        labels = labels.view(-1, 1)

        lossD_real = criterion(output, labels)

        lossD_real.backward()

        noise = torch.randn(batch_size, 100, device=device)

        fake_data = netG(noise)

        labels.fill_(0)

        output = netD(fake_data.detach())

        lossD_fake = criterion(output, labels)

        lossD_fake.backward()

        optimizerD.step()

        # 更新生成器:minimize log(1 - D(G(z))) ≈ maximize log(D(G(z)))

        netG.zero_grad()

        labels.fill_(1)  # fake labels are real for generator cost

        output = netD(fake_data)

        loss_G = criterion(output, labels)

        loss_G.backward()

        optimizerG.step()

       

        lossD.append(lossD_real.item() + lossD_fake.item())

        lossG.append(loss_G.item())

        if (i+1) % 100 == 0:

            print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss_D: {lossD_real.item() + lossD_fake.item():.4f}, Loss_G: {loss_G.item():.4f}')

# 可视化一些生成的图片

noise = torch.randn(64, 100, device=device)

fake_images = netG(noise)

fake_images = fake_images.reshape(fake_images.size(0), 1, 28, 28)

fake_images = (fake_images + 1) / 2  # 调整像素值范围到 [0, 1]

img_grid = utils.make_grid(fake_images, normalize=True)

img_grid = img_grid.cpu()  # 首先将张量移至 CPU

plt.imshow(img_grid.permute(1, 2, 0).numpy())

plt.savefig("z.png")

plt.close()

# 绘制曲线

y_values1 = lossD

y_values2 = lossG

x_values = range(1, len(y_values1) + 1)

plt.plot(x_values, y_values1, label='Discriminator Loss')

plt.plot(x_values, y_values2, label='Generator Loss')

# 添加标题和标签

plt.title('loss for discriminator and generator')

plt.xlabel('Batch')

plt.ylabel('Loss')

plt.legend(['Discriminator', 'Generator'])

# 显示图形

plt.savefig('loss-DCGAN.png')

2:WGAN源代码

import torch

import torch.nn as nn

import torch.optim as optim

from torchvision import datasets, transforms

import matplotlib.pyplot as plt

# 设备配置

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 定义生成器网络

class Generator(nn.Module):

    def __init__(self, latent_dim, img_shape):

        super(Generator, self).__init__()

        self.model = nn.Sequential(

            nn.Linear(latent_dim, 128),

            nn.LeakyReLU(0.2, inplace=True),

            nn.Linear(128, 256),

            nn.BatchNorm1d(256),

            nn.LeakyReLU(0.2, inplace=True),

            nn.Linear(256, img_shape),

            nn.Tanh()

        )

    def forward(self, z):

        z = z.to(next(self.parameters()).device)

        img = self.model(z)

        return img

# 定义判别器网络

class Discriminator(nn.Module):

    def __init__(self, img_shape):

        super(Discriminator, self).__init__()

        self.model = nn.Sequential(

            nn.Linear(img_shape, 256),

            nn.LeakyReLU(0.2, inplace=True),

            nn.Linear(256, 128),

            nn.BatchNorm1d(128),

            nn.LeakyReLU(0.2, inplace=True),

            nn.Linear(128, 1)

        )

    def forward(self, img):

        validity = self.model(img)

        return validity

# 参数

latent_dim = 100

img_shape = 28 * 28

batch_size = 64

# 准备数据

transform = transforms.Compose([

    transforms.ToTensor(),

    transforms.Normalize((0.5,), (0.5,))

])

train_dataset = datasets.FashionMNIST(root='./data', train=True, transform=transform, download=True)

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True)

# 初始化网络和优化器

generator = Generator(latent_dim, img_shape).to(device)

discriminator = Discriminator(img_shape).to(device)

optimizer_G = optim.RMSprop(generator.parameters(), lr=0.00005)

optimizer_D = optim.RMSprop(discriminator.parameters(), lr=0.00005)

# 训练模型

lossD = []

lossG = []

n_epochs = 30

for epoch in range(n_epochs):

    for i, (imgs, _) in enumerate(train_loader):

        # 训练判别器

        optimizer_D.zero_grad()

        # 真实图像

        real_imgs = imgs.view(-1, img_shape).to(device)

        validity_real = discriminator(real_imgs)

       

        # 生成潜在空间向量

        z = torch.randn(batch_size, latent_dim).to(device)

        fake_imgs = generator(z).detach()

        validity_fake = discriminator(fake_imgs)

        # 计算损失

        d_loss = -torch.mean(validity_real) + torch.mean(validity_fake)

        d_loss_item = d_loss.item()

       

        # 反向传播和优化

        d_loss.backward()

        optimizer_D.step()

        # 限制判别器参数

        for p in discriminator.parameters():

            p.data.clamp_(-0.01, 0.01)

        # 训练生成器

        optimizer_G.zero_grad()

        # 生成潜在空间向量

        z = torch.randn(batch_size, latent_dim)

        fake_imgs = generator(z)

        validity = discriminator(fake_imgs)

        # 计算损失

        g_loss = -torch.mean(validity)

        g_loss_item = g_loss.item()

        # 反向传播和优化

        g_loss.backward()

        optimizer_G.step()

        lossD.append(d_loss.item())

        lossG.append(g_loss.item())

       

        # 打印损失信息

        if i % 500 == 0:

            print(

                "[Epoch %d/%d] [Batch %d/%d] [D loss: %.4f] [G loss: %.4f]"

                % (epoch, n_epochs, i, len(train_loader), d_loss.item(), g_loss.item())

            )

# 生成图像

z = torch.randn(64, latent_dim, device=device)

generated_images = generator(z)

generated_images = generated_images.detach().cpu().numpy()

# 显示生成的图像

fig, axes = plt.subplots(nrows=8, ncols=8, figsize=(10, 10))

for i, ax in enumerate(axes.flatten()):

    ax.imshow(generated_images[i].reshape(28, 28), cmap='gray')

    ax.axis('off')

plt.tight_layout()

plt.savefig('zz.png')

plt.close()

# 绘制曲线

y_values1 = lossD

y_values2 = lossG

x_values = range(1, len(y_values1) + 1)

plt.plot(x_values, y_values1, label='Discriminator Loss')

plt.plot(x_values, y_values2, label='Generator Loss')

# 添加标题和标签

plt.title('loss for discriminator and generator')

plt.xlabel('Batch')

plt.ylabel('Loss')

plt.legend(['Discriminator', 'Generator'])

# 显示图形

plt.savefig('loss-WGAN.png')

3:玉米数据集上的DCGAN

import torch

from torch import nn, optim

from torchvision import transforms, utils

import matplotlib.pyplot as plt

import os

from PIL import Image

from torch.utils.data import Dataset, DataLoader

class CustomDataset(Dataset):

    def __init__(self, data_dir, transform=None):

        self.data_dir = data_dir

        self.transform = transform

        self.image_files = os.listdir(data_dir)

    def __len__(self):

        return len(self.image_files)

    def __getitem__(self, idx):

        img_name = os.path.join(self.data_dir, self.image_files[idx])

        image = Image.open(img_name).convert("RGB")  # 读取图像,并转换为RGB格式

        if self.transform:

            image = self.transform(image)

        return image

# 数据集文件夹路径

data_dir = r"/home/ubuntu/zz-test"

# 设备配置

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 数据预处理

transform = transforms.Compose([

    transforms.Resize((28, 28)),  # 将图像调整为28x28大小

    transforms.ToTensor(),

    transforms.Normalize((0.5,), (0.5,))

])

# 加载数据集

train_data = CustomDataset(data_dir, transform=transform)

train_loader = DataLoader(train_data, batch_size=32, shuffle=True)

# 生成器

class Generator(nn.Module):

    def __init__(self):

        super(Generator, self).__init__()

        self.main = nn.Sequential(

            nn.Linear(100, 128*7*7),

            nn.BatchNorm1d(128*7*7),

            nn.ReLU(True),

            nn.Unflatten(1, (128, 7, 7)),

            nn.ConvTranspose2d(128, 64, 4, stride=2, padding=1),

            nn.BatchNorm2d(64),

            nn.ReLU(True),

            nn.ConvTranspose2d(64, 3, 4, stride=2, padding=1),  # 修改这里的输出通道数为3

            nn.Tanh()

        )

    def forward(self, x):

        return self.main(x)

# 判别器

class Discriminator(nn.Module):

    def __init__(self):

        super(Discriminator, self).__init__()

        self.main = nn.Sequential(

            nn.Conv2d(3, 64, 4, stride=2, padding=1),  # 修改这里的输入通道数为3

            nn.LeakyReLU(0.2, inplace=True),

            nn.Conv2d(64, 128, 4, stride=2, padding=1),

            nn.BatchNorm2d(128),

            nn.LeakyReLU(0.2, inplace=True),

            nn.Flatten(),

            nn.Linear(128*7*7, 1),

            nn.Sigmoid()

        )

    def forward(self, x):

        return self.main(x)

# 实例化模型

netG = Generator().to(device)

netD = Discriminator().to(device)

# 损失函数和优化器

criterion = nn.BCELoss()

optimizerD = optim.Adam(netD.parameters(), lr=0.0002, betas=(0.5, 0.999))

optimizerG = optim.Adam(netG.parameters(), lr=0.0002, betas=(0.5, 0.999))

# 训练

num_epochs = 500

lossD = []

lossG = []

for epoch in range(num_epochs):

    for i, images in enumerate(train_loader):

        # 更新判别器:maximize log(D(x)) + log(1 - D(G(z)))

        netD.zero_grad()

        real_data = images.to(device)

        batch_size = real_data.size(0)

        labels = torch.full((batch_size,), 1, dtype=torch.float, device=device)

        output = netD(real_data)

        labels = labels.view(-1, 1)

        lossD_real = criterion(output, labels)

        lossD_real.backward()

        noise = torch.randn(batch_size, 100, device=device)

        fake_data = netG(noise)

        labels.fill_(0)

        output = netD(fake_data.detach())

        lossD_fake = criterion(output, labels)

        lossD_fake.backward()

        optimizerD.step()

        # 更新生成器:minimize log(1 - D(G(z))) ≈ maximize log(D(G(z)))

        netG.zero_grad()

        labels.fill_(1)  # fake labels are real for generator cost

        output = netD(fake_data)

        loss_G = criterion(output, labels)

        loss_G.backward()

        optimizerG.step()

       

        lossD.append(lossD_real.item() + lossD_fake.item())

        lossG.append(loss_G.item())

        if (i+1) % 100 == 0:

            print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss_D: {lossD_real.item() + lossD_fake.item():.4f}, Loss_G: {loss_G.item():.4f}')

# 保存生成的图像

noise = torch.randn(4, 100, device=device)

fake_images = netG(noise)

fake_images = (fake_images + 1) / 2  # 调整像素值范围到 [0, 1]

img_grid = utils.make_grid(fake_images, nrow=2, normalize=True)  # 将图像网格化,并且每行显示8张图像

img_grid = img_grid.permute(1, 2, 0).cpu().numpy()  # 将张量转换为NumPy数组,并将通道维度放到最后

plt.imshow(img_grid)

plt.axis('off')  # 关闭坐标轴

plt.savefig("generated_images.png")

plt.close()

# 绘制损失曲线

plt.plot(lossD, label='Discriminator Loss')

plt.plot(lossG, label='Generator Loss')

# 添加标题和标签

plt.title('Loss for Discriminator and Generator')

plt.xlabel('Batch')

plt.ylabel('Loss')

plt.legend()

# 保存损失曲线图

plt.savefig('loss-DCGAN.png')

plt.close()

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

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

相关文章

SaaS销售新指标|一文带你读懂什么是反向拒付指标

saas企业销售也需要一系列的指标来衡量企业运营情况如何?有哪些值得改善的地方?今天林叔发现一个比较有意思的新指标:反向拒付。希望能帮助saas企业更好的运营。 一、什么是反向拒付? **反向拒付指标(反拒付指标&…

C基础-标准库下

上:http://t.csdnimg.cn/qj5uA 目录 七. math.h 八. setjmp.h 九. signal.h 十. stdarg.h 十一.stddef.h 十二. stdio.h 十三. stdlib. 十四. string.h 十五. time.h 七. math.h 定义了各种数学函数和一个宏。 宏和函数描述 序号宏 & 描述1HUGE_VAL 当函数的结…

Vue3——实现word,pdf上传之后,预览功能(实测有效)

vue-office/pdf - npm支持多种文件(**docx、excel、pdf**)预览的vue组件库,支持vue2/3。也支持非Vue框架的预览。. Latest version: 2.0.2, last published: a month ago. Start using vue-office/pdf in your project by running npm i vue-office/pdf. There are …

Mybatis实现树形结构方式

1,三级分类树形结构查询 /*** DDD(Domain-Driven Design): 领域驱动设计** 三级分类树形结构;* 支持无限层级;* 当前项目只有三级*/ Data public class CategoryTreeTo {private Long categoryId; //1private String categoryName;private …

ENVI 5.3/6.0打开Landsat 8/9 C2L2级别数据(带有Metadata),附常见问题

ENVI 5.3/6.0打开Landsat 8/9 C2L2级别数据(带有Metadata) 文章目录 ENVI 5.3/6.0打开Landsat 8/9 C2L2级别数据(带有Metadata)前言数据下载ENVI 5.3打开Landsat 8 C2L2级别数据ENVI 5.3打开Landsat 9 C2L2级别数据ENVI 6.0打开La…

手写防抖debounce

手写防抖debounce 应用场景 当需要在事件频繁触发时,只执行最后一次操作,可以使用防抖函数来控制函数的执行频率,比如窗口resize事件和输入框input事件; 这段代码定义了一个名为 debounce 的函数,它接收两个参数:fn…

颠覆传统:探索Web3对传统计算机模式的冲击

随着Web3技术的崛起,传统计算机模式正面临着前所未有的冲击与挑战。Web3作为下一代互联网的代表,以其去中心化、安全可信的特性,正在颠覆着传统计算机模式的种种假设和局限性。本文将深入探讨Web3对传统计算机模式的冲击,并探索其…

关于stm32的复用和重映射问题

目录 需求IO口的复用和重映射使用复用复用加重映射 总结参考资料 需求 一开始使用stm32c8t6,想实现pwm输出,但是原电路固定在芯片的引脚PB10和PB11上,查看了下引脚的功能,需要使用到复用功能。让改引脚作为定时器PWM的输出IO口。…

PMP应考小技巧有哪些?

首先,制定合理的学习计划。将备考过程分解为小目标,并为每个目标设定截止日期。这样可以帮助我们有条不紊地进行学习,避免拖延和压力过大。 其次,选择适合自己的学习资源。PMP考试教材众多,可以选择一本权威的教材作为…

Idea-Linux远程开发部署

第一步:File->Remote Development 第二步: 第三步: 第四步:在Host位置填写Linux虚拟机的IP地址,在Username、Password填写对应的账号密码后点击Test Connection测试连接。 第五步: 第六步:在…

项目:仿RabbitMQ实现的消息队列组件

文章目录 写在前面开源仓库和项目上线其他文档说明 需求分析BrokerServer交换机类型持久化消息应答 模块划分服务端模块客户端模块交换机数据管理模块队列数据管理模块绑定数据管理模块消息数据管理模块队列信息管理模块虚拟机数据管理模块路由匹配模块消费者管理模块信道管理模…

折半查找二分查找

简介 折半查找也就是二分查找,也可以叫二分法,本质上都是一样的,通过比对中间值与目标值,一次性就能筛掉一半的数字。 举例: 一个猜数字游戏,让你来猜1-100中我选中的数,如果猜中游戏结束&…

露营地管理小程序基于ThinkPHP+FastAdmin+UniApp开发

应用介绍 本文来自:露营地管理小程序基于ThinkPHPFastAdminUniApp开发 - 源码1688 基于ThinkPHPFastAdminUniApp开发的现代化的露营地管理小程序,是专为露营业务设计开发小程序应用。平台拥有多角色管理,同时具有营位预定、门票购买等功能模…

【距离四六级只剩一个星期!】刘晓艳四级保命班课程笔记(2)(可分享治资料~)

这一节是专门的听力课程,众所周知,咱们刘晓艳刘老师的口语不是特别的突出,当然口才是一流的☝️。 文章目录 听力预判听前预判 听力过程八大出题关键点视听一致同义转换 听完一道题后平时练习精听步骤 听力预判 听前预判 画关键词&#xff…

融合通信系统 | 让传统通信沟通无边界

随着通信技术以及互联网的发展,融合通信在各行各业中的应用日益增多,融合通信多样的通信方式为行业用户带来了极佳的通信体验,助力各行各业蓬勃发展,同时也为人们的生活和工作带来了极大的便利和效率。 融合通信系统是一种集成多种…

C语言基础——数组(2)

ʕ • ᴥ • ʔ づ♡ど 🎉 欢迎点赞支持🎉 个人主页:励志不掉头发的内向程序员; 专栏主页:C语言基础; 文章目录 前言 一、二维数组的创建 1.1 二维数组的概念 1.2二维数组的创建 二、二维数组…

四川古力未来科技抖音小店:诚信之选,品质铸就信赖之路

在当今这个数字化、网络化的时代,电商平台如雨后春笋般涌现,抖音小店作为其中的佼佼者,以其独特的经营模式和广泛的用户基础,吸引了越来越多的消费者。而在这众多的抖音小店中,四川古力未来科技抖音小店凭借其卓越的品…

头颈肿瘤在PET/CT中的分割:HECKTOR挑战赛| 文献速递-深度学习肿瘤自动分割

Title 题目 Head and neck tumor segmentation in PET/CT: The HECKTOR challenge 头颈肿瘤在PET/CT中的分割:HECKTOR挑战赛 01 文献速递介绍 高通量医学影像分析,常被称为放射组学,已显示出其在揭示定量影像生物标志物与癌症预后之间关…

基于单片机的超声波倒车雷达设计

摘 要:文 章设计了一种基于单片机的超声波倒车雷达系统,以 AT89C51 型单片机作为控制核心,集距离测量、显示,方位显示和危险报警于一体,以提高驾驶者在倒车泊车时的安全性和舒适性。本设计采用 Keil 软件对系统程序…

已办理劳务资质,为何无法在全国建筑市场网查询到企业?

已办理劳务资质的企业无法在全国建筑市场网(四库一平台)查询到,可能的原因如下: 数据更新延迟: 全国建筑市场监管公共服务平台(四库一平台)的数据更新可能存在延迟。新获得的劳务资质信息在平台…