43這周打卡——生成手勢圖像 (可控制生成)

目錄

前言

1.導入數據及數據可視化

2.構建模型

3.訓練模型

4.模型分析并生成指定圖像

總結


前言

  • ???🍨?本文為🔗365天深度學習訓練營中的學習記錄博客
  • 🍖?原作者:K同學啊

1.導入數據及數據可視化

from torchvision       import datasets, transforms
from torch.autograd    import Variable
from torchvision.utils import save_image, make_grid
from torchsummary      import summary
import matplotlib.pyplot as plt
import numpy             as np
import torch.nn          as nn
import torch.optim       as optim
import torchdevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
devicebatch_size = 128train_transform = transforms.Compose([transforms.Resize(128),transforms.ToTensor(),transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5])])train_dataset = datasets.ImageFolder(root='data/data/rps/', transform=train_transform)train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True,num_workers=6)# 可視化第一個 batch 的數據
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)


2.構建模型

latent_dim    = 100
n_classes     = 3
embedding_dim = 100# 自定義權重初始化函數,用于初始化生成器和判別器的權重
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 image
generator = Generator().to(device)
generator.apply(weights_init)
print(generator)from torchinfo import summarysummary(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 outputdiscriminator = Discriminator().to(device)
discriminator.apply(weights_init)
print(discriminator)summary(discriminator)a = torch.ones(2,3,128,128)
b = torch.ones(2,1)
b = b.long()
a = a.to(device)
b = b.to(device)c = discriminator((a,b))
c.size()


3.訓練模型

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_losslearning_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))# 設置訓練的總輪數
num_epochs = 300
# 初始化用于存儲每輪訓練中判別器和生成器損失的列表
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.item())# 反向傳播更新判別器的參數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.item())# 反向傳播更新生成器的參數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))

4.模型分析并生成指定圖像

G_loss_list = [i.item() for i in G_loss_plot]
D_loss_list = [i.item() for i in D_loss_plot]import matplotlib.pyplot as plt
#隱藏警告
import warnings
warnings.filterwarnings("ignore")               #忽略警告信息
plt.rcParams['font.sans-serif']    = ['SimHei'] # 用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus'] = False      # 用來正常顯示負號
plt.rcParams['figure.dpi']         = 100        #分辨率plt.figure(figsize=(8,4))
plt.title("Generator and Discriminator Loss During Training")
plt.plot(G_loss_list,label="G")
plt.plot(D_loss_list,label="D")
plt.xlabel("iterations")
plt.ylabel("Loss")
plt.legend()
plt.show()# 導入所需的庫
from numpy.random import randint, randn
from numpy        import linspace
from matplotlib   import pyplot, gridspec# 導入生成器模型
generator.load_state_dict(torch.load('./training_weights/generator_epoch_300.pth'), strict=False)
generator.eval()   interpolated = randn(100)  # 生成兩個潛在空間的點
# 將數據轉換為torch張量并將其移至GPU(假設device已正確聲明為GPU)
interpolated = torch.tensor(interpolated).to(device).type(torch.float32)label  = 0  # 手勢標簽,可在0,1,2之間選擇
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']         = 100        #分辨率plt.figure(figsize=(8, 3))pred = (predictions[0, :, :, :] + 1 ) * 127.5
pred = np.array(pred)
plt.imshow(pred.astype(np.uint8))
plt.show()


總結

在本次實驗中,我們完成了數據準備、模型構建、訓練與結果分析的完整流程。

數據準備方面,采用 torchvision.datasets.ImageFolder 從自定義文件夾中加載圖像數據,并依次進行縮放、張量化和歸一化等預處理操作。為了直觀了解輸入情況,利用 show_images 函數展示了訓練集中首個批次的圖像,這有助于確認數據管道是否正常。

模型設計部分包括生成器和判別器兩個核心模塊。生成器接收潛在向量與類別標簽作為輸入,其中類別標簽先經過嵌入層映射為特征向量,再與潛在向量結合,經由多層反卷積逐步生成目標圖像。判別器則接收圖像和類別標簽作為輸入,將標簽轉化為特征圖并與圖像拼接,隨后通過多層卷積進行特征提取,最終輸出一個標量用于判別真偽。此外,使用自定義的 weights_init 方法對模型參數進行初始化,保證了訓練的穩定性。

訓練過程中,損失函數選擇了二元交叉熵(BCELoss),優化器采用 Adam,對生成器與判別器分別進行參數更新。具體流程為:在每個 epoch 內,判別器和生成器交替更新;對于每個 batch,先更新判別器,使其更好地區分真實與偽造圖像,再更新生成器,使其生成的結果更具迷惑性。訓練過程中,每隔 10 個 epoch 保存生成樣本和模型權重,方便后續分析與復現。

結果分析環節,通過記錄生成器和判別器的損失曲線,可以直觀反映訓練進展和收斂趨勢。隨著對抗博弈的進行,生成器不斷提高欺騙判別器的能力,而判別器也在努力提升辨別水平,二者的競爭推動了模型整體性能的提升。

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

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

相關文章

TDengine 時間函數 TIMEDIFF() 用戶手冊

TDengine TIMEDIFF() 函數詳細使用手冊 目錄 功能概述函數語法參數說明返回值說明版本變更說明技術特性使用場景及示例時間單位處理數據類型兼容性注意事項常見問題最佳實踐 功能概述 TIMEDIFF() 函數用于計算兩個時間戳的差值,返回 expr1 - expr2 的結果。結果…

【2025ICCV-持續學習方向】一種用于提示持續學習(Prompt-based Continual Learning, PCL)的新方法

1. 背景與問題 (Background & Problem):?? ?持續學習 (CL):?? 目標是在不遺忘舊任務知識的情況下,讓模型持續學習一系列新任務。主要挑戰是災難性遺忘。 ?基于提示的持續學習 (PCL):?? 利用預訓練視覺Transformer (ViT),凍結其權重,通過微調稱為“提示”(prompt…

2025 年 08 月 GitHub 十大熱門項目排行榜

歡迎來到 2025 年 8 月 GitHub 熱門開源項目排行榜!本月榜單集中展示了來自智能體平臺、AI 編程助手、多模態角色系統、本地化部署工具到可視化白板與企業協同平臺的多元創新。從構建 AI 助手中樞的 Archon,到終端 AI 編碼拍檔 Crush,再到虛擬…

LeetCode每日一題,2025-9-4

多數元素 投票法 讓你找到序列中出現超過二分之一的元素,一定要記住這個規則。 記錄兩個值val和cnt,剛開始val為任意數,cnt0。 如果cnt是0,就把當前val num。接下來判斷,ifnum val,則cnt ,e…

第7章 安全配置

7.1 安全概述 Jenkins安全威脅 常見安全風險: 訪問控制風險: - 未授權訪問Jenkins實例 - 權限提升攻擊 - 橫向移動攻擊 - 敏感信息泄露代碼執行風險: - 惡意腳本注入 - 構建腳本篡改 - 插件漏洞利用 - 遠程代碼執行數據安全風險: …

騰訊混元世界模型Voyager開源:單圖生成3D世界的“核彈級”突破,游戲、VR、自動駕駛迎來新變量

當AI繪畫、視頻生成技術逐漸從“新鮮感”走向“實用化”,3D內容生成卻始終卡在“效率低、成本高、門檻高”的瓶頸里。傳統3D建模需要專業軟件、大量人工調整,甚至依賴昂貴的硬件設備,讓中小團隊和個人創作者望而卻步。 但騰訊AI實驗室最近開…

數據庫(基礎操作)

SQL 結構化的查詢語句 我們現在需要寫SQL語句 --- 這個玩意兒就是數據庫的操作語句我們的數據庫就類似于一個excl表格它有n列,每一列為一個大類,數據以行存在,一行代表一個條目數據如:我現在想建立一個數據庫保存學生的信息你需要…

linux ubi文件系統

1,UBI(Unsorted Block Images)是 Linux 內核中為原始 Flash 設備提供的一種抽象層,位于 MTD(Memory Technology Device)和文件系統(如 UBIFS)之間。它負責壞塊管理、磨損均衡、邏輯卷…

深度厚金板PCB與厚銅PCB的區別

厚金板PCB和厚銅PCB在電子制造領域都有重要應用,它們有著不同的特點和適用場景。下面為你詳細介紹二者的區別。厚金PCB是什么厚金PCB是在印制電路板表面鍍上較厚金層的電路板。這層厚金能提升電路板的導電性、抗氧化性和耐磨性。在一些對信號傳輸要求極高、使用環境…

一階低通濾波器應用示例(演示)

1. 代碼 這段代碼實現了一個一階低通濾波器(也稱為指數加權移動平均濾波器)。它適用于需要平滑數據、減少噪聲的場合。以下是一些常見的應用場景: 傳感器數據平滑:在嵌入式系統或物聯網設備中,傳感器(如溫度…

RT-Thread源碼分析字節實現socket源碼

無論是客戶端還是服務器程序,發送的底層都是發送AT指令:1)發送命令到串口;2)阻塞等待返回結果接收的底層都是1)阻塞等待;2)被喚醒后拷貝處理數據兩者均由后臺任務喚醒,后…

keil 5 STM32工程介紹

目錄 一、工程文件介紹 1.自動生成的文件 2.自建文件 (1)USER 文件夾 (2)FWLIB 文件夾 (3)CMSIS 文件夾 二、工程創建教程 1.下載固件庫 2.創建工程 (1)創建不完善的工程 …

AI大模型如何重塑日常?從智能辦公到生活服務的5個核心改變

AI大模型重塑日常:從智能辦公到生活服務的5個核心改變一、引言? 簡述AI大模型技術的快速發展背景,說明其已從技術領域逐步滲透到大眾日常生活? 提出核心觀點:AI大模型正從辦公和生活服務兩大場景,深度改變人們的行為模式與…

邁威通信從送快遞角度教你分清網絡二層和三層

還在為網絡里的二層、三層概念頭大?其實就像送快遞那么簡單!今天邁威通信用最接地氣的方式給你講明白~網絡傳輸 送快遞?沒錯!二層網絡:本地送貨員負責同小區的包裹配送(局域網傳輸),就像小區里的快遞站(對應設備:交換機)&#…

【Linux】網絡安全管理:SELinux 和 防火墻聯合使用 | Redhat

本專欄文章持續更新,新增內容使用藍色表示。 往期相關內容 【Linux】權限管理詳解(三):SELinux安全性管理 | Redhat-CSDN博客 【Linux】網絡安全管理:Netfilter、nftables 與 Firewalld | Redhat_linux netfilter-C…

微論-構建完整的智能環:具身智能系統的層級化架構探析

### **構建完整的智能環:具身智能系統的層級化架構探析**#### **引言:邁向與現實交互的智能**人工智能的發展正經歷一場從“虛擬”走向“現實”的范式遷移。具身智能,作為這一浪潮的核心,強調智能體必須擁有“身體”,并…

Spring如何解決循環依賴:深入理解三級緩存機制

Spring如何解決循環依賴:深入理解三級緩存機制 引言 在我們之前的文章中,我們探討了什么是循環依賴以及它帶來的問題。作為Java生態系統中最重要的框架之一,Spring Framework在處理循環依賴方面有著獨特而精妙的解決方案。今天,讓…

HTML第六課:表格展示

HTML第六課&#xff1a;表格展示學生花名冊學生花名冊 效果示列 代碼展示 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang"zh-CN"> <head><meta …

醫療行業API管理優化:使用QuickAPI提高數據安全與接口性能

背景與挑戰在醫療行業&#xff0c;特別是醫院信息系統&#xff08;HIS&#xff09;或其他相關部門&#xff08;如實驗室信息系統LIS、藥品管理系統等&#xff09;&#xff0c;數據安全和隱私保護一直是核心問題。然而&#xff0c;許多醫療機構仍然面臨著以下問題&#xff1a;數…

docker 部署RustDesk服務

最近要用到遠程桌面服務&#xff0c;網上的資料很豐富&#xff0c;但是和我的情況有點點區別&#xff0c;我是要搭一臺局域網使用的遠程桌面服務。 首先是源的問題&#xff1a; 很多都是不能用的&#xff0c;我用的docker桌面版&#xff0c; 其他的不重要&#xff0c;源地址&…