AIGC实战——生成对抗网络(Generative Adversarial Network)

AIGC实战——生成对抗网络

    • 0. 前言
    • 1. 生成对抗网络
      • 1.1 生成对抗网络核心思想
      • 1.2 深度卷积生成对抗网络
    • 2. 数据集分析
      • 3. 构建深度卷积生成对抗网络
      • 3.1 判别器
      • 3.2 生成器
      • 3.3 DCGAN 模型训练
    • 4. GAN 训练技巧
      • 4.1 判别器强于生成器
      • 4.2 生成器强于判别器
      • 4.3 信息量不足
      • 4.4 超参数
    • 小结
    • 系列链接

0. 前言

生成对抗网络 (Generative Adversarial Network, GAN) 是由 Ian Goodfellow 等人在 2014 年提出的一种强大的深度学习模型,可以用于生成新数据样本,比如图像、音频、文本等。GAN 包含两个神经网络:生成器和判别器。生成器根据输入的噪声信号生成一些伪造的数据样本,而判别器则负责判断该数据样本是真实的还是伪造的。在本节中,首先阐述生成对抗网络的理论基础,然后使用 Keras 构建生成对抗网络模型。

1. 生成对抗网络

1.1 生成对抗网络核心思想

生成对抗网络 (Generative Adversarial NetworkGAN) 可以通过类比为一个伪造专家与一个检测专家之间的博弈。生成器 (generator) 是伪造专家,目标是制造出逼真的假样本,以尽可能地欺骗检测专家。而鉴别器 (discriminator) 则是检测专家,旨在区分真实样本和生成器产生的假样本,并尽可能准确地识别它们。
在开始时,生成器只能制造出不完美的假样本,而鉴别器擅长辨别真伪并且准确率相对较高。然而,随着训练的进行,生成器变得更加熟练,并努力提高自己的技艺,从而创造逼真的样本。同时,鉴别器也在不断学习和调整自己的判别能力,以保持对假样本的敏感度。
通过反复的博弈和训练,生成器和鉴别器逐渐达到一种平衡状态。生成器学会了创造足以迷惑鉴别器的逼真作品,而鉴别器也不断提高自己的判别能力。最终,生成器能够创造出几乎无法与真实样本区分的逼真假样本,而鉴别器也变得越来越难以区分真伪。
GAN 的核心思想是生成器和判别器之间的对抗,生成器试图将随机噪声转换为看起来像是从原始数据集中采样而来的观测样本,而判别器则试图预测一个观测样本是来自原始数据集还是生成器的伪造品。下图展示了生成器与判别器的输入和输出的示例。

生成对抗网络架构

在开始时,生成器会输出充满噪声的图片,同样判别器的预测也是随机的。GAN 的关键在于交替训练这两个网络,才能让生成器越来越擅长欺骗判别器,而判别器必须通过训练保证其正确识别真伪的能力,这又会驱使生成器找到欺骗判别器的新方法,从而推动循环不断向前进行。

1.2 深度卷积生成对抗网络

为了更深入了解生成对抗网络的训练流程,我们将使用 Keras 构建深度卷积生成对抗网络 (Deep Convolutional GAN, DCGAN),来生成积木的图片。GAN 的原论文中没有使用卷积层,而是使用了全连接层,但实践已经证明,卷积层能够提供更强大的性能,因此现在基本上所有的 GAN 架构都包含卷积层。

2. 数据集分析

首先,需要下载训练数据,使用 Kaggle 上的乐高积木图像数据集。该数据集中包含了 40,000 张不同角度的 50 种不同玩具积木的照片,示例样本图片如下所示:

积木数据集

可以通过 Kaggle 官方网站下载数据集,下载完成后将这些图像和相关的元数据保存到 ./data 文件夹中。
使用 Kerasimage_dataset_from_directory 函数来创建一个指向存储图像目录的 TensorFlow 数据集,以便可以在需要时(例如,在训练期间)将图像批量读入内存,从而能够处理大型数据集,而无需担心将整个数据集都放入内存中导致内存不足的情况。同时将图像尺寸调整为 64 × 64,并在像素值之间进行插值处理:

train_data = image_dataset_from_directory("data/lego_brick",label_mode=None,color_mode="grayscale",image_size=(IMAGE_SIZE, IMAGE_SIZE),batch_size=BATCH_SIZE,shuffle=True,interpolation="bilinear",
)

原始数据的像素强度范围为 [0, 255]。在训练 GAN 时,我们将数据缩放到范围 [-1, 1],以便在生成器的最后一层使用 tanh 激活函数。相对于 sigmoid 函数,tanh 激活函数的梯度更大,有助于更快地收敛:

def preprocess(img):"""Normalize and reshape the images"""img = (tf.cast(img, "float32") - 127.5) / 127.5return imgtrain = train_data.map(lambda x: preprocess(x)).as_numpy_iterator()

3. 构建深度卷积生成对抗网络

3.1 判别器

鉴别器的目标是预测图像是真实的还是伪造的,这属于图像分类问题,因此我们可以使用常见的深度神经网络架构,即先堆叠的卷积层,最后使用带有一个输出节点的全连接层。判别器的完整架构如下:

判别器

使用 Keras 实现判别器:

# 定义判别器的输入(图像)层
discriminator_input = layers.Input(shape=(IMAGE_SIZE, IMAGE_SIZE, CHANNELS))
# 堆叠 Conv2D 层,并在其间添加 BatchNormalization、LeakyReLU 激活和 Dropout 层
x = layers.Conv2D(64, kernel_size=4, strides=2, padding="same", use_bias=False)(discriminator_input
)
x = layers.LeakyReLU(0.2)(x)
x = layers.Dropout(0.3)(x)
x = layers.Conv2D(128, kernel_size=4, strides=2, padding="same", use_bias=False
)(x)
x = layers.BatchNormalization(momentum=0.9)(x)
x = layers.LeakyReLU(0.2)(x)
x = layers.Dropout(0.3)(x)
x = layers.Conv2D(256, kernel_size=4, strides=2, padding="same", use_bias=False
)(x)
x = layers.BatchNormalization(momentum=0.9)(x)
x = layers.LeakyReLU(0.2)(x)
x = layers.Dropout(0.3)(x)
x = layers.Conv2D(512, kernel_size=4, strides=2, padding="same", use_bias=False
)(x)
x = layers.BatchNormalization(momentum=0.9)(x)
x = layers.LeakyReLU(0.2)(x)
x = layers.Dropout(0.3)(x)
x = layers.Conv2D(1,kernel_size=4,strides=1,padding="valid",use_bias=False,activation="sigmoid",
)(x)
# 将最后一个卷积层展平,得到张量的形状为 1×1×1,因此不再需要 Dense 层
discriminator_output = layers.Flatten()(x)
# 定义判别器模型,该模型接受一个输入图像,并输出一个介于 0 和 1 之间的概率值
discriminator = models.Model(discriminator_input, discriminator_output)
print(discriminator.summary())

需要注意的是,为了缩小张量在网络中传递时的空间形状(从原始图像的 64 开始,然后是 321684,最后是 1),某些 Conv2D 层的步幅为 2,同时增加通道数(灰度输入图像中通道数为 1,然后变为 64128256,最后为 512),最后展平为单个预测值。
在最后一个 Conv2D 层上使用 sigmoid 激活函数,以确保输出值介于 01 之间,表示预测图像为真的概率。

3.2 生成器

接下来,构建生成器。生成器的输入是从多元标准正态分布中抽取的向量,输出是与原始训练数据中的图像大小相同的图像。GAN 的生成器和变分自编码器 (Variational Autoencoder, VAE) 的解码器具有完全相同的目标:将潜空间中的向量转换为图像。在生成模型中,从潜空间映射回原始域的概念非常常见,因为通过这个概念,我们能够在潜空间中操作向量以改变原始域中图像的高级特征。生成器架构如下所示:

生成器架构

使用 Keras 实现以上生成器模型:

# 定义生成器的输入层,长度为 100 的随机向量
generator_input = layers.Input(shape=(Z_DIM,))
# 使用 Reshape 层将输入向量转化为 1×1×100 的张量,以便应用转置卷积操作
x = layers.Reshape((1, 1, Z_DIM))(generator_input)
# 堆叠四个 Conv2DTranspose 层,并在其间添加 BatchNormalization 和 LeakyReLU 层
x = layers.Conv2DTranspose(512, kernel_size=4, strides=1, padding="valid", use_bias=False
)(x)
x = layers.BatchNormalization(momentum=0.9)(x)
x = layers.LeakyReLU(0.2)(x)
x = layers.Conv2DTranspose(256, kernel_size=4, strides=2, padding="same", use_bias=False
)(x)
x = layers.BatchNormalization(momentum=0.9)(x)
x = layers.LeakyReLU(0.2)(x)
x = layers.Conv2DTranspose(128, kernel_size=4, strides=2, padding="same", use_bias=False
)(x)
x = layers.BatchNormalization(momentum=0.9)(x)
x = layers.LeakyReLU(0.2)(x)
x = layers.Conv2DTranspose(64, kernel_size=4, strides=2, padding="same", use_bias=False
)(x)
x = layers.BatchNormalization(momentum=0.9)(x)
x = layers.LeakyReLU(0.2)(x)
# 最后一个 Conv2DTranspose 层使用 tanh 激活函数将输出转换到区间 [-1, 1],以匹配原始图像域
generator_output = layers.Conv2DTranspose(CHANNELS,kernel_size=4,strides=2,padding="same",use_bias=False,activation="tanh",
)(x)
# 定义生成器模型,其接受长度为100的向量并输出形状为 [64, 64, 1] 的张量
generator = models.Model(generator_input, generator_output)
print(generator.summary())

需要注意的是,为了增加张量在网络中传递时的空间形状(原始向量中为 1,然后是 481632,最后是 64),某些 Conv2DTranspose 层的步幅为 2,同时减少通道数(首先是 512,然后是 25612864,最后是 1,以匹配灰度图像输出)。

UpSampling2D 与 Conv2DTranspose
除了使用 Conv2DTranspose 层来增加图像尺寸外,还可以使用 UpSampling2D 层,并在 UpSampling2D 后添加一个步幅为 1 的普通 Conv2D 层:

x = layers.UpSampling2D(size = 2)(x)
x = layers.Conv2D(256, kernel_size=4, strides=1, padding="same")(x)

UpSampling2D 层简单地将输入的每一行和每一列重复,用以将张量的宽度和高度加倍。然后,利用步幅为 1Conv2D 层执行卷积操作。这种方法与转置卷积类似,但不同的是,上采样只是重复现有的像素值,而不是用零填充像素之间的空隙。
实践证明,Conv2DTranspose 方法会导致输出图像中出现伪影,如下图中所示的细小棋盘格形状,这会破坏输出的质量。然而,在许多性能优异的 GAN 中仍然使用转置卷积。

棋盘伪影

这两种方法,UpSampling2D + Conv2DConv2DTranspose,都可以用于将随即向量转换回原始图像域,在实践中,我们可以尝试不同方法,以获得最佳生成效果。

3.3 DCGAN 模型训练

DCGAN 中生成器和判别器的架构非常简单,与 VAE 模型并没有太大的区别。理解 GAN 的关键在于了解生成器和判别器的训练过程。
为了训练判别器,我们可以创建一个训练集,其中一些图像是来自训练集的真实观测样本,还有一些图像是生成器的输出结果,真实图像对应的标签为 1,生成图像对应点标签为 0。如果将其视为一个监督学习问题,那么就可以训练判别器如何区分原始图像和生成图像之间的差异,输出结果表示输入图像为真实图像的概率,使用二元交叉熵作为损失函数。
在训练生成器时,我们需要找到一种评价每个生成的图像的方法,以便它可以优化图像。判别器正是这种评价方法,生成器可以生成一批图像,并将其通过判别器以获取每个图像的真实性概率得分。为了让生成的图像欺骗判别器,即我们希望判别器对生成器生成的图片输出结果接近于 1,因此生成器的损失函数就是判别器的输出概率与一个全为1的向量之间的二元交叉熵。
因此,为了训练生成器,我们必须将生成器连接到判别器体,具体而言,我们将生成器的输出图像输入到判别器后,这个组合模型就可以根据判别器,输出生成图像为真的概率
为了训练这个组合模型,我们必须交替训练这两个网络,并确保一次只更新一个网络的权重。例如,在生成器训练过程中,我们必须冻结判别器的权重,只更新生成器的权重。如果我们也允许判别器的权重发生变化,那么判别器只会调整自己,以便更有可能将生成的图像预测为真实图像,而这不是我们期望的结果。我们希望生成的图像被预测接近 1 (真实)是由于生成器性能强,而不是因为判别器性能弱。下图展示了判别器和生成器的训练过程。

GAN 训练流程

Keras 中,可以通过自定义 train_step 函数实现以上训练过程:

class DCGAN(models.Model):def __init__(self, discriminator, generator, latent_dim):super(DCGAN, self).__init__()self.discriminator = discriminatorself.generator = generatorself.latent_dim = latent_dimdef compile(self, d_optimizer, g_optimizer):super(DCGAN, self).compile()# 生成器和判别器的损失函数均为 BinaryCrossentropyself.loss_fn = losses.BinaryCrossentropy()self.d_optimizer = d_optimizerself.g_optimizer = g_optimizerself.d_loss_metric = metrics.Mean(name="d_loss")self.d_real_acc_metric = metrics.BinaryAccuracy(name="d_real_acc")self.d_fake_acc_metric = metrics.BinaryAccuracy(name="d_fake_acc")self.d_acc_metric = metrics.BinaryAccuracy(name="d_acc")self.g_loss_metric = metrics.Mean(name="g_loss")self.g_acc_metric = metrics.BinaryAccuracy(name="g_acc")@propertydef metrics(self):return [self.d_loss_metric,self.d_real_acc_metric,self.d_fake_acc_metric,self.d_acc_metric,self.g_loss_metric,self.g_acc_metric,]def train_step(self, real_images):# Sample random points in the latent spacebatch_size = tf.shape(real_images)[0]# 从多元标准正态分布中随机采样一批向量random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim))# Train the discriminator on fake imageswith tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:# 将这些向量通过生成器生成一批图像generated_images = self.generator(random_latent_vectors, training=True)#  使用判别器预测真实图像与生成图像的真实性概率real_predictions = self.discriminator(real_images, training=True)fake_predictions = self.discriminator(generated_images, training=True)real_labels = tf.ones_like(real_predictions)real_noisy_labels = real_labels + NOISE_PARAM * tf.random.uniform(tf.shape(real_predictions))fake_labels = tf.zeros_like(fake_predictions)fake_noisy_labels = fake_labels - NOISE_PARAM * tf.random.uniform(tf.shape(fake_predictions))#  判别器损失是真实图像(标签为 1 )和生成图像(标签为 0 )的二元交叉熵的平均值d_real_loss = self.loss_fn(real_noisy_labels, real_predictions)d_fake_loss = self.loss_fn(fake_noisy_labels, fake_predictions)d_loss = (d_real_loss + d_fake_loss) / 2.0# 生成器损失是判别器对生成图像的预测与标签 1 之间的二元交叉熵g_loss = self.loss_fn(real_labels, fake_predictions)gradients_of_discriminator = disc_tape.gradient(d_loss, self.discriminator.trainable_variables)gradients_of_generator = gen_tape.gradient(g_loss, self.generator.trainable_variables)#  分别更新判别器和生成器的权重self.d_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))self.g_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))# Update metricsself.d_loss_metric.update_state(d_loss)self.d_real_acc_metric.update_state(real_labels, real_predictions)self.d_fake_acc_metric.update_state(fake_labels, fake_predictions)self.d_acc_metric.update_state([real_labels, fake_labels], [real_predictions, fake_predictions])self.g_loss_metric.update_state(g_loss)self.g_acc_metric.update_state(real_labels, fake_predictions)return {m.name: m.result() for m in self.metrics}# Create a DCGAN
dcgan = DCGAN(discriminator=discriminator, generator=generator, latent_dim=Z_DIM
)dcgan.compile(d_optimizer=optimizers.Adam(learning_rate=LEARNING_RATE, beta_1=ADAM_BETA_1, beta_2=ADAM_BETA_2),g_optimizer=optimizers.Adam(learning_rate=LEARNING_RATE, beta_1=ADAM_BETA_1, beta_2=ADAM_BETA_2),
)dcgan.fit(train, epochs=EPOCHS)

在生成器训练期间,由于判别器被冻结,它的权重不会被更新,而生成器的权重将朝着能够更好地生成图像(更有可能骗过判别器的图像)的方向移动(也就是让判别器的预测值接近 1)。
判别器和生成器不断博弈可能导致 DCGAN 的训练过程不稳定。理想情况下,训练过程能够找到一个平衡点,使得生成器能够从判别器中学习到有意义的信息,并且图像的质量开始提高。经过足够多的 epochs 后,判别器往往会占优势,但生成器在此时可能已经学会生成足够高质量的图像了。
为标签添加一些微小的随机噪音是训练 GAN 时的一个有用技巧。这有助于提高训练过程的稳定性并增强生成的图像。这种标签平滑能够使判别器处理更具挑战性的任务,而不至于令生成器无法训练。
通过观察训练过程中生成器的生成图像,可以明显看出生成器生成的图像越来越接近从训练集中采样的图像。

生成图像

可以看到,神经网络有能力将随机噪音转化为有意义的内容,同时,除了原始图像外,我们没有为模型提供任何额外的特征,因此它必须独自学习高级特征,例如绘制阴影、立方体和圆圈。
成功的生成模型还需要满足一个要求,即它不能仅仅是复制训练集中已有的图像。为了测试这一点,我们可以从训练数据集中找到与生成图像最接近的图像,可以使用 L1 距离度量图像间的距离:

def compare_images(img1, img2):return np.mean(np.abs(img1 - img2))

下图展示了一些生成图像在训练集中与之最接近的观测样本。可以看出,虽然生成的图像和训练集之间存在一定程度的相似性,但它们并非完全相同。这表明生成器已经学习到训练数据集中的高级特征,并能够生成与训练数据集中图像不同的样本。

训练集中最接近生成样本的观测样本

4. GAN 训练技巧

虽然 GAN 是生成模型领域的重大突破,但也存在训练难度较大的问题。在本节中,我们将探讨训练 GAN 时遇到的一些最常见的问题,以及相应的解决方案。

4.1 判别器强于生成器

如果判别器变得过强,损失函数的信号就会变得过弱,无法推动生成器产生有意义的改进。在最糟糕的情况下,判别器完全学会了区分真实图像和虚假图像,导致梯度完全消失,从而无法进行任何训练。
如果判别器的损失函数失控,就需要弱判别器:

  • 增加判别器中 Dropout 层的丢弃率,减少信息通过网络的量
  • 降低判别器的学习率
  • 减少判别器中的卷积滤波器数量
  • 在训练判别器时,为标签添加噪声
  • 在训练判别器时,随机将一些图像的标签反转(从 0 变为 1,或从 1 变为 0)

4.2 生成器强于判别器

如果判别器不够强大,生成器会找到轻松欺骗判别器的方法,并只生成一小部分几乎相同的图像样本,这称为模式坍塌 (Mode Collapse)。
假设我们在不更新判别器的情况下对生成器进行了多次训练。生成器倾向于找到一个总是能够欺骗判别器的单个观测样本(也称为模式),并开始将潜在输入空间中的每个点映射到这个观测样本图像。此外,损失函数的梯度会趋近于零,因此无法从此状态恢复。
即使我们随后尝试重新训练判别器,以阻止其被这一个模式欺骗,生成器仍会找到另一个模式判别器的模式,因为它已经没有多样化输出的动力。
如果生成器出现模式崩溃的问题,可以尝试使用与上一小节相反的方法来加强判别器。此外,也可以尝试减小两个网络的学习率并增加批大小。

4.3 信息量不足

由于深度学习模型被编译为最小化损失函数,因此可能自然地认为生成器的损失函数越小,生成的图像质量就越好。然而,由于生成器只针对当前的判别器进行评估,而判别器在不断改进,我们无法比较在训练过程中不同时间点评估的损失函数。实际上,在训练过程中,尽管图像质量明显提高,生成器的损失也可能会随着时间的推移而增加。由于生成器损失与图像质量之间缺乏相关性,有时使得 GAN 的训练难以监控。

4.4 超参数

GAN 训练过程中,我们可以看到,即使是简单的 GAN 也有大量需要调整的超参数 (Hyperparameter)。除了判别器和生成器的整体架构外,还有一些参数控制着批归一化、Dropout、学习率、激活层、卷积核大小、步长、批大小和潜空间大小等。GAN 对这些参数的微小变化非常敏感,因此找到一组有效的参数通常需要反复实验,而没有一套既定的准则。
因此了解 GAN 的内部工作原理并知道如何解读损失函数至关重要,只有这样才能合理的进行超参数调整,以提高模型的稳定性。

小结

在本节中,我们首先介绍了生成对抗网络 (Generative Adversarial Network, GAN) 的基本原理,并学习了如何训练 DCGAN 生成玩具积木图像,GAN 能够学会以图像的形式真实地表示 3D 对象,包括阴影、形状和纹理;还探讨了 GAN 训练过程中可能会遇到的问题,及相应的解决方法和训练技巧。

系列链接

AIGC实战——生成模型简介
AIGC实战——深度学习 (Deep Learning, DL)
AIGC实战——卷积神经网络(Convolutional Neural Network, CNN)
AIGC实战——自编码器(Autoencoder)
AIGC实战——变分自编码器(Variational Autoencoder, VAE)
AIGC实战——使用变分自编码器生成面部图像

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

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

相关文章

数据结构与算法之美学习笔记:29 | 堆的应用:如何快速获取到Top 10最热门的搜索关键词?

目录 前言堆的应用一:优先级队列堆的应用二:利用堆求 Top K堆的应用三:利用堆求中位数解答开篇内容小结 前言 本节课程思维导图: 搜索引擎的热门搜索排行榜功能你用过吗?搜索引擎每天会接收大量的用户搜索请求&#x…

HTML5+CSS3+JS小实例:数字滑动选择控件

实例:数字滑动选择控件 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content=&quo…

IPtables防火墙详解

一、IPtables介绍 iptables是unix/linux自带的一款开放源代码的完全自由的基于包过滤(对OSI模型的四层或者是四层以下进行过滤)的防火墙工具&#xff0c;它的功能十分强大&#xff0c;使用非常灵活&#xff0c;可以对流入和流出服务器的数据包进行很精细的控制。主要针对网络访…

最全最详细ChatGPT角色预设词教程,Prompt分享

使用指南 1、可直复制使用 2、可以前往已经添加好Prompt预设的AI系统测试使用&#xff08;可自定义添加使用&#xff09; 雅思写作考官 我希望你假定自己是雅思写作考官&#xff0c;根据雅思评判标准&#xff0c;按我给你的雅思考题和对应答案给我评分&#xff0c;并且按照雅…

开会做笔记的时候用什么软件比较好?

在工作生涯中&#xff0c;会经历很多大大小小的会议&#xff0c;而如何快速准确记录下会议上重要的内容&#xff0c;成了很多上班族的必修课。在会上做笔记&#xff0c;选择什么样的工具才能事半功倍&#xff0c;成了一个值得深思的问题。而经过一段时间的测评后&#xff0c;我…

Postman:专业API测试工具,提升Mac用户体验

如果你是一名开发人员或测试工程师&#xff0c;那么你一定知道Postman。这是一个广泛使用的API测试工具&#xff0c;适用于Windows、Mac和Linux系统。今天&#xff0c;我们要重点介绍Postman的Mac版本&#xff0c;以及为什么它是你进行API测试的理想选择。 一、强大的功能和易…

在 AlmaLinux9 上安装Oracle Database 23c

在 AlmaLinux9 上安装Oracle Database 23c 0. 下载 Oracle Database 23c 安装文件1. 安装 Oracle Database 23c3. 连接 Oracle Database 23c4. &#xff08;谨慎&#xff09;卸载 Oracle Database 23c 0. 下载 Oracle Database 23c 安装文件 版权问题&#xff0c;下载地址请等待…

工单派单管理系统有什么用?企业如何提升生产效率与产品质量?

在当今竞争激烈的市场环境中&#xff0c;企业需要一个高效、精准的管理工具来提升生产制造的效率和品质。工单派单管理系统正是这样一种工具&#xff0c;能够实现生产计划、任务分配、进度追踪、工时掌控等环节的优化&#xff0c;提高整体生产运营的效率和精度。 一、工单生成 …

Pycharm 初学者使用教程Ⅰ

目录 1. 下载 Pycharm2. 安装 Pycharm3.打开 Pycharm4.初始化配置界面ProjectsCustomizePluginsLearn 关联博文 1. 下载 Pycharm 下载链接&#xff1a;https://www.jetbrains.com/pycharm/download/?sectionwindows 在下载链接网页中&#xff0c;首先看到的是PyCharm Profes…

计算机网络(二)

&#xff08;八&#xff09;客户端软件设计的细节 A、解析协议号 客户端可能会需要通过协议名指定协议&#xff0c;但是Socket接口是用协议号指定的&#xff0c;这时候我们就需要使用getprotobyname()函数实现协议名到协议号的转换&#xff0c;该函数会返回一个指向protoent的…

【开源威胁情报挖掘2】开源威胁情报融合评价

基于开源信息平台的威胁情报挖掘综述 写在最前面4 开源威胁情报融合评价开源威胁情报的特征与挑战4.1 开源威胁情报数据融合融合处理方法 4.1 开源威胁情报的质量评价4.1.1 一致性分析本体的定义与组成本体构建的层次 4.1.2 去伪去重4.1.3 数据融合分析 4.2 开源威胁情报质量及…

[SWPUCTF 2021 新生赛]PseudoProtocols

题目很明确了就是伪协议 php://filter/convert.base64-encode/resourcehint.php 提交的伪协议的内容需要是 I want flag&#xff0c;就会echo flag 方法1&#xff1a;adata://text/plain,I want flag 方法2&#xff1a;adata://text/plain;base64,SSB3YW50IGZsYWc

KAO2 入门到熟练 看这一篇文章就够了

KOA 介绍 官网地址&#xff1a; https://koa.bootcss.com/ Koa 是一个新的 web 框架&#xff0c;由 Express 幕后的原班人马打造&#xff0c; 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数&#xff0c;Koa 帮你丢弃回调…

万字解析设计模式之策略模式、命令模式

一、策略模式 1.1概述 先看下面的图片&#xff0c;我们去旅游选择出行模式有很多种&#xff0c;可以骑自行车、可以坐汽车、可以坐火车、可以坐飞机。 策略模式&#xff08;Strategy Pattern&#xff09;是一个行为型设计模式&#xff0c;它定义了一组算法家族&#xff0c;分…

看Spring源码不得不会的@Enable模块驱动实现原理讲解

这篇文章我想和你聊一聊 spring的Enable模块驱动的实现原理。 在我们平时使用spring的过程中&#xff0c;如果想要加个定时任务的功能&#xff0c;那么就需要加注解EnableScheduling&#xff0c;如果想使用异步的功能&#xff0c;那就要加EnableScheduling注解&#xff0c;其实…

「盘点」界面控件DevExtreme UI v23.1中的API增强

DevExtreme拥有高性能的HTML5 / JavaScript小部件集合&#xff0c;使您可以利用现代Web开发堆栈&#xff08;包括React&#xff0c;Angular&#xff0c;ASP.NET Core&#xff0c;jQuery&#xff0c;Knockout等&#xff09;构建交互式的Web应用程序。从Angular和Reac&#xff0c…

【赠书第10期】从概念到现实:ChatGPT和Midjourney的设计之旅

文章目录 前言 1 ChatGPT的崛起 2 Midjourney的探索 3 技术创新的交汇 4 对未来的影响 5 结论 6 推荐图书 7 粉丝福利 前言 在过去的几年里&#xff0c;自然语言处理和聊天模型的领域取得了飞速的发展。ChatGPT 作为一个由OpenAI 开发的大型语言模型&#xff0c;以其强…

【opencv】计算机视觉基础知识

目录 前言 1、什么是计算机视觉 2、图片处理基础操作 2.1 图片处理&#xff1a;读入图像 2.2 图片处理&#xff1a;显示图像 2.3 图片处理&#xff1a;图像保存 3、图像处理入门基础 3.1 图像成像原理介绍 3.2 图像分类 3.2.1 二值图像 3.2.2灰度图像 3.2.3彩色图像…

算法与数据结构有区别吗?

算法和数据结构并不是同一件事。严格来说&#xff0c;它们并不是等效的。但是&#xff0c;我们通常在使用的时候会互换这两个术语。为了简便&#xff0c;后文我们会用数据结构这个术语来指代“数据结构及其所有相关的方法”。 有很多方法可以用来说明这两个术语之间的区别&…

企业软件手机app定制开发趋势|小程序网站搭建

企业软件手机app定制开发趋势|小程序网站搭建 随着移动互联网的快速发展和企业数字化转型的加速&#xff0c;企业软件手机App定制开发正成为一个新的趋势。这种趋势主要是由于企业对于手机App的需求增长以及现有的通用应用不能满足企业特定需求的情况下而产生的。 1.企业软件手…