畳み込みについて勉強したので、PyTorchのチュートリアルに戻れそうです。
PyTorchのチュートリアルはある程度知識がないとすらすらできないね。
前回、「畳み込み」という処理について勉強しました。これで、PyTorchのチュートリアルで出てくる「畳み込みニューラルネットワーク」について進めていけそうな雰囲気です。やっとPyTorchのチュートリアルを進めることができます。と思いましたが、まずはPythonのクラスについて復習を行って、進めていきます。そして、プログラムで定義されているニューラルネットワークの大枠を理解していきたいと思います。
「畳み込み」処理については前回の記事もご参考ください。
こんな人の役に立つかも
・機械学習プログラミングを勉強している人
・PyTorchでニューラルネットワークを勉強したい人
・PyTorchのチュートリアルで迷ってしまった人
Pythonのクラスを復習
PyTorchのプログラミングでは、ニューラルネットワークを「クラス」というもので定義したりしますので、Pythonのクラスの挙動について復習しておきます。
#親クラス
class parent_class:
#親クラスのコンストラクタ
def __init__(self):
print("Initialize_parent")
def func1(self,num):
print("parent")
print(num)
#子クラス
class child_class(parent_class):
#子クラスのコンストラクタ
def __init__(self):
#親クラスのコンストラクタを呼び出した後追加の処理
super().__init__()
print("Initialize_child")
def fnc2(self,num):
#親クラスのfunc1を処理してから追加の処理
super().func1(num)
print("child")
print(num)
クラスは、プログラムの設計図のようなもので、使える機能(メソッド)や変数をひとまとめにします。
クラスparent_classには、「__init__(self)」という初期化機能、「func1」という機能が備わっています。これらの機能を「メソッド」と言っています。クラスがもつ関数のことですね。
クラスchild_classは、「(parent_class)」と記載してあるので、parent_classを「継承」しています。継承すると、super()として親クラスのメソッドを呼び出すことができます。例えば、child_classのfunc1メソッドの中で、super().func1としてfunc1を呼び出しています。
また、クラスの「__init__(self)」は「コンストラクタ」と呼ばれている初期化のためのメソッドになります。コンストラクタは、「インスタンス化」された時に呼び出され、変数などを初期化したりします。
「インスタンス化」は、次のプログラムのように、クラス(設計図)を変数に実態として展開することです。次のプログラムのように、同じクラス(設計図)で何個も実態を作成することができます。これを実行すると、__init__()のコンストラクタが実行されてる様子も伺えます。
#child_classのインスタンスを作成
t_instance = child_class()
t_instance2 = child_class()
最初の2行がt_instamceのコンストラクタ、後の2行がt_instance2のコンストラクタがptintしたものですね。
Initialize_parent
Initialize_child
Initialize_parent
Initialize_child
t_instanceから、メソッドfunc2を利用してみます。func2は、親クラスのfunc1を実行して「child」という文字列と、引数に与えた数字を表示する機能を持っています。メソッドの利用は、普段ライブラリを利用しているので問題ないですね。
#メソッドにアクセス
t_instance.fnc2(1)
次のような動作になります。
parent
1
child
1
多分このくらいの復習で大丈夫だと思います。
今回、復習だけで結構時間かかってるね。
畳み込みニューラルネットワークの定義
PyTorchから、ニューラルネットワークに必要となるライブラリをimportします。
import torch
import torch.nn as nn
import torch.nn.functional as F
次に、クラスとしてニューラルネットワークを定義していきます。これは、今回作成するニューラルネットワークの設計図のようなものです。
Netというクラスでニューラルネットワークを定義します。先ほどクラスの復習でやったように、「nn.Module」というPyTorchが準備してくれているクラスを継承することで基本的な機能はライブラリにまかせ、追加の機能を自分でカスタマイズしてプログラミングしていくことが可能です。自分の工夫を盛り込んだニューラルネットワークを作成できるということです。
class Net(nn.Module):
#①初期化
def __init__(self):
super(Net, self).__init__()
#畳み込み層を順番に2層分定義
# 畳み込み層1を定義:1入力画像, 6の出力チャンネル, 3×3の矩形フィルタ
self.conv1 = nn.Conv2d(1, 6, 3)
# 畳み込み層2を定義:6入力イメージ, 16の出力チャンネル, 3×3の矩形フィルタ
self.conv2 = nn.Conv2d(6, 16, 3)
#全結合ニューラルネットワークの入力層を定義
self.fc1 = nn.Linear(16 * 6 * 6, 120) # 6*6 from image dimension
#中間層を定義
self.fc2 = nn.Linear(120, 84)
#出力層を定義
self.fc3 = nn.Linear(84, 10)
#②順伝播の定義
def forward(self, x):
#2-1.畳み込み層1からの出力を2×2の枠でMAXプーリングを行う
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
#2-2.xに畳み込み層1からのプーリングされた画像を畳み込み層2へ
#フィルタサイズは矩形であれば1つの数字指定でもOK 2×2は2と単一の数値のみでOK
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
#2-3.全結合ニューラルネットワークの入力層に入るデータ形式に整える。(下のメソッドnum_flat...を利用)
x = x.view(-1, self.num_flat_features(x))
#2-4.全結合ニューラルネットワークへ
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
#2-5.予測値を返す
return x
#全結合ニューラルネットワークへ入力するデータへ変換するための機能
def num_flat_features(self, x):
size = x.size()[1:] # all dimensions except the batch dimension
num_features = 1
for s in size:
num_features *= s
return num_features
①初期化
コンストラクタにて、畳み込み層を「conv1、conv2」という名前で2層分定義しています。そのため、メソッド内から「self.conv1(入力画像データ)」と呼び出すことで畳み込み層1で畳み込みすることができます。また、全結合ニューラルネットワーク部分も同様に「fc1、fc2、fc3」と定義されています。
②順伝播の定義
順伝播は、入力データから分類結果を返す動作です。
メソッドとしてここで定義します。xに入力された画像データは2-1で畳み込み層1の変換を経てプーリングされます。畳み込み層1の処理からのプーリング層1の処理まで1行で記載されています。一般的に、畳み込みされた画像データは活性化関数としてReLUを利用するらしいです。また、畳み込み層からの出力は活性化関数「ReLU」に通すようです。xは、ここで畳み込み層1のデータをプーリングしたものに上書きされます。
2-2も同様に、畳み込み層2からのプーリングです。xは同様に上書きされていきます。
2-3にて、全結合ニューラルネットワークへ入力するためのデータへと整えられるようです。後に定義されているメソッド「num_flat_features」はここで利用されています。
2-4は、一般的な全結合ニューラルネットワークです。
最後の2-5では、ネットワークから得られた結果を返しています。
ニューラルネットワークの利用
この畳み込みニューラルネットワーククラス「Net」はプログラム中で次のようにインスタンス化して利用できるようになります。
net = Net()
print(net)
netという変数にNetクラスがインスタンス化されました。
netをprintすることで、この畳み込みニューラルネットワークがどのような構造となっているのかがわかります。
Net(
(conv1): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(3, 3), stride=(1, 1))
(fc1): Linear(in_features=576, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
畳み込みニューラルネットワークの大まかな流れとか、機能が少しづつ理解できてきました。
チュートリアルのニューラルネットワーク定義のところまでやりました。引き続き次回もチュートリアルを進めていきます。
次の記事はこちらです。