Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

畳み込みニューラル ネットワークの活性化の可視化

この例では、畳み込みニューラル ネットワークにイメージを供給して、ネットワークのさまざまな層の活性化を表示する方法を説明します。活性化を調べ、活性化の領域を元のイメージと比較して、ネットワークが学習する特徴を確認します。初期の層のチャネルでは色やエッジなどの単純な特徴が学習され、深い層のチャネルでは目などの複雑な特徴が学習されていることを確認します。この方法で特徴を識別すると、ネットワークが学習した内容を把握するのに役立ちます。

この例には、Deep Learning Toolbox™ および Image Processing Toolbox™ が必要です。

事前学習済みのネットワークおよびデータの読み込み

事前学習済みの SqueezeNet ネットワークを読み込みます。

net = squeezenet;

イメージを読み取って表示します。後で使用するためにサイズを保存します。

im = imread('face.jpg');
imshow(im)

imgSize = size(im);
imgSize = imgSize(1:2);

ネットワーク アーキテクチャの表示

ネットワークを解析して、表示可能な層を確認します。畳み込み層では、学習可能なパラメーターを使用して畳み込みが行われます。ネットワークは、有用な特徴 (通常、チャネル 1 つにつき 1 つの特徴) を識別することを学習します。最初の畳み込み層に 64 個のチャネルがあることを確認します。

analyzeNetwork(net)

イメージ入力層では、入力サイズが指定されます。ネットワークにイメージを渡す前にイメージのサイズを変更できますが、ネットワークで大きなイメージを処理することもできます。ネットワークに大きなイメージを供給すると、活性化のサイズも大きくなります。ただし、ネットワークの学習はサイズが 227 x 227 のイメージについて行われており、このサイズより大きいオブジェクトまたは特徴を認識するようには行われていません。

最初の畳み込み層の活性化の表示

イメージに対して畳み込み層のどの領域が活性化するかを確認し、元のイメージの対応する領域と比較することによって特徴を調べます。畳み込みニューラル ネットワークの各層は、"チャネル" と呼ばれる多数の 2 次元配列で構成されています。イメージをネットワークに渡して、conv1 層の出力活性化を確認します。

act1 = activations(net,im,'conv1');

活性化は 3 次元配列として返されます。この配列の 3 番目の次元で、conv1 層のチャネルがインデックス化されています。関数 imtile を使用してこれらの活性化を表示するには、配列の形状を 4 次元に変更します。imtile の入力の 3 番目の次元は、イメージ カラーを表します。活性化には色が設定されていないため、3 番目の次元のサイズが 1 になるように設定します。4 番目の次元でチャネルがインデックス化されます。

sz = size(act1);
act1 = reshape(act1,[sz(1) sz(2) 1 sz(3)]);

これで、活性化を表示できるようになりました。各活性化は任意の値を取ることができるため、mat2gray を使用して出力を正規化します。活性化の最小値が 0、最大値が 1 になるように、すべての活性化がスケーリングされます。64 個のイメージ (層のチャネルごとに 1 つのイメージ) を 8 x 8 のグリッドに表示します。

I = imtile(mat2gray(act1),'GridSize',[8 8]);
imshow(I)

特定のチャネルの活性化の調査

活性化のグリッドの各タイルは、conv1 層のチャネルの出力です。白のピクセルは強い正の活性化を表し、黒のピクセルは強い負の活性化を表します。チャネルがほとんどグレーの場合、入力イメージはそれほど強く活性化されません。チャネルの活性化におけるピクセルの位置は、元のイメージにおける同じ位置に対応します。チャネルにある白いピクセルは、その位置でチャネルが強く活性化されることを示します。

チャネル 22 の活性化のサイズが元のイメージと同じになるように変更して、活性化を表示します。

act1ch22 = act1(:,:,:,22);
act1ch22 = mat2gray(act1ch22);
act1ch22 = imresize(act1ch22,imgSize);

I = imtile({im,act1ch22});
imshow(I)

チャネルの白に近いピクセルが元のイメージの赤い領域に対応しているので、このチャネルは赤いピクセルに対して活性化することがわかります。

最も強い活性化チャネルの確認

強く活性化するチャネルをプログラムで調べて、興味深いチャネルを見つけることもできます。関数 max を使用して最も強く活性化するチャネルを見つけ、活性化のサイズを変更して表示します。

[maxValue,maxValueIndex] = max(max(max(act1)));
act1chMax = act1(:,:,:,maxValueIndex);
act1chMax = mat2gray(act1chMax);
act1chMax = imresize(act1chMax,imgSize);

I = imtile({im,act1chMax});
imshow(I)

元のイメージと比較すると、このチャネルはエッジに対して活性化することがわかります。左側が薄く右側が濃いエッジでは正に活性化され、左側が濃く右側が薄いエッジでは負に活性化されます。

深い層の調査

最初の畳み込み層で、ほとんどの畳み込みニューラル ネットワークは色やエッジといった特徴の検出を学習します。深い畳み込み層では、ネットワークはより複雑な特徴を検出することを学習します。後続の層は、それ以前の層の特徴を組み合わせることによって特徴を構築します。conv1 層と同じ方法で fire6-squeeze1x1 層を調べます。グリッドで活性化の計算、形状変更、および表示を行います。

act6 = activations(net,im,'fire6-squeeze1x1');
sz = size(act6);
act6 = reshape(act6,[sz(1) sz(2) 1 sz(3)]);

I = imtile(imresize(mat2gray(act6),[64 64]),'GridSize',[6 8]);
imshow(I)

詳しく調べるにはイメージの数が多すぎるため、興味深いと思われるいくつかのイメージに注目します。fire6-squeeze1x1 層で最も強い活性化を表示します。

[maxValue6,maxValueIndex6] = max(max(max(act6)));
act6chMax = act6(:,:,:,maxValueIndex6);
imshow(imresize(mat2gray(act6chMax),imgSize))

この場合、最大の活性化チャネルには他のいくつかのチャネルほど興味深い詳細な特徴がなく、強い負の (色の濃い) 活性化と正の (色の薄い) 活性化が表示されます。このチャネルは、顔に焦点を当てている可能性があります。

すべてのチャネルのグリッドには、目に対して活性化するチャネルがあります。チャネル 14 および 47 をさらに詳細に調べます。

I = imtile(imresize(mat2gray(act6(:,:,:,[14 47])),imgSize));
imshow(I)

多くのチャネルには、色の薄い活性化領域と色の濃い活性化領域の両方が含まれています。これらはそれぞれ、正の活性化と負の活性化です。ただし、fire6-squeeze1x1 層の後には正規化線形ユニット (ReLU) が続くため、使用されるのは正の活性化のみです。正の活性化のみを調べるには、解析を繰り返して fire6-relu_squeeze1x1 層の活性化を視覚化します。

act6relu = activations(net,im,'fire6-relu_squeeze1x1');
sz = size(act6relu);
act6relu = reshape(act6relu,[sz(1) sz(2) 1 sz(3)]);

I = imtile(imresize(mat2gray(act6relu(:,:,:,[14 47])),imgSize));
imshow(I)

fire6-squeeze1x1 層の活性化と比べて、fire6-relu_squeeze1x1 層の活性化は、顔の強い特徴が含まれるイメージの領域を明確に特定します。

チャネルによる目の認識のテスト

fire6-relu_squeeze1x1 層のチャネル 14 および 47 が、目に対して活性化するかどうかを確認します。片目を閉じている新しいイメージをネットワークに入力し、結果として得られる活性化を元のイメージの活性化と比較します。

片目を閉じているイメージを読み取って表示し、fire6-relu_squeeze1x1 層の活性化を計算します。

imClosed = imread('face-eye-closed.jpg');
imshow(imClosed)

act6Closed = activations(net,imClosed,'fire6-relu_squeeze1x1');
sz = size(act6Closed);
act6Closed = reshape(act6Closed,[sz(1),sz(2),1,sz(3)]);

イメージと活性化を 1 つの Figure 内にプロットします。

channelsClosed = repmat(imresize(mat2gray(act6Closed(:,:,:,[14 47])),imgSize),[1 1 3]);
channelsOpen = repmat(imresize(mat2gray(act6relu(:,:,:,[14 47])),imgSize),[1 1 3]);
I = imtile(cat(4,im,channelsOpen*255,imClosed,channelsClosed*255));
imshow(I)
title('Input Image, Channel 14, Channel 47');

活性化から、チャネル 14 と 47 の両方が個々の目に対して活性化し、口の周囲の領域に対してもある程度活性化することがわかります。

ネットワークに対して目について学習するように指定していないにもかかわらず、目がイメージのクラスを区別するために有益な特徴であると学習しています。以前の機械学習のアプローチでは通常、問題に固有の特徴を手動で作成していましたが、上記の深層畳み込みネットワークは有益な特徴を自動で学習することができます。たとえば、目を識別する学習が、ネットワークで豹と豹柄のカーペットを区別するのに役立つ可能性があります。

参考

| |

関連するトピック