一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - PyTorch簡單手寫數(shù)字識別的實(shí)現(xiàn)過程

PyTorch簡單手寫數(shù)字識別的實(shí)現(xiàn)過程

2022-03-04 17:29回家種蜜柚 Python

Pytorch是熱門的深度學(xué)習(xí)框架之一,通過經(jīng)典的MNIST數(shù)據(jù)集進(jìn)行快速的pytorch入門,這篇文章主要給大家介紹了關(guān)于PyTorch簡單手寫數(shù)字識別的相關(guān)資料,需要的朋友可以參考下

具體流程:

① 導(dǎo)入相應(yīng)的包,下載訓(xùn)練集和測試集對應(yīng)需要的圖像數(shù)據(jù)。
②進(jìn)行圖像數(shù)據(jù)的變換,使圖像數(shù)據(jù)轉(zhuǎn)化成pytorch可識別并計(jì)算的張量數(shù)據(jù)類型
③數(shù)據(jù)預(yù)覽測試和數(shù)據(jù)裝載
④模型搭建和參數(shù)優(yōu)化
⑤總代碼
⑥測試

一、包導(dǎo)入及所需數(shù)據(jù)的下載

torchvision包的主要功能是實(shí)現(xiàn)數(shù)據(jù)的處理、導(dǎo)入、預(yù)覽等,所以如果需要對計(jì)算機(jī)視覺的相關(guān)問題進(jìn)行處理,就可以借用在torchvision包中提供的大量的類來完成相應(yīng)的工作。

代碼的開始部分有這兩個(gè):

?
1
2
import torch
from torchvision import datasets, transforms  # torchvision包的主要功能是實(shí)現(xiàn)數(shù)據(jù)的處理、導(dǎo)入和預(yù)覽等

torchvision.datasets:實(shí)現(xiàn)對數(shù)據(jù)集的訓(xùn)練集和測試集的下載,只需使用torchvision再加上需要下載的數(shù)據(jù)集的名稱就可以了,比如本例的mnist

下載數(shù)據(jù)集的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
data_train = datasets.mnist(
    transform=transform,
    root="./data/",
    train=true,
    download=true
)
data_test = datasets.mnist(
    root="./data/",
    transform=transform,
    train=true,
    download=false
)

①root用于指定數(shù)據(jù)集在下載之后的存放路徑,這里存放在根目錄下的data文件夾

②transform用于指定導(dǎo)入數(shù)據(jù)集是需要對數(shù)據(jù)進(jìn)行哪種變換操作

train用于指定數(shù)據(jù)集下載完成后需要載入哪部分?jǐn)?shù)據(jù)(如果設(shè)置為true,則說明載入的是該數(shù)據(jù)集的訓(xùn)練集部分;如果設(shè)置為false,則說明載入的是該數(shù)據(jù)集的測試集部分)

關(guān)于數(shù)據(jù)集引入的改動

此處我對此進(jìn)行了稍微地小改動,因?yàn)檎麄€(gè)導(dǎo)入下載的數(shù)據(jù)集大約有6萬張圖片,這是一個(gè)極大的數(shù)據(jù)量,一臺配置正常的電腦程序運(yùn)行的時(shí)間需求將會是巨大的,我當(dāng)時(shí)大約跑了一上午(一臺正常配置的學(xué)生電腦),所以此處我將6萬張數(shù)據(jù)集的訓(xùn)練集和測試集都只截取了前1000張用作訓(xùn)練和測試,雖然說精度會降低,使得偏差較大,但是也足夠用了,在時(shí)間上會有極大的節(jié)省,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
from torch.utils.data import random_split
 
data_train, _ = random_split(
    dataset=data_train,
    lengths=[1000, 59000],
    generator=torch.generator().manual_seed(0)
)
data_test, _ = random_split(
    dataset=data_test,
    lengths=[1000, 59000],
    generator=torch.generator().manual_seed(0)
)

我調(diào)用torch.utils.data import random_split函數(shù)對數(shù)據(jù)集進(jìn)行了切割,使得數(shù)據(jù)量減少,提升了運(yùn)行速率。

二、進(jìn)行數(shù)據(jù)處理變換操作

在torch.transforms中提供了豐富的類對載入的數(shù)據(jù)進(jìn)行變換。我們知道,在計(jì)算機(jī)視覺中處理的數(shù)據(jù)集有很大一部分是圖片類型的,而在pytorch中實(shí)際進(jìn)行計(jì)算的是tensor數(shù)據(jù)類型的變量,所以我們首先需要解決的是數(shù)據(jù)類型轉(zhuǎn)換的問題
對數(shù)據(jù)進(jìn)行載入及有相應(yīng)變化的代碼如下:

?
1
2
3
transform = transforms.compose(
[transforms.totensor(), transforms.normalize(mean=[0.5], std=[0.5])]
)

我們可以將以上代碼中的torchvision.transforms.compose類看成一種容器,它能夠同時(shí)對多種數(shù)據(jù)變換進(jìn)行組合。傳入的參數(shù)是一個(gè)列表,列表中的元素就開始對載入的數(shù)據(jù)進(jìn)行各種變換操作。例如本例:

①轉(zhuǎn)化數(shù)據(jù)類型為tensor(張量)
②對均值(mean)和標(biāo)準(zhǔn)差(std)均為0.5的原始數(shù)據(jù)進(jìn)行數(shù)據(jù)標(biāo)準(zhǔn)化變化

三、數(shù)據(jù)預(yù)覽測試和數(shù)據(jù)裝載

數(shù)據(jù)下載完成并載入之后,我們還需對數(shù)據(jù)進(jìn)行裝載。

我們可以將數(shù)據(jù)的載入理解為對圖片的處理,在處理完成后,我們就需要將這些圖片打包好送給我們的模型進(jìn)行訓(xùn)練了,而裝載就是這個(gè)打包的過程

代碼片如下:

?
1
2
3
4
5
6
7
data_loader_train = torch.utils.data.dataloader(dataset=data_train,
                                                batch_size=4,
                                                shuffle=true)
 
data_loader_test = torch.utils.data.dataloader(dataset=data_test,
                                               batch_size=4,
                                               shuffle=true)

對數(shù)據(jù)的裝載使用的是torch.utils.data.dataloader類,類中的參數(shù):

①batch_size參數(shù)設(shè)置了每個(gè)包中的圖片數(shù)據(jù)個(gè)數(shù),代碼中的值是4(此處如果電腦配置不是很高或者想讓程序跑的快一點(diǎn)的話可以稍微調(diào)低,原本為64,此處我將其調(diào)為4
②dataset參數(shù)用于指定我們載入的數(shù)據(jù)集的名稱。 ③將shuffle參數(shù)設(shè)置為true,在裝載的過程中會將數(shù)據(jù)隨機(jī)打亂順序并進(jìn)行打包。

在裝載完成后,我們可以選取其中一個(gè)批次的數(shù)據(jù)進(jìn)行預(yù)覽。進(jìn)行數(shù)據(jù)預(yù)覽的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
images, labels = next(iter(data_loader_train))
 
img = torchvision.utils.make_grid(images)
img = img.numpy().transpose(1, 2, 0)
 
std = [0.5]
mean = [0.5]
img = img * std + mean
 
print([labels[i] for i in range(4)])
plt.imshow(img)
plt.show()

在以上代碼中使用了iternext來獲取一個(gè)批次的圖片數(shù)據(jù)(images)和其對應(yīng)的圖片標(biāo)簽(abels)

然后使用torchvision.utils中的make_grid類方法將一個(gè)批次的圖片構(gòu)造成網(wǎng)格模式

需要傳遞給torchvision.utils.make_grid的參數(shù)就是一個(gè)批次的裝載數(shù)據(jù),每個(gè)批次的裝載數(shù)據(jù)都是4維的,維度的構(gòu)成從前往后分別為batch_size、channel、height、weight,分別對應(yīng)一個(gè)批次中的數(shù)據(jù)個(gè)數(shù)、每張圖片的色彩通道數(shù)、每張圖片的高度和寬度

在通過torchvision.utils.make_grid之后,圖片的維度就變成了(channel,height,weight),這個(gè)批次的圖片全部被整合到了一起,所以在這個(gè)維度中對應(yīng)的值也和之前不一樣了,但是色彩通道數(shù)保持不變。

若我們想使用matplotlib將數(shù)據(jù)顯示成正常的圖片形式,則使用的數(shù)據(jù)首先必須是數(shù)組,其次這個(gè)數(shù)組的維度必須是(height、weight、channel),即色彩通道數(shù)在最后面。

所以我們要通過numpytranspose完成原始數(shù)據(jù)類型的轉(zhuǎn)換和數(shù)據(jù)維度的交換,這樣才能夠使用matplotlib繪制出正確的圖像。

在完成數(shù)據(jù)預(yù)覽的代碼中,我們先打印輸出了這個(gè)批次中的數(shù)據(jù)的全部標(biāo)簽,然后才對這個(gè)批次中的所有圖片數(shù)據(jù)進(jìn)行顯示。結(jié)果如下:

PyTorch簡單手寫數(shù)字識別的實(shí)現(xiàn)過程

效果圖如下,可以看到,打印輸出的首先是4張圖片對應(yīng)的標(biāo)簽,然后是4張圖片的預(yù)覽效果

PyTorch簡單手寫數(shù)字識別的實(shí)現(xiàn)過程

plt.show()的話如果是使用pycham編譯的話一定要加上去,不然會出現(xiàn)顯示不出圖像的情況

?
1
plt.show()

四、模型搭建和參數(shù)優(yōu)化

在順利完成數(shù)據(jù)裝載之后,我們就可以開始編寫卷積神經(jīng)網(wǎng)絡(luò)的搭建和參數(shù)優(yōu)化的代碼了。

卷積層使用torch.nn.conv2d類方法來搭建;
激活層使用torch.nn.relu()類方法來搭建;
池化層使用torch.nn.maxpool2d類方法來搭建;
全連接層使用torch.nn.linear類方法來搭建

實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)模型搭建的代碼如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class model(torch.nn.module):
 
    def __init__(self):
        super(model, self).__init__()
        self.conv1 = torch.nn.sequential(
            torch.nn.conv2d(1, 64, kernel_size=3, stride=1, padding=1),
            torch.nn.relu(),
            torch.nn.conv2d(64, 128, kernel_size=3, stride=1, padding=1),
            torch.nn.relu(),
            torch.nn.maxpool2d(stride=2, kernel_size=2)
        )
 
        self.dense = torch.nn.sequential(
            torch.nn.linear(14 * 14 * 128, 1024),
            torch.nn.relu(),
            torch.nn.dropout(p=0.5),
            torch.nn.linear(1024, 10)
        )
 
    def forward(self, x):
        x = self.conv1(x)  # 卷積處理
        x = x.view(-1, 14*14*128# 對參數(shù)實(shí)行扁平化處理
        x = self.dense(x)
        return x

我們選擇搭建一個(gè)在結(jié)構(gòu)層次上有所簡化的卷積神經(jīng)網(wǎng)絡(luò)模型,在結(jié)構(gòu)上使用了兩個(gè)卷積層:一個(gè)最大池化層和兩個(gè)全連接層

torch.nn.conv2d():用于搭建卷積神經(jīng)網(wǎng)絡(luò)的卷積層,主要的輸入?yún)?shù)有輸入通道數(shù)、輸出通道數(shù)、卷積核大小、卷積核移動步長和padding值。其中,
輸入通道數(shù)的數(shù)據(jù)類型是整型,用于確定輸入數(shù)據(jù)的層數(shù);
輸出通道數(shù)的數(shù)據(jù)類型也是整型,用于確定輸出數(shù)據(jù)的層數(shù);
卷積核大小的數(shù)據(jù)類型是整型,用于確定卷積核的大小;
卷積核移動步長的數(shù)據(jù)類型是整型,用于確定卷積核每次滑動的步長;
paddingde的數(shù)據(jù)類型是整型,值為0時(shí)代表不進(jìn)行邊界像素的填充,如果值大于0,那么增加數(shù)字所對應(yīng)的邊界像素層數(shù)。

torch.nn.maxpool2d():用于實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)中的最大池化層,主要的輸入?yún)?shù)時(shí)池化窗口的大小、池化窗口移動步長和paddingde值。
同樣:
池化窗口大小的數(shù)據(jù)類型是整型,用于確定池化窗口的大小。
池化窗口步長的數(shù)據(jù)類型也是整型,用于確定池化窗口每次移動的步長。
paddingde值和在torch.nn.conv2d中定義的paddingde值的用法和意義時(shí)一樣的。

torch.nn.dropout():torch.nn.dropout類用于防止卷積神經(jīng)網(wǎng)絡(luò)在訓(xùn)練的過程中發(fā)生過擬合,其工作原理簡單來說就是在模型訓(xùn)練的過程中,以一定的隨機(jī)概率將卷積神經(jīng)網(wǎng)絡(luò)模型的部分參數(shù)歸零,以達(dá)到減少相鄰兩層神經(jīng)連接的目的。

代碼前向傳播forward函數(shù)中的內(nèi)容:

首先,經(jīng)過self.conv1進(jìn)行卷積處理;然后進(jìn)行x.view(-1 ,14 * 14 *128),對參數(shù)實(shí)現(xiàn)扁平化因?yàn)橹缶o挨著就是全連接層,所以如果不進(jìn)行扁平化處理,則全連接層的實(shí)際輸出的參數(shù)維度和其定義輸入的維度將不匹配,程序會報(bào)錯(cuò);最后,通過self.dense定義的全連接進(jìn)行最后的分類。

在編輯完搭建卷積神經(jīng)網(wǎng)絡(luò)模型的代碼之后,我們就可以開始對模型進(jìn)行訓(xùn)練和對參數(shù)進(jìn)行優(yōu)化了。首先,定義在訓(xùn)練之前使用哪種損失函數(shù)和優(yōu)化函數(shù):

?
1
2
3
4
5
6
model = model()
cost = torch.nn.crossentropyloss()
optimizer = torch.optim.adam(model.parameters())
# 損失函數(shù): 交叉熵
# 優(yōu)化函數(shù): adam自適應(yīng)優(yōu)化算法,需要優(yōu)化的參數(shù)實(shí)在model中生成的全部參數(shù),
#因?yàn)闆]有定義學(xué)習(xí)速率的值,所以使用默認(rèn)值

最后,卷積神經(jīng)網(wǎng)絡(luò)模型進(jìn)行模型訓(xùn)練和參數(shù)優(yōu)化的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
epochs_n = 5
for epoch in range(epochs_n):
    running_loss = 0.0
    running_correct = 0
    print("epoch{}/{}".format(epoch, epochs_n))
    print("-" * 10)
    for data in data_loader_train:
        x_train, y_train = data
        x_train, y_train = variable(x_train), variable(y_train)
        outputs = model(x_train)
        _,pred = torch.max(outputs.data, 1)
        optimizer.zero_grad()
        loss = cost(outputs, y_train)
 
        loss.backward()
        optimizer.step()
        running_loss += loss.data
        running_correct += torch.sum(pred == y_train.data)
    testing_correct = 0
    for data in data_loader_test:
        x_test, y_test = data
        x_test, y_test = variable(x_test), variable(y_test)
        outputs = model(x_test)
        _, pred = torch.max(outputs.data, 1)
        testing_correct += torch.sum(pred == y_test.data)
        print("loss is:{:.4f},train accuracy is:{:.4f}%, test accuracy is:{:.4f}".format(running_loss / len(data_train),100 * running_correct / len(data_train),100 * testing_correct / len(data_test)))

關(guān)于模型搭建的改動

在此處我對上面模型進(jìn)行了優(yōu)化改動,大大優(yōu)化了運(yùn)行的時(shí)間,但是對應(yīng)也減少了一些訓(xùn)練精度。

原理就是,卷積層的運(yùn)算量不會太大,但全連接層的運(yùn)算量比較大,所以降低全連接的參數(shù)量,以及降低圖像特征圖的尺寸

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class model(torch.nn.module):
 
    def __init__(self):
        super(model, self).__init__()
        self.conv1 = torch.nn.sequential(
            torch.nn.conv2d(1, 64, kernel_size=3, stride=2, padding=1),
            torch.nn.relu(),
            torch.nn.conv2d(64, 128, kernel_size=3, stride=2, padding=1),
            torch.nn.relu(),
            # torch.nn.maxpool2d(stride=2, kernel_size=2)
        )
 
        self.dense = torch.nn.sequential(
            # torch.nn.linear(14 * 14 * 128, 1024),
            torch.nn.linear(7 * 7 * 128, 512),
            torch.nn.relu(),
            # torch.nn.dropout(p=0.5),
            torch.nn.dropout(p=0.8),
            torch.nn.linear(512, 10)
        )
 
    def forward(self, x):
        x = self.conv1(x)  # 卷積處理
        # x = x.view(-1, 14*14*128)  # 對參數(shù)實(shí)行扁平化處理
        x = x.view(-1, 7*7*128# 對參數(shù)實(shí)行扁平化處理
        x = self.dense(x)
        return x

為了驗(yàn)證我們訓(xùn)練的模型是不是真的已如結(jié)果顯示的一樣準(zhǔn)確,則最好的方法就是隨機(jī)選取一部分測試集中的圖片,用訓(xùn)練好的模型進(jìn)行預(yù)測,看看和真實(shí)值有多大偏差,并對結(jié)果進(jìn)行可視化,測試的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
x_test, y_test = next(iter(data_loader_test))
inputs = variable(x_test)
pred = model(inputs)
_, pred = torch.max(pred,1)
 
print("predict label is:", [i for i in pred.data])
print("real label is:", [i for i in y_test])
 
img = torchvision.utils.make_grid(x_test)
img = img.numpy().transpose(1,2,0)
 
std = [0.5, 0.5, 0.5]
mean = [0.5, 0.5, 0.5]
 
img = img*std+mean
plt.imshow(img)
plt.show()

記得末尾一定加上plt.show()

用于測試的數(shù)據(jù)標(biāo)簽結(jié)果輸出如下:

PyTorch簡單手寫數(shù)字識別的實(shí)現(xiàn)過程

PyTorch簡單手寫數(shù)字識別的實(shí)現(xiàn)過程

在輸出結(jié)果中

第1個(gè)結(jié)果是我們訓(xùn)練好的模型的預(yù)測值,第2個(gè)結(jié)果是這4個(gè)測試數(shù)據(jù)的真實(shí)值。

對測試數(shù)據(jù)進(jìn)行可視化,如下圖所示:

PyTorch簡單手寫數(shù)字識別的實(shí)現(xiàn)過程

可以看到,在上圖可視化的這部分測試集圖片,模型的預(yù)測結(jié)果和真實(shí)結(jié)果是完全一致的。當(dāng)然如果想選取更多的測試集進(jìn)行可視化,則只需將batch_size設(shè)置的更大,但考慮對應(yīng)程序的運(yùn)行速度將會略微降低

總代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import torch
import numpy
import torchvision
import matplotlib.pyplot as plt
 
from torchvision import datasets, transforms  # torchvision包的主要功能是實(shí)現(xiàn)數(shù)據(jù)的處理、導(dǎo)入和預(yù)覽等
from torch.autograd import variable
 
transform = transforms.compose([transforms.totensor(), transforms.normalize(mean=[0.5], std=[0.5])])
data_train = datasets.mnist(
    transform=transform,
    root="./data/",
    train=true,
    download=true
)
data_test = datasets.mnist(
    root="./data/",
    transform=transform,
    train=true,
    download=false
)
 
from torch.utils.data import random_split
 
data_train, _ = random_split(
    dataset=data_train,
    lengths=[1000, 59000],
    generator=torch.generator().manual_seed(0)
)
data_test, _ = random_split(
    dataset=data_test,
    lengths=[1000, 59000],
    generator=torch.generator().manual_seed(0)
)
 
data_loader_train = torch.utils.data.dataloader(dataset=data_train,
                                                batch_size=4,
                                                shuffle=true)
 
data_loader_test = torch.utils.data.dataloader(dataset=data_test,
                                               batch_size=4,
                                               shuffle=true)
 
 
# images, labels = next(iter(data_loader_train))
#
# img = torchvision.utils.make_grid(images)
# img = img.numpy().transpose(1, 2, 0)
#
# std = [0.5]
# mean = [0.5]
# img = img * std + mean
#
# print([labels[i] for i in range(64)])
# plt.imshow(img)
# plt.show()
 
 
# class model(torch.nn.module):
#
#     def __init__(self):
#         super(model, self).__init__()
#         self.conv1 = torch.nn.sequential(
#             torch.nn.conv2d(1, 64, kernel_size=3, stride=1, padding=1),
#             torch.nn.relu(),
#             torch.nn.conv2d(64, 128, kernel_size=3, stride=1, padding=1),
#             torch.nn.relu(),
#             torch.nn.maxpool2d(stride=2, kernel_size=2)
#         )
#
#         self.dense = torch.nn.sequential(
#             torch.nn.linear(14 * 14 * 128, 1024),
#             torch.nn.relu(),
#             torch.nn.dropout(p=0.5),
#             torch.nn.linear(1024, 10)
#         )
#
#     def forward(self, x):
#         x = self.conv1(x)  # 卷積處理
#         x = x.view(-1, 14*14*128)  # 對參數(shù)實(shí)行扁平化處理
#         x = self.dense(x)
#         return x
 
class model(torch.nn.module):
 
    def __init__(self):
        super(model, self).__init__()
        self.conv1 = torch.nn.sequential(
            torch.nn.conv2d(1, 64, kernel_size=3, stride=2, padding=1),
            torch.nn.relu(),
            torch.nn.conv2d(64, 128, kernel_size=3, stride=2, padding=1),
            torch.nn.relu(),
            # torch.nn.maxpool2d(stride=2, kernel_size=2)
        )
 
        self.dense = torch.nn.sequential(
            # torch.nn.linear(14 * 14 * 128, 1024),
            torch.nn.linear(7 * 7 * 128, 512),
            torch.nn.relu(),
            # torch.nn.dropout(p=0.5),
            torch.nn.dropout(p=0.8),
            torch.nn.linear(512, 10)
        )
 
    def forward(self, x):
        x = self.conv1(x)  # 卷積處理
        # x = x.view(-1, 14*14*128)  # 對參數(shù)實(shí)行扁平化處理
        x = x.view(-1, 7 * 7 * 128# 對參數(shù)實(shí)行扁平化處理
        x = self.dense(x)
        return x
 
 
model = model()
cost = torch.nn.crossentropyloss()
optimizer = torch.optim.adam(model.parameters())
 
epochs_n = 5
for epoch in range(epochs_n):
    running_loss = 0.0
    running_correct = 0
    print("epoch{}/{}".format(epoch, epochs_n))
    print("-" * 10)
 
    for data in data_loader_train:
        x_train, y_train = data
        x_train, y_train = variable(x_train), variable(y_train)
        outputs = model(x_train)
        _, pred = torch.max(outputs.data, 1)
        optimizer.zero_grad()
        loss = cost(outputs, y_train)
 
        loss.backward()
        optimizer.step()
        running_loss += loss.data
        running_correct += torch.sum(pred == y_train.data)
    testing_correct = 0
    for data in data_loader_test:
        x_test, y_test = data
        x_test, y_test = variable(x_test), variable(y_test)
        outputs = model(x_test)
        _, pred = torch.max(outputs.data, 1)
        testing_correct += torch.sum(pred == y_test.data)
        print("loss is:{:.4f},train accuracy is:{:.4f}%, test accuracy is:{:.4f}".format(running_loss / len(data_train),
                                                                                         100 * running_correct / len(
                                                                                             data_train),
                                                                                         100 * testing_correct / len(
                                                                                             data_test)))
 
x_test, y_test = next(iter(data_loader_test))
inputs = variable(x_test)
pred = model(inputs)
_, pred = torch.max(pred, 1)
 
print("predict label is:", [i for i in pred.data])
print("real label is:", [i for i in y_test])
 
img = torchvision.utils.make_grid(x_test)
img = img.numpy().transpose(1, 2, 0)
 
std = [0.5, 0.5, 0.5]
mean = [0.5, 0.5, 0.5]
 
img = img * std + mean
plt.imshow(img)
plt.show()

測試

最后,關(guān)于這類代碼的運(yùn)行時(shí)間的需求都是巨大的,所以短時(shí)間內(nèi)出不來很正常,盡量別中途中斷程序,若你想檢測程序是否運(yùn)行:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
epochs_n = 5
for epoch in range(epochs_n):
    running_loss = 0.0
    running_correct = 0
    print("epoch{}/{}".format(epoch, epochs_n))
    print("-" * 10)
    
    iter = 0
    for data in data_loader_train:
    
        iter+=1
        
        print(iter)
        x_train, y_train = data
        x_train, y_train = variable(x_train), variable(y_train)
        outputs = model(x_train)
        _, pred = torch.max(outputs.data, 1)
        optimizer.zero_grad()
        loss = cost(outputs, y_train)
 
        loss.backward()
        optimizer.step()
        running_loss += loss.data
        running_correct += torch.sum(pred == y_train.data)
    testing_correct = 0
    for data in data_loader_test:
        x_test, y_test = data
        x_test, y_test = variable(x_test), variable(y_test)
        outputs = model(x_test)
        _, pred = torch.max(outputs.data, 1)
        testing_correct += torch.sum(pred == y_test.data)
        print("loss is:{:.4f},train accuracy is:{:.4f}%, test accuracy is:{:.4f}".format(running_loss / len(data_train),
                                                                                         100 * running_correct / len(
                                                                                             data_train),
                                                                                         100 * testing_correct / len(
                                                                                             data_test)))

你可以在此處加上一個(gè)int型的測試變量iter,通過觀察iter是否累加迭代來判斷程序是否繼續(xù)在運(yùn)行

PyTorch簡單手寫數(shù)字識別的實(shí)現(xiàn)過程

PyTorch簡單手寫數(shù)字識別的實(shí)現(xiàn)過程

總結(jié)

到此這篇關(guān)于pytorch簡單手寫數(shù)字識別的文章就介紹到這了,更多相關(guān)pytorch手寫數(shù)字識別內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://blog.csdn.net/m0_53245772/article/details/121443967

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 青青成人福利国产在线视频 | 精品一区二区三区色花堂 | 国内精品久久久久影院中国 | 国产资源视频在线观看 | a黄色| 四缺一小说 | 成人欧美一区二区三区黑人 | 99热影院| 日韩在线第一区 | 亚洲色导航 | 麻豆视频入口 | 蜜桃破解版免费看nba | 国产网站免费观看 | 色天使亚洲综合在线观看 | 色综七七久久成人影 | 情欲满载2012美国dvd | 超高清欧美同性videos | chinese男gay飞机同志 | 教练你好大轻点漫 | 草莓香蕉榴莲丝瓜秋葵绿巨人在线看 | 高清不卡一区二区 | 日本高清全集免费观看 | 门卫老张和女警花小说 | 亚洲同性男男gay1069 | ysav67| free service性v极品 | 久久中文字幕免费高清 | 男人使劲躁女人视频免费 | 亚洲色图二区 | 婷婷在线观看香蕉五月天 | 国产精品林美惠子在线观看 | 香蕉视频在线观看网址 | 青丝视频免费版在线看 | 亚洲va久久久久综合 | 免费看视频高清在线观看 | h在线动漫 | 明星裸乳照无奶罩 | 亚洲无毛片 | 国产亚洲精品久久yy5099 | 啪啪大幂幂被c | 果冻传媒 天美 麻豆 |