pytorch 在torchvision包里面有很多的的打包好的數據集,例如minist,Imagenet-12,CIFAR10 和CIFAR100。在torchvision的dataset包里面,用的時候直接調用就行了。具體的調用格式可以去看文檔(目前好像只有英文的)。網上也有很多源代碼。
不過,當我們想利用自己制作的數據集來訓練網絡模型時,就要有自己的方法了。pytorch在torchvision.dataset包里面封裝過一個函數ImageFolder()。這個函數功能很強大,只要你直接將數據集路徑保存為例如“train/1/1.jpg ,rain/1/2.jpg …… ”就可以根據根目錄“./train”將數據集裝載了。
1
|
dataset.ImageFolder(root = "datapath" , transfroms.ToTensor()) |
但是后來我發現一個問題,就是這個函數加載出來的圖像矩陣都是三通道的,并且沒有什么參數調用可以讓其變為單通道。如果我們要用到單通道數據集(灰度圖)的話,比如自己加載Lenet-5模型的數據集,就只能自己寫numpy數組再轉為pytorch的Tensor()張量了。
接下來是我做的過程:
首先,還是要用到opencv,用灰度圖打開一張圖片,省事。
1
2
3
4
5
6
7
8
9
10
11
|
#讀取圖片 這里是灰度圖 for item in all_path: img = cv2.imread(item[ 1 ], 0 ) img = cv2.resize(img,( 28 , 28 )) arr = np.asarray(img,dtype = "float32" ) data_x[i ,:,:,:] = arr i + = 1 data_y.append( int (item[ 0 ])) data_x = data_x / 255 data_y = np.asarray(data_y) |
其次,pytorch有自己的numpy轉Tensor函數,直接轉就行了。
1
2
|
data_x = torch.from_numpy(data_x) data_y = torch.from_numpy(data_y) |
下一步利用torch.util和torchvision里面的dataLoader函數,就能直接得到和torchvision.dataset里面封裝好的包相同的數據集樣本了
1
2
|
dataset = dataf.TensorDataset(data_x,data_y) loader = dataf.DataLoader(dataset, batch_size = batchsize, shuffle = True ) |
最后就是自己建網絡設計參數訓練了,這部分和文檔以及github中的差不多,就不贅述了。
下面是整個程序的源代碼,我利用的還是上次的車標識別的數據集,一共分四類,用的是2層卷積核兩層全連接。
源代碼:
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
166
|
# coding=utf-8 import os import cv2 import numpy as np import random import torch import torch.nn as nn import torch.utils.data as dataf from torch.autograd import Variable import torch.nn.functional as F import torch.optim as optim #訓練參數 cuda = False train_epoch = 20 train_lr = 0.01 train_momentum = 0.5 batchsize = 5 #測試訓練集路徑 test_path = "/home/test/" train_path = "/home/train/" #路徑數據 all_path = [] def load_data(data_path): signal = os.listdir(data_path) for fsingal in signal: filepath = data_path + fsingal filename = os.listdir(filepath) for fname in filename: ffpath = filepath + "/" + fname path = [fsingal,ffpath] all_path.append(path) #設立數據集多大 count = len (all_path) data_x = np.empty((count, 1 , 28 , 28 ),dtype = "float32" ) data_y = [] #打亂順序 random.shuffle(all_path) i = 0 ; #讀取圖片 這里是灰度圖 最后結果是i*i*i*i #分別表示:batch大小 , 通道數, 像素矩陣 for item in all_path: img = cv2.imread(item[ 1 ], 0 ) img = cv2.resize(img,( 28 , 28 )) arr = np.asarray(img,dtype = "float32" ) data_x[i ,:,:,:] = arr i + = 1 data_y.append( int (item[ 0 ])) data_x = data_x / 255 data_y = np.asarray(data_y) # lener = len(all_path) data_x = torch.from_numpy(data_x) data_y = torch.from_numpy(data_y) dataset = dataf.TensorDataset(data_x,data_y) loader = dataf.DataLoader(dataset, batch_size = batchsize, shuffle = True ) return loader # print data_y train_load = load_data(train_path) test_load = load_data(test_path) class L5_NET(nn.Module): def __init__( self ): super (L5_NET , self ).__init__(); #第一層輸入1,20個卷積核 每個5*5 self .conv1 = nn.Conv2d( 1 , 20 , kernel_size = 5 ) #第二層輸入20,30個卷積核 每個5*5 self .conv2 = nn.Conv2d( 20 , 30 , kernel_size = 5 ) #drop函數 self .conv2_drop = nn.Dropout2d() #全鏈接層1,展開30*4*4,連接層50個神經元 self .fc1 = nn.Linear( 30 * 4 * 4 , 50 ) #全鏈接層1,50-4 ,4為最后的輸出分類 self .fc2 = nn.Linear( 50 , 4 ) #前向傳播 def forward( self ,x): #池化層1 對于第一層卷積池化,池化核2*2 x = F.relu(F.max_pool2d( self .conv1(x) , 2 ) ) #池化層2 對于第二層卷積池化,池化核2*2 x = F.relu(F.max_pool2d( self .conv2_drop( self .conv2(x) ) , 2 ) ) #平鋪軸30*4*4個神經元 x = x.view( - 1 , 30 * 4 * 4 ) #全鏈接1 x = F.relu( self .fc1(x) ) #dropout鏈接 x = F.dropout(x , training = self .training) #全鏈接w x = self .fc2(x) #softmax鏈接返回結果 return F.log_softmax(x) model = L5_NET() if cuda : model.cuda() optimizer = optim.SGD(model.parameters() , lr = train_lr , momentum = train_momentum ) #預測函數 def train(epoch): model.train() for batch_idx, (data, target) in enumerate (train_load): if cuda: data, target = data.cuda(), target.cuda() data, target = Variable(data), Variable(target) #求導 optimizer.zero_grad() #訓練模型,輸出結果 output = model(data) #在數據集上預測loss loss = F.nll_loss(output, target) #反向傳播調整參數pytorch直接可以用loss loss.backward() #SGD刷新進步 optimizer.step() #實時輸出 if batch_idx % 10 = = 0 : print ( 'Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}' . format ( epoch, batch_idx * len (data), len (train_load.dataset), 100. * batch_idx / len (train_load), loss.data[ 0 ])) # #測試函數 def test(epoch): model. eval () test_loss = 0 correct = 0 for data, target in test_load: if cuda: data, target = data.cuda(), target.cuda() data, target = Variable(data, volatile = True ), Variable(target) #在測試集上預測 output = model(data) #計算在測試集上的loss test_loss + = F.nll_loss(output, target).data[ 0 ] #獲得預測的結果 pred = output.data. max ( 1 )[ 1 ] # get the index of the max log-probability #如果正確,correct+1 correct + = pred.eq(target.data).cpu(). sum () #loss計算 test_loss = test_loss test_loss / = len (test_load) #輸出結果 print ( '\nThe {} epoch result : Average loss: {:.6f}, Accuracy: {}/{} ({:.2f}%)\n' . format ( epoch,test_loss, correct, len (test_load.dataset), 100. * correct / len (test_load.dataset))) for epoch in range ( 1 , train_epoch + 1 ): train(epoch) test(epoch) |
最后的訓練結果和在keras下差不多,不過我訓練的時候好像把訓練集和測試集弄反了,數目好像測試集比訓練集還多,有點尷尬,不過無傷大雅。結果圖如下:
以上這篇Pytorch自己加載單通道圖片用作數據集訓練的實例就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/qq_31548387/article/details/73302319