当前位置: 首页 > news >正文

广西网站设计公司排行榜社会化媒体营销

广西网站设计公司排行榜,社会化媒体营销,icp备案添加网站,农业网站源码带数据DAY 53 对抗生成网络 知识点回顾: 1. 对抗生成网络的思想:关注损失从何而来 2. 生成器、判别器 3. nn.sequential容器:适合于按顺序运算的情况,简化前向传播写法 4. leakyReLU介绍:避免relu的神经元失活现象 ps&am…

DAY 53 对抗生成网络

知识点回顾:

1.  对抗生成网络的思想:关注损失从何而来

2.  生成器、判别器

3.  nn.sequential容器:适合于按顺序运算的情况,简化前向传播写法

4.  leakyReLU介绍:避免relu的神经元失活现象

ps;如果你学有余力对于gan的损失函数的理解,建议去找找视频看看,如果只是用,没必要学

作业:对于心脏病数据集,对于病人这个不平衡的样本用GAN来学习并生成病人样本,观察不用GAN和用GAN的F1分数差异。

一、GAN生成对抗网络思想

假设现在有1个造假币的a,和一个警察b,他们都是初始化的神经网络

为了让警察能分辨真币,我需要给他看真币的样子,也就是先训练警察知道什么是真币,但是只给他一个真币他也没法训练,我中间得掺杂一些无意义的噪声图片,无意义的肯定不可能是真币,所以他大概可以训练好。此时他就是一个基础的分类模型,能分别真币和假币

然后我随机初始化这个造假币的a,我每次给他随机的输入,他会生成不同的假币,每一张假币都会让警察来判断,警察能够分别出真假,如果说你是假的,那么造假币的就要更新参数,如果是真的,那么造假币的参数就不用更新,警察要更新参数。所以后续二者就在不断博弈中进步,知道最后假币专家造假以假乱真,只要更新的轮数多,即使骗不过专家,但是也很棒了。

我们把这个造假币的叫做生成器,把这个警察叫做判别器

这个过程有点类似于二者互相对抗,所以叫做对抗生成网络,目的就是在对抗中找到一个可以模仿原有数据的模型。生成器基于随机噪声生成样本,判别器对样本(真实数据 + 生成数据)进行分类,双方根据判别结果更新参数(生成器尝试让判别器误判,判别器尝试提高准确率)。

他的损失由2部分构成,生成器的损失和判别器的损失。判别器的损失定义在先,生成器的损失定义基于判别器的反馈。

1. 判别器的损失:就是分类问题的损失,二分类是二元交叉熵损失BCE(本质分类输出的是概率,并不是非黑即白)

2. 生成器的损失:依靠判别器的损失,如果判别器说是假的,生成器的损失就大,反之亦然。

判别器损失同时包含 “真实数据判真” 和 “生成数据判假” 两部分,而生成器损失仅针对 “生成数据被判别为真” 的目标。实际训练中,两者的优化是交替进行的(先训判别器,再训生成器)。两者的损失共同推动 GAN 逼近 “以假乱真” 的平衡状态。

日常中,我们经常遇到不平衡数据中某一类别样本过少,之前说过结构化数据有smote等过采样方式来提高,图像数据可以数据增强,还可以设置权重等方式来

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
# 设置中文字体支持
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题# 检查GPU是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")LATENT_DIM = 10     # 潜在空间的维度,这里根据任务复杂程度任选
EPOCHS = 10000      # 训练的回合数,一般需要比较长的时间
BATCH_SIZE = 32     # 每批次训练的样本数
LR = 0.0002         # 学习率
BETA1 = 0.5         # Adam优化器的参数# 检查是否有可用的GPU,否则使用CPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")# --- 2. 加载并预处理数据 ---iris = load_iris()
X = iris.data
y = iris.target# 只选择 'Setosa' (类别 0)
X_class0 = X[y == 0] # 一种简便写法# 数据缩放到 [-1, 1]
scaler = MinMaxScaler(feature_range=(-1, 1)) 
X_scaled = scaler.fit_transform(X_class0) # 转换为 PyTorch Tensor 并创建 DataLoader
# 注意需要将数据类型转为 float
real_data_tensor = torch.from_numpy(X_scaled).float() 
dataset = TensorDataset(real_data_tensor)
dataloader = DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True)print(f"成功加载并预处理数据。用于训练的样本数量: {len(X_scaled)}")
print(f"数据特征维度: {X_scaled.shape[1]}")

二、生成器

# --- 3. 构建模型 ---# (A) 生成器 (Generator)
class Generator(nn.Module):def __init__(self):super(Generator, self).__init__()self.model = nn.Sequential(nn.Linear(LATENT_DIM, 16),nn.ReLU(),nn.Linear(16, 32),nn.ReLU(),nn.Linear(32, 4),# 最后的维度只要和目标数据对齐即可nn.Tanh() # 输出范围是 [-1, 1])def forward(self, x):return self.model(x) # 因为没有像之前一样做定义x=某些东西,所以现在可以直接输出模型

2.1 nn.Sequential容器

这里我们用了torch中的容器这个概念,sequential是一个按顺序存放神经网络的容器,这样写神经网路的属性的时候,把这些内容都写在一个容器中,然后作为属性,后面定义前向传播的视时候会方便很多。

除了nn.sequential这种按顺序运算的容器,还有一些其他的容器,比如nn.ModuleList对于消融实验会起到简化代码的作用。

这种写法很好用,比如像encoder-decoder架构,就可以借助这种写法来实现简单的定义前向传播

 def forward(self, x):x = self.encoder(x)x = self.decoder(x)return x

当网络结构不满足线性顺序执行时(如包含残差连接、多分支、条件判断等),必须手动编写forward()方法。例如:

def forward(self, x):identity = xout = self.conv1(x)out = self.relu(out)out = self.conv2(out)out += identity  # 残差连接(无法用Sequential实现)return self.relu(out)

这是一个残差连接的写法,无法用sequential这个容器按顺序搭建。

总结:

  • 对于网络层按线性顺序堆叠(如 MLP、CNN 的主体部分),可以使用 Sequential 模型。
  • 对于网络包含复杂分支结构(如 ResNet 的残差连接、Inception 的多分支),建议手动编写 forward () 方法。

这两种方式本质上是等价的,但前者更符合模块化编程的思想,能让你的代码更易读、易维护。

不得不说,代码其实本质上就是几个常见的运算,但是由于不断封装,具备了各种各样的类、属性、语法糖等等写法。

三、判别器

# (B) 判别器 (Discriminator)
class Discriminator(nn.Module):def __init__(self):super(Discriminator, self).__init__()self.model = nn.Sequential(nn.Linear(4, 32),nn.LeakyReLU(0.2), # LeakyReLU 是 GAN 中的常用选择nn.Linear(32, 16),nn.LeakyReLU(0.2), # 负斜率参数为0.2nn.Linear(16, 1), # 这里最后输出1个神经元,所以用sigmoid激活函数nn.Sigmoid() # 输出 0 到 1 的概率)def forward(self, x):return self.model(x)

3.1分类问题激活函数和损失函数的对应

概括下激活函数和损失函数对应的情况:

二分类问题,常见的输出有2种

1. 单输出 + Sigmoid

2.  双输出 + Softmax

二者完全等价,一般推荐第一个

sigmoid一般对应BCE损失,softmax一般对应 CrossEntropy 损失

3.2 LeakyReLU

标准relu: f(x) = max(0, x)  小于0的输入直接置为0,计算简单,能缓解梯度消失问题,引入非线性。存在 “神经元死亡” 问题(当输入为负时,梯度为 0,参数无法更新)

LeakyReLU: f(x) = max(0.01x, x)   对负数输入保留一个小的梯度(如0.01倍),在输入为负时,仍有非零梯度(如 0.01),避免神经元永久死亡

许多 GAN 变体(如 DCGAN、WGAN)都默认使用 LeakyReLU,实践证明它能显著提高模型收敛速度和生成质量。

# 实例化模型并移动到指定设备
generator = Generator().to(device)
discriminator = Discriminator().to(device)print(generator)
print(discriminator)# --- 4. 定义损失函数和优化器 ---criterion = nn.BCELoss() # 二元交叉熵损失# 分别为生成器和判别器设置优化器
g_optimizer = optim.Adam(generator.parameters(), lr=LR, betas=(BETA1, 0.999))
d_optimizer = optim.Adam(discriminator.parameters(), lr=LR, betas=(BETA1, 0.999))


# --- 5. 执行训练循环 ---print("\n--- 开始训练 ---")
for epoch in range(EPOCHS):for i, (real_data,) in enumerate(dataloader):# 将数据移动到设备real_data = real_data.to(device)current_batch_size = real_data.size(0)# 创建真实和虚假的标签real_labels = torch.ones(current_batch_size, 1).to(device)fake_labels = torch.zeros(current_batch_size, 1).to(device)# ---------------------#  训练判别器# ---------------------d_optimizer.zero_grad() # 梯度清零# (1) 用真实数据训练real_output = discriminator(real_data)d_loss_real = criterion(real_output, real_labels)# (2) 用假数据训练noise = torch.randn(current_batch_size, LATENT_DIM).to(device)# 使用 .detach() 防止在训练判别器时梯度流回生成器,这里我们未来再说fake_data = generator(noise).detach() fake_output = discriminator(fake_data)d_loss_fake = criterion(fake_output, fake_labels)# 总损失并反向传播d_loss = d_loss_real + d_loss_faked_loss.backward()d_optimizer.step()# ---------------------#  训练生成器# ---------------------g_optimizer.zero_grad() # 梯度清零# 生成新的假数据,并尝试"欺骗"判别器noise = torch.randn(current_batch_size, LATENT_DIM).to(device)fake_data = generator(noise)fake_output = discriminator(fake_data)# 计算生成器的损失,目标是让判别器将假数据误判为真(1)g_loss = criterion(fake_output, real_labels)# 反向传播并更新生成器g_loss.backward()g_optimizer.step()# 每 1000 个 epoch 打印一次训练状态if (epoch + 1) % 1000 == 0:print(f"Epoch [{epoch+1}/{EPOCHS}], "f"Discriminator Loss: {d_loss.item():.4f}, "f"Generator Loss: {g_loss.item():.4f}")print("--- 训练完成 ---")

# --- 6. 生成新数据并进行可视化对比 ---print("\n--- 生成并可视化结果 ---")
# 将生成器设为评估模式
generator.eval()# 使用 torch.no_grad() 来关闭梯度计算
with torch.no_grad():num_new_samples = 50noise = torch.randn(num_new_samples, LATENT_DIM).to(device)generated_data_scaled = generator(noise)# 将生成的数据从GPU移到CPU,并转换为numpy数组
generated_data_scaled_np = generated_data_scaled.cpu().numpy()# 逆向转换回原始尺度
generated_data = scaler.inverse_transform(generated_data_scaled_np)
real_data_original_scale = scaler.inverse_transform(X_scaled)# 可视化对比
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
fig.suptitle('真实数据 vs. GAN生成数据 的特征分布对比 (PyTorch)', fontsize=16)feature_names = iris.feature_namesfor i, ax in enumerate(axes.flatten()):ax.hist(real_data_original_scale[:, i], bins=10, density=True, alpha=0.6, label='Real Data')ax.hist(generated_data[:, i], bins=10, density=True, alpha=0.6, label='Generated Data')ax.set_title(feature_names[i])ax.legend()plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()# 将生成的数据与真实数据并排打印出来看看
print("\n前5个真实样本 (Setosa):")
print(pd.DataFrame(real_data_original_scale[:5], columns=feature_names))print("\nGAN生成的5个新样本:")
print(pd.DataFrame(generated_data[:5], columns=feature_names))

GAN 训练效果的关键指标是 生成数据分布与真实数据分布的重合度:  

- 若两者分布高度重叠 → 生成数据质量高,GAN 学得好  

- 若分布差异大、峰谷错位明显 → 生成数据存在偏差,GAN 学习不充分  

那么如何评价好这个分布情况呢?最好是采取定量指标:KL散度,我们以后有机会再说,主要还使用在图像数据上的,GAN

作业

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import f1_score
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
# 设置中文字体支持
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题# 检查GPU是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")LATENT_DIM = 10     # 潜在空间的维度
EPOCHS = 10000      # 训练的回合数
BATCH_SIZE = 32     # 每批次训练的样本数
LR = 0.0002         # 学习率
BETA1 = 0.5         # Adam优化器的参数# --- 2. 加载并预处理数据 ---data = pd.read_csv(r"F:\Program Files\MyPythonProjects\day53\heart.csv")
print("成功从本地路径加载数据")# 分割特征和标签
X = data.drop('target', axis=1).values
y = data['target'].valuesfeature_names = data.drop('target', axis=1).columns.tolist()# 检查数据是否不平衡
print(f"样本分布: 病人({sum(y)}) vs 非病人({len(y)-sum(y)})")# 提取病人样本(标签为1)
X_patient = X[y == 1]# 数据缩放到 [-1, 1]
scaler = MinMaxScaler(feature_range=(-1, 1)) 
X_scaled = scaler.fit_transform(X_patient) # 转换为 PyTorch Tensor 并创建 DataLoader
real_data_tensor = torch.from_numpy(X_scaled).float() 
dataset = TensorDataset(real_data_tensor)
dataloader = DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True)print(f"成功加载并预处理数据。用于训练的病人样本数量: {len(X_scaled)}")
print(f"数据特征维度: {X_scaled.shape[1]}")# --- 3. 构建模型 ---# (A) 生成器 (Generator)
class Generator(nn.Module):def __init__(self):super(Generator, self).__init__()self.model = nn.Sequential(nn.Linear(LATENT_DIM, 16),nn.ReLU(),nn.Linear(16, 32),nn.ReLU(),nn.Linear(32, X_scaled.shape[1]),  # 输出维度与数据特征维度匹配nn.Tanh()  # 输出范围是 [-1, 1])def forward(self, x):return self.model(x)# (B) 判别器 (Discriminator)
class Discriminator(nn.Module):def __init__(self):super(Discriminator, self).__init__()self.model = nn.Sequential(nn.Linear(X_scaled.shape[1], 32),  # 输入维度与数据特征维度匹配nn.LeakyReLU(0.2),nn.Linear(32, 16),nn.LeakyReLU(0.2),nn.Linear(16, 1),nn.Sigmoid()  # 输出 0 到 1 的概率)def forward(self, x):return self.model(x)# 实例化模型并移动到指定设备
generator = Generator().to(device)
discriminator = Discriminator().to(device)print(generator)
print(discriminator)# --- 4. 定义损失函数和优化器 ---criterion = nn.BCELoss()  # 二元交叉熵损失# 分别为生成器和判别器设置优化器
g_optimizer = optim.Adam(generator.parameters(), lr=LR, betas=(BETA1, 0.999))
d_optimizer = optim.Adam(discriminator.parameters(), lr=LR, betas=(BETA1, 0.999))# --- 5. 执行训练循环 ---print("\n--- 开始训练 ---")
for epoch in range(EPOCHS):for i, (real_data,) in enumerate(dataloader):# 将数据移动到设备real_data = real_data.to(device)current_batch_size = real_data.size(0)# 创建真实和虚假的标签real_labels = torch.ones(current_batch_size, 1).to(device)fake_labels = torch.zeros(current_batch_size, 1).to(device)# ---------------------#  训练判别器# ---------------------d_optimizer.zero_grad()  # 梯度清零# (1) 用真实数据训练real_output = discriminator(real_data)d_loss_real = criterion(real_output, real_labels)# (2) 用假数据训练noise = torch.randn(current_batch_size, LATENT_DIM).to(device)fake_data = generator(noise).detach() fake_output = discriminator(fake_data)d_loss_fake = criterion(fake_output, fake_labels)# 总损失并反向传播d_loss = d_loss_real + d_loss_faked_loss.backward()d_optimizer.step()# ---------------------#  训练生成器# ---------------------g_optimizer.zero_grad()  # 梯度清零# 生成新的假数据,并尝试"欺骗"判别器noise = torch.randn(current_batch_size, LATENT_DIM).to(device)fake_data = generator(noise)fake_output = discriminator(fake_data)# 计算生成器的损失,目标是让判别器将假数据误判为真(1)g_loss = criterion(fake_output, real_labels)# 反向传播并更新生成器g_loss.backward()g_optimizer.step()# 每 1000 个 epoch 打印一次训练状态if (epoch + 1) % 1000 == 0:print(f"Epoch [{epoch+1}/{EPOCHS}], "f"Discriminator Loss: {d_loss.item():.4f}, "f"Generator Loss: {g_loss.item():.4f}")print("--- 训练完成 ---")# --- 6. 生成新数据并进行可视化对比 ---print("\n--- 生成并可视化结果 ---")
# 将生成器设为评估模式
generator.eval()# 使用 torch.no_grad() 来关闭梯度计算
with torch.no_grad():num_new_samples = 50noise = torch.randn(num_new_samples, LATENT_DIM).to(device)generated_data_scaled = generator(noise)# 将生成的数据从GPU移到CPU,并转换为numpy数组
generated_data_scaled_np = generated_data_scaled.cpu().numpy()# 逆向转换回原始尺度
generated_data = scaler.inverse_transform(generated_data_scaled_np)
real_data_original_scale = scaler.inverse_transform(X_scaled)# 可视化对比 - 选择前4个特征进行可视化
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
fig.suptitle('真实数据 vs. GAN生成数据 的特征分布对比', fontsize=16)# 选择前4个特征进行可视化
selected_features = [0, 1, 2, 3]for i, ax in enumerate(axes.flatten()):if i < len(selected_features):feature_idx = selected_features[i]ax.hist(real_data_original_scale[:, feature_idx], bins=10, density=True, alpha=0.6, label='真实数据')ax.hist(generated_data[:, feature_idx], bins=10, density=True, alpha=0.6, label='生成数据')ax.set_title(feature_names[feature_idx])ax.legend()plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()# 将生成的数据与真实数据并排打印出来看看
print("\n前5个真实病人样本:")
print(pd.DataFrame(real_data_original_scale[:5], columns=feature_names).head())print("\nGAN生成的5个新病人样本:")
print(pd.DataFrame(generated_data[:5], columns=feature_names).head())# --- 7. 评估F1分数差异 ---
print("\n--- 评估模型性能 ---")# 准备原始数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)# 不使用GAN的模型
model_no_gan = RandomForestClassifier(random_state=42)
model_no_gan.fit(X_train, y_train)
y_pred_no_gan = model_no_gan.predict(X_test)
f1_no_gan = f1_score(y_test, y_pred_no_gan)
print(f"不使用GAN的F1分数: {f1_no_gan:.4f}")# 准备使用GAN增强的数据集
# 创建生成的样本标签 
y_generated = np.ones(num_new_samples)# 将生成的数据添加到训练集中
X_train_gan = np.vstack([X_train, generated_data])
y_train_gan = np.hstack([y_train, y_generated])# 使用GAN增强数据的模型
model_with_gan = RandomForestClassifier(random_state=42)
model_with_gan.fit(X_train_gan, y_train_gan)
y_pred_with_gan = model_with_gan.predict(X_test)
f1_with_gan = f1_score(y_test, y_pred_with_gan)
print(f"使用GAN增强数据的F1分数: {f1_with_gan:.4f}")# 可视化F1分数对比
plt.figure(figsize=(10, 6))
plt.bar(['不使用GAN', '使用GAN'], [f1_no_gan, f1_with_gan], color=['#66b3ff', '#99ff99'])
plt.ylim(0, 1)
plt.title('F1分数对比')
plt.ylabel('F1分数')
for i, v in enumerate([f1_no_gan, f1_with_gan]):plt.text(i, v + 0.02, f'{v:.4f}', ha='center')
plt.show()

但是有些遗憾,使用GAN后F1没有变化。我还重新运行过好几次甚至出现过使用GAN后F1不升反降的情况。

询问了一下AI分析可能导致该结果的原因是什么

@浙大疏锦行

http://www.khdw.cn/news/13589.html

相关文章:

  • 盗版软件做的网站会被起诉吗百度seo点击工具
  • 二级栏目网站免费建站的网站
  • 专业类网站企业如何进行宣传和推广
  • wordpress实例网站seo推广营销公司
  • 设计网站公司地址郴州网站seo外包
  • 微网站制作价格湖南优化电商服务有限公司
  • 购物网站风格互联网营销策划是做什么的
  • 网站说服力 营销型网站策划 下载seo专员是指什么意思
  • 做一个网站怎么做线上营销怎么推广
  • 公司网站seo外包怎么做电商卖东西
  • 做网站白云东莞网络推广优化排名
  • 三亚做网站口碑营销经典案例
  • 做网站项目需求分析是什么域名查询工具
  • 好看的网站后台模板百度游戏排行榜风云榜
  • 销售公司怎么做网站html网页制作步骤
  • wordpress 全站 下载百度快快速排名
  • 上海集团网站建设百度电脑网页版
  • 手机网站会员中心模板下载深圳债务优化公司
  • 抖音官方网站在线客服网站关键词查询
  • vps一定要Wordpress吗长沙靠谱seo优化价格
  • 泊头做网站电话东莞企业网站设计公司
  • wordpress 网站的占有手机百度搜索引擎入口
  • 建设网站的技术手段长沙做网站推广
  • 东莞建网站公司动销售推广的方法都有哪些
  • 学会建网站如何做网络营销微信营销工具
  • 建设网站前端江北seo页面优化公司
  • 网站制作的论文福州seo推广服务
  • 杭州高端网站建设公司哪家好搜索引擎查关键词排名的软件
  • wordpress反爬虫济宁seo优化公司
  • 腾讯云如何创建网站最近新闻热点事件