激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

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

服務器之家 - 腳本之家 - Python - PyTorch簡單手寫數字識別的實現過程

PyTorch簡單手寫數字識別的實現過程

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

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

具體流程:

① 導入相應的包,下載訓練集和測試集對應需要的圖像數據。
②進行圖像數據的變換,使圖像數據轉化成pytorch可識別并計算的張量數據類型
③數據預覽測試和數據裝載
④模型搭建和參數優化
⑤總代碼
⑥測試

一、包導入及所需數據的下載

torchvision包的主要功能是實現數據的處理、導入、預覽等,所以如果需要對計算機視覺的相關問題進行處理,就可以借用在torchvision包中提供的大量的類來完成相應的工作。

代碼的開始部分有這兩個:

?
1
2
import torch
from torchvision import datasets, transforms  # torchvision包的主要功能是實現數據的處理、導入和預覽等

torchvision.datasets:實現對數據集的訓練集和測試集的下載,只需使用torchvision再加上需要下載的數據集的名稱就可以了,比如本例的mnist

下載數據集的代碼如下:

?
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用于指定數據集在下載之后的存放路徑,這里存放在根目錄下的data文件夾

②transform用于指定導入數據集是需要對數據進行哪種變換操作

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

關于數據集引入的改動

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

?
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)
)

我調用torch.utils.data import random_split函數對數據集進行了切割,使得數據量減少,提升了運行速率。

二、進行數據處理變換操作

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

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

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

①轉化數據類型為tensor(張量)
②對均值(mean)和標準差(std)均為0.5的原始數據進行數據標準化變化

三、數據預覽測試和數據裝載

數據下載完成并載入之后,我們還需對數據進行裝載。

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

代碼片如下:

?
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)

對數據的裝載使用的是torch.utils.data.dataloader類,類中的參數:

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

在裝載完成后,我們可以選取其中一個批次的數據進行預覽。進行數據預覽的代碼如下:

?
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來獲取一個批次的圖片數據(images)和其對應的圖片標簽(abels)

然后使用torchvision.utils中的make_grid類方法將一個批次的圖片構造成網格模式

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

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

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

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

在完成數據預覽的代碼中,我們先打印輸出了這個批次中的數據的全部標簽,然后才對這個批次中的所有圖片數據進行顯示。結果如下:

PyTorch簡單手寫數字識別的實現過程

效果圖如下,可以看到,打印輸出的首先是4張圖片對應的標簽,然后是4張圖片的預覽效果

PyTorch簡單手寫數字識別的實現過程

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

?
1
plt.show()

四、模型搭建和參數優化

在順利完成數據裝載之后,我們就可以開始編寫卷積神經網絡的搭建和參數優化的代碼了。

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

實現卷積神經網絡模型搭建的代碼如下

?
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# 對參數實行扁平化處理
        x = self.dense(x)
        return x

我們選擇搭建一個在結構層次上有所簡化的卷積神經網絡模型,在結構上使用了兩個卷積層:一個最大池化層和兩個全連接層

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

torch.nn.maxpool2d():用于實現卷積神經網絡中的最大池化層,主要的輸入參數時池化窗口的大小、池化窗口移動步長和paddingde值。
同樣:
池化窗口大小的數據類型是整型,用于確定池化窗口的大小。
池化窗口步長的數據類型也是整型,用于確定池化窗口每次移動的步長。
paddingde值和在torch.nn.conv2d中定義的paddingde值的用法和意義時一樣的。

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

代碼前向傳播forward函數中的內容:

首先,經過self.conv1進行卷積處理;然后進行x.view(-1 ,14 * 14 *128),對參數實現扁平化因為之后緊挨著就是全連接層,所以如果不進行扁平化處理,則全連接層的實際輸出的參數維度和其定義輸入的維度將不匹配,程序會報錯;最后,通過self.dense定義的全連接進行最后的分類。

在編輯完搭建卷積神經網絡模型的代碼之后,我們就可以開始對模型進行訓練和對參數進行優化了。首先,定義在訓練之前使用哪種損失函數和優化函數:

?
1
2
3
4
5
6
model = model()
cost = torch.nn.crossentropyloss()
optimizer = torch.optim.adam(model.parameters())
# 損失函數: 交叉熵
# 優化函數: adam自適應優化算法,需要優化的參數實在model中生成的全部參數,
#因為沒有定義學習速率的值,所以使用默認值

最后,卷積神經網絡模型進行模型訓練和參數優化的代碼如下:

?
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)))

關于模型搭建的改動

在此處我對上面模型進行了優化改動,大大優化了運行的時間,但是對應也減少了一些訓練精度。

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

?
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)  # 對參數實行扁平化處理
        x = x.view(-1, 7*7*128# 對參數實行扁平化處理
        x = self.dense(x)
        return x

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

?
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()

用于測試的數據標簽結果輸出如下:

PyTorch簡單手寫數字識別的實現過程

PyTorch簡單手寫數字識別的實現過程

在輸出結果中

第1個結果是我們訓練好的模型的預測值,第2個結果是這4個測試數據的真實值。

對測試數據進行可視化,如下圖所示:

PyTorch簡單手寫數字識別的實現過程

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

總代碼:

?
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包的主要功能是實現數據的處理、導入和預覽等
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)  # 對參數實行扁平化處理
#         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)  # 對參數實行扁平化處理
        x = x.view(-1, 7 * 7 * 128# 對參數實行扁平化處理
        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()

測試

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

?
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)))

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

PyTorch簡單手寫數字識別的實現過程

PyTorch簡單手寫數字識別的實現過程

總結

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 精品一区二区三区欧美 | 精品一区久久久 | 55夜色66夜色国产精品视频 | 成人在线免费视频播放 | 精品一区二区三区免费视频 | 伊人网站| 国产一区二区二 | 亚洲一区久久久 | 91成人一区二区三区 | 永久免费av片在线观看全网站 | 大学生a级毛片免费视频 | 国产免费福利视频 | 国产成人综合在线视频 | 永久在线观看电影 | 男女羞羞视频在线观看免费 | 在线成人一区二区 | 久色亚洲| 97超视频在线观看 | 免费观看一级淫片 | 中文字幕在线观看精品 | 国产成人精品午夜视频' | 一本精品999爽爽久久久 | 欧美一级黄 | 国产第一页精品 | 人人舔人人射 | 一区二区三区欧美精品 | 成人免费毛片片v | 草莓福利社区在线 | 中文字幕在线观看1 | 国产午夜电影在线观看 | 欧美性成人 | 国产精品久久久久久久久粉嫩 | 欧美成年视频 | aaaaa国产欧美一区二区 | 一级黄色毛片播放 | 午夜热门福利 | 久久人体| av在线免费看网站 | 香蕉黄色网 | 黄色网址免费入口 | 久久99精品久久久久久青青日本 |