def 小児科医():

かけだし小児科医が仕事の合間にプログラミングを勉強するブログです。

畳み込みニューラルネットワークの話

 

以前ディープラーニングを勉強してみたことがあったのだが、もうほとんど覚えていない。

 

defpediatric.hatenablog.com

この本も深層学習の分野に入った。

 

 

 

畳み込みニューラルネットワーク(convolutional neural network;CNN)

画像分類に長けた順伝播型ネットワーク

特徴として、「畳み込み」「プーリング(ダウンサンプリング)」という2つの演算を組み合わせることが必要

 

畳み込み

フィルタ(kernelともいう)という画素数の小さい画像を考える

畳み込みは画像とフィルタを重ねた時の画素同士の積を求めて、その和を計算すること。

なので畳み込みを行うと画像の画素数は小さくなる。

 

イメージ的には青のフィルターをずらしていって、

ここでの積の和を計算

ちょっとずらしてまた計算。これを繰り返す。

という感じ。

このずらしをどれくらいずつずらすかというのをストライドという。

ストライドが大きいと画素数はより小さくなるので、ダウンサンプリングにも用いられる。

 

グレースケールの場合はこれでおしまいだが、実際にはカラー画像を使うことが多いので、色分けした分3次元方向に配列が増えることになる。この層のことをチャネルとい、3次元配列のことをテンソルというらしい。

ただ3次元方向に層が増えても、フィルタも同次元存在するので計算量が増えただけで特にやることは一緒っぽい。

 

この畳み込みされたものに活性化関数を適用して、次の層に伝播していく。

 

プーリング

素数を下げること(ダウンサンプリング)はストライドを増やすか、プーリングを行うことで可能。

プーリングは局所の値の要約をして、画素数を下げる方法。

例えばこの中の最大値とか平均値とかを計算して、画素数の少ない出力画像を出す。みたいな。

 

CIFAR10で練習

今回はtensorflowのCIFAR10というデータセットを使って練習。

これは32*32ピクセルの画像がラベル付けされて60000枚格納されているデータ。

1つのピクセルにRBGの三種類のデータが格納されている。

ラベルは飛行機、自動車、鳥、猫、鹿、犬、カエル、馬、船、トラックの10種類

 

データ前処理

1つ1つのデータは0-255の値をとっているが、処理しにくいので、0-1の値を取るようにする

ラベルは最終的に出力層になるの0と1で表せる(6だったら[0,0,0,0,0,0,1,0,0,0]みたいな)ようにする(one-hot encordingという)

 

モデル構築

#モデル構築
model = Sequential()

model.add(Conv2D(filters=32, kernel_size=(3, 3),
padding="same", input_shape=x_train.shape[1:],
activation="relu", name="conv2d_1"))
model.add(MaxPooling2D(pool_size=(2, 2), padding="valid"))

model.add(Conv2D(filters=64, kernel_size=(3, 3),
padding="same", input_shape=x_train.shape[1:],
activation="relu", name="conv2d_2"))
model.add(MaxPooling2D(pool_size=(2, 2), padding="valid"))

model.add(Flatten())
model.add(Dense(512, activation="relu"))
model.add(Dense(len(label_names), activation="softmax"))

print(model.summary())

model.compile(optimizer = optimizers.Adam(learning_rate=0.001), loss="categorical_crossentropy", metrics=["accuracy"])

batch_size = 64
epochs=20

#学習開始
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.1, verbose=1)

今回は畳み込み→プーリング→畳み込み→プーリングの2層でモデルを構築。

活性化関数はReLu関数、出力層はsoftmax関数を使用している。

 

 

評価

検証

学習を開始すると、エポックごとに訓練データの10%を使って検証(Validation)を行うようになっている。

訓練データの精度と、検証データの精度や損失関数がエポックごとにどうなるかで過学習の程度がわかる。

検証データの精度が上がらない=過学習が進んでいる。

損失関数が増加する=間違えた時にめっちゃ間違えてるor正解した時もギリギリ。

 

混同行列

混同行列を可視化することによって、どの問題で間違えたのかがわかる。

間違えた問題の画像を増やしたり、ネットワークの工夫をすることで改善できる。

 

注目した特徴量の可視化

深層学習は分類した理由がわからないとされているが、最近はどこに注目しているかをある程度可視化できる方法が出てきているらしい。

そのうちの一つがGrad-CAMという手法を使う

これは元々クラス活性マッピング(class activate mapping:CAM)という方法を拡張したもので、畳み込み層の出力をチャネルごとに重みづけして和を求め、あるクラスの出力の説明になるように重みを設定(具体的には出力をチャネルごとの成分で微分した行列の平均を使うらしい)して、それを画像として表示すれば注目している部分がわかる。らしい。

ちょっと難しくてあんまりわかってないせいで説明がわかりにくいのでchatGPTに説明を依頼。

 私は機械学習の初学者です。pythonを用いて深層学習の練習をしています。Grad-CAMについて説明してください。ただし専門用語を使用する場合は簡潔に但書をしてください。

 

もちろんです、Grad-CAM(Gradient-weighted Class Activation Mapping)について説明しますね。Grad-CAMはニューラルネットワークの特定の出力クラスに対する重要度を視覚的に理解するための手法です。

Grad-CAMは、特定のクラスの予測に寄与する画像領域をヒートマップとして描画します。これにより、ニューラルネットワークがどの部分に注目しているのかを理解するのに役立ちます。Grad-CAMはConvolutional Neural Networks(畳み込みニューラルネットワーク)に対して特に有用で、画像認識タスクによく使用されます。

Grad-CAMの基本的な考え方は以下のとおりです。

1. ネットワークの最後の畳み込み層(これは、ネットワークが特徴を学習する層)で各ニューロンの勾配を計算します。ここでの「勾配」とは、クラスのスコアを改善するために各ニューロンの活性化(出力)をどれだけ変更すべきかを表す量です。

2. 各ニューロンの活性化に対する勾配の平均値を計算します。これにより、それぞれのニューロンが予測クラスにどれだけ影響を与えるかを判断できます。

3. 各ニューロンの活性化とその勾配の平均値を掛け合わせて、重み付けされた活性化マップを生成します。これが、Grad-CAMの「ヒートマップ」になります。

このヒートマップは、画像中の特定の部分が予測にどれほど寄与しているかを視覚的に示しています。つまり、ニューラルネットワークが画像のどの部分を「重要」と判断しているかを理解するのに役立ちます。

PythonディープラーニングライブラリであるKerasやPyTorchを使用すれば、Grad-CAMの実装が比較的簡単にできます。これらのライブラリはニューラルネットワークの勾配を計算するのに必要な自動微分機能を提供しているためです。

 

ということみたいです。

実際にはこんな感じで映る

この手法の欠点は重みで特徴量を判断するのであんまり根拠がないこと。ただ対象の層が出力層と近ければ信頼できるらしい。

 

今回は以上。

深層学習難しいな、、、まだまだ勉強が必要です。