G4周:CGAN,手势生成

 本文为🔗365天深度学习训练营 中的学习记录博客
 原作者:K同学啊|接辅导、项目定制

我的环境:

1.语言:python3.7

2.编译器:pycharm

3.深度学习框架Pytorch 1.8.0+cu111


一、CGAN介绍

条件生成对抗网络(Conditional Generative Adversarial Network,简称cGAN)是一种深度学习模型,属于生成对抗网络(GAN)的一种变体。它的基本思想是通过训练生成器和判别器两个网络,使生成器能够生成与给定条件相匹配的合成数据,而判别器则负责区分真实数据和生成数据。cGAN在生成器和判别器的结构上引入了条件信息,使得生成过程可以受到外部条件的控制。

cGAN的结构包括两个主要部分:

  1. 生成器(Generator): 生成器负责从随机噪声和条件信息中生成合成数据。与普通的生成器不同的是,cGAN的生成器除了接收随机噪声作为输入,还接受一个条件向量,这个条件向量可以是任何有助于生成特定类型数据的信息,例如类别标签、图像特征等。生成器的目标是生成尽可能逼真的数据,使得判别器难以区分生成的数据和真实数据。

  2. 判别器(Discriminator): 判别器负责区分生成器生成的数据和真实数据。它接收真实数据和生成器生成的数据,通过学习鉴别两者的差异,从而推动生成器生成更逼真的数据。与生成器一样,判别器也接收条件向量,以帮助区分不同条件下的数据。

cGAN的训练过程是一个动态平衡的过程。生成器和判别器相互竞争,通过对抗的方式逐渐提升生成器生成真实样本的能力,同时判别器也不断提高对生成样本和真实样本的辨别能力。

cGAN在图像生成、图像编辑、风格转换等任务上取得了显著的成果,其能够根据给定条件生成具有语义信息的合成数据,为许多应用领域提供了强大的工具。

条件生成对抗网络(cGAN)有一些显著的特点,使其在许多任务中表现出色。以下是一些关键特点:

  1. 条件输入: cGAN引入了条件输入,使得生成器可以受到外部条件的指导。这个条件可以是任何形式的信息,例如类别标签、文本描述、图像特征等。这使得生成的结果更有针对性和语义合理性。

  2. 有监督学习: 由于条件信息的引入,cGAN在一些任务中可以进行有监督学习。通过提供真实样本的标签作为条件,生成器可以学习生成与给定标签相对应的合成数据,从而在特定任务上取得更好的性能。

  3. 图像到图像的转换: cGAN在图像生成任务中表现出色,特别是在图像到图像的转换任务上,例如图像翻译、风格迁移、超分辨率等。通过条件信息,生成器可以更好地理解并保留输入图像的语义结构。

  4. 样本多样性: cGAN的生成过程是基于随机噪声的,因此可以生成多样性的结果。在相同的条件下,生成器可以产生多个不同但符合条件的合成样本。

  5. 对抗训练: cGAN通过生成器和判别器的对抗训练,使得两者相互竞争,逐渐提升生成器的能力同时提高判别器的辨别能力。这种对抗训练的方式有助于生成更逼真的合成数据。

  6. 无监督学习: 虽然cGAN可以进行有监督学习,但它也可以在无监督设置下进行训练。在无监督学习中,生成器可以学习从随机噪声中生成逼真的数据,而无需额外的条件信息。

总体而言,cGAN以其能够根据条件信息生成具有高语义合理性和多样性的数据而著称,广泛应用于图像生成和转换任务。

二、准备工作

import torch
import numpy as np
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets,transforms
from torch.autograd import Variable
from torchvision.utils import save_image
from torchvision.utils import make_grid
from torchsummary import summary
import matplotlib.pyplot as pltdevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

1、导入数据

train_transform = transforms.Compose([transforms.Resize(int(128* 1.12)),   ## 图片放大1.12倍transforms.RandomCrop((128, 128)),     ## 随机裁剪成原来的大小transforms.ToTensor(),transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5])])train_dataset = datasets.ImageFolder(root='E:/GAN/G3/rps/', transform=train_transform)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True,num_workers=6)

Resize与RandomCrop:将图像先放大再随机裁剪,有利于防止过拟合,获得更好的泛化能力。

ToTensor(): 将图像转换为 PyTorch 的张量(tensor)格式。

Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]): 对图像进行标准化,将其像素值归一化到 [-1, 1] 的范围。这里的参数分别是均值和标准差。

2、数据可视化

def show_images(dl):for images,_ in dl:fig,ax = plt.subplots(figsize=(10,10))ax.set_xticks([]);ax.set_yticks([])ax.imshow(make_grid(images.detach(),nrow=16).permute(1,2,0))breakshow_images(train_loader)

 

这段代码定义了一个名为 show_images 的函数,该函数接受一个 DataLoader 对象 dl 作为参数。在函数内部,通过迭代 DataLoader 中的每个批次数据(images,_),进行以下操作:

  1. 创建一个图形对象 fig 和轴对象 ax,设置图形大小为 (10,10)。
  2. 禁用坐标轴的刻度。
  3. 使用 make_grid 函数将批次中的图像以16列的形式排列,并通过 permute(1,2,0) 调整维度顺序以适应 Matplotlib 图像显示的需求。
  4. 通过 ax.imshow 在轴上显示调整后的图像。
  5. 使用 break 语句,只显示 DataLoader 中的第一个批次,然后退出循环。

 

 三、构建模型

latent_dim = 100
n_classes = 3
embedding_dim = 100

weights_init用于权重初始化。

# 自定义权重初始化函数,用于初始化生成器和判别器的权重
def weights_init(m):# 获取当前层的类名classname = m.__class__.__name__# 如果当前层是卷积层(类名中包含 'Conv' )if classname.find('Conv') != -1:# 使用正态分布随机初始化权重,均值为0,标准差为0.02torch.nn.init.normal_(m.weight, 0.0, 0.02)# 如果当前层是批归一化层(类名中包含 'BatchNorm' )elif classname.find('BatchNorm') != -1:# 使用正态分布随机初始化权重,均值为1,标准差为0.02torch.nn.init.normal_(m.weight, 1.0, 0.02)# 将偏置项初始化为全零torch.nn.init.zeros_(m.bias)class Generator(nn.Module):def __init__(self):super(Generator, self).__init__()# 定义条件标签的生成器部分,用于将标签映射到嵌入空间中# n_classes:条件标签的总数# embedding_dim:嵌入空间的维度self.label_conditioned_generator = nn.Sequential(nn.Embedding(n_classes, embedding_dim),  # 使用Embedding层将条件标签映射为稠密向量nn.Linear(embedding_dim, 16)             # 使用线性层将稠密向量转换为更高维度)# 定义潜在向量的生成器部分,用于将噪声向量映射到图像空间中# latent_dim:潜在向量的维度self.latent = nn.Sequential(nn.Linear(latent_dim, 4*4*512),  # 使用线性层将潜在向量转换为更高维度nn.LeakyReLU(0.2, inplace=True)  # 使用LeakyReLU激活函数进行非线性映射)# 定义生成器的主要结构,将条件标签和潜在向量合并成生成的图像self.model = nn.Sequential(# 反卷积层1:将合并后的向量映射为64x8x8的特征图nn.ConvTranspose2d(513, 64*8, 4, 2, 1, bias=False),nn.BatchNorm2d(64*8, momentum=0.1, eps=0.8),  # 批标准化nn.ReLU(True),  # ReLU激活函数# 反卷积层2:将64x8x8的特征图映射为64x4x4的特征图nn.ConvTranspose2d(64*8, 64*4, 4, 2, 1, bias=False),nn.BatchNorm2d(64*4, momentum=0.1, eps=0.8),nn.ReLU(True),# 反卷积层3:将64x4x4的特征图映射为64x2x2的特征图nn.ConvTranspose2d(64*4, 64*2, 4, 2, 1, bias=False),nn.BatchNorm2d(64*2, momentum=0.1, eps=0.8),nn.ReLU(True),# 反卷积层4:将64x2x2的特征图映射为64x1x1的特征图nn.ConvTranspose2d(64*2, 64*1, 4, 2, 1, bias=False),nn.BatchNorm2d(64*1, momentum=0.1, eps=0.8),nn.ReLU(True),# 反卷积层5:将64x1x1的特征图映射为3x64x64的RGB图像nn.ConvTranspose2d(64*1, 3, 4, 2, 1, bias=False),nn.Tanh()  # 使用Tanh激活函数将生成的图像像素值映射到[-1, 1]范围内)def forward(self, inputs):noise_vector, label = inputs# 通过条件标签生成器将标签映射为嵌入向量label_output = self.label_conditioned_generator(label)# 将嵌入向量的形状变为(batch_size, 1, 4, 4),以便与潜在向量进行合并label_output = label_output.view(-1, 1, 4, 4)# 通过潜在向量生成器将噪声向量映射为潜在向量latent_output = self.latent(noise_vector)# 将潜在向量的形状变为(batch_size, 512, 4, 4),以便与条件标签进行合并latent_output = latent_output.view(-1, 512, 4, 4)# 将条件标签和潜在向量在通道维度上进行合并,得到合并后的特征图concat = torch.cat((latent_output, label_output), dim=1)# 通过生成器的主要结构将合并后的特征图生成为RGB图像image = self.model(concat)return imagegenerator = Generator().to(device)
generator.apply(weights_init)
print(generator)a = torch.ones(100)
b = torch.ones(1)
b = b.long()
a = a.to(device)
b = b.to(device)
import torch
import torch.nn as nnclass Discriminator(nn.Module):def __init__(self):super(Discriminator, self).__init__()# 定义一个条件标签的嵌入层,用于将类别标签转换为特征向量self.label_condition_disc = nn.Sequential(nn.Embedding(n_classes, embedding_dim),     # 嵌入层将类别标签编码为固定长度的向量nn.Linear(embedding_dim, 3*128*128)         # 线性层将嵌入的向量转换为与图像尺寸相匹配的特征张量)# 定义主要的鉴别器模型self.model = nn.Sequential(nn.Conv2d(6, 64, 4, 2, 1, bias=False),       # 输入通道为6(包含图像和标签的通道数),输出通道为64,4x4的卷积核,步长为2,padding为1nn.LeakyReLU(0.2, inplace=True),             # LeakyReLU激活函数,带有负斜率,增加模型对输入中的负值的感知能力nn.Conv2d(64, 64*2, 4, 3, 2, bias=False),    # 输入通道为64,输出通道为64*2,4x4的卷积核,步长为3,padding为2nn.BatchNorm2d(64*2, momentum=0.1, eps=0.8),  # 批量归一化层,有利于训练稳定性和收敛速度nn.LeakyReLU(0.2, inplace=True),nn.Conv2d(64*2, 64*4, 4, 3, 2, bias=False),  # 输入通道为64*2,输出通道为64*4,4x4的卷积核,步长为3,padding为2nn.BatchNorm2d(64*4, momentum=0.1, eps=0.8),nn.LeakyReLU(0.2, inplace=True),nn.Conv2d(64*4, 64*8, 4, 3, 2, bias=False),  # 输入通道为64*4,输出通道为64*8,4x4的卷积核,步长为3,padding为2nn.BatchNorm2d(64*8, momentum=0.1, eps=0.8),nn.LeakyReLU(0.2, inplace=True),nn.Flatten(),                               # 将特征图展平为一维向量,用于后续全连接层处理nn.Dropout(0.4),                            # 随机失活层,用于减少过拟合风险nn.Linear(4608, 1),                         # 全连接层,将特征向量映射到输出维度为1的向量nn.Sigmoid()                                # Sigmoid激活函数,用于输出范围限制在0到1之间的概率值)def forward(self, inputs):img, label = inputs# 将类别标签转换为特征向量label_output = self.label_condition_disc(label)# 重塑特征向量为与图像尺寸相匹配的特征张量label_output = label_output.view(-1, 3, 128, 128)# 将图像特征和标签特征拼接在一起作为鉴别器的输入concat = torch.cat((img, label_output), dim=1)# 将拼接后的输入通过鉴别器模型进行前向传播,得到输出结果output = self.model(concat)return output

 

  1. 条件标签的嵌入层:

    • self.label_condition_disc 是一个包含两个层的序列。首先是一个嵌入层 (nn.Embedding),用于将类别标签编码为固定长度的向量。然后是一个线性层 (nn.Linear),将嵌入的向量转换为与图像尺寸相匹配的特征张量。
  2. 主要的鉴别器模型:

    • self.model 是一个包含卷积层、批量归一化层、LeakyReLU激活函数、全连接层等的序列,构成了整个鉴别器的主体部分。
    • 输入通道为6,其中包括图像和经过嵌入层处理后的标签通道数。这是因为通过嵌入层后,标签被转换为一个与图像尺寸相匹配的特征张量。
    • 通过卷积层和下采样,网络逐渐减小特征图的空间尺寸。
    • 使用LeakyReLU激活函数,有助于网络对输入中的负值的感知能力。
    • 批量归一化层有助于训练的稳定性和收敛速度。
    • 使用Flatten将最终的特征图展平为一维向量,用于后续的全连接层处理。
    • Dropout层用于减少过拟合风险。
    • 最后的全连接层将特征向量映射到输出维度为1的向量,而Sigmoid激活函数用于输出范围限制在0到1之间的概率值。
  3. 前向传播方法 (forward):

    • 接受输入 inputs,其中包含图像 img 和标签 label
    • 类别标签通过条件标签的嵌入层转换为特征向量,并重塑为与图像尺寸相匹配的特征张量。
    • 将图像特征和标签特征在通道维度上拼接在一起,形成最终的输入。
    • 通过鉴别器模型进行前向传播,得到输出结果,即对输入图像的鉴别结果。

总体而言,这个鉴别器模型是一个基于卷积神经网络的条件GAN的组成部分,其设计旨在处理包含条件信息的图像数据。它通过将标签嵌入到特征向量中,并将其与图像特征拼接在一起,从而允许生成器和鉴别器之间的条件信息传递。

 

四、训练模型

1、损失函数

adversarial_loss = nn.BCELoss() def generator_loss(fake_output, label):gen_loss = adversarial_loss(fake_output, label)return gen_lossdef discriminator_loss(output, label):disc_loss = adversarial_loss(output, label)return disc_loss

2、优化器

learning_rate = 0.0002G_optimizer = optim.Adam(generator.parameters(),     lr = learning_rate, betas=(0.5, 0.999))
D_optimizer = optim.Adam(discriminator.parameters(), lr = learning_rate, betas=(0.5, 0.999))

3、训练模型

# 设置训练的总轮数
num_epochs = 100
# 初始化用于存储每轮训练中判别器和生成器损失的列表
D_loss_plot, G_loss_plot = [], []# 循环进行训练
for epoch in range(1, num_epochs + 1):# 初始化每轮训练中判别器和生成器损失的临时列表D_loss_list, G_loss_list = [], []# 遍历训练数据加载器中的数据for index, (real_images, labels) in enumerate(train_loader):# 清空判别器的梯度缓存D_optimizer.zero_grad()# 将真实图像数据和标签转移到GPU(如果可用)real_images = real_images.to(device)labels      = labels.to(device)# 将标签的形状从一维向量转换为二维张量(用于后续计算)labels = labels.unsqueeze(1).long()# 创建真实目标和虚假目标的张量(用于判别器损失函数)real_target = Variable(torch.ones(real_images.size(0), 1).to(device))fake_target = Variable(torch.zeros(real_images.size(0), 1).to(device))# 计算判别器对真实图像的损失D_real_loss = discriminator_loss(discriminator((real_images, labels)), real_target)# 从噪声向量中生成假图像(生成器的输入)noise_vector = torch.randn(real_images.size(0), latent_dim, device=device)noise_vector = noise_vector.to(device)generated_image = generator((noise_vector, labels))# 计算判别器对假图像的损失(注意detach()函数用于分离生成器梯度计算图)output = discriminator((generated_image.detach(), labels))D_fake_loss = discriminator_loss(output, fake_target)# 计算判别器总体损失(真实图像损失和假图像损失的平均值)D_total_loss = (D_real_loss + D_fake_loss) / 2D_loss_list.append(D_total_loss)# 反向传播更新判别器的参数D_total_loss.backward()D_optimizer.step()# 清空生成器的梯度缓存G_optimizer.zero_grad()# 计算生成器的损失G_loss = generator_loss(discriminator((generated_image, labels)), real_target)G_loss_list.append(G_loss)# 反向传播更新生成器的参数G_loss.backward()G_optimizer.step()# 打印当前轮次的判别器和生成器的平均损失print('Epoch: [%d/%d]: D_loss: %.3f, G_loss: %.3f' % ((epoch), num_epochs, torch.mean(torch.FloatTensor(D_loss_list)), torch.mean(torch.FloatTensor(G_loss_list))))# 将当前轮次的判别器和生成器的平均损失保存到列表中D_loss_plot.append(torch.mean(torch.FloatTensor(D_loss_list)))G_loss_plot.append(torch.mean(torch.FloatTensor(G_loss_list)))if epoch%10 == 0:# 将生成的假图像保存为图片文件save_image(generated_image.data[:50], './images/sample_%d' % epoch + '.png', nrow=5, normalize=True)# 将当前轮次的生成器和判别器的权重保存到文件torch.save(generator.state_dict(), './training_weights/generator_epoch_%d.pth' % (epoch))torch.save(discriminator.state_dict(), './training_weights/discriminator_epoch_%d.pth' % (epoch))
  1. 总轮次和损失记录初始化:

    • num_epochs 设置总的训练轮次。
    • D_loss_plotG_loss_plot 是用于存储每轮训练中判别器和生成器损失的列表。
  2. 训练循环:

    • 外层循环遍历每个训练轮次。
    • 内层循环遍历训练数据加载器中的每个批次。
  3. 判别器训练(Discriminator Training):

    • 清空判别器的梯度缓存。
    • 将真实图像数据和标签移到GPU(如果可用)。
    • 计算判别器对真实图像的损失(D_real_loss)。
    • 从噪声向量中生成假图像,并计算判别器对假图像的损失(D_fake_loss)。
    • 计算判别器总体损失(D_total_loss),是真实图像损失和假图像损失的平均值。
    • 反向传播更新判别器的参数。
  4. 生成器训练(Generator Training):

    • 清空生成器的梯度缓存。
    • 从噪声向量中生成假图像。
    • 计算生成器的损失(G_loss),这个损失是判别器对生成图像的输出与真实标签之间的误差。
    • 反向传播更新生成器的参数。
  5. 打印和记录损失:

    • 在每个训练轮次结束时,打印判别器和生成器的平均损失。
    • 将当前轮次的判别器和生成器的平均损失保存到列表中。
  6. 可选的保存操作:

    • 每隔10个训练轮次,生成一些假图像并将它们保存为图片文件。
    • 将当前轮次的生成器和判别器的权重保存到文件。

这段代码的目标是通过训练生成器和判别器来生成逼真的图像,其中生成器试图生成足够逼真的图像以欺骗判别器,而判别器则试图区分真实图像和生成图像。在训练的过程中,两者通过对抗学习逐渐提高性能。

五、生成指定图像

from numpy.random import randint, randn
from numpy import linspace
from matplotlib import pyplot as plt, gridspec
import numpy as np# Assuming 'generator' and 'device' are defined earlier in your codegenerator.load_state_dict(torch.load('E:/GAN/G4/generator_epoch_300.pth'), strict=False)
generator.eval()interpolated = randn(100)
interpolated = torch.tensor(interpolated).to(device).type(torch.float32)label = 0
labels = torch.ones(1) * label
labels = labels.to(device).unsqueeze(1).long()predictions = generator((interpolated, labels))
predictions = predictions.permute(0, 2, 3, 1).detach().cpu()import warnings
warnings.filterwarnings("ignore")
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['figure.dpi'] = 100plt.figure(figsize=(8, 3))pred = (predictions[0, :, :, :] + 1) * 127.5
pred = np.array(pred)
plt.imshow(pred.astype(np.uint8))
plt.show()

   从已训练的生成器(generator)中加载参数,生成一张图像,并使用 Matplotlib 显示生成的图像。假设在代码的其他地方已经定义了生成器(generator)和设备(device)。这段代码加载预训练的生成器参数,并将生成器设置为评估模式(eval())。

  生成一个包含 100 个随机数的噪声向量(interpolated),将其转换为 PyTorch 张量并移到指定的设备上。同时,创建一个标签(label)并将其转换为 PyTorch 张量,最后在设备上调整形状和数据类型。

  使用生成器和生成的噪声与标签生成图像,并将图像的通道顺序调整为 Matplotlib 所需的顺序(通常是 HWC - Height, Width, Channel)。然后将图像的计算图分离(detach())并移动到 CPU 上。

  创建一个 Matplotlib 图形对象,将生成的图像进行处理,然后使用 plt.imshow 显示图像。最后,通过 plt.show() 将图形显示出来。

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

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

相关文章

transforms图像增强(一)

一、数据增强 数据增强(Data Augmentation)是一种常用的数据预处理技术,通过对训练集进行各种变换和扩增操作,可以增加训练数据的多样性和丰富性,从而提高模型的泛化能力。 数据增强的目的是通过对训练集中的图像进行…

安装PyTorch及环境配置(应用于Python上的YOLO)

这个基本都是Bilibili网站里面叫“小手丫子”up的视频教程,此前自己需要装了好几次又卸载了好几次,现在根据视频教学整理出来自己所理解的文档。 注意事项 1.安装的pycharm版本和anaconda版本无要求。 2.运行pycharm尽量以管理员身份运行。 3.Cuda是独…

使用CentOS 7.6搭建HTTP隧道代理服务器

在现代网络环境中,HTTP隧道代理服务器因其灵活性和安全性而受到广泛关注。CentOS 7.6,作为一个稳定且功能强大的Linux发行版,为搭建此类服务器提供了坚实的基础。 首先,我们需要明确HTTP隧道代理的基本原理。HTTP隧道代理允许客户…

Mac解决node-sass: Command failed 问题

1.以为Command failed 错误是因为缺少依赖项或者版本不兼容导致的(不适用我) 此项目的package版本,node版本14.21.3为版本对应正确 "node-sass": "^4.13.0","sass": "^1.24.2","sass-loader&q…

【Pytorch】学习记录分享10——TextCNN用于文本分类处理

【Pytorch】学习记录分享10——PyTorchTextCNN用于文本分类处理 1. TextCNN用于文本分类2. 代码实现 1. TextCNN用于文本分类 具体流程: 2. 代码实现 # coding: UTF-8 import torch import torch.nn as nn import torch.nn.functional as F import numpy as np…

MongoDB笔记

文章目录 安装查看数据库命令手册 学习地址:https://www.bilibili.com/video/BV16u4y1y7Fm 安装 下载地址 https://www.mongodb.com/try/download/community-kubernetes-operator查看数据库 查看当前数据库 show dbs show databases切换数据库 use 数据库名称cls…

jmeter自动录制脚本功能

问题排查: 建议用 google浏览器; 重启一下jmeter; 过滤规则重新检查下; 看下代理设置是否正常; 注意:下面的的过滤设置中 用的都是正则表达式的规则。

Apache SeaTunnel:探索下一代高性能分布式数据集成工具

大家下午好,我叫刘广东,然后是来自Apache SeaTunnel社区的一名Committer。今天给大家分享的议题是下一代高性能分布式海量数据集成工具,后面的整个的PPT,主要是基于开发者的视角去看待Apache SeaTunnel。后续所有的讲解主要是可能…

redis安装与配置

目录 1. 切换到 root 用户 2. 搜索安装包 3. 安装 redis 4. 查看 redis 是否正常存在 5. 修改ip 6. 重新启动服务器 7. 连接服务器 1. 切换到 root 用户 通过 su 命令切换到 root 用户。 2. 搜索安装包 apt search redis 这里安装的是下面的版本: 3. 安装 …

Elasticsearch 8.X进阶搜索之“图搜图”实战

Elasticsearch 8.X “图搜图”实战 1、什么是图搜图? "图搜图"指的是通过图像搜索的一种方法,用户可以通过上传一张图片,搜索引擎会返回类似或者相关的图片结果。这种搜索方式不需要用户输入文字,而是通过比较图片的视…

SpringBoot内嵌的Tomcat启动过程以及请求

1.springboot内嵌的tomcat的pom坐标 启动后可以看到tomcat版本为9.0.46 2.springboot 内嵌tomcat启动流程 点击进入SpringApplication.run()方法里面 看这次tomcat启动相关的核心代码refreshContext(context);刷新上下文方法 public ConfigurableApplicationContext run(Stri…

kubesphere和k8s的使用分享

文章目录 什么是kubernetesKubernetes的部分核心概念互式可视化管理平台与kubernetes的关系市面是常见的kubernetes管理平台 什么是kubesphereKubesphere默认安装的组件Kubesphere涉及的服务组件kubesphere的安装Kubesphere相关的内容 什么是kubernetes 就在这场因“容器”而起…

2024 AIGC应用层十大趋势:AI Agent将成为AI应用主流形态

ITValue 钉钉这类平台型应用加生态,成为大模型产业居中而立的一个桥梁。 钛媒体作者|张帅 ITValue 2023年的科技产业喧嚣且骚动,AIGC蔓延到一切领域,产业各方仿佛要拿出所有的精力和资源,生怕错过这一班通向未来的快车…

MYSQL多种提权方式

🐙MYSQL-提权条件 - 数据库的最高权限用户的密码 - secure-file-priv没进行目录限制 - 拿下了网站的权限(通过webshell或者其他方式) - 获取到了数据库的账号密码 (获取密码:D:/phpstudy/MySQL/data/mysql/user.MYD…

es简单入门

星光下的赶路人star的个人主页 努力努力再努力 文章目录 1、简介2、使用场景3、基本知识4、中文文档和官网链接5、增删改查(php代码)6、基本查询7、HTTP操作7.1 索引操作7.1.1 创建索引 7.2 文档操作7.2.1 创建文档7.2.2 查看文档7.2.3 修改文档7.2.4 修…

MySQL-数据库概述

数据库相关概念: 数据库(DateBase)简称DB,就是一个存储数据的仓库,数据有组织的进行存储。 数据库分为关系型数据库简称RDBMS和非关系型数据库 关系型数据库简称RDBMS:建立在关系模型的基础上,由多张相互连接的二维表组成的数据库.简单来说…

音频播放软件Foobar2000 mac特点介绍

Foobar2000 mac是一款高度可定制的音频播放器,适用于Windows平台。它支持各种音频格式,包括MP3、FLAC、AAC、WMA等,同时也支持各种音频插件和效果器,可以提供更好的音质和用户体验。 Foobar2000 mac软件特点 1. 高度可定制&#…

洛谷——P1983 [NOIP2013 普及组] 车站分级(拓扑排序、c++)

文章目录 一、题目[NOIP2013 普及组] 车站分级题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示 二、题解基本思路:代码 一、题目 [NOIP2013 普及组] 车站分级 题目背景 NOIP2013 普及组 T4 题目描述 一条单…

免费的GPT4来了,你还不知道吗?

程序员的公众号:源1024,获取更多资料,无加密无套路! 最近整理了一波电子书籍资料,包含《Effective Java中文版 第2版》《深入JAVA虚拟机》,《重构改善既有代码设计》,《MySQL高性能-第3版》&…

Maven(mvn)的学习下载和配置

文章目录 Maven(mvn)1.Maven 是什么?2.Maven做什么?2.1传统方式对项目的管理2.2Maven对jar包的管理 3.Maven怎么学3.1Maven如何创建项目3.2Maven的下载与配置3.3Maven的项目结构3.4Maven依赖的引入3.5Maven依赖的剔除3.6Maven依赖…