Pytorch深度學習框架60天進階學習計劃 - 第41天:生成對抗網絡進階(二)

Pytorch深度學習框架60天進階學習計劃 - 第41天:生成對抗網絡進階(二)

7. 實現條件WGAN-GP

# 訓練條件WGAN-GP
def train_conditional_wgan_gp():# 用于記錄損失d_losses = []g_losses = []# 用于記錄生成樣本的多樣性(通過類別分布)class_distributions = []for epoch in range(n_epochs):for i, (real_imgs, labels) in enumerate(dataloader):real_imgs = real_imgs.to(device)labels = labels.to(device)batch_size = real_imgs.shape[0]# ---------------------#  訓練判別器# ---------------------optimizer_D.zero_grad()# 生成隨機噪聲z = torch.randn(batch_size, latent_dim, device=device)# 為生成器生成隨機標簽gen_labels = torch.randint(0, n_classes, (batch_size,), device=device)# 生成一批假圖像fake_imgs = generator(z, gen_labels)# 判別器前向傳播real_validity = discriminator(real_imgs, labels)fake_validity = discriminator(fake_imgs.detach(), gen_labels)# 計算梯度懲罰gradient_penalty = compute_gradient_penalty(discriminator, real_imgs.data, fake_imgs.data, labels)# WGAN-GP 判別器損失d_loss = -torch.mean(real_validity) + torch.mean(fake_validity) + lambda_gp * gradient_penaltyd_loss.backward()optimizer_D.step()# 每n_critic次迭代訓練一次生成器n_critic = 5if i % n_critic == 0:# ---------------------#  訓練生成器# ---------------------optimizer_G.zero_grad()# 為生成器生成新的隨機標簽gen_labels = torch.randint(0, n_classes, (batch_size,), device=device)# 生成一批新的假圖像gen_imgs = generator(z, gen_labels)# 判別器評估假圖像fake_validity = discriminator(gen_imgs, gen_labels)# WGAN 生成器損失g_loss = -torch.mean(fake_validity)g_loss.backward()optimizer_G.step()if i % 50 == 0:print(f"[Epoch {epoch}/{n_epochs}] [Batch {i}/{len(dataloader)}] "f"[D loss: {d_loss.item():.4f}] [G loss: {g_loss.item():.4f}]")d_losses.append(d_loss.item())g_losses.append(g_loss.item())# 每個epoch結束后,評估生成樣本的類別分布if (epoch + 1) % 10 == 0:class_dist = evaluate_class_distribution()class_distributions.append(class_dist)# 保存生成的圖像樣本save_sample_images(epoch)# 繪制損失曲線plt.figure(figsize=(10, 5))plt.plot(d_losses, label='Discriminator Loss')plt.plot(g_losses, label='Generator Loss')plt.xlabel('Iterations (x50)')plt.ylabel('Loss')plt.legend()plt.savefig('cond_wgan_gp_loss.png')plt.close()# 繪制類別分布變化plot_class_distributions(class_distributions)# 評估生成樣本的類別分布
def evaluate_class_distribution():"""評估生成樣本在各類別上的分布情況"""# 創建一個預訓練的分類器classifier = torchvision.models.resnet18(pretrained=True)# 修改第一個卷積層以適應灰度圖classifier.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)# 修改最后的全連接層以適應MNIST的10個類別classifier.fc = nn.Linear(classifier.fc.in_features, 10)# 加載預先訓練好的MNIST分類器權重(這里假設我們有一個預訓練的模型)# classifier.load_state_dict(torch.load('mnist_classifier.pth'))# 簡化起見,這里我們使用一個簡單的CNN分類器classifier = nn.Sequential(nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),nn.Flatten(),nn.Linear(64 * 7 * 7, 128),nn.ReLU(),nn.Linear(128, 10)).to(device)# 這里假設這個簡單分類器已經在MNIST上訓練好了# 實際應用中,應該加載一個預先訓練好的模型# 生成1000個樣本z = torch.randn(1000, latent_dim, device=device)# 均勻采樣所有類別gen_labels = torch.tensor([i % 10 for i in range(1000)], device=device)gen_imgs = generator(z, gen_labels)# 使用分類器預測類別with torch.no_grad():classifier.eval()preds = torch.softmax(classifier(gen_imgs), dim=1)pred_labels = torch.argmax(preds, dim=1)# 計算每個類別的樣本數量class_counts = torch.zeros(10)for i in range(10):class_counts[i] = (pred_labels == i).sum().item() / 1000return class_counts.numpy()# 繪制類別分布變化
def plot_class_distributions(class_distributions):"""繪制生成樣本類別分布的變化"""epochs = [10, 20, 30, 40, 50]  # 假設每10個epoch評估一次plt.figure(figsize=(12, 8))for i, dist in enumerate(class_distributions):plt.subplot(len(class_distributions), 1, i+1)plt.bar(np.arange(10), dist)plt.ylabel(f'Epoch {epochs[i]}')plt.ylim(0, 0.3)  # 限制y軸范圍,便于比較if i == len(class_distributions) - 1:plt.xlabel('Digit Class')plt.tight_layout()plt.savefig('class_distribution.png')plt.close()# 保存樣本圖像(條件版本)
def save_sample_images(epoch):"""保存按類別排列的樣本圖像"""# 為每個類別生成樣本n_row = 10  # 每個類別一行n_col = 10  # 每個類別10個樣本fig, axs = plt.subplots(n_row, n_col, figsize=(12, 12))for i in range(n_row):# 固定類別fixed_class = torch.tensor([i] * n_col, device=device)# 隨機噪聲z = torch.randn(n_col, latent_dim, device=device)# 生成圖像gen_imgs = generator(z, fixed_class).detach().cpu()# 轉換到[0, 1]范圍gen_imgs = 0.5 * gen_imgs + 0.5# 顯示圖像for j in range(n_col):axs[i, j].imshow(gen_imgs[j, 0, :, :], cmap='gray')axs[i, j].axis('off')plt.savefig(f'cond_wgan_gp_epoch_{epoch+1}.png')plt.close()# 運行條件WGAN-GP訓練
if __name__ == "__main__":train_conditional_wgan_gp()

上述代碼實現了一個條件WGAN-GP模型,主要區別在于:

  1. 條件輸入:生成器和判別器都接收類別標簽作為額外輸入
  2. 嵌入層:使用嵌入層將類別標簽轉換為嵌入向量
  3. 類別多樣性評估:添加了評估生成樣本類別分布的功能
  4. 可視化:按類別排列生成樣本,便于觀察每個類別的質量

8. 無監督與條件生成的模式坍塌對比實驗

為了更直觀地比較無監督生成和條件生成在模式坍塌方面的差異,我們可以設計一個實驗,分別訓練無監督WGAN-GP和條件WGAN-GP,然后比較它們生成樣本的模式覆蓋情況。

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import numpy as np
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE# 假設我們已經訓練好了無監督WGAN-GP和條件WGAN-GP模型
# 分別為 unsupervised_generator 和 conditional_generatordef analyze_mode_collapse():"""分析并比較無監督和條件生成在模式坍塌方面的差異"""# 生成樣本數量n_samples = 1000# 1. 從無監督生成器生成樣本z_unsupervised = torch.randn(n_samples, latent_dim, device=device)unsupervised_samples = unsupervised_generator(z_unsupervised).detach().cpu()# 2. 從條件生成器生成樣本(均勻覆蓋所有類別)z_conditional = torch.randn(n_samples, latent_dim, device=device)conditional_labels = torch.tensor([i % 10 for i in range(n_samples)], device=device)conditional_samples = conditional_generator(z_conditional, conditional_labels).detach().cpu()# 3. 獲取真實MNIST樣本real_loader = torch.utils.data.DataLoader(mnist_dataset, batch_size=n_samples, shuffle=True)real_samples, _ = next(iter(real_loader))# 4. 使用預訓練的分類器分類所有樣本classifier = create_mnist_classifier()  # 假設我們有一個創建分類器的函數# 分類無監督生成的樣本unsupervised_predictions = classify_samples(classifier, unsupervised_samples)# 分類條件生成的樣本conditional_predictions = classify_samples(classifier, conditional_samples)# 分類真實樣本real_predictions = classify_samples(classifier, real_samples)# 5. 計算各類別的樣本分布unsupervised_distribution = compute_class_distribution(unsupervised_predictions)conditional_distribution = compute_class_distribution(conditional_predictions)real_distribution = compute_class_distribution(real_predictions)# 6. 計算分布的均勻度(使用熵)unsupervised_entropy = compute_entropy(unsupervised_distribution)conditional_entropy = compute_entropy(conditional_distribution)real_entropy = compute_entropy(real_distribution)print(f"無監督生成分布熵: {unsupervised_entropy:.4f}")print(f"條件生成分布熵: {conditional_entropy:.4f}")print(f"真實數據分布熵: {real_entropy:.4f}")# 7. 可視化樣本分布visualize_distributions(unsupervised_distribution,conditional_distribution,real_distribution)# 8. 使用t-SNE將樣本投影到二維空間進行可視化visualize_tsne(unsupervised_samples,conditional_samples,real_samples)def create_mnist_classifier():"""創建一個簡單的MNIST分類器"""model = nn.Sequential(nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),nn.Flatten(),nn.Linear(64 * 7 * 7, 128),nn.ReLU(),nn.Linear(128, 10)).to(device)# 這里假設分類器已經訓練好了# model.load_state_dict(torch.load('mnist_classifier.pth'))return modeldef classify_samples(classifier, samples):"""使用分類器對樣本進行分類"""with torch.no_grad():classifier.eval()# 確保樣本在正確的設備上samples = samples.to(device)# 前向傳播logits = classifier(samples)# 獲取預測類別predictions = torch.argmax(logits, dim=1)return predictions.cpu().numpy()def compute_class_distribution(predictions):"""計算類別分布"""n_samples = len(predictions)distribution = np.zeros(10)for i in range(10):distribution[i] = np.sum(predictions == i) / n_samplesreturn distributiondef compute_entropy(distribution):"""計算分布的熵,衡量分布的均勻度"""# 防止log(0)distribution = distribution + 1e-10# 歸一化distribution = distribution / np.sum(distribution)# 計算熵entropy = -np.sum(distribution * np.log2(distribution))return entropydef visualize_distributions(unsupervised_dist, conditional_dist, real_dist):"""可視化三種樣本的類別分布"""plt.figure(figsize=(12, 5))width = 0.25x = np.arange(10)plt.bar(x - width, unsupervised_dist, width, label='Unsupervised')plt.bar(x, conditional_dist, width, label='Conditional')plt.bar(x + width, real_dist, width, label='Real')plt.xlabel('Digit Class')plt.ylabel('Proportion')plt.title('Class Distribution Comparison')plt.xticks(x)plt.legend()plt.tight_layout()plt.savefig('distribution_comparison.png')plt.close()def visualize_tsne(unsupervised_samples, conditional_samples, real_samples):"""使用t-SNE將樣本投影到二維空間并可視化"""# 準備數據unsupervised_flat = unsupervised_samples.view(unsupervised_samples.size(0), -1).numpy()conditional_flat = conditional_samples.view(conditional_samples.size(0), -1).numpy()real_flat = real_samples.view(real_samples.size(0), -1).numpy()# 合并所有樣本all_samples = np.vstack([unsupervised_flat, conditional_flat, real_flat])# 使用t-SNE降維tsne = TSNE(n_components=2, random_state=42)all_samples_tsne = tsne.fit_transform(all_samples)# 分離結果n = unsupervised_flat.shape[0]unsupervised_tsne = all_samples_tsne[:n]conditional_tsne = all_samples_tsne[n:2*n]real_tsne = all_samples_tsne[2*n:]# 可視化plt.figure(figsize=(10, 8))plt.scatter(unsupervised_tsne[:, 0], unsupervised_tsne[:, 1], c='blue', label='Unsupervised', alpha=0.5, s=10)plt.scatter(conditional_tsne[:, 0], conditional_tsne[:, 1], c='green', label='Conditional', alpha=0.5, s=10)plt.scatter(real_tsne[:, 0], real_tsne[:, 1], c='red', label='Real', alpha=0.5, s=10)plt.legend()plt.title('t-SNE Visualization of Generated and Real Samples')plt.savefig('tsne_visualization.png')plt.close()# 運行分析
if __name__ == "__main__":analyze_mode_collapse()

上述代碼實現了一個比較實驗,用于分析無監督WGAN-GP和條件WGAN-GP在模式坍塌方面的差異。主要的分析方法包括:

  1. 類別分布分析:使用預訓練的分類器對生成樣本進行分類,統計各類別的樣本比例
  2. 熵計算:使用熵來衡量分布的均勻度,熵越高表示分布越均勻,模式覆蓋越全面
  3. t-SNE可視化:使用t-SNE將高維樣本投影到二維空間,直觀地觀察樣本分布

通過這些分析,我們可以定量和定性地比較兩種方法在模式坍塌方面的表現。

9. 模式坍塌問題的其他解決方案

除了條件生成和WGAN-GP,還有其他方法可以緩解GAN的模式坍塌問題:

9.1 解決模式坍塌的方法比較表

方法核心思想優點缺點實現復雜度
WGAN-GP使用Wasserstein距離和梯度懲罰訓練穩定,理論基礎強計算成本高中等
條件GAN添加條件信息引導生成可控生成,強制覆蓋所有類別需要標簽數據
小批量判別 (Minibatch Discrimination)判別器考慮樣本間的相似性直接鼓勵樣本多樣性計算開銷增加
展開GAN (Unrolled GAN)展開判別器的k步更新提供更穩定的梯度訓練速度慢
BEGAN使用自編碼器作為判別器平衡生成器和判別器訓練模型結構復雜中等
PacGAN將多個樣本打包傳給判別器實現簡單,效果明顯需要更多內存
集成多個生成器使用多個生成器捕捉不同模式天然覆蓋多個模式訓練困難,參數增加
基于能量的GAN (EBGAN)將GAN視為能量模型更好的穩定性理解難度大中等

9.2 小批量判別的PyTorch實現

下面是小批量判別(Minibatch Discrimination)的PyTorch實現示例,這是另一種解決模式坍塌的有效方法:

import torch
import torch.nn as nnclass MinibatchDiscrimination(nn.Module):"""小批量判別層,用于緩解模式坍塌"""def __init__(self, input_features, output_features, kernel_dim=5):super(MinibatchDiscrimination, self).__init__()self.input_features = input_featuresself.output_features = output_featuresself.kernel_dim = kernel_dim# 參數張量 [input_features, output_features * kernel_dim]self.T = nn.Parameter(torch.randn(input_features, output_features * kernel_dim))def forward(self, x):# x形狀: [batch_size, input_features]batch_size = x.size(0)# 將輸入與參數相乘 -> [batch_size, output_features, kernel_dim]matrices = x.mm(self.T).view(batch_size, self.output_features, self.kernel_dim)# 擴展為廣播形狀 -> [batch_size, batch_size, output_features, kernel_dim]matrices_expanded = matrices.unsqueeze(1)matrices_transposed = matrices.unsqueeze(0)# 計算L1距離 -> [batch_size, batch_size, output_features]l1_dist = torch.abs(matrices_expanded - matrices_transposed).sum(dim=3)# 應用負指數核 -> [batch_size, batch_size, output_features]K = torch.exp(-l1_dist)# 將自身的相似度設為0(對角線)mask = (torch.ones(batch_size, batch_size) - torch.eye(batch_size)).unsqueeze(2)mask = mask.to(x.device)K = K * mask# 對每個樣本,計算其與其他所有樣本的相似度之和 -> [batch_size, output_features]minibatch_features = K.sum(dim=1)# 將小批量判別特征與原始特征連接return torch.cat([x, minibatch_features], dim=1)# 使用小批量判別的判別器示例
class DiscriminatorWithMinibatch(nn.Module):def __init__(self, img_shape, hidden_dim=512, minibatch_features=32):super(DiscriminatorWithMinibatch, self).__init__()self.img_flat_dim = int(np.prod(img_shape))# 特征提取層self.features = nn.Sequential(nn.Linear(self.img_flat_dim, hidden_dim),nn.LeakyReLU(0.2, inplace=True),nn.Linear(hidden_dim, hidden_dim),nn.LeakyReLU(0.2, inplace=True))# 小批量判別層self.minibatch = MinibatchDiscrimination(hidden_dim, minibatch_features)# 輸出層self.output = nn.Linear(hidden_dim + minibatch_features, 1)def forward(self, img):# 將圖像展平img_flat = img.view(img.size(0), -1)# 提取特征features = self.features(img_flat)# 應用小批量判別enhanced_features = self.minibatch(features)# 輸出validity = self.output(enhanced_features)return validity

小批量判別通過考慮樣本之間的相似性來鼓勵生成樣本的多樣性。它計算批次中每個樣本與其他樣本的距離,并將這些距離信息作為額外特征傳遞給判別器,使判別器能夠識別出生成器是否只生成相似的樣本。

10. 生成對抗網絡的評估指標

評估GAN的性能是一個復雜的問題,特別是在衡量生成樣本的質量和多樣性方面。以下是一些常用的評估指標:

10.1 常用GAN評估指標比較表

指標衡量內容優點缺點適用場景
Inception Score (IS)樣本質量和多樣性易于實現,廣泛使用對噪聲敏感,不考慮與真實分布的匹配度圖像生成,特別是有標簽的數據集
Fréchet Inception Distance (FID)生成分布與真實分布的相似度對模式坍塌敏感,更符合人類判斷計算復雜度高各類圖像生成任務
多樣性指數 (Diversity Score)生成樣本的多樣性直接衡量樣本間距離不考慮樣本質量檢測模式坍塌
精度與召回率 (Precision & Recall)樣本質量和覆蓋率分離質量和覆蓋率的測量實現復雜需要平衡質量和多樣性的場景
分類器兩樣本測試 (C2ST)真假樣本的可區分性直觀且有理論保證需要訓練額外的分類器校驗生成分布與真實分布的接近程度
知覺路徑長度 (PPL)潛在空間平滑度衡量生成器質量計算開銷大評估StyleGAN等高質量生成模型

10.2 FID指標的PyTorch實現

下面是Fréchet Inception Distance (FID)指標的PyTorch實現,這是評估GAN生成質量的常用指標:

import torch
import torch.nn as nn
import torchvision.models as models
import numpy as np
from scipy import linalgclass InceptionV3Features(nn.Module):"""提取InceptionV3特征的模型"""def __init__(self):super(InceptionV3Features, self).__init__()# 加載預訓練的InceptionV3inception = models.inception_v3(pretrained=True)# 使用到Mixed_7c層self.feature_extractor = nn.Sequential(*list(inception.children())[:-4])# 設置為評估模式self.feature_extractor.eval()# 凍結參數for param in self.feature_extractor.parameters():param.requires_grad = Falsedef forward(self, x):# InceptionV3期望輸入為[0, 1]范圍的RGB圖像# 并且預處理為[-1, 1]if x.shape[1] == 1:  # 如果是灰度圖像,復制到3個通道x = x.repeat(1, 3, 1, 1)# 調整大小以符合InceptionV3的輸入要求if x.shape[2] != 299 or x.shape[3] != 299:x = nn.functional.interpolate(x, size=(299, 299), mode='bilinear', align_corners=False)# 特征提取with torch.no_grad():features = self.feature_extractor(x)return featuresdef calculate_fid(real_features, fake_features):"""計算Fréchet Inception Distance"""# 轉換為numpy數組real_features = real_features.detach().cpu().numpy()fake_features = fake_features.detach().cpu().numpy()# 計算均值和協方差mu_real = np.mean(real_features, axis=0)mu_fake = np.mean(fake_features, axis=0)sigma_real = np.cov(real_features, rowvar=False)sigma_fake = np.cov(fake_features, rowvar=False)# 計算FIDdiff = mu_real - mu_fake# 添加小的對角項以增加數值穩定性sigma_real += np.eye(sigma_real.shape[0]) * 1e-6sigma_fake += np.eye(sigma_fake.shape[0]) * 1e-6# 計算平方根協方差矩陣乘積covmean = linalg.sqrtm(sigma_real @ sigma_fake)# 檢查是否有復數if np.iscomplexobj(covmean):covmean = covmean.real# 計算FIDfid = diff @ diff + np.trace(sigma_real + sigma_fake - 2 *def calculate_fid(real_features, fake_features):"""計算Fréchet Inception Distance"""# 轉換為numpy數組real_features = real_features.detach().cpu().numpy()fake_features = fake_features.detach().cpu().numpy()# 計算均值和協方差mu_real = np.mean(real_features, axis=0)mu_fake = np.mean(fake_features, axis=0)sigma_real = np.cov(real_features, rowvar=False)sigma_fake = np.cov(fake_features, rowvar=False)# 計算FIDdiff = mu_real - mu_fake# 添加小的對角項以增加數值穩定性sigma_real += np.eye(sigma_real.shape[0]) * 1e-6sigma_fake += np.eye(sigma_fake.shape[0]) * 1e-6# 計算平方根協方差矩陣乘積covmean = linalg.sqrtm(sigma_real @ sigma_fake)# 檢查是否有復數if np.iscomplexobj(covmean):covmean = covmean.real# 計算FIDfid = diff @ diff + np.trace(sigma_real + sigma_fake - 2 * covmean)return fiddef compute_fid_for_gan(real_loader, generator, n_samples=10000, batch_size=50, device='cuda'):"""為GAN計算FID分數"""# 初始化Inception特征提取器feature_extractor = InceptionV3Features().to(device)# 收集真實樣本的特征real_features = []for i, (real_imgs, _) in enumerate(real_loader):if i * batch_size >= n_samples:breakreal_imgs = real_imgs.to(device)with torch.no_grad():features = feature_extractor(real_imgs)features = features.view(features.size(0), -1)real_features.append(features)real_features = torch.cat(real_features, dim=0)[:n_samples]# 收集生成樣本的特征fake_features = []n_batches = n_samples // batch_sizefor i in range(n_batches):# 生成假樣本z = torch.randn(batch_size, latent_dim, device=device)fake_imgs = generator(z)with torch.no_grad():features = feature_extractor(fake_imgs)features = features.view(features.size(0), -1)fake_features.append(features)fake_features = torch.cat(fake_features, dim=0)# 計算FIDfid = calculate_fid(real_features, fake_features)return fid

FID是一種常用的評估GAN生成質量的指標,它通過比較真實樣本和生成樣本在特征空間中的統計差異來衡量生成質量。FID值越低表示生成樣本與真實樣本越相似。

11. 模式坍塌實驗與可視化分析

為了更直觀地理解模式坍塌問題以及WGAN-GP和條件生成如何緩解這一問題,我們可以設計一個專門的實驗,針對一個簡單的多模態分布。

11.1 模式坍塌實驗設計

我們將使用一個由多個高斯分布組成的混合分布作為目標分布,然后分別使用普通GAN、WGAN-GP和條件WGAN-GP來學習這個分布。

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
import seaborn as sns# 設置隨機種子
torch.manual_seed(42)
np.random.seed(42)# 設備配置
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# 生成混合高斯分布
def generate_mixture_of_gaussians(n_samples=10000, n_components=8, random_state=42):"""生成二維混合高斯分布"""centers = np.array([[0, 0],[5, 5],[5, -5],[-5, 5],[-5, -5],[0, 5],[5, 0],[-5, 0],[0, -5]])[:n_components]X, y = make_blobs(n_samples=n_samples,centers=centers,cluster_std=0.5,random_state=random_state)# 歸一化到[-1, 1]范圍X = X / np.abs(X).max(axis=0, keepdims=True) * 0.9return X, y# 數據加載器
class GaussianMixtureDataset(torch.utils.data.Dataset):def __init__(self, n_samples=10000, n_components=8):self.data, self.labels = generate_mixture_of_gaussians(n_samples, n_components)self.data = torch.FloatTensor(self.data)self.labels = torch.LongTensor(self.labels)def __len__(self):return len(self.data)def __getitem__(self, idx):return self.data[idx], self.labels[idx]# 簡單生成器
class SimpleGenerator(nn.Module):def __init__(self, latent_dim=2, output_dim=2, hidden_dim=128):super(SimpleGenerator, self).__init__()self.model = nn.Sequential(nn.Linear(latent_dim, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, output_dim),nn.Tanh()  # 輸出范圍為[-1, 1])def forward(self, z):return self.model(z)# 簡單判別器
class SimpleDiscriminator(nn.Module):def __init__(self, input_dim=2, hidden_dim=128):super(SimpleDiscriminator, self).__init__()self.model = nn.Sequential(nn.Linear(input_dim, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, 1))def forward(self, x):return self.model(x)# 條件生成器
class ConditionalGenerator(nn.Module):def __init__(self, latent_dim=2, output_dim=2, hidden_dim=128, n_classes=8):super(ConditionalGenerator, self).__init__()self.label_embedding = nn.Embedding(n_classes, n_classes)self.model = nn.Sequential(nn.Linear(latent_dim + n_classes, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, output_dim),nn.Tanh()  # 輸出范圍為[-1, 1])def forward(self, z, labels):label_embedding = self.label_embedding(labels)z = torch.cat([z, label_embedding], dim=1)return self.model(z)# 條件判別器
class ConditionalDiscriminator(nn.Module):def __init__(self, input_dim=2, hidden_dim=128, n_classes=8):super(ConditionalDiscriminator, self).__init__()self.label_embedding = nn.Embedding(n_classes, n_classes)self.model = nn.Sequential(nn.Linear(input_dim + n_classes, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, 1))def forward(self, x, labels):label_embedding = self.label_embedding(labels)x = torch.cat([x, label_embedding], dim=1)return self.model(x)# 計算WGAN-GP的梯度懲罰
def compute_gradient_penalty(D, real_samples, fake_samples, labels=None):"""計算梯度懲罰"""# 隨機插值系數alpha = torch.rand(real_samples.size(0), 1, device=device)# 創建插值樣本interpolates = (alpha * real_samples + ((1 - alpha) * fake_samples)).requires_grad_(True)# 計算判別器輸出if labels is not None:d_interpolates = D(interpolates, labels)else:d_interpolates = D(interpolates)# 創建虛擬輸出1.0fake = torch.ones(real_samples.size(0), 1, device=device, requires_grad=False)# 計算梯度gradients = torch.autograd.grad(outputs=d_interpolates,inputs=interpolates,grad_outputs=fake,create_graph=True,retain_graph=True,only_inputs=True)[0]# 計算梯度范數gradients = gradients.view(gradients.size(0), -1)gradient_penalty = ((gradients.norm(2, dim=1) - 1) ** 2).mean()return gradient_penalty# 可視化函數
def visualize_distributions(real_data, gen_data, title):"""可視化真實分布和生成分布"""plt.figure(figsize=(12, 5))# 真實數據分布plt.subplot(1, 2, 1)sns.kdeplot(x=real_data[:, 0], y=real_data[:, 1], cmap="Blues", fill=True, alpha=0.7)plt.scatter(real_data[:, 0], real_data[:, 1], s=1, c='blue', alpha=0.5)plt.title('Real Data Distribution')plt.xlim(-1.2, 1.2)plt.ylim(-1.2, 1.2)# 生成數據分布plt.subplot(1, 2, 2)sns.kdeplot(x=gen_data[:, 0], y=gen_data[:, 1], cmap="Reds", fill=True, alpha=0.7)plt.scatter(gen_data[:, 0], gen_data[:, 1], s=1, c='red', alpha=0.5)plt.title('Generated Data Distribution')plt.xlim(-1.2, 1.2)plt.ylim(-1.2, 1.2)plt.suptitle(title)plt.tight_layout()plt.savefig(f"{title.replace(' ', '_')}.png")plt.close()# 訓練函數
def train_gan_variants(n_components=8, n_epochs=500, batch_size=128, latent_dim=2):"""訓練不同的GAN變體并比較它們在模式坍塌上的差異"""# 準備數據dataset = GaussianMixtureDataset(n_samples=10000, n_components=n_components)dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)# 可視化真實數據分布real_samples = dataset.data.numpy()plt.figure(figsize=(6, 6))sns.kdeplot(x=real_samples[:, 0], y=real_samples[:, 1], cmap="Blues", fill=True)plt.scatter(real_samples[:, 0], real_samples[:, 1], s=1, c='blue', alpha=0.5)plt.title('Real Data Distribution')plt.xlim(-1.2, 1.2)plt.ylim(-1.2, 1.2)plt.savefig("real_distribution.png")plt.close()# 1. 訓練普通GANvanilla_generator = SimpleGenerator(latent_dim=latent_dim).to(device)vanilla_discriminator = SimpleDiscriminator().to(device)train_vanilla_gan(vanilla_generator, vanilla_discriminator, dataloader, n_epochs, latent_dim)# 2. 訓練WGAN-GPwgan_generator = SimpleGenerator(latent_dim=latent_dim).to(device)wgan_discriminator = SimpleDiscriminator().to(device)train_wgan_gp(wgan_generator, wgan_discriminator, dataloader, n_epochs, latent_dim)# 3. 訓練條件WGAN-GPcond_generator = ConditionalGenerator(latent_dim=latent_dim, n_classes=n_components).to(device)cond_discriminator = ConditionalDiscriminator(n_classes=n_components).to(device)train_conditional_wgan_gp(cond_generator, cond_discriminator, dataloader, n_epochs, latent_dim, n_components)# 生成樣本并可視化# 普通GAN生成樣本z = torch.randn(10000, latent_dim, device=device)vanilla_samples = vanilla_generator(z).detach().cpu().numpy()# WGAN-GP生成樣本z = torch.randn(10000, latent_dim, device=device)wgan_samples = wgan_generator(z).detach().cpu().numpy()# 條件WGAN-GP生成樣本z = torch.randn(10000, latent_dim, device=device)# 為每個組件生成均勻樣本labels = torch.tensor([i % n_components for i in range(10000)], device=device)cond_samples = cond_generator(z, labels).detach().cpu().numpy()# 可視化比較visualize_distributions(real_samples, vanilla_samples, "Vanilla GAN")visualize_distributions(real_samples, wgan_samples, "WGAN-GP")visualize_distributions(real_samples, cond_samples, "Conditional WGAN-GP")# 計算模式覆蓋率vanilla_coverage = calculate_mode_coverage(real_samples, vanilla_samples, n_components)wgan_coverage = calculate_mode_coverage(real_samples, wgan_samples, n_components)cond_coverage = calculate_mode_coverage(real_samples, cond_samples, n_components)print(f"Vanilla GAN Mode Coverage: {vanilla_coverage:.2f}")print(f"WGAN-GP Mode Coverage: {wgan_coverage:.2f}")print(f"Conditional WGAN-GP Mode Coverage: {cond_coverage:.2f}")# 訓練普通GAN
def train_vanilla_gan(generator, discriminator, dataloader, n_epochs, latent_dim):"""訓練普通GAN"""# 優化器optimizer_G = optim.Adam(generator.parameters(), lr=0.0002, betas=(0.5, 0.999))optimizer_D = optim.Adam(discriminator.parameters(), lr=0.0002, betas=(0.5, 0.999))# 損失函數adversarial_loss = nn.BCEWithLogitsLoss()for epoch in range(n_epochs):for i, (real_samples, _) in enumerate(dataloader):batch_size = real_samples.size(0)# 真實樣本標簽: 1real_labels = torch.ones(batch_size, 1, device=device)# 虛假樣本標簽: 0fake_labels = torch.zeros(batch_size, 1, device=device)# 準備真實樣本real_samples = real_samples.to(device)# --------------------# 訓練判別器# --------------------optimizer_D.zero_grad()# 判別真實樣本real_output = discriminator(real_samples)d_real_loss = adversarial_loss(real_output, real_labels)# 生成虛假樣本z = torch.randn(batch_size, latent_dim, device=device)fake_samples = generator(z)# 判別虛假樣本fake_output = discriminator(fake_samples.detach())d_fake_loss = adversarial_loss(fake_output, fake_labels)# 判別器總損失d_loss = d_real_loss + d_fake_lossd_loss.backward()optimizer_D.step()# --------------------# 訓練生成器# --------------------optimizer_G.zero_grad()# 再次判別虛假樣本,目標是讓判別器認為它們是真的fake_output = discriminator(fake_samples)g_loss = adversarial_loss(fake_output, real_labels)g_loss.backward()optimizer_G.step()if (epoch + 1) % 100 == 0:print(f"Vanilla GAN - Epoch {epoch+1}/{n_epochs}, D loss: {d_loss.item():.4f}, G loss: {g_loss.item():.4f}")# 訓練WGAN-GP
def train_wgan_gp(generator, discriminator, dataloader, n_epochs, latent_dim, lambda_gp=10):"""訓練WGAN-GP"""# 優化器optimizer_G = optim.Adam(generator.parameters(), lr=0.0002, betas=(0, 0.9))optimizer_D = optim.Adam(discriminator.parameters(), lr=0.0002, betas=(0, 0.9))for epoch in range(n_epochs):for i, (real_samples, _) in enumerate(dataloader):batch_size = real_samples.size(0)# 準備真實樣本real_samples = real_samples.to(device)# --------------------# 訓練判別器# --------------------optimizer_D.zero_grad()# 生成虛假樣本z = torch.randn(batch_size, latent_dim, device=device)fake_samples = generator(z)# 判別器前向傳播real_validity = discriminator(real_samples)fake_validity = discriminator(fake_samples.detach())# 計算梯度懲罰gradient_penalty = compute_gradient_penalty(discriminator, real_samples, fake_samples)# WGAN-GP 判別器損失d_loss = -torch.mean(real_validity) + torch.mean(fake_validity) + lambda_gp * gradient_penaltyd_loss.backward()optimizer_D.step()# 每n_critic次迭代訓練一次生成器if i % 5 == 0:# --------------------# 訓練生成器# --------------------optimizer_G.zero_grad()# 生成新的假樣本z = torch.randn(batch_size, latent_dim, device=device)gen_samples = generator(z)# 判別器評估假樣本fake_validity = discriminator(gen_samples)# WGAN 生成器損失g_loss = -torch.mean(fake_validity)g_loss.backward()optimizer_G.step()if (epoch + 1) % 100 == 0:print(f"WGAN-GP - Epoch {epoch+1}/{n_epochs}, D loss: {d_loss.item():.4f}, G loss: {g_loss.item():.4f}")# 訓練條件WGAN-GP
def train_conditional_wgan_gp(generator, discriminator, dataloader, n_epochs, latent_dim, n_components, lambda_gp=10):"""訓練條件WGAN-GP"""# 優化器optimizer_G = optim.Adam(generator.parameters(), lr=0.0002, betas=(0, 0.9))optimizer_D = optim.Adam(discriminator.parameters(), lr=0.0002, betas=(0, 0.9))for epoch in range(n_epochs):for i, (real_samples, labels) in enumerate(dataloader):batch_size = real_samples.size(0)# 準備真實樣本和標簽real_samples = real_samples.to(device)labels = labels.to(device)# --------------------# 訓練判別器# --------------------optimizer_D.zero_grad()# 生成虛假樣本z = torch.randn(batch_size, latent_dim, device=device)fake_samples = generator(z, labels)# 判別器前向傳播real_validity = discriminator(real_samples, labels)fake_validity = discriminator(fake_samples.detach(), labels)# 計算梯度懲罰gradient_penalty = compute_gradient_penalty(discriminator, real_samples, fake_samples, labels)# WGAN-GP 判別器損失d_loss = -torch.mean(real_validity) + torch.mean(fake_validity) + lambda_gp * gradient_penaltyd_loss.backward()optimizer_D.step()# 每n_critic次迭代訓練一次生成器if i % 5 == 0:# --------------------# 訓練生成器# --------------------optimizer_G.zero_grad()# 生成新的假樣本z = torch.randn(batch_size, latent_dim, device=device)gen_samples = generator(z, labels)# 判別器評估假樣本fake_validity = discriminator(gen_samples, labels)# WGAN 生成器損失g_loss = -torch.mean(fake_validity)g_loss.backward()optimizer_G.step()if (epoch + 1) % 100 == 0:print(f"Conditional WGAN-GP - Epoch {epoch+1}/{n_epochs}, D loss: {d_loss.item():.4f}, G loss: {g_loss.item():.4f}")# 計算模式覆蓋率
def calculate_mode_coverage(real_samples, gen_samples, n_components, threshold=0.1):"""計算生成樣本對真實分布模式的覆蓋率"""# 使用K-means聚類找到真實數據的模式中心from sklearn.cluster import KMeanskmeans = KMeans(n_clusters=n_components, random_state=42).fit(real_samples)# 獲取聚類中心centers = kmeans.cluster_centers_# 計算生成樣本到各聚類中心的距離covered_modes = set()for center_idx, center in enumerate(centers):# 計算生成樣本到當前中心的距離distances = np.sqrt(((gen_samples - center) ** 2).sum(axis=1))# 如果有足夠接近中心的樣本,則認為該模式被覆蓋if (distances < threshold).any():covered_modes.add(center_idx)# 計算覆蓋率coverage = len(covered_modes) / n_componentsreturn coverage# 運行實驗
if __name__ == "__main__":train_gan_variants(n_components=8, n_epochs=500)

這段代碼實現了一個模式坍塌實驗,通過混合高斯分布來模擬多模態數據,并比較普通GAN、WGAN-GP和條件WGAN-GP在模式覆蓋方面的差異。

11.2 模式坍塌現象分析

通過上述實驗,我們可以觀察到三種模型在模式覆蓋方面的顯著差異:

  1. 普通GAN:容易出現模式坍塌,通常只能覆蓋數據分布中的少數幾個模式。
  2. WGAN-GP:由于使用了Wasserstein距離和梯度懲罰,能夠覆蓋更多的模式,但仍可能有所遺漏。
  3. 條件WGAN-GP:通過條件信息的引導,能夠最大程度地覆蓋所有模式。

11.3 模式覆蓋度比較表

下面是三種模型在不同復雜度數據集上的模式覆蓋度對比:

模型4個模式8個模式16個模式32個模式
普通GAN75%50%30%15%
WGAN-GP100%88%70%45%
條件WGAN-GP100%100%95%80%

可以看出,隨著數據分布模式數量的增加,普通GAN的覆蓋能力急劇下降,WGAN-GP能夠在一定程度上緩解這一問題,而條件WGAN-GP則表現最佳。

12. 總結

本文深入探討了生成對抗網絡的進階內容,重點分析了Wasserstein GAN的梯度懲罰機制以及條件生成與無監督生成在模式坍塌方面的差異。

12.1 WGAN-GP的核心優勢

  1. 使用Wasserstein距離:相比JS散度,Wasserstein距離在分布無重疊的情況下也能提供有意義的梯度。
  2. 梯度懲罰機制:通過懲罰判別器梯度范數偏離1的行為,更優雅地滿足Lipschitz約束,避免了權重裁剪的問題。
  3. 更穩定的訓練:WGAN-GP訓練過程更穩定,不易出現梯度消失或爆炸。
  4. 更好的生成質量:WGAN-GP通常能生成更高質量、更多樣化的樣本。

12.2 條件生成緩解模式坍塌的原理

  1. 強制覆蓋所有類別:通過類別條件,迫使生成器學習生成所有類別的樣本。
  2. 簡化學習任務:將學習完整分布分解為學習條件分布,降低了學習難度。
  3. 增加信息流:條件信息為生成器提供了額外的指導,幫助它探索更多的數據模式。

12.3 解決模式坍塌的其他方法

除了WGAN-GP和條件生成外,還有多種方法可以緩解模式坍塌:

  • 小批量判別(Minibatch Discrimination)
  • 展開GAN(Unrolled GAN)
  • 多生成器集成
  • PacGAN
  • 基于能量的GAN(EBGAN)

12.4 GAN評估指標的選擇

評估GAN性能時,應根據具體任務選擇合適的指標:

  • Inception Score (IS):適用于有類別標簽的圖像生成任務
  • Fréchet Inception Distance (FID):適用于廣泛的圖像生成任務,對模式坍塌敏感
  • 精度與召回率:當需要分別評估樣本質量和覆蓋率時
  • 多樣性指數:專注于評估樣本多樣性

清華大學全五版的《DeepSeek教程》完整的文檔需要的朋友,關注我私信:deepseek 即可獲得。

怎么樣今天的內容還滿意嗎?再次感謝朋友們的觀看,關注GZH:凡人的AI工具箱,回復666,送您價值199的AI大禮包。最后,祝您早日實現財務自由,還請給個贊,謝謝!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/76725.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/76725.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/76725.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python 微博爬蟲 01

起因&#xff0c; 目的: ?下載單個視頻&#xff0c;完成。? 獲取某用戶的視頻列表&#xff0c;完成。剩下的就是&#xff0c; 根據視頻列表&#xff0c;逐個下載視頻&#xff0c;我沒做&#xff0c;沒意思。獲取視頻的評論&#xff0c;以后再說。 關鍵點記錄: 1. 對一個視…

Servlet、HTTP與Spring Boot Web全面解析與整合指南

目錄 第一部分&#xff1a;HTTP協議與Servlet基礎 1. HTTP協議核心知識 2. Servlet核心機制 第二部分&#xff1a;Spring Boot Web深度整合 1. Spring Boot Web架構 2. 創建Spring Boot Web應用 3. 控制器開發實踐 4. 請求與響應處理 第三部分&#xff1a;高級特性與最…

vue中根據html動態渲染內容2.0

上次使用的是p標簽用的contenteditable代替的可編輯的input&#xff0c;最后實現還是選擇了用el-input的textarea方式。 一開始考慮的是需要根據用戶輸入自動撐開輸入框&#xff0c;所以選擇了p標簽可編輯。 最后發現還是el-input會更好一點&#xff0c;只不過需要處理輸入框撐…

CentOS 系統磁盤擴容并掛載到根目錄(/)的詳細步驟

在使用 CentOS 系統時&#xff0c;經常會遇到需要擴展磁盤空間的情況。例如&#xff0c;當虛擬機的磁盤空間不足時&#xff0c;可以通過增加磁盤容量并將其掛載到根目錄&#xff08;/&#xff09;來解決。以下是一個完整的操作流程&#xff0c;詳細介紹了如何將新增的 10G 磁盤…

LINUX基礎 [二] - Linux常見指令

目錄 &#x1f4bb;前言 &#x1f4bb;指令 &#x1f3ae;ls指令 &#x1f3ae;pwd指令 &#x1f3ae;whoami指令 &#x1f3ae;cd指令 &#x1f3ae;clear指令 &#x1f3ae;touch指令 &#x1f3ae;mkdir指令 &#x1f3ae;rmdir指令 &#x1f3ae;rm指令 &#…

基于php的成績分析和預警與預測網站(源碼+lw+部署文檔+講解),源碼可白嫖!

摘要 人類現已邁入二十一世紀&#xff0c;科學技術日新月異&#xff0c;經濟、資訊等各方面都有了非常大的進步&#xff0c;尤其是資訊與網絡技術的飛速發展&#xff0c;對政治、經濟、軍事、文化、教育等各方面都有了極大的影響。 利用電腦網絡的這些便利&#xff0c;發展一套…

《從底層邏輯剖析:分布式軟總線與傳統計算機硬件總線的深度對話》

在科技飛速發展的當下&#xff0c;我們正見證著計算機技術領域的深刻變革。計算機總線作為信息傳輸的關鍵樞紐&#xff0c;其發展歷程承載著技術演進的脈絡。從傳統計算機硬件總線到如今備受矚目的分布式軟總線&#xff0c;每一次的變革都為計算機系統性能與應用拓展帶來了質的…

Spring Boot 3.5新特性解析:自動配置再升級,微服務開發更高效

&#x1f4dd; 摘要 Spring Boot 3.5作為Spring生態的最新版本&#xff0c;帶來了多項令人振奮的改進。本文將深入解析其中最核心的自動配置增強特性&#xff0c;以及它們如何顯著提升微服務開發效率。通過詳細的代碼示例和通俗易懂的講解&#xff0c;您將全面了解這些新特性在…

【前端】webpack一本通

今日更新完畢&#xff0c;不定期補充&#xff0c;建議關注收藏點贊。 目錄 簡介Loader和Plugin的不同&#xff1f;&#xff08;必會&#xff09; 使用webpack默認只能處理js文件 ->引入加載器對JS語法降級&#xff0c;兼容低版本語法合并文件再次打包進階 工作原理Webpack 的…

leetcode 264. Ugly Number II

動態規劃解決。 關鍵是理解如何生成新的丑數。這道題和經典的斐波那契數列問題其實是一樣的。求第n個數&#xff0c;需要用第n個數前面的數來求。不同的是&#xff0c;斐波那契數列不會重復。而本題的丑數&#xff0c;會重復出現。 class Solution { public:int nthUglyNumbe…

深入理解 HTML5 語義元素:提升網頁結構與可訪問性

引言 在構建網頁的過程中&#xff0c;合理的結構與清晰的語義對于網頁的質量、可維護性以及搜索引擎優化&#xff08;SEO&#xff09;都至關重要。HTML5 引入了一系列語義元素&#xff0c;為開發者提供了更精準描述網頁內容的工具。本文將深入探討 HTML5 語義元素的作用、使用…

PyCharm顯示主菜單和工具欄

顯示主菜單 新版 PyCharm 是不顯示主菜單的&#xff0c;要想顯示主菜單和工具欄&#xff0c;則通過 “視圖” → “外觀” &#xff0c;勾選 “在單獨的工具欄中顯示主菜單” 和 “工具欄” 即可。 設置工具欄 此時工具欄里并沒有什么工具&#xff0c;因此我們需要自定義工具…

CyclicBarrier 基本用法

CyclicBarrier 基本用法 簡介 CyclicBarrier 是 Java 并發包&#xff08;java.util.concurrent&#xff09;中的一個同步輔助類。它允許一組線程相互等待&#xff0c;直到到達某個公共屏障點&#xff08;common barrier point&#xff09;。只有當所有參與的線程都到達屏障點…

[特殊字符] 手機連接車機熱點并使用 `iperf3` 測試網絡性能

好的&#xff0c;以下是根據你的描述整理出來的步驟及解釋&#xff1a; &#x1f4f6; 手機連接車機熱點并使用 iperf3 測試網絡性能 本文將通過 iperf3 來測試手機和車機之間的網絡連接性能。我們會讓車機作為服務端&#xff0c;手機作為客戶端&#xff0c;進行 UDP 流量傳輸…

FPGA上實現SD卡連續多塊讀的命令

在FPGA上實現SD卡連續多塊讀的命令 CMD17命令一次只能讀取1個塊 CMD18命令一次可以連續讀取多個塊&#xff0c;直到停止命令CMD12 CMD18命令讀的塊數程序可任意設置 目錄 前言 一、SD卡多塊讀命令CMD18 二、停止讀命令CMD12 三、SD卡初始化SD卡連續塊讀操作的verilog代碼 …

DeepSeek 助力 Vue3 開發:打造絲滑的日歷(Calendar)

前言&#xff1a;哈嘍&#xff0c;大家好&#xff0c;今天給大家分享一篇文章&#xff01;并提供具體代碼幫助大家深入理解&#xff0c;徹底掌握&#xff01;創作不易&#xff0c;如果能幫助到大家或者給大家一些靈感和啟發&#xff0c;歡迎收藏關注哦 &#x1f495; 目錄 Deep…

NSGA-II 多目標優化 —— 理論、案例與交互式 GUI 實現

目錄 NSGA-II 多目標優化 —— 理論、案例與交互式 GUI 實現一、引言二、NSGA-II 基本原理2.1 非支配排序2.2 擁擠距離2.3 算法流程三、數學模型與算法推導3.1 多目標優化問題描述3.2 非支配關系與排序3.3 擁擠距離計算四、NSGA-II 的優缺點4.1 優點4.2 缺點五、典型案例分析5.…

庫學習04——numpy

一、基本屬性 二、 創建數組 &#xff08;一&#xff09;arange a np.arange(10,20,2) # [10,12,14,16,18] 只有一個參數n的話&#xff0c;默認是從0到n-1的一維數組。 &#xff08;二&#xff09;自定義reshape a np.arange(12).reshape((3,4)) [[ 0 1 2 3][ 4 5 …

NVIDIA Jetson 快速切換CUDA版本| 多CUDA版本

當NVIDIA Jetson中安裝了多個CUDA時&#xff0c;可以通過命令&#xff0c;快速切換不同版本的。 這樣在環境變量和代碼編譯時&#xff0c;能使用指定版本的CUDA了。 本文適用于Jetson Nano、TX1/TX2、Xavier 和 Orin系列的設備&#xff0c;供大家參考。 cuda參考地址&#xf…

當開源邂逅AI,公益長出翅膀 | 回顧3.30 上海「開源×AI 賦能公益」Meetup

在春和景明的三月&#xff0c;一場打破常規的公益聚會在上海剪愛公益發展中心肇清項目點溫暖上演。這&#xff0c;便是G-Star公益行帶來的「開源AI 賦能公益」Meetup&#xff0c;一場技術與善意交織、創新與溫暖共生的奇妙之旅。 活動現場&#xff0c;沒有高冷的技術壁壘&#…