- 生成式人工智能(基于PyTorch實現)
- (美)劉煥良
- 2252字
- 2025-06-19 18:35:03
2.2 使用PyTorch完成端到端深度學習項目
在接下來的幾節中,我們將使用PyTorch完成一個示范性的深度學習項目,將服裝的灰度圖像分類到10種類別中的1種。
本節將先對涉及的步驟進行高層次概述,然后討論如何獲取該項目的訓練數據,以及如何對數據進行預處理。
2.2.1 PyTorch深度學習:高層次概述
在本項目中,我們的任務是在PyTorch中創建并訓練一個深度神經網絡,對服裝的灰度圖像進行分類。圖2.1概括描述了涉及的相關步驟。
首先,我們需要準備一個服裝灰度圖像數據集,如圖2.1左側所示。圖像均為原始像素形式,我們會把它們轉換成浮點數形式的PyTorch張量(步驟1)。每張圖像都帶有一個標簽。

圖2.1 深度學習模型訓練步驟
然后,我們在PyTorch中創建一個深度神經網絡,如圖2.1中心區域所示。本書中的一些神經網絡涉及卷積神經網絡(CNN)。對于這個簡單的分類問題,我們暫時只使用密集(dense)層。
我們將為多類別分類選擇一個損失函數,此類任務通常使用交叉熵損失(cross-entropy loss)。交叉熵損失衡量標簽的預測概率分布與標簽的真實分布之間的差異,訓練過程將使用Adam優化器(梯度下降算法的一種變體)來更新網絡權重。我們將學習率設置為0.001。學習率控制了模型權重在訓練過程中相較于損失梯度的調整程度。
機器學習所使用的優化器
機器學習所使用的優化器是一種能根據梯度信息更新模型參數以最小化損失函數的算法。隨機梯度下降(stochastic gradient descent,SGD)是最基本的優化器,它可以基于損失梯度進行直接更新。Adam也是一種流行的優化器,它結合了自適應梯度算法(adaptive gradient algorithm,AdaGrad)和均方根傳播(root mean square propagation,RMSProp)的優點,以高效和開箱即用的性能而著稱。盡管存在差異,但所有優化器的目標都是迭代調整參數,以最小化損失函數,每個優化器都會通過獨特的優化方式實現這一目標。
我們將訓練數據分為訓練集和驗證集。在機器學習中,通常使用驗證集對模型進行無偏評估,并選擇最佳超參數,如學習率、訓練的輪次(epoch)等。驗證集還可用于避免模型過擬合,也就是避免模型在訓練集上表現良好,但在未見過的數據上表現不佳。一個輪次是指使用所有訓練數據訓練模型一次且只訓練一次。
在訓練過程中,會遍歷訓練數據。在前向傳遞過程中,會將圖像輸入網絡以獲得預測(步驟2),并通過比較預測標簽和實際標簽來計算損失(步驟3;見圖2.1右側)。然后通過網絡反向傳播梯度來更新權重,這才是真正的學習過程(步驟4),如圖2.1底部所示。
我們使用驗證集來確定何時停止訓練。為此需要計算驗證集的損失。如果模型在固定數量的輪次后不再繼續改進,即可認為模型已經訓練好了。隨后用測試集評估訓練好的模型,以評估模型將圖像分類為不同標簽時的性能。
至此,讀者已經對PyTorch中深度學習的工作原理有了一個整體了解,讓我們深入探索端到端的項目吧!
2.2.2 數據預處理
本項目將使用Fashion MNIST數據集。在此過程中,我們將學習如何使用Torchvision庫中的datasets和transforms包,以及PyTorch中的Dataloader包,本書的后續內容也將用到它們,我們會用這些工具來預處理數據。Torchvision庫為深度學習應用提供了圖像處理工具,包括流行的數據集、模型架構和常見的圖像轉換。
我們先導入所需的庫,并實例化transforms包中的Compose()類,從而將原始圖像轉換為PyTorch張量,代碼如清單2.2所示。
清單2.2 將原始圖像數據轉換為PyTorch張量
import torch import torch.nn as nn import torchvision import torchvision.transforms as T torch.manual_seed(42) transform=T.Compose([ ? T.ToTensor(), ? T.Normalize([0.5],[0.5])]) ?
? #將多個轉換操作組合在一起
? #將圖像像素轉換為PyTorch張量
? #將值歸一化到[-1, 1]
我們使用PyTorch中的manual_seed()方法來固定隨機狀態,從而使結果可復現。Torchvision中的transforms包可以幫助我們創建一系列預處理圖像所需的“轉換”。ToTensor()類可將圖像數據(PIL圖像格式或NumPy數組)轉換為PyTorch張量。具體來說,圖像數據是0~255的整數,ToTensor()類可將它們轉換為0.0~1.0的浮點張量。
Normalize()類用n個通道的均值和標準差對張量圖像進行歸一化(normalize)。Fashion MNIST數據是服裝的灰度圖像,因此只有一個顏色通道。在本書的后續部分,我們將處理包含3個顏色通道(紅、綠、藍,即R、G、B)的圖像。在清單2.2中,Normalize([0.5],[0.5])表示從數據中減去0.5,然后將差值除以0.5。這樣得到的圖像數據范圍為-1~1。將輸入數據歸一化到[-1, 1],可以讓梯度下降法在不同維度上維持更一致的步長,從而更高效地運行,這有助于在訓練過程中更快地收斂。在本書中我們會經常這樣做。
注意
清單2.2中的代碼僅定義了數據轉換過程,并未執行實際轉換。實際轉換將在下一個代碼示例中進行。
接下來,需要使用Torchvision中的datasets軟件包將數據集下載到計算機上的一個文件夾中,然后執行轉換:
train_set=torchvision.datasets.FashionMNIST( ? root=".", ? train=True, ? download=True, ? transform=transform) ? test_set=torchvision.datasets.FashionMNIST(root=".", train=False,download=True,transform=transform)
? #指定要下載的數據集
? #指定數據的保存位置
? #設置為訓練數據集或測試數據集
? #判斷是否將數據下載到計算機上
? #執行數據轉換操作
我們可以輸出訓練集中的第一個樣本:
print(train_set[0])
第一個樣本由一個包含784個值和一個標簽“9”的張量組成。這784個值代表了28像素×28像素灰度圖像,標簽9表示圖像內容是“ankle boot”(踝靴)。讀者可能會想:該怎么知道標簽9代表踝靴呢?有10種不同類別的服裝,它們在數據集中的標簽編號從0到9(可在本書的GitHub上查找“Fashion-MNIST-PyTorch”)。下面的text_labels列表包含與數字標簽0~9對應的10個文本標簽。例如,數據集中某一項的數字標簽為0,則對應的文本標簽為“t-shirt”(T恤)。列表text_labels的定義如下:
text_labels=['t-shirt', 'trouser', 'pullover', 'dress', 'coat', 'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
我們可以繪制數據,以可視化的方式查看數據集中的服裝,代碼如清單2.3所示。
清單2.3 服裝可視化
!pip install matplotlib import matplotlib.pyplot as plt plt.figure(dpi=300,figsize=(8,4)) for i in range(24): ax=plt.subplot(3, 8, i + 1) ? img=train_set[i][0] ? img=img/2+0.5 ? img=img.reshape(28, 28) ? plt.imshow(img, cmap="binary") plt.axis('off') plt.title(text_labels[train_set[i][1]], ? fontsize=8) plt.show()
? #設置圖像的保存位置
? #獲取訓練數據集中的第i張圖像
? #將值從[-1,1]轉換到[0,1]
? #將圖像形狀調整為28像素×28像素
? #為每張圖像添加文本標簽
圖2.2顯示了外套、套頭衫、涼鞋等24種服裝。

圖2.2 Fashion MNIST數據集中服裝的灰度圖像
接下來的兩節將介紹如何使用PyTorch創建深度神經網絡,進而執行二分類和多類別分類。