CWGAN-GP 原理及实现(pytorch版)
CWGAN-GP
- 一、CWGAN-GP 原理
- 1.1 CWGAN-GP 的核心改进
- 1.2 CWGAN-GP 的损失函数
- 1.3 CWGAN-GP 的优势
- 1.4 关键参数选择
- 1.5 应用场景
- 二、CWGAN-GP 实现
- 2.1 导包
- 2.2 数据加载和处理
- 2.3 构建生成器
- 2.4 构建判别器
- 2.5 训练和保存模型
- 2.6 查看训练损失
- 2.7 图片转GIF
- 2.8 模型加载和推理
一、CWGAN-GP 原理
CWGAN-GP
(Conditional Wasserstein GAN with Gradient Penalty)是 WGAN-GP 的条件生成版本,结合了 条件生成对抗网络
(CGAN) 和 Wasserstein GAN 的梯度惩罚(GP)
,以提高生成样本的质量和训练稳定性。
1.1 CWGAN-GP 的核心改进
(1)条件生成(Conditional Generation)
- CGAN 思想:生成器 G G G 和判别器 D D D 都接收额外的条件信息 y y y(如类别标签、文本描述等),使生成的数据 G ( z ∣ y ) G(z|y) G(z∣y) 与条件 y y y 相关。
- 数学表达:
- 生成器: G ( z ∣ y ) → x f a k e G(z|y) \rightarrow x_{fake} G(z∣y)→xfake
- 判别器: D ( x ∣ y ) → 评分 D(x|y) \rightarrow \text{评分} D(x∣y)→评分
(2)Wasserstein 距离(WGAN)
- WGAN 用
Earth-Mover(EM)距离
(即 Wasserstein-1 距离)替代原始 GAN 的 JS 散度,解决梯度消失/爆炸问题:
W ( P r , P g ) = sup ∥ D ∥ L ≤ 1 E x ∼ P r [ D ( x ) ] − E x ∼ P g [ D ( x ) ] W(P_r, P_g) = \underset{\|D\|_L \leq 1}{\sup} \mathbb{E}_{x \sim P_r}[D(x)] - \mathbb{E}_{x \sim P_g}[D(x)] W(Pr,Pg)=∥D∥L≤1supEx∼Pr[D(x)]−Ex∼Pg[D(x)]- D D D 需要是 1-Lipschitz 函数(梯度范数 ≤ 1)
(3) 梯度惩罚(Gradient Penalty, GP)
- WGAN-GP 通过
梯度惩罚
强制判别器满足 Lipschitz 约束,替代 WGAN 的权重裁剪(更稳定):
L G P = λ ⋅ E x ^ ∼ P x ^ [ ( ∥ ∇ x ^ D ( x ^ ∣ y ) ∥ 2 − 1 ) 2 ] \mathcal{L}_{GP} = \lambda \cdot \mathbb{E}_{\hat{x} \sim P_{\hat{x}}} \left[ (\|\nabla_{\hat{x}} D(\hat{x}|y)\|_2 - 1)^2 \right] LGP=λ⋅Ex^∼Px^[(∥∇x^D(x^∣y)∥2−1)2]- x ^ \hat{x} x^ 是真实数据和生成数据的随机插值点:
x ^ = ϵ x r e a l + ( 1 − ϵ ) x f a k e , ϵ ∼ U [ 0 , 1 ] \hat{x} = \epsilon x_{real} + (1 - \epsilon) x_{fake}, \quad \epsilon \sim U[0,1] x^=ϵxreal+(1−ϵ)xfake,ϵ∼U[0,1] - λ \lambda λ 是惩罚系数(通常设为 10)
- x ^ \hat{x} x^ 是真实数据和生成数据的随机插值点:
1.2 CWGAN-GP 的损失函数
(1)判别器损失
L D = E x ∼ P r [ D ( x ∣ y ) ] − E z ∼ p ( z ) [ D ( G ( z ∣ y ) ∣ y ) ] ⏟ Wasserstein 距离 + λ ⋅ E x ^ ∼ P x ^ [ ( ∥ ∇ x ^ D ( x ^ ∣ y ) ∥ 2 − 1 ) 2 ] ⏟ 梯度惩罚 \mathcal{L}_D = \underbrace{\mathbb{E}_{x \sim P_r}[D(x|y)] - \mathbb{E}_{z \sim p(z)}[D(G(z|y)|y)]}_{\text{Wasserstein 距离}} + \underbrace{\lambda \cdot \mathbb{E}_{\hat{x} \sim P_{\hat{x}}}[(\|\nabla_{\hat{x}} D(\hat{x}|y)\|_2 - 1)^2]}_{\text{梯度惩罚}} LD=Wasserstein 距离 Ex∼Pr[D(x∣y)]−Ez∼p(z)[D(G(z∣y)∣y)]+梯度惩罚 λ⋅Ex^∼Px^[(∥∇x^D(x^∣y)∥2−1)2]
(2) 生成器损失
L G = − E z ∼ p ( z ) [ D ( G ( z ∣ y ) ∣ y ) ] \mathcal{L}_G = -\mathbb{E}_{z \sim p(z)}[D(G(z|y)|y)] LG=−Ez∼p(z)[D(G(z∣y)∣y)]
- 生成器的目标是
让判别器对生成样本的评分最大化
(即最小化 − L G -\mathcal{L}_G −LG)
1.3 CWGAN-GP 的优势
改进点 | WGAN | WGAN-GP | CWGAN-GP |
---|---|---|---|
距离度量 | Wasserstein | Wasserstein + GP | Wasserstein + GP |
条件生成 | ❌ | ❌ | ✅ |
训练稳定性 | 权重裁剪(不稳定) | 梯度惩罚(稳定) | 梯度惩罚 + 条件控制 |
模式崩溃 | 较少 | 更少 | 最少(因条件约束) |
1.4 关键参数选择
- 梯度惩罚系数 λ \lambda λ:通常设为 10
- 判别器训练次数 n c r i t i c n_{critic} ncritic:通常 3~5 次/生成器 1 次
- 学习率:建议 1 0 − 4 10^{-4} 10−4(Adam 优化器, β 1 = 0.5 , β 2 = 0.9 \beta_1=0.5, \beta_2=0.9 β1=0.5,β2=0.9)
1.5 应用场景
- 图像生成(如条件生成 MNIST 数字)
- 文本到图像合成(如 StackGAN)
- 数据增强(生成特定类别的数据)
CWGAN-GP 通过 条件输入 + 梯度惩罚
,显著提升了生成质量和训练稳定性,是许多现代 GAN 变种(如 ProGAN、StyleGAN)的基础架构
二、CWGAN-GP 实现
2.1 导包
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from torchvision import datasets, transforms
from torchvision.utils import save_image
import numpy as npimport os
import time
import matplotlib.pyplot as plt
from tqdm.notebook import tqdm
from torchsummary import summary# 判断是否存在可用的GPU
device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")# 设置日志
time_str = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())
log_dir = os.path.join("./logs/cwgan-gp", time_str)
os.makedirs(log_dir, exist_ok=True)
writer = SummaryWriter(log_dir=log_dir) os.makedirs("./img/cwgan-gp_mnist", exist_ok=True) # 存放生成样本目录
os.makedirs("./model", exist_ok=True) # 模型存放目录# 超参数配置
config = {"num_epochs": 100,"batch_size": 64,"lr": 1e-4,"img_channels": 1,"img_size": 32,"features_g": 64,"features_d": 64,"z_dim": 100, "num_classes": 10, # 分类数"label_embed_dim": 10, # 嵌入维度"lambda_gp": 10, # 梯度惩罚系数"n_critic": 5, # 判别器更新次数/生成器更新1次
}
2.2 数据加载和处理
# 加载 MNIST 数据集
def load_data(config):transform = transforms.Compose([transforms.Resize(config["img_size"]),transforms.ToTensor(), # 将图像转换为张量transforms.Normalize(mean=[0.5], std=[0.5]) # 归一化到[-1,1]])# 下载训练集和测试集train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)# 创建 DataLoadertrain_loader = DataLoader(dataset=train_dataset, batch_size=config["batch_size"],shuffle=True)test_loader = DataLoader(dataset=test_dataset, batch_size=config["batch_size"], shuffle=False)return train_loader, test_loader
2.3 构建生成器
class Generator(nn.Module):"""生成器"""def __init__(self, config):super(Generator,self).__init__()# 定义嵌入层 [B]-> [B,label_embed_dim]=[64,10]self.label_embed = nn.Embedding(config["num_classes"], config["label_embed_dim"]) # num_classes 个类别, label_embed_dim 维嵌入# 定义模型结构self.model = nn.Sequential(# 转置卷积-1: [B,z_dim + label_embed_dim,1,1]-> [B,features_g*8,4,4]nn.ConvTranspose2d(config["z_dim"] + config["label_embed_dim"],config["features_g"]*8, 4, 1, 0),nn.BatchNorm2d(config["features_g"]*8),nn.LeakyReLU(negative_slope=0.0001, inplace=True),# 转置卷积-2: [B,features_g*8,4,4]-> [B,features_g*4,8,8]nn.ConvTranspose2d(config["features_g"]*8, config["features_g"]*4, 4, 2, 1),nn.BatchNorm2d(config["features_g"]*4),nn.LeakyReLU(negative_slope=0.0001, inplace=True),# 转置卷积-3: [B,features_g*4,8,8]-> [B,features_g*2,16,16]nn.ConvTranspose2d(config["features_g"]*4, config["features_g"]*2, 4, 2, 1),nn.BatchNorm2d(config["features_g"]*2),nn.LeakyReLU(negative_slope=0.0001, inplace=True),# 转置卷积-4: [B,features_g*2,16,16]-> [B,img_channels,32,32]nn.ConvTranspose2d(config["features_g"]*2, config["img_channels"], 4, 2, 1),nn.Tanh() # 输出归一化到[-1,1] )def forward(self, z, labels): # z[B,z_dim,1,1]# 嵌入标签 [B]-> [B,label_embed_dim]=[B,10]label_embed = self.label_embed(labels)# 标签升维 [B,label_embed_dim]-> [B,label_embed_dim,1,1]=[B,10,1,1]label_embed = label_embed.unsqueeze(2).unsqueeze(3)# 拼接噪声和嵌入标签 ->[B,z_dim + label_embed_dim ,1,1]=[B,100+10,1,1]gen_input= torch.cat([z,label_embed], dim=1)# 生成图片 [B,label_embed_dim + z_dim,1,1]-> [B,img_channels,32,32]img=self.model(gen_input)return img # [B,1,32,32]
2.4 构建判别器
class Discriminator(nn.Module):def __init__(self, img_shape=(1,32,32),num_classes=10,label_embed_dim=10,features_d=64):"判别器"super(Discriminator, self).__init__()# 定义嵌入层 [B]-> [B,label_embed_dim]=[B,10]self.label_embed = nn.Embedding(config["num_classes"], config["label_embed_dim"]) # num_classes 个类别, label_embed_dim 维嵌入# 定义模型结构self.model = nn.Sequential(# 卷积-1:[B,img_channels + label_embed_dim,32,32]-> [B,features_d,16,16]nn.Conv2d(config["img_channels"] + config["label_embed_dim"], config["features_d"], 4,2,1),nn.LeakyReLU(negative_slope=0.2, inplace=True),# 卷积-2:[B,features_d,16,16]-> [B,features_d*2,8,8]nn.Conv2d( config["features_d"], config["features_d"]* 2, 4, 2, 1),nn.InstanceNorm2d( config["features_d"]* 2),nn.LeakyReLU(negative_slope=0.2, inplace=True),# 卷积-3:[B,features_d*2,8,8]-> [B,features_d*4,4,4]nn.Conv2d( config["features_d"]*2, config["features_d"]*4, 4, 2, 1),nn.InstanceNorm2d( config["features_d"]*4),nn.LeakyReLU(negative_slope=0.2, inplace=True),# 卷积-4:[B,features_d*4,4,4]-> [B,1,1,1]nn.Conv2d( config["features_d"]*4, 1, 4, 1, 0),nn.Flatten(), # 展平,4维[B,1,1,1]-> 2维[B,1,1,1])def forward(self, img, labels):# 嵌入标签 [B]-> [B,label_embed_dim]=[B,10]label_embed = self.label_embed(labels)# 标签升维 [B,label_embed_dim]-> [B,label_embed_dim,1,1]=[B,10,1,1]label_embed = label_embed.unsqueeze(2).unsqueeze(3)# 沿着空间维度(高度和宽度)进行复制扩展,使其与目标图像的空间尺寸匹配label_embed = label_embed.repeat(1, 1, img.shape[2], img.shape[3])# 拼接图片和嵌入标签 ->[B,img.shape[0]+label_embed_dim ,img.shape[2],img.shape[3]]=[B,1+10,32,32]dis_input= torch.cat([img,label_embed], dim=1)# 进行判定validity = self.model(dis_input)return validity # [B,1]
2.5 训练和保存模型
- 定义梯度惩罚函数
# 梯度惩罚计算函数
def compute_gradient_penalty(disc, real_samples, fake_samples, labels,device=device):"""计算梯度惩罚项"""# 随机插值系数alpha = torch.rand(real_samples.shape[0], 1, 1, 1).to(device)# 生成插值样本interpolates = (alpha * real_samples + (1 - alpha) * fake_samples).requires_grad_(True)# 计算判别器对插值样本的输出d_interpolates = disc(interpolates, labels)# 计算梯度gradients = torch.autograd.grad(outputs=d_interpolates,inputs=interpolates,grad_outputs=torch.ones_like(d_interpolates),create_graph=True,retain_graph=True,only_inputs=True,)[0]# 计算梯度惩罚项 gradients = gradients.view(gradients.shape[0], -1) # 多维-> 2维 [B,*]gradient_penalty = ((gradients.norm(2, dim=1) - 1) ** 2).mean()return gradient_penalty
- 定义保存生成样本
def sample_image(G,n_row, batches_done,latent_dim=100,device=device):"""Saves a grid of generated digits ranging from 0 to n_classes"""# 随机噪声-> [n_row ** 2,latent_dim]=[100,100]z=torch.normal(0,1,size=(n_row ** 2,latent_dim,1,1),device=device) #从正态分布中抽样# 条件标签->[100]labels = torch.arange(n_row, dtype=torch.long, device=device).repeat_interleave(n_row)gen_imgs = G(z, labels)save_image(gen_imgs.data, "./img/cwgan-gp_mnist/%d.png" % batches_done, nrow=n_row, normalize=True)
- 训练和保存
# 加载数据
train_loader,_= load_data(config)# 实例化生成器G、判别器D
G=Generator(config).to(device)
D=Discriminator(config).to(device)# 设置优化器
optimizer_G = torch.optim.Adam(G.parameters(), lr=config["lr"],betas=(0.5, 0.9))
optimizer_D = torch.optim.Adam(D.parameters(), lr=config["lr"],betas=(0.5, 0.9))# 开始训练
start_time = time.time() # 计时器
loader_len=len(train_loader) #训练集加载器的长度
for epoch in range(config["num_epochs"]):# 进入训练模式G.train()D.train()loop = tqdm(train_loader, desc=f"第{epoch+1}轮")for i, (real_imgs, labels) in enumerate(loop):real_imgs=real_imgs.to(device) # [B,C,H,W]labels=labels.to(device) # [B]# -----------------# 训练判别器# 1. 必须 gen_imgs.detach(),防止生成器的梯度干扰判别器更新# 2. 损失函数为 D(real_img) - D(gen_img.detach()) + 惩罚项# -----------------for _ in range(config["n_critic"]):# 获取噪声样本[B,latent_dim,1,1]及对应的条件标签 [B]z=torch.normal(0,1,size=(real_imgs.shape[0],config["z_dim"],1,1),device=device) #从正态分布中抽样# --- 计算判别器损失 ---# Step-1:对真实图片损失valid_loss=torch.mean(D(real_imgs,labels))# Step-2:对生成图片损失gen_imgs=G(z,labels) # 生成图片fake_loss=torch.mean(D(gen_imgs.detach(),labels))# Step-3:计算梯度惩罚gradient_penalty = compute_gradient_penalty(D, real_imgs.data, gen_imgs.data, labels)# Step-4:整体损失dis_loss= -(valid_loss - fake_loss) + config["lambda_gp"]* gradient_penalty# 更新判别器参数optimizer_D.zero_grad() #梯度清零dis_loss.backward() #反向传播,计算梯度optimizer_D.step() #更新判别器 # -----------------# 训练生成器# 1.禁止gen_imgs.detach(),需保持完整的计算图# 2.损失函数应为 -D(gen_img)(WGAN 的目标是最大化判别器对生成样本的评分)# -----------------# 计算生成器损失 gen_loss = -torch.mean(D(gen_imgs, labels)) # 更新生成器参数optimizer_G.zero_grad() #梯度清零gen_loss.backward() #反向传播,计算梯度optimizer_G.step() #更新生成器 # --- 记录损失到TensorBoard ---batches_done = epoch * loader_len + iif batches_done % 100 == 0:writer.add_scalars("CWGAN-GP",{"Generator": gen_loss.item(),"Discriminator": dis_loss.item(),},global_step=epoch * loader_len + i, # 全局步数)# 更新进度条loop.set_postfix(gen_loss=f"{gen_loss:.8f}",dis_loss=f"{dis_loss:.8f}")if batches_done % 400 == 0:sample_image(G,10, batches_done)writer.close()
print('总共训练用时: %.2f min' % ((time.time() - start_time)/60))#仅保存模型的参数(权重和偏置),灵活性高,可以在不同的模型结构之间加载参数
torch.save(G.state_dict(), "./model/CWGAN-GP_G.pth")
torch.save(D.state_dict(), "./model/CWGAN-GP_D.pth")
2.6 查看训练损失
# 加载魔术命令
%reload_ext tensorboard# 启动TensorBoard(
%tensorboard --logdir ./logs/cwgan-gp --port=6007
2.7 图片转GIF
from PIL import Imagedef create_gif(img_dir="./img/cwgan-gp_mnist", output_file="./img/cwgan-gp_mnist/cwgan-gp_figure.gif", duration=100):images = []img_paths = [f for f in os.listdir(img_dir) if f.endswith(".png")]# 自定义排序:按 "x.png" 的排序img_paths_sorted = sorted(img_paths,key=lambda x: (int(x.split('.')[0]), ))for img_file in img_paths_sorted:img = Image.open(os.path.join(img_dir, img_file))images.append(img)images[0].save(output_file, save_all=True, append_images=images[1:], duration=duration, loop=0)print(f"GIF已保存至 {output_file}")
create_gif()

2.8 模型加载和推理
#载入训练好的模型
G = Generator(config) # 定义模型结构
G.load_state_dict(torch.load("./model/CWGAN-GP_G.pth",weights_only=True,map_location=device)) # 加载保存的参数
G.to(device)
G.eval() # 获取噪声样本[10,100]及对应的条件标签 [10]
z=torch.normal(0,1,size=(10,100,1,1),device=device) #从正态分布中抽样
gen_labels = torch.arange(10, dtype=torch.long, device=device) #0~9整数#生成假样本
gen_imgs=G(z,gen_labels).view(-1,32,32) # 4维->3维
gen_imgs=gen_imgs.detach().cpu().numpy()#绘制
plt.figure(figsize=(8, 5))
plt.rcParams.update({'font.family': 'serif',
})
for i in range(10):plt.subplot(2, 5, i + 1) plt.xticks([], []) plt.yticks([], []) plt.imshow(gen_imgs[i], cmap='gray') plt.title(f"Figure {i}", fontsize=12)
plt.tight_layout()
plt.show()

相关文章:
CWGAN-GP 原理及实现(pytorch版)
CWGAN-GP 一、CWGAN-GP 原理1.1 CWGAN-GP 的核心改进1.2 CWGAN-GP 的损失函数1.3 CWGAN-GP 的优势1.4 关键参数选择1.5 应用场景 二、CWGAN-GP 实现2.1 导包2.2 数据加载和处理2.3 构建生成器2.4 构建判别器2.5 训练和保存模型2.6 查看训练损失2.7 图片转GIF2.8 模型加载和推理…...
zookeeper平滑扩缩容
在进行ZooKeeper的扩容和缩容操作时,需要注意以下几点: 数据一致性 重要性:ZooKeeper的核心特性之一是保证数据的一致性。在操作过程中,必须确保数据的一致性,以避免数据丢失或损坏。 实现方式:ZooKeeper通…...
Github 热点项目 ChartDB AI自动导表结构+迁移脚本,3分钟生成专业数据库关系图
ChartDB堪称数据库设计神器!亮点①:动动手指输入SQL,秒出结构图,表关系一目了然,团队评审时再也不用画图两小时。亮点②:AI智能转换超贴心,MySQL转PostgreSQL只需点个按钮,跨平台迁移…...
RVOS-1.环境搭建与系统引导
0.环境搭建 riscv-operating-system-mooc: 开放课程《循序渐进,学习开发一个 RISC-V 上的操作系统》配套教材代码仓库。 mirror to https://github.com/plctlab/riscv-operating-system-mooc 在 Ubuntu 20.04 以上环境下我们可以直接使用官方提供的 GNU工具链和 QEM…...
Java List<JSONObject> 转换为 List<实体类>
可以使用 Fastjson 的 toJavaObject 方法直接转换,无需中间序列化步骤。以下是具体实现和注意事项: import com.alibaba.fastjson.JSONObject; import java.util.List; import java.util.stream.Collectors;public class Converter {public static List…...
CesiumEarth v1.12 更新,支持安卓平板离线浏览3DTiles格式的三维倾斜模型
CesiumEarth v1.12 更新 2025年4月8日 阅读需 1 分钟 发布时间:2025年04月08日 新增用户登录: 从1.12版本开始需要通过登录方可使用CesiumEarth 账号可以通过邮箱免费注册 后续将陆续发布云服务相关的功能 发布Desktop版本: Deskt…...
OpenEuler运维实战-系统资源监控与性能优化-CPU·内存·IO
CPU 基本概念定界定位思路常用CPU性能分析工具 基本概念 中央处理器(Central Processing Unit,简称CPU)是计算机的主要设备之一,其功能是解释计算机指令以及处理计算机软件中的数据。 物理核:可以真实看到的CPU核&…...
react实现SVG地图区域中心点呈现圆柱体,不同区域数据不同,圆柱体高度不同
效果图: 代码: import React, { useState, useEffect } from react;const InnerMongoliaMap () > {// 每个区域的数据(名称、中心坐标、圆柱体高度值)const [regionData, setRegionData] useState([{ id: "呼和浩特市…...
Qwen - 14B 怎么实现本地部署,权重参数大小:21GB
Qwen - 14B 权重参数大小:21GB 参数量与模型占用存储空间(GB)是不同概念。Qwen - 14B参数量约140亿 。其模型大小在不同精度下占用存储空间不同,如在一些资料中提到,Qwen - 14B在特定情况下占用空间约21GB 。实际存储…...
线程实现参考资料
参考 并发编程系列 - Java线程池监控及CompletableFuture详解_taskexecutor.execute没有执行如何监控到-CSDN博客 JAVA异步实现的四种方式_java异步编程的四种方法-CSDN博客 Java线程池深度解析与自定义实战-CSDN博客 Java8 CompletableFuture 异步多线程的实现_java_脚本之…...
python-63-前后端分离之图书管理系统的Flask后端
文章目录 1 flask后端1.1 数据库实例extension.py1.2 数据模型models.py1.3 .flaskenv1.4 app.py1.5 运行1.6 测试链接2 关键函数和文件2.1 请求视图类MethodView2.2 .flaskenv文件3 参考附录基于flask形成了图书管理系统的后端,同时对其中使用到的关键文件.flaskenv和函数类M…...
Qt网络编程之服务端
Qt网络编程之服务端 TCP(传输控制协议)是一种可靠的、面向流的、面向连接的传输协议。它特别适合连续的数据传输。 1. 主要类和函数 1.1 QTcpServer 监听函数: bool QTcpServer::listen(const QHostAddress &address QHostAddress::…...
案例-流量统计
1.建一个data目录,在data下建log.txt文件 输入手机号码 上行流量 下行流量 2.在com.example.flow下建四个Java类3.flowBean flowMapper flowReducer flowDriver...
开源身份和访问管理方案之keycloak(二)管理员引导和恢复
文章目录 开源身份和访问管理方案之keycloak(二)管理员引导和恢复管理员引导和恢复在 Keycloak 启动时引导临时管理员帐户对于恢复丢失的管理员访问权限使用专用命令引导管理员用户或服务帐户创建一个管理员用户创建一个服务账号重新获得对具有更高安全性…...
TCP,UDP协议和域名地址
1.TCP(传输控制协议)是面向连接,UDP(用户数据报协议)是无连接的 2.应用层:FTP,HTTP,SMTP,TELNET,DNS,TFTP 传输层;TCP,UDP 网际层:IP,ICMP,ARP,RARP 3.TCP21:20端口数据传输;21端…...
算法进阶指南 分形
问题描述 分形,具有以非整数维形式充填空间的形态特征。通常被定义为: “一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”,即具有自相似的性质。 现…...
2025年 npm淘宝镜像最新地址
查看当前镜像 npm config get registry 切换陶宝镜像源 npm config set registry https://registry.npmmirror.com/ 验证npm镜像源是否切换成功 npm config get registry 如果返回的地址是https://registry.npmmirror.com/,那么说明你已经成功切换到淘宝的npm…...
0基础 | 硬件 | LM386芯片
LM386芯片:音频功率放大器芯片 内部集成三极管功能将微弱信号放大20-200倍,并且驱动内阻为8Ω的扬声器注意CD系列芯片,内部集成MOS管 LM386特性 LM386主要由以下三个部分组成 内部电路 差分输入 差分输入 多个三极管左右对称,形…...
Spring Boot集成APK Parser库实现APK文件解析
目录 1. 添加依赖 2. 创建APK解析服务 3. 创建控制器 4. 测试 注意事项 在Spring Boot项目中集成APK Parser库并解析APK文件,可以按照以下步骤进行操作: 1. 添加依赖 在项目的pom.xml文件中添加apk-parser库的依赖: <dependency&…...
java基础 迭代Iterable接口以及迭代器Iterator
Itera迭代 Iterable < T>迭代接口(1) Iterator iterator()(2) forEach(Consumer<? super T> action)forEach结合Consumer常见场景forEach使用注意细节 (3)Spliterator spliterator() Iterator< T>迭代器接口如何“接收” Iterator<T>核心方法迭代器的…...
Linux: network: tcpdump: packets dropped by kernel
文章目录 最近遇到一个问题原因libpcap/tcpdump 接口linux/libpcap 接口内核的处理原因可能有以下几种:解决方法:man pcap_stats最近遇到一个问题 tcpdump命令显示有dropped的包,而且是被内核drop的。 [root@-one-01 ~]# tcpdump -i any udp and port 8080 -v -w /root/udp…...
TCP三次握手和TCP四次挥手
一 TCP三次握手 TCP建立连接的过程叫做握手,握手需要客户端和服务器之间交换三个TCP报文段。如图所示,假设主机A为TCP客户端,主机B为TCP服务端。在最初时间,两端的TCP进程都是处于CLOSED状态 (1)主机A主动…...
博途 TIA Portal之1200做主站与调试助手的TCP通讯
博途支持的通讯非常多,常见的有S7、TCP/IP,UDP等等,本文将演示TCP的通讯,通讯的双方是1200PLC和调试助手之间,编程采用ST语言。 1、硬件准备 1200PLC一台,带调试助手的PC机一台,调试助手是我经…...
第十天 - socket编程基础 - TCP/UDP服务开发 - 练习:简易端口扫描器
Python网络编程入门:从Socket到端口扫描器实战 一、前言:为什么要学网络编程? 在这个万物互联的时代,掌握网络编程技术就像拥有了一把打开互联网世界的钥匙。无论是开发聊天软件、网络游戏,还是构建分布式系统&#…...
欧税通香港分公司办公室正式乔迁至海港城!
3月20日,欧税通香港分公司办公室正式乔迁至香港油尖旺区的核心商业区海港城!左手挽着内地市场,右手牵起国际航道——这波乔迁选址操作堪称“地理课代表”! 乔迁仪式秒变行业大联欢!感谢亚马逊合规团队、亚马逊云、阿里国际站、Wayfair、coupang、美客多…...
Maven的安装配置-项目管理工具
各位看官,大家早安午安晚安呀~~~ 如果您觉得这篇文章对您有帮助的话 欢迎您一键三连,小编尽全力做到更好 欢迎您分享给更多人哦 今天我们来学习:Maven的安装配置-项目管理工具 目录 1.什么是Maven?Maven用来干什么的?…...
【Linux篇】缓冲区的工作原理:如何影响你程序的输入输出速度
从内存到磁盘:缓冲区如何提升文件I/O效率 一. 缓冲区1.1 什么是缓冲区1.2 为什么要引入缓冲区1.3 缓冲区类型1.4 FILE1.4.1 基本概念1.4.2 FILE 结构体的作用1.4.3 FILE 的工作机制 二. 最后 在程序开发中,缓冲区是一个经常被提及却不容易深入理解的概念…...
编写junit测试类 import org.junit.Test;
1. 添加依赖 <!-- Spring Boot Starter Test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> 2. …...
初识数据结构——深入理解LinkedList与链表:吃透LinkedList与链表的终极指南
📌 深入理解LinkedList与链表:从原理到实战应用 🌟 引言 在Java集合框架中,LinkedList和ArrayList是最常用的两种列表结构。它们各有优劣,适用于不同的场景。本文将带你深入探索LinkedList的底层实现——链表&#x…...
C++版Qt之登录界面设计
在C开发中,使用Qt框架可以快速构建美观且功能强大的GUI应用程序。本文将介绍如何设计一个漂亮的登录界面,包括账号和密码输入框,并确保只有验证成功后才能进入主窗口。 项目结构 文件列表 LoginDialog.h:登录对话框的头文件Logi…...
Java logback框架日志输出中文乱码的解决方案(windows)
在Java开发中,日志记录是一个重要的部分,它可以帮我们定位问题、运行时监控、错误排查与故障恢复。但是,在有些情况下,使用Logback记录的中文日志会出现乱码,这会影响日志的可读性,给维护带来麻烦。本文将探…...
【c++】c/c++内存管理
小编个人主页详情<—请点击 小编个人gitee代码仓库<—请点击 c系列专栏<—请点击 倘若命中无此运,孤身亦可登昆仑,送给屏幕面前的读者朋友们和小编自己! 目录 前言一、c语言内存管理二、一图搞懂c/c中的程序内存区域划分三、c内存管理1. new和d…...
【C++】Stack Queue 仿函数
📝前言: 这篇文章我们来讲讲STL中的stack和queue。因为前面我们已经有了string、vector和list的学习基础,所以这篇文章主要关注一些stack和queue的细节问题,以及了解一下deque(缝合怪)和priority_queue &am…...
Python:基于Flask框架的数据可视化系统
以下是一个基于Flask框架的数据可视化系统代码示例,包含核心功能实现: python 复制 # app.py 后端核心代码 from flask import Flask, render_template, jsonify import sqlite3 from collections import defaultdict import jieba import reapp Fla…...
JVM即时编译(JIT)
JVM基础回顾 Java 作为一门高级程序语言,由于它自身的语言特性,它并非直接在硬件上运行,而是通过编译器(前端编译器)将 Java 程序转换成该虚拟机所能识别的指令序列,也就是字节码,然后运行在虚拟机之上的;…...
JVM高阶架构:并发模型×黑科技×未来趋势解析
🚀前言 “你是否还在为synchronized锁竞争头疼?是否好奇ZGC如何实现亚毫秒停顿?Java的未来将走向何方? 本文将带你深入JVM最硬核的三大领域: 并发模型:揭秘happens-before如何保证多线程安全(…...
Java的JDK、JRE、JVM关系与作用
Java的JDK、JRE、JVM关系与作用 java中的JDK、JRE和JVM是三个核心组件,各自承担不同角色,且存在层级依赖关系 1. JVM(Java Virtual Machine,Java虚拟机) 是什么: JVM是虚拟的计算机,能够执行…...
XMLHttpRequest vs Fetch API:一场跨越时代的“浏览器宫斗剧“
## 序幕:两个API的"身世之谜" 在Web开发的江湖里,XMLHttpRequest(简称XHR)就像一位身经百战的老将,而Fetch API则是手持光剑的绝地武士。让我们先来段"DNA检测": - **XHR(…...
Windows Anaconda使用Sentence-BERT获取句子向量
1、安装Anaconda: Anaconda是一个流行的Python数据科学平台,它包含了许多科学计算和数据分析的库,包括transformers和sentence_transformers。虽然不是必需的,但使用Anaconda可以简化环境管理和依赖安装的过程。 可以从Anaconda官…...
【Java设计模式】第5章 工厂方法模式讲解
5. 工厂方法模式 5.1 工厂方法讲解 定义:定义一个创建对象的接口,由子类决定实例化的类,将对象创建延迟到子类。适用场景: 创建对象需要大量重复代码。客户端不依赖具体产品的创建细节。优点: 符合开闭原则,新增产品只需扩展子类。客户端仅依赖抽象接口,不依赖具体实现…...
结合 Less + CSS 变量实现切换主题
一开始的思路是通过 Less 变量作用范围 来切换 light 和 dark 主题,但 Less 本身不会动态监听类名变化,所以直接这样写是 不可行的,因为 Less 是 预处理语言,它在编译阶段就确定了 color 的值,而不是在运行时动态切换。…...
数据分析之python处理常用复杂转置数据
前段时间根据需求配合ai写了个转置excel代码,挺好用的,而且可以选择excel,不局限于excel存在哪个地方,都可以转置,但是转置后的excel记得要先创建放在转置文件的目录下。 原本的数据长这样 转置后则可以变为这样&…...
未来杭州:科技与诗意的时空交响曲
故事背景 故事发生在中国浙江杭州的未来科技时代,通过六个充满未来感的场景展现传统文明与尖端科技的完美融合。全篇无人物角色,专注于构建兼具东方美学与赛博朋克风格的沉浸式景观。 故事内容 从晨雾中浮现全息诗句的西湖,到吞吐智能包裹的运…...
彩虹表是什么
彩虹表是一种用于破解加密散列函数的预计算表,主要用于破解密码的哈希值。以下是关于加密文件与彩虹表的相关信息: 彩虹表的原理 • 时空折中:彩虹表基于时空折中理论,通过预先计算并存储大量可能的密码及其哈希值,减少…...
[BreachCTF 2025]
周末的这个居然一个密码都不会,作了4个pwn,给原码看着真方便 FSWn3d #define _GNU_SOURCE #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <unistd.h>char buffer[152…...
行业案例 | 印度航空借助 Azure AI,提升智能航空体验
自2022年塔塔集团(Tata Group)接管以来,印度航空启动了全面现代化升级,不仅豪掷470架新飞机订单以重塑“以人为本”的品牌形象,更将数字化作为核心战略——将所有工作负载(包括全新官网)从本地数…...
【Java设计模式】第7章 建造者模式讲解
7-1 建造者模式讲解 1. 定义与类型 定义: 将复杂对象的构建与表示分离,使相同构建过程可创建不同表示。类型: 创建型模式。通俗解释: 分步构建含多组件的对象,流程固定但顺序灵活(如做菜时放盐顺序可变)。2. 适用场景 对象内部结构复杂(多属性或多步骤)。需将对象创建与…...
鸿蒙ArkTS实战:从零打造智能表达式计算器(附状态管理+路由传参核心实现)
还在为组件状态混乱、页面跳转丢参数而头疼? 这篇博客将揭秘如何用鸿蒙ArkTS打造一个漂亮美观的智能计算器: ✅ 输入完整表达式,秒出结果——字符串切割简单计算 ✅ 状态管理黑科技——Provide/Consume 实现跨组件实时响应 ✅ 路由传参实战—…...
虚拟机上安装openEuler和openGauss数据库
1.虚拟机版本选择VM 16 PRO 2.openEuler版本选择openEuler-22.03-LTS-SP4-x86_64 下载地址:https://mirrors.aliyun.com/openeuler/openEuler-22.03-LTS-SP4/ISO/x86_64/openEuler-22.03-LTS-SP4-x86_64-dvd.iso 3.虚拟机安装openEuler过程: 4.安装ope…...
深入解析 Jenkins Agent 的 .jnlp 启动文件
🧩 深入解析 Jenkins Agent 的 .jnlp 启动文件 在 Jenkins 中,通过 JNLP(Java Network Launch Protocol)方式连接 Agent 是一种常见且灵活的方式。你可能曾见过类似这样的命令: java -jar agent.jar -jnlpUrl file:/…...