零基礎學習人工智慧—Python—Pytorch學習(七)

kiba518發表於2024-08-22

前言

本文主要講神經網路的下半部分。
其實就是結合之前學習的全部內容,進行一次神經網路的訓練。

神經網路

下面是使用MNIST資料集進行的手寫數字識別的神經網路訓練和使用。
MNIST 資料集,是一個常用的手寫數字識別資料集。MNIST 資料集包含 60,000 張 28x28 畫素的灰度訓練影像和 10,000 張測試影像,每張影像都表示一個手寫的數字(0-9)。

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
# device config
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# hyper parameters
input_size = 784  # 28x28
hidden_size = 100
num_classes = 10 
batch_size = 100
learning_rate = 0.001


# MNIST
# torchvision.datasets.MNIST: 這是一個用於載入MNIST資料集的類。 MNIST 資料集,它包含灰度的手寫數字影像。每張影像的尺寸是 28x28 畫素,灰度影像只有一個通道(channels=1)
# root='./data': root 引數指定了資料集的儲存位置 './data' 表示一個相對路徑,表示資料集將儲存在當前工作目錄下的 data 資料夾中。如果這個資料夾不存在,PyTorch 會自動建立它。
# train=True: 表示載入的是訓練集資料。
# transform=transforms.ToTensor(): 將影像轉換為PyTorch張量,並歸一化為[0, 1]的範圍。
# download=True: 如果指定的 root 路徑下沒有找到資料集,會自動從網際網路下載MNIST資料集。
train_dataset = torchvision.datasets.MNIST(
    root='./data', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = torchvision.datasets.MNIST(
    root='./data', train=False, transform=transforms.ToTensor())
# torchvision.datasets.MNIST 是內建的資料集,所以不用去像之前內容中,要搞一個csv檔案
# 這裡直接把MNIST匯入進DataLoader
# batch_size 指定了一次輸入模型的資料量。指定batch_size為100,那就是一批次讀取100個,利用資料集的索引就可以讀取,因為下面還有個引數shuffle=True,所以讀取的時候,資料是被打亂的。
train_loader = torch.utils. data.DataLoader(
    dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(
    dataset=test_dataset, batch_size=batch_size, shuffle=False)
print('每份100個,被分成多了份',len(train_loader))

examples = iter(train_loader)  # 轉換為迭代器,這樣可以呼叫next,一行一行的取資料,只不過他這一行,是一組資料
samples, labels = examples.__next__()  # 這裡取出 x和y
print(samples.shape, labels.shape) # samples即x,是一個批次,即100個影像
# 這裡輸出的是torch.Size([100, 1, 28, 28]) torch.Size([100])
# 其中x是的資料維度是下面這樣的。
# 第一個維度 (64): 表示批次中包含的樣本數量,即 batch_size。在這個例子中,一次輸入模型的有 100 張影像。
# 第二個維度 (1): 表示影像的通道數。對於灰度影像,通道數是 1,彩色影像則通常有 3 個通道(對應 RGB)。
# 第三個維度 (28): 表示影像的高度。MNIST 影像的高度為 28 畫素。
# 第四個維度 (28): 表示影像的寬度。MNIST 影像的寬度也是 28 畫素。
# y只有一個維度,就是100張影像

# x裡都資料都是手寫的數字,這裡可以用影像把他們展示出來看一看
for i in range(6):
    plt.subplot(2, 3, i+1)  # 在影像視窗中建立一個 2 行 3 列的子圖佈局,並選擇第 i+1 個子圖位置。
    plt.imshow(samples[i][0], cmap='gray')
    # plt.show()


class NeuralNet(nn.Module):
    def __init__(self, input_size, hidden_size, num_classes):
        super(NeuralNet, self).__init__()
        self.linear1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        self.linear2 = nn.Linear(hidden_size, num_classes)

    def forward(self, x):
        out = self.linear1(x)
        out = self.relu(out)
        out = self.linear2(out)
        # no softmax at the end
        return out


model = NeuralNet(input_size=input_size,
                  hidden_size=hidden_size, num_classes=num_classes)
criterion = nn.CrossEntropyLoss()  # (applies Softmax) 這裡會呼叫啟用函式,所以上面不呼叫啟用函式了

optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# training loop
n_total_steps = len(train_loader)
num_epochs = 2 
#下面這個迴圈就走2次,意思是在訓練完集合裡的全部資料後,在重新來一遍
for epoch in range(num_epochs):  #for——range模式=其他語言的for
    #下面這個迴圈是訓練集合裡的全部資料
    for i, (images, labels) in enumerate(train_loader): #for——enumerate模式=其他語言的foreach
        # 這裡的images是100個影像,也就是一個批次
       
        # 將100,1,28,28  這個四維陣列 轉換成2維陣列,轉換結果應該是 100,784 
        # to(device) 是指將資料轉移到這個裝置上計算,如果有GPU,這個計算會被加速
        images = images.reshape(-1, 28*28).to(device) 
        labels = labels.to(device)
        # forward
        outputs = model(images)
        loss = criterion(outputs, labels)
        # backwards
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if (i+1) % 100 == 0:
            print(
                f'epoch {epoch+1} / {num_epochs}, step {i+1}/{n_total_steps}, loss = {loss.item}')
# test
with torch.no_grad():
    n_correct = 0
    n_samples = 0
    for images, labels in test_loader:
        images = images.reshape(-1, 28*28).to(device) #轉二維陣列
        labels = labels.to(device)
        outputs = model(images) # 透過我們訓練的模型,我們得到了y_predicted

        # value,index
        _, predictions = torch.max(outputs, 1) #torch.max(outputs, 1) 會在 outputs 的每一行(對應每個樣本)中找到最大值及其索引。由於模型輸出的是每個類別的機率分佈,所以最大值的索引代表模型對該影像的預測類別。
        n_samples += labels.shape[0] #labels.shape[0]會返回y的行數,就是100,因為一個批次100個影像
        print("y行數",labels.shape[0])
        #predictions == labels 會生成一個布林張量(True 表示預測正確,False 表示預測錯誤)
        #sum() 計算正確預測的數量並加到 n_correct 上
        n_correct += (predictions == labels).sum().item()

acc = 100.0*n_correct/n_samples #計算正確率
print(f'accuracy ={acc}')

圖形

現在我們學會了使用神經網路開發,我們在來看一些圖形,就能看懂了。
比如這個M-P神經元模型。

在比如這個神經網路結構圖。
下面粉色是輸入層,綠色是隱藏層,藍色是輸出層。雖然下面畫的隱藏層節點比輸入層多,但實際情況並不一定,這只是個示意圖,比如我們上面,輸入的x是784列,隱藏層計算後,就剩100列。
image

結語

本質上我並不是python程式設計師,其實看我的註釋就應該能感覺到吧,比如我對python的for迴圈都會加註釋。
我之所以寫這個系列,就是因為我不是python開發,這個系列是為了當我間隔超長時間重新使用python時,喚起死去的記憶用的。
不過,我感覺我寫的順序還不錯,如果大家反覆的仔細的閱讀,應該也能掌握神經網路開發。
而且,正因為我不是python開發,反正更好的證明了,python的學習和人工智慧的學習,並沒有想象中那麼難,相信大家只有認真研究,一定都能學會。


傳送門:
零基礎學習人工智慧—Python—Pytorch學習(一)
零基礎學習人工智慧—Python—Pytorch學習(二)
零基礎學習人工智慧—Python—Pytorch學習(三)
零基礎學習人工智慧—Python—Pytorch學習(四)
零基礎學習人工智慧—Python—Pytorch學習(五)
零基礎學習人工智慧—Python—Pytorch學習(六)
零基礎學習人工智慧—Python—Pytorch學習(七)


注:此文章為原創,任何形式的轉載都請聯絡作者獲得授權並註明出處!



若您覺得這篇文章還不錯,請點選下方的【推薦】,非常感謝!

https://www.cnblogs.com/kiba/p/18372411

相關文章