PytorchはCIFAR 10のCNN集積ニューラルネットワークを構築する
56487 ワード
ソース参照https://github.com/zergtant/pytorch-handbook/blob/master/chapter1/4_cifar10_tutorial.ipynb少し修正する
CIFAR 10データ
torchvision.datasets.CIFAR 10()はすべてのデータを直接ダウンロードし、train=True/Falseによって訓練セットまたはテストセットに割り当てられた[0255]RGBイメージ画像を決定することができる. 訓練に用いるデータセットは通常正規化の必要があり、データを読み取る際にtransform=transformで直接実現することができ、一般的にtransform=torchvisionである.transforms.ToTensor()はtorchvisionに[0255]を[0,1]のfloat RGBに出力させることができ、本論文では正規化normalizationを継続した. transforms.Componentは複数のtransformコマンドの組み合わせを実現し、ここではtransforms.ToTensor()実装出力は[0,1]であり、transformsに続く.Normalize(0.5,0.5,0.5),(0.5,0.5,0.5)は[0,1]のRGBを[−1,1]に正規化した.最初のパラメータは(0,0,0)が平均値0に正規化されるべきであると考えられていたことに注意してください.しかしtransformsのソースコードにより, torchvision.datasets.CIFAR 10の出力は実際にはdatasetになっていて、直接dataloaderでバッチロードすることができて、BATCH_SIZEはバッチごとのデータであり、本明細書では計算のたびに4枚の図を反復する. torch.utils.data.DataLoaderもう一つ注意すべき点はnum_workers=2は2つのコアを同時に並行するが、直接実行するとRuntimeError:An attempt has been made to start a new process before the current process has finished its bootstrapping phase.これはpythonがパラレルコンピューティングマルチプロセスを使用するにはメインプログラムにif name==「main」:メインプログラムを実行する必要があるためです.詳細は、既知の記事を参照してください.https://zhuanlan.zhihu.com/p/39542342;
Pythonのモジュールmatplotlibは便利な絵です. plt.imshow()はnumpy arrayをサポートし、(M,N,3)のRGBに対して画像を出力することができ、RGB値は[0,1]のfloatであってもよいし、[255]のintであってもよい. 興味深いのは、trainsetがtransformを通って出てくるとすでに[-1,1]のtensorだと思っていたが、実際にはtrainset.dataには元のarray[0.255](32323)が残っていますplt.imshow()は直接画像を生成します. trainset自体が伝達するのはメタグループであり、それぞれimageとlabelであり、imageはtorchである.tensor,[−1,1](33232),以下: (images_comb*0.5+0.5).numpy()は、実際には逆正規化プロセスであり、[−1,1]を[0,1]のarrayに復元し、[32,32,3](np.transpose(images_comb_unnor,(1,2,0))に変換してimshow()入力に供する.
ネットワークの構築は継承torchに基づいている.nn.Moduleの親、基本フォーマットは以下の通りです. CNNのネットワーク基本構造は、ボリューム末端、アクティブ層、プール化層、全接続層である.torch.nn.Conv 2 d()で定義された入力レイヤ数in_チャンネル、出力レイヤ数out_channels,ボリュームコアサイズkernel_size、ボリュームステップstride、paddingなどのパラメータを充填します.torch.nn.MaxPool 2 d()は最大プール化され、同様にボリュームサイズやステップ長などのパラメータを定義する. 全接続層は、巻き上げられた画像を平らにし、全接続ニューラルネットワークに接続する.全接続層の確立には、入力特徴数が畳み込み出力と一致し、畳み込み出力のタイルサイズがW=MMC、Mが縦横寸法、Cが層数(チャネル数)であることに注意する必要がある.具体的な計算方法は、畳み込みまたはプール化計算方法に共通し、M=(N-kernel_size+2*padding)/stride+1が下向きに整頓され、Nが入力Nである×N画像のアスペクト寸法. 全接続層の最終出力は10であり、CIFAR 10分類ラベルの10クラスに対応する.
ランダム勾配降下を最適化器とし,クロスエントロピーは損失関数 である.
EPOCHはサンプルを何度も訓練した. loss = loss_func(outputs,b_y)は予測値と実際のlabelとのクロスエントロピー誤差を計算するが,計算誤差の場合,one-hot形式ではなく1 D Tensor,(batch,),torchが伝わることに注意が必要である.nn.CrossEntropyLoss()は、受信したtensorをonehotし、softmaxで計算誤差をアクティブにします. ではlossは減少し続けていることがわかるが,EPOCHは2にすぎないためlossの低下はまだ不十分である.また、合計50000枚の画像、batchsizeは4で、epochごとに12500 step があります.
with torch.no_grad()は主に予測時にtorchの下の変数に勾配を計算する必要がなく、計算時間と空間を節約できることを教え、それ以外にこのコードを加えなくても結果に影響しない. outputもtensor torch.max(input) → Tensor torch.max(a,1)は、各行の最大値の要素を返し、そのインデックス(この行の最大要素の列インデックスを返す)torchを返す.max(a,0)は各列の最大値の要素を返し、インデックス(この列の最大要素の行インデックスを返す)はtensorであることに注意する. はoutputsに対してもよい.dataはF.softmax()をアクティブにしてから最大値を求めるが、出力インデックスは変化しない.torch.max(F.softmax(outputs),1) 最新torch 1.0バージョン以上、torch.Tensorとtorch.Tensor.dataはマージされているようなので不要です.dataはtensorの値を取得します. 現在のネットワークの計算精度は53%であり、CNNネットワークのいくつかのパラメータを修正することで精度を向上させることができる.
ネットワークの複雑さを増加させ、ボリューム出力層数、全接続層のノード数などを含め、精度を63%に向上させることができる. epochを8に増加すれば、73%に上昇し続けることができる.
CIFAR 10データ
CIFAR 10は基本的なピクチャーデータベースで、全部で10種類の分類で、訓練セットは50000枚のピクチャーがあって、テストセットは10000枚のピクチャーがあって、ピクチャーはすべて32*32解像度です.PytorchのtorchvisionはCIFAR 10を使ったデータを簡単にダウンロードできます.コードは以下の通りです.import torch
import torchvision
import torchvision.transforms as transforms
#
BATCH_SIZE = 4
EPOCH = 2
#torchvision CIFAR10 , transform [0,1]
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data',train = True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset,batch_size = BATCH_SIZE,
shuffle = True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='./data',train = False,
download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset,batch_size = BATCH_SIZE,
shuffle = False, num_workers=2)
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
コードコメント
pytorchは、MNIST、CIFAR 10など、汎用データベースのダウンロードに便利なインタフェースを提供し、トレーニングセットとテストセットを出力します.
import torch
import torchvision
import torchvision.transforms as transforms
#
BATCH_SIZE = 4
EPOCH = 2
#torchvision CIFAR10 , transform [0,1]
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data',train = True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset,batch_size = BATCH_SIZE,
shuffle = True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='./data',train = False,
download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset,batch_size = BATCH_SIZE,
shuffle = False, num_workers=2)
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
output[channel] = (input[channel] - mean[channel]) / std[channel]
,すなわち,((0,1)−0.5)/0.5=(−1,1);画像を表示
plt.imshow(trainset.data[86]) #trainset.data , array
plt.show()
dataiter = iter(trainloader)
images, labels = dataiter.next()
images_comb = torchvision.utils.make_grid(images)
images_comb_unnor = (images_comb*0.5+0.5).numpy()
plt.imshow(np.transpose(images_comb_unnor, (1, 2, 0)))
plt.show()
Pythonのモジュールmatplotlibは便利な絵です.
trainset[0][1]
Out[13]: 6
trainset[0][0]
Out[14]:
tensor([[[-0.5373, -0.6627, -0.6078, ..., 0.2392, 0.1922, 0.1608],
[-0.8745, -1.0000, -0.8588, ..., -0.0353, -0.0667, -0.0431],
[-0.8039, -0.8745, -0.6157, ..., -0.0745, -0.0588, -0.1451],
...,
[ 0.6314, 0.5765, 0.5529, ..., 0.2549, -0.5608, -0.5843],
[ 0.4118, 0.3569, 0.4588, ..., 0.4431, -0.2392, -0.3490],
[ 0.3882, 0.3176, 0.4039, ..., 0.6941, 0.1843, -0.0353]],
[[-0.5137, -0.6392, -0.6235, ..., 0.0353, -0.0196, -0.0275],
[-0.8431, -1.0000, -0.9373, ..., -0.3098, -0.3490, -0.3176],
[-0.8118, -0.9451, -0.7882, ..., -0.3412, -0.3412, -0.4275],
...,
[ 0.3333, 0.2000, 0.2627, ..., 0.0431, -0.7569, -0.7333],
[ 0.0902, -0.0353, 0.1294, ..., 0.1608, -0.5137, -0.5843],
[ 0.1294, 0.0118, 0.1137, ..., 0.4431, -0.0745, -0.2784]],
[[-0.5059, -0.6471, -0.6627, ..., -0.1529, -0.2000, -0.1922],
[-0.8431, -1.0000, -1.0000, ..., -0.5686, -0.6078, -0.5529],
[-0.8353, -1.0000, -0.9373, ..., -0.6078, -0.6078, -0.6706],
...,
[-0.2471, -0.7333, -0.7961, ..., -0.4510, -0.9451, -0.8431],
[-0.2471, -0.6706, -0.7647, ..., -0.2627, -0.7333, -0.7333],
[-0.0902, -0.2627, -0.3176, ..., 0.0980, -0.3412, -0.4353]]])
trainset[0][0].shape
Out[15]: torch.Size([3, 32, 32])
type(trainset[0])
Out[16]: tuple
type(trainset[0])
Out[19]: tuple
type(trainset[0][0])
Out[20]: torch.Tensor
type(trainset[0][1])
Out[21]: int
ボリュームニューラルネットワークの定義
class CNN_NET(torch.nn.Module):
def __init__(self):
super(CNN_NET,self).__init__()
self.conv1 = torch.nn.Conv2d(in_channels = 3,
out_channels = 6,
kernel_size = 5,
stride = 1,
padding = 0)
self.pool = torch.nn.MaxPool2d(kernel_size = 2,
stride = 2)
self.conv2 = torch.nn.Conv2d(6,16,5)
self.fc1 = torch.nn.Linear(16*5*5,120)
self.fc2 = torch.nn.Linear(120,84)
self.fc3 = torch.nn.Linear(84,10)
def forward(self,x):
x=self.pool(F.relu(self.conv1(x)))
x=self.pool(F.relu(self.conv2(x)))
x=x.view(-1,16*5*5) # batchsize 16*5*5 , sample,16*5*5
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = CNN_NET()
class CNN_NET(torch.nn.Module):
def __init__(self):
super(CNN_NET,self).__init__()
...
def forward(self,x):
return x
損失関数とオプティマイザ
import torch.optim as optim
optimizer = optim.SGD(net.parameters(),lr=0.001,momentum=0.9)
loss_func =torch.nn.CrossEntropyLoss() # ( )
CNNトレーニング
for epoch in range(EPOCH):
running_loss = 0.0
for step, (b_x,b_y)in enumerate(trainloader):
outputs = net(b_x) # net x,
loss = loss_func(outputs, b_y) #
optimizer.zero_grad() #
loss.backward() # ,
optimizer.step() # net parameters
#
running_loss += loss.item()
if step % 1000 == 999: # 2000
print('[%d, %5d] loss: %.3f' %
(epoch + 1, step + 1, running_loss / 2000))
running_loss = 0.0
print('Finished Training')
[1, 2000] loss: 2.186
[1, 4000] loss: 1.879
[1, 6000] loss: 1.671
[1, 8000] loss: 1.594
[1, 10000] loss: 1.537
[1, 12000] loss: 1.479
[2, 2000] loss: 1.408
[2, 4000] loss: 1.400
[2, 6000] loss: 1.360
[2, 8000] loss: 1.342
[2, 10000] loss: 1.337
[2, 12000] loss: 1.283
テストセット精度の検証
correct = 0
total = 0
with torch.no_grad():
# ,
for (images,labels) in testloader:
outputs = net(images)
numbers,predicted = torch.max(outputs.data,1)
total +=labels.size(0)
correct+=(predicted==labels).sum().item()
print('Accuracy of the network on the 10000 test images: %d %%' % (
100 * correct / total))
メッシュパラメータの調整
class CNN_NET(torch.nn.Module):
def __init__(self):
super(CNN_NET,self).__init__()
self.conv1 = torch.nn.Conv2d(in_channels = 3,
out_channels = 64,
kernel_size = 5,
stride = 1,
padding = 0)
self.pool = torch.nn.MaxPool2d(kernel_size = 3,
stride = 2)
self.conv2 = torch.nn.Conv2d(64,64,5)
self.fc1 = torch.nn.Linear(64*4*4,384)
self.fc2 = torch.nn.Linear(384,192)
self.fc3 = torch.nn.Linear(192,10)
def forward(self,x):
x=self.pool(F.relu(self.conv1(x)))
x=self.pool(F.relu(self.conv2(x)))
x=x.view(-1,64*4*4)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
完全なコード
######################## ############################
import numpy as np
import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import torch.nn.functional as F
#hyper parameter
BATCH_SIZE = 4
EPOCH = 2
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data',train = True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset,batch_size = BATCH_SIZE,
shuffle = True, num_workers=1)
testset = torchvision.datasets.CIFAR10(root='./data',train = False,
download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset,batch_size = BATCH_SIZE,
shuffle = False, num_workers=1)
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
# plt.imshow(trainset.data[86]) #trainset.data , array
# plt.show()
# dataiter = iter(trainloader)
# images, labels = dataiter.next()
# images_comb = torchvision.utils.make_grid(images)
# images_comb_unnor = (images_comb*0.5+0.5).numpy()
# plt.imshow(np.transpose(images_comb_unnor, (1, 2, 0)))
# plt.show()
class CNN_NET(torch.nn.Module):
def __init__(self):
super(CNN_NET,self).__init__()
self.conv1 = torch.nn.Conv2d(in_channels = 3,
out_channels = 64,
kernel_size = 5,
stride = 1,
padding = 0)
self.pool = torch.nn.MaxPool2d(kernel_size = 3,
stride = 2)
self.conv2 = torch.nn.Conv2d(64,64,5)
self.fc1 = torch.nn.Linear(64*4*4,384)
self.fc2 = torch.nn.Linear(384,192)
self.fc3 = torch.nn.Linear(192,10)
def forward(self,x):
x=self.pool(F.relu(self.conv1(x)))
x=self.pool(F.relu(self.conv2(x)))
x=x.view(-1,64*4*4)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = CNN_NET()
import torch.optim as optim
optimizer = optim.SGD(net.parameters(),lr=0.001,momentum=0.9)
loss_func =torch.nn.CrossEntropyLoss()
for epoch in range(EPOCH):
running_loss = 0.0
for step, data in enumerate(trainloader):
b_x,b_y=data
outputs = net.forward(b_x)
loss = loss_func(outputs, b_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
#
running_loss += loss.item()
if step % 1000 == 999: # 2000
print('[%d, %5d] loss: %.3f' %
(epoch + 1, step + 1, running_loss / 2000))
running_loss = 0.0
print('Finished Training')
dataiter = iter(trainloader)
images, labels = dataiter.next()
images_comb = torchvision.utils.make_grid(images)
images_comb_unnor = (images_comb*0.5+0.5).numpy()
plt.imshow(np.transpose(images_comb_unnor, (1, 2, 0)))
plt.show()
predicts=net.forward(images)
######## #######
correct = 0
total = 0
with torch.no_grad():
# ,
for (images,labels) in testloader:
outputs = net(images)
numbers,predicted = torch.max(outputs.data,1)
total +=labels.size(0)
correct+=(predicted==labels).sum().item()
print('Accuracy of the network on the 10000 test images: %d %%' % (
100 * correct / total))