GAN培训挑战:用于彩色图像的DCGAN

news2024/11/29 8:42:31

GAN培训挑战:用于彩色图像的DCGAN

    • 1. 效果图
    • 2. 原理
      • 2.1 用于彩色图像的 DCGAN
      • 2.3 准备数据
      • 2.4 生成器
      • 2.5 鉴别器
      • 2.6 DCGAN模型及回调函数
      • 2.7 GAN培训挑战
      • 2.8 未能聚合(Non-convergence)
      • 2.9 模式崩溃(Mode collapse)
      • 2.10 难以评估
      • 2.11 GAN评估指标
    • 2. 源码
    • 参考

这篇博客将介绍如何训练 DCGAN 以生成彩色时尚图像。将通过培训过程学习GAN常见的挑战、应对这些挑战的技术以及 GAN 评估指标。 在下一篇文章中,还将学习如何使用Wasserstein GAN(WGAN)和Wasserstein GAN with Gradient Penalty(WGAN-GP)进一步提高训练稳定性。

本课是GAN教程系列的第三篇文章:

1. 生成对抗网络 (GAN) 简介
2. 入门:面向时尚的DCGAN-MNIST
3. GAN培训 挑战:用于彩色图像的DCGAN (这篇文章)

上一篇博客介绍了如何训练DCGAN来生成灰度Fashion-MNIST图像。在这篇文章中用彩色图像训练DCGAN,以演示GAN训练的常见挑战,还将简要讨论一些改进技术和GAN评估指标。

1. 效果图

其中一个图像:
在这里插入图片描述

生成器模型:
在这里插入图片描述

鉴别器模型:
在这里插入图片描述

训练1个纪元 VS 25纪元 VS 50纪元效果图如下:
在这里插入图片描述

2. 原理

2.1 用于彩色图像的 DCGAN

DCGAN 代码将以我上一篇文章 作为基线,然后进行调整以训练彩色图像。由于在上一篇文章中详细介绍了DCGAN端到端训练,现在将只关注为彩色图像训练DCGAN所需的关键更改:

  • 数据: 从Kaggle下载彩色图像并对其进行预处理,使其 [-1, 1]。
  • 生成器: 调整如何对模型架构进行上采样以生成彩色图像。
  • 鉴别器: 调整输入图像形状 28×28×1 自 64×64×3。

通过这些更改可以在彩色图像上训练DCGAN;但是当处理彩色图像或MNIST或Fashion-MNIST以外的任何数据时,您将意识到GAN训练的挑战性。即使是使用Fashion-MNIST灰度图像进行训练也可能很棘手。

2.3 准备数据

数据集来训练DCGAN 名为Kaggle的Clothing & Models 该数据集是从 Zalando.com 抓取的服装的集合。有六个类别和超过 16k 的彩色图像 606×875,其大小将调整为 64×64 用于培训。
指定图像大小 64×64 和批量大小 32.

2.4 生成器

在build_generator函数中使用keras Sequential API创建生成器体系结构。在之前的DCGAN文章中已经详细介绍了如何创建生成器架构。下面看看如何调整上采样以生成所需的64×64×3的彩色图像大小:
为彩色图像更新CHANNELS=3,而不是为灰度图像更新1。2的步幅是宽度和高度的一半,因此可以向后计算初始图像尺寸:对于Fashion MNIST,将其上采样为7->14->28。现在使用的训练图像大小为64×64,因此将多次上采样为8->16->32->64。
这意味着再添加一组Conv2DTranspose->BatchNormalization->ReLU。
对生成器所做的另一个更改是将内核大小从5更新为4,以避免减少生成图像中的棋盘伪影(见图2)。
根据后反卷积和棋盘伪像(Deconvolution and Checkerboard Artifacts),5的内核大小不能被2的步长整除。因此,解决方案是使用4而不是5的内核大小
generator.summary(),在代码中可视化生成器体系结构

2.5 鉴别器

鉴别器架构的主要变化是图像输入形状:使用[64,64,3]的形状而不是[28,28,1]。还添加了一组Conv2D->BatchNormalization->LeakyReLU,以平衡生成器中增加的架构复杂性,如上所述。其他一切都保持不变。
discriminator.summary(),在代码中可视化鉴别器DCGAN架构

2.6 DCGAN模型及回调函数

通过子类keras.model定义DCGAN模型架构,并覆盖train_step来定义自定义训练循环。代码中唯一的细微变化是对实际标签应用单侧标签平滑。
real_labels = tf.ones((batch_size, 1))
real_labels += 0.05 * tf.random.uniform(tf.shape(real_labels))
该技术减少了鉴别器的过度自信,因此有助于稳定GAN训练。
有关标签平滑的详细信息,请参阅Adrian Rosebrock的文章《使用Keras、TensorFlow和深度学习进行标签平滑》:https://pyimagesearch.com/2019/12/30/label-smoothing-with-keras-tensorflow-and-deep-learning/。
在《训练GANs的改进技术》一文中提出了用于规范GANs训练的“单侧标签平滑”技术,在https://arxiv.org/abs/1606.03498还可以找到其他改进技术。

2.7 GAN培训挑战

现在已经完成了用彩色图像训练DCGAN。让我们讨论一下GAN培训的一些常见挑战。
GANs很难训练,以下是一些众所周知的挑战:

  • 不收敛:不稳定、梯度消失或训练缓慢(Non-convergence: instability, vanishing gradients, or slow training)
  • 模式崩溃(Mode collapse)
  • 难以评估(Difficult to evaluate )

2.8 未能聚合(Non-convergence)

与训练其他模型(如图像分类器)不同,训练期间D和G的损失或准确性仅单独测量D和G,而不测量GAN的整体性能以及生成器在创建图像方面的表现。当发生器和鉴别器之间达到平衡时,GAN模型是“好的”,通常当鉴别器的损耗约为0.5时。

GAN训练不稳定(GAN training instability):很难保持D和G的平衡以达到平衡。看看训练中的损失,你会注意到它们可能会剧烈波动。D和G都可能陷入困境,永远无法改善。长时间的训练并不总是能让生成器变得更好。生成器的图像质量可能随着时间的推移而劣化。
消失梯度(Vanishing gradient):在自定义训练循环中,介绍了如何计算鉴别器和生成器损失,计算梯度,然后使用梯度进行更新。生成器依赖于鉴别器的反馈来进行改进。如果鉴别器太强,以至于它压倒了生成器:它可以在每次出现假图像时分辨出来,那么生成器就停止了训练。
您可能会注意到,有时生成的图像即使经过一段时间的训练,质量仍然很差。这意味着该模型未能在鉴别器和生成器之间找到平衡。

实验:使D架构更强(模型架构中的参数更多)或比G训练得更快(例如,将D的学习率提高到比G高得多)。

2.9 模式崩溃(Mode collapse)

当生成器重复生成相同的图像或训练图像的一小部分时,会发生模式崩溃。一个好的生成器应该生成各种各样的图像,这些图像在所有类别中都与训练图像相似。当鉴别器无法判断生成的图像是假的时,就会发生模式崩溃,因此生成器会不断生成相同的图像来欺骗鉴别器。
实验:为了模拟代码中的模式崩溃问题,尝试将噪声向量维数从100降低到10;或者将噪声向量维度从100增加到128以增加图像多样性。

2.10 难以评估

评估GAN模型很有挑战性,因为没有简单的方法来确定生成的图像是否“好”。与图像分类器不同,根据基本事实标签,预测要么正确,要么不正确。这就引出了下面关于如何评估GAN模型的讨论。

2.11 GAN评估指标

一个成功的生成器有两个标准-它应该使用以下内容生成图像:

  • 质量好:高保真逼真,
  • 多样性(diversity or variety):训练图像的不同类型(或类别)的良好表现。

我们可以定性地(目视检查图像)或用一些指标定量地评估模型。
通过目视检查进行定性评估。正如在DCGAN训练中所做的那样,我们观察在同一种子上生成的一组图像,并在训练过程中目视检查这些图像是否看起来更好。这适用于玩具示例,但对于大规模训练来说,这太耗费人力了。

启始得分(Inception Score IS)和Fréchet启始距离(Fréchet Inception Distance FID)是定量比较GAN模型的两个常用指标。

本文介绍了**“启动得分”:训练GANs的改进技术。它测量生成图像的质量和多样性。其想法是使用初始模型对生成的图像进行分类,并使用预测来评估生成器。分数越高表示该模型越好。**
Fréchet初始距离(FID)还使用初始网络进行特征提取并计算数据分布。FID通过观察生成的图像和训练图像而不是仅孤立地观察生成的图片来改进IS。较低的FID意味着生成的图像与真实图像更相似,因此是更好的GAN模型。

2. 源码

https://github.com/margaretmz/GANs-in-Art-and-Design/blob/main/3_dcgan_color_images.ipynb

# DCGAN 代码将以我上一篇文章 作为基线,然后进行调整以训练彩色图像。
# 由于在上一篇文章中: dcgan_minist.py 详细介绍了DCGAN端到端训练,现在将只关注为彩色图像训练DCGAN所需的关键更改
# python dcgan_color_minist.py

import os

import numpy as np
import tensorflow as tf
from matplotlib import pyplot as plt
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential

os.environ['KAGGLE_USERNAME'] = ''
os.environ['KAGGLE_KEY'] = ''

# 1. 数据预处理
# 下载数据并将其解压缩到名为 dataset/
# !kaggle datasets download -d dqmonn/zalando-store-crawl -p datasets
# !unzip datasets/zalando-store-crawl.zip -d datasets/

# 下载和解压文件后,设置文件夹目录
zalando_data_dir = "color_images/"

# 使用目录下的图片及image_dataset_from_directory 创建 tf.data.Dataset 设置图像大小为64x64,批处理大小为32
train_images = tf.keras.utils.image_dataset_from_directory(zalando_data_dir, label_mode=None, image_size=(64, 64),
                                                           batch_size=32)
# 将图像归一化到[-1,1]的范围,因为生成器的最终层激活使用tanh。最后,我们通过使用tf.dataset的map函数和lambda函数来应用规范化
train_images = train_images.map(lambda x: (x - 127.5) / 127.5)

image_batch = next(iter(train_images))
random_index = np.random.choice(image_batch.shape[0])
random_image = image_batch[random_index].numpy().astype("int32")
plt.axis("off")
plt.imshow(random_image)
plt.show()

# 随机噪声的潜在维数
LATENT_DIM = 100
# Con2DTranspose层的权重初始化
WEIGHT_INIT = tf.keras.initializers.RandomNormal(mean=0.0, stddev=0.02)
# 图像的颜色通道, 1:灰色图像,3 彩色图像
CHANNELS = 3  # UPDATED from 1


# 2. 生成器
# 在build_generator函数中使用keras Sequential API创建生成器体系结构。在之前的DCGAN文章中已经详细介绍了如何创建生成器架构。下面看看如何调整上采样以生成所需的64×64×3的彩色图像大小:
# 为彩色图像更新CHANNELS=3,而不是为灰度图像更新1。2的步幅是宽度和高度的一半,因此可以向后计算初始图像尺寸:对于Fashion MNIST,将其上采样为7->14->28。现在使用的训练图像大小为64×64,因此将多次上采样为8->16->32->64。
# 这意味着再添加一组Conv2DTranspose->BatchNormalization->ReLU。
# 对生成器所做的另一个更改是将内核大小从5更新为4,以避免减少生成图像中的棋盘伪影(见图2)。
# 根据后反卷积和棋盘伪像(Deconvolution and Checkerboard Artifacts),5的内核大小不能被2的步长整除。因此,解决方案是使用4而不是5的内核大小
# generator.summary(),在代码中可视化生成器体系结构
def build_generator():
    # 使用Keras Sequential API创建模型
    model = Sequential(name='generator')

    # prepare for reshape: FC => BN => RN layers, note: input shape defined in the 1st Dense layer
    model.add(layers.Dense(8 * 8 * 512, input_dim=LATENT_DIM))
    # model.add(layers.BatchNormalization())
    model.add(layers.ReLU())
    # layers.LeakyReLU(alpha=0.2)

    # reshape 1D => 3D
    model.add(layers.Reshape((8, 8, 512)))

    # upsample to 16x16: apply a transposed CONV => BN => RELU
    model.add(layers.Conv2DTranspose(256, (4, 4), strides=(2, 2), padding="same", kernel_initializer=WEIGHT_INIT))
    # model.add(layers.BatchNormalization())
    model.add((layers.ReLU()))

    # upsample to 32x32: apply a transposed CONV => BN => RELU
    model.add(layers.Conv2DTranspose(128, (4, 4), strides=(2, 2), padding="same", kernel_initializer=WEIGHT_INIT))
    # model.add(layers.BatchNormalization())
    model.add((layers.ReLU()))

    # upsample to 64x64: apply a transposed CONV => BN => RELU
    model.add(layers.Conv2DTranspose(64, (4, 4), strides=(2, 2), padding="same", kernel_initializer=WEIGHT_INIT))
    # model.add(layers.BatchNormalization())
    model.add((layers.ReLU()))

    # final layer: Conv2D with tanh activation
    model.add(layers.Conv2D(CHANNELS, (4, 4), padding="same", activation="tanh"))

    # return the generator model
    return model


# 3. 鉴别器
# 鉴别器架构的主要变化是图像输入形状:使用[64,64,3]的形状而不是[28,28,1]。还添加了一组Conv2D->BatchNormalization->LeakyReLU,以平衡生成器中增加的架构复杂性,如上所述。其他一切都保持不变。
# discriminator.summary(),在代码中可视化鉴别器DCGAN架构
def build_discriminator(width, height, depth, alpha=0.2):
    # 使用Keras Sequential API创建模型
    model = Sequential(name='discriminator')
    input_shape = (height, width, depth)

    # We use Conv2D, BatchNormalization, and LeakyReLU twice to downsample.
    # 使用Conv2D, BatchNormalization, and LeakyReLU 2次以进行下采样
    # first set of CONV => BN => leaky ReLU layers
    model.add(layers.Conv2D(64, (5, 5), strides=(2, 2), padding="same", input_shape=input_shape))
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU(alpha=alpha))

    # second set of CONV => BN => leacy ReLU layers
    model.add(layers.Conv2D(128, (5, 5), strides=(2, 2), padding="same"))
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU(alpha=alpha))

    # Flatten and apply dropout 展平以及应用dropout
    model.add(layers.Flatten())
    model.add(layers.Dropout(0.3))

    # 最后一层使用 sigmoid激活函数一输出二进制分类(binary classification)的结果
    model.add(layers.Dense(1, activation="sigmoid"))

    return model


# 4. DCGAN模型
# 通过子类keras.model定义DCGAN模型架构,并覆盖train_step来定义自定义训练循环。代码中唯一的细微变化是对实际标签应用单侧标签平滑。
# real_labels = tf.ones((batch_size, 1))
# real_labels += 0.05 * tf.random.uniform(tf.shape(real_labels))
# 该技术减少了鉴别器的过度自信,因此有助于稳定GAN训练。
# 有关标签平滑的详细信息,请参阅Adrian Rosebrock的文章《使用Keras、TensorFlow和深度学习进行标签平滑》:https://pyimagesearch.com/2019/12/30/label-smoothing-with-keras-tensorflow-and-deep-learning/。
# 在《训练GANs的改进技术》一文中提出了用于规范GANs训练的“单侧标签平滑”技术,在https://arxiv.org/abs/1606.03498还可以找到其他改进技术。
class DCGAN(keras.Model):
    def __init__(self, discriminator, generator, latent_dim):
        super(DCGAN, self).__init__()
        self.discriminator = discriminator
        self.generator = generator
        self.latent_dim = latent_dim

    def compile(self, d_optimizer, g_optimizer, loss_fn):
        super(DCGAN, self).compile()
        self.d_optimizer = d_optimizer
        self.g_optimizer = g_optimizer
        self.loss_fn = loss_fn
        self.d_loss_metric = keras.metrics.Mean(name="d_loss")
        self.g_loss_metric = keras.metrics.Mean(name="g_loss")

    @property
    def metrics(self):
        return [self.d_loss_metric, self.g_loss_metric]

    # DCGAN模型:覆盖train_step
    # 已经定义了生成器和鉴别器架构,并了解了损失函数是如何工作的。准备好将D和G放在一起,通过子类化keras.model并重写train_step()来训练鉴别器和生成器,从而创建DCGAN模型。
    # 以下是关于如何编写低级别代码以自定义model.fit()的文档。这种方法的优点是仍然可以使用GradientTape进行自定义训练循环,同时仍然可以受益于fit()的方便功能(例如,回调和内置分发支持等)。
    # 因此对keras.Model进行子类化,以创建DCGAN类–类DCGAN(keras.MModel)
    def train_step(self, real_images):
        batch_size = tf.shape(real_images)[0]
        noise = tf.random.normal(shape=(batch_size, self.latent_dim))

        # 用真实图像(标记为1)和伪图像(标记为0)来训练鉴别器
        with tf.GradientTape() as tape:
            # 在真实图像上计算鉴别器损失
            pred_real = self.discriminator(real_images, training=True)
            d_loss_real = self.loss_fn(tf.ones((batch_size, 1)), pred_real)

            # 在伪图像上计算鉴别器损失
            fake_images = self.generator(noise)
            pred_fake = self.discriminator(fake_images, training=True)
            d_loss_fake = self.loss_fn(tf.zeros((batch_size, 1)), pred_fake)

            # 总的鉴别器损失
            d_loss = (d_loss_real + d_loss_fake) / 2

        # 计算鉴别器梯度gradients
        grads = tape.gradient(d_loss, self.discriminator.trainable_variables)
        # 更新鉴别器权重
        self.d_optimizer.apply_gradients(zip(grads, self.discriminator.trainable_variables))

        # 不更新鉴别器权重的情况下训练生成器
        misleading_labels = tf.ones((batch_size, 1))
        with tf.GradientTape() as tape:
            fake_images = self.generator(noise, training=True)
            pred_fake = self.discriminator(fake_images, training=True)
            g_loss = self.loss_fn(misleading_labels, pred_fake)
        # 计算生成器梯度
        grads = tape.gradient(g_loss, self.generator.trainable_variables)
        # 更新生成器权重
        self.g_optimizer.apply_gradients(zip(grads, self.generator.trainable_variables))

        self.d_loss_metric.update_state(d_loss)
        self.g_loss_metric.update_state(g_loss)
        return {
            "d_loss": self.d_loss_metric.result(),
            "g_loss": self.g_loss_metric.result(),
        }


# 损失函数:修改后的极大极小损失
# 在创建DCGAN模型之前,先讨论一下损失函数。计算损失是DCGAN(或任何GAN)训练的核心。对于DCGAN将实现修改的极大极小损失,它使用二进制交叉熵(BCE)损失函数。随着在GAN系列中的进展将了解不同GAN变体中的其他损失函数。
# 需要计算两个损失:一个用于鉴别器损失,另一个用于生成器损失。
# 鉴别器损失
# 由于有两组图像被输入鉴别器(真实图像和伪图像),将计算每组图像的损失,并将它们组合作为鉴别器损失。
# total_D_loss = loss_from_real_images + loss_from_fake_images
# 生成器损失
# 对于生成器损失可以训练G来最大化log D(G(z)),而不是训练G来最小化log(1−D(G))。这就是修正后的极小极大损失。
# 为训练监控定义Kera回调
# 相同的代码没有更改-覆盖Keras回调,以在训练期间监控和可视化生成的图像。
class GANMonitor(keras.callbacks.Callback):
    def __init__(self, num_img=3, latent_dim=128):
        self.num_img = num_img
        self.latent_dim = latent_dim

        # 创建训练可视化的随机噪音种子
        self.seed = tf.random.normal([16, latent_dim])

    def on_epoch_end(self, epoch, logs=None):
        generated_images = self.model.generator(self.seed)
        generated_images = (generated_images * 127.5) + 127.5
        generated_images.numpy()

        fig = plt.figure(figsize=(4, 4))
        for i in range(self.num_img):
            plt.subplot(4, 4, i+1)
            img = keras.utils.array_to_img(generated_images[i])
            plt.imshow(img)
            plt.axis('off')
        plt.savefig('color_images/epoch_{:03d}.png'.format(epoch))
        plt.show()

    def on_train_end(self, logs=None):
        self.model.generator.save('generator.h5')


# 构建生成器
generator = build_generator()
print(generator.summary())
# 构建鉴定器
discriminator = build_discriminator(64, 64, 3)
print(discriminator.summary())



# 编译模型,使用Adam优化器,鉴别器学习率0.0001,生成器0.0003 二进制交叉熵损失函数(Binary Cross Entropy)
dcgan = DCGAN(discriminator=discriminator, generator=generator, latent_dim=LATENT_DIM)

D_LR = 0.0001 # UPDATED: discriminator learning rate
G_LR = 0.0003 # UPDATED: generator learning rate

dcgan.compile(
    d_optimizer=keras.optimizers.Adam(learning_rate=D_LR, beta_1 = 0.5),
    g_optimizer=keras.optimizers.Adam(learning_rate=G_LR, beta_1 = 0.5),
    loss_fn=keras.losses.BinaryCrossentropy(),
)

# 只需调用model.fit()来训练dcgan模型
NUM_EPOCHS = 50 # number of epochs
dcgan.fit(train_images, epochs=NUM_EPOCHS, callbacks=[GANMonitor(num_img=16, latent_dim=LATENT_DIM)])

参考

  • https://pyimagesearch.com/2021/12/13/gan-training-challenges-dcgan-for-color-images/
  • 数据集:https://www.kaggle.com/dqmonn/zalando-store-crawl
  • https://github.com/margaretmz/GANs-in-Art-and-Design/blob/main/3_dcgan_color_images.ipynb

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

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

相关文章

chatgpt赋能python:Python取元素里的数字

Python取元素里的数字 Python是一种高级编程语言,它的使用范围非常广泛,在数据科学、人工智能、网络编程等领域都有很多应用。在Python程序中,我们经常需要从字符串或列表中提取数字,这篇文章将介绍在Python中如何取元素里的数字…

Anolis OS8 磁盘扩容

最近学习的时候,使用Vmware安装了AnolisOS8进行测试,随着学习的深入,组件安装越来越多,磁盘不够用了,但是安装的组件又太多,重新装个虚拟机又得重新装各种组件。所以决定对磁盘进行扩容,在这里做…

chatgpt赋能python:Python如何只提取文本中的数字?

Python如何只提取文本中的数字? 随着数字化时代的到来,数字成为了我们生活中不可或缺的一部分。我们每天都需要处理大量的数字,比如账单、统计数据等等,这些数字都散落在各个文本中。如果我们需要将这些数字提取出来,…

计算机视觉:目标检测理论及实战

有关锚框的部分可以看我的另一篇文章:点击这里。下文不再赘述 文章目录 多尺度目标检测多尺度锚框 数据集单发多框检测(SSD)模型设计类别预测层边界框预测层连结多尺度的预测高和宽减半块基本网络块完整的模型 训练导入数据集定义损失函数Utils函数(用于为每个锚框标…

【内网穿透】Linux本地搭建GitLab服务器

文章目录 前言1. 下载Gitlab2. 安装Gitlab3. 启动Gitlab4. 安装cpolar内网穿透5. 创建隧道配置访问地址6. 固定GitLab访问地址6.1 保留二级子域名6.2 配置二级子域名 7. 测试访问二级子域名 转载自cpolar极点云文章:Linux搭建GitLab私有仓库,并内网穿透实…

chatgpt赋能python:Python取款:让你的银行账户管理更智能

Python取款:让你的银行账户管理更智能 介绍 Python不仅是一种全球广泛应用的计算机编程语言,而且还拥有很多适合财务管理和数据处理的工具,用于提高效率和减少错误。本文将重点介绍如何使用Python自动管理银行账户的取款,以及它…

chatgpt赋能python:Python句点:为什么它如此重要?

Python句点:为什么它如此重要? 介绍 Python是一种高级编程语言,它以简单且易理解的语法而闻名。Python中有一种符号——句点(.),它在Python中扮演着非常重要的作用。在本文中,我们将深入研究P…

chatgpt赋能python:Python只取小数

Python只取小数 Python是一种高级编程语言,被广泛应用于数据科学、人工智能、Web开发等领域。在数据分析和计算中,往往需要只保留小数,本文将介绍如何使用Python只取小数,并提供相关代码。 什么是小数? 在数学中,小…

Golang每日一练(leetDay0086) 回文链表、删除链表节点

目录 234. 回文链表 Palindrome Linked-list 🌟 237. 删除链表中的节点 Delete Node In a Linked-list 🌟🌟 🌟 每日一练刷题专栏 🌟 Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练…

安卓逆向 -- Frida环境搭建(HOOK实例)

一、开启抓包程序Postern和Charles 二、目标分析 打开jadx,把apk拖拽进去,全局搜索"pwd",挨个分析,明显来自于这条代码,后面是md5,可以判断pwd加密是md5,我们hook该地方 三、Frida环…

【23种设计模式】观察者模式(Observer Pattern)

个人主页:金鳞踏雨 个人简介:大家好,我是金鳞,一个初出茅庐的Java小白 目前状况:22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作 我的博客&am…

二叉树的链式结构 - C语言(含有大量递归)

目录: 🍔前言 🍔二叉树链式结构的实现 🍟基本构架 😍代码: 🍔二叉树的遍历 🍟前序遍历 🍟中序遍历 🍟后序遍历 🍟层序遍历 &#x1f53…

chatgpt赋能python:Python快捷键:轻松运行你的代码

Python快捷键:轻松运行你的代码 Python是一种广泛使用的编程语言,因为它易于学习、易于使用,并提供了许多强大的库和框架。但是,在日常使用中经常需要重复与代码交互的操作,这可能会降低编程效率。使用Python快捷键可…

day43:1049. 最后一块石头的重量 II; 474. 一和零; 494.目标和:有多少种方式装满背包

01背包 [1049. 最后一块石头的重量 II (与416分割等和子集类似)](https://leetcode.cn/problems/last-stone-weight-ii/submissions/436837708/)1. dp数组以及下标名义2. 递归公式3. dp数组如何初始化4. 遍历顺序:从后往前遍历5. 代码 494.目标和:有多少种方式装满背包1. dp数组…

皮卡丘xss之htmlspecialchars、xss之href输出、xss之js输出

1.xss之htmlspecialchars htmlspecialchars()函数的功能如下: htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。 预定义的字符是: (1)& (和号)成为 & (2)…

【编译、链接、装载三】编译器——语法分析、词法分析、语义分析、编译器后端

【编译和链接三】编译器——语法分析、词法分析、语义分析、编译器后端 内容总结一、词法分析(Lexical Analysis)二、语法分析 (Syntactic Analysis, or Parsing)三、语义分析(Semantic Analysis)四、编译器…

chatgpt赋能python:Python取出元素详解

Python取出元素详解 在Python编程中,常见到需要取出某个列表、元组或字典中的元素。本文将详细介绍Python如何取出这些元素,并提供相关代码和案例。 取出列表元素 列表是Python编程中最常见的数据结构,下面是列表的定义方式: …

chatgpt赋能python:Python程序的暂停使用介绍

Python程序的暂停使用介绍 Python是一种高级编程语言,适用于各种应用程序,包括Web开发、数据分析、机器学习等领域。它是一个非常强大的工具,但很多人可能不知道Python是否可以被暂停。在这篇文章中,我们将探讨Python是否可以暂停…

总结8881

学习目标: 月目标:6月(线性代数强化9讲2遍,背诵15篇短文,考研核心词过三遍) 周目标:线性代数强化1讲,英语背3篇文章并回诵,检测 每日必复习(5分钟&#xff…

MySQL数据库基础(基础命令详解)

1、数据库操作 1.1、显示当前的数据库 SHOW DATABASES; 1.2、创建数据库 CREATE DATABASE IF NOT EXISTS 库名; 1.3、使用数据库 USE 库名; 1.4、删除数据库 DROP DATABASE IF EXISTS 库名; 说明:数据库删除之后,内部看不到对应…