この記事では、CNN モデルのカテゴリ視覚化入力画像 (クラス インプレッション マップ) を実装するための完全なコードを示し、これに基づいて敵対的なサンプル画像を生成します。
1. 完全なコード
前回の記事 でCNNの特徴可視化のコードを示しましたが、これをベースに少し修正することで、各カテゴリのフィードバックに応じて生成された入力画像を取得することができます。または、最初に完全なコードを指定します。
import torch
import torchvision.models as models
import cv2
import time
t0 = time.time()
mu = torch.Tensor([0.485, 0.456, 0.406]).unsqueeze(-1).unsqueeze(-1).cuda()
std = torch.Tensor([0.229, 0.224, 0.225]).unsqueeze(-1).unsqueeze(-1).cuda()
unnormalize = lambda x: x*std + mu
normalize = lambda x: (x-mu)/std
batch_size = 1
num_classes = 1000
model = models.resnet18(pretrained=True).cuda()
for params in model.parameters():
params.requires_grad = False
model.eval()
'''
mask = torch.zeros((batch_size,3,224,224), dtype=torch.bool).cuda()
mask[:,:,100:-100,100:-100] = True
'''
for clas in range(num_classes):
data = torch.rand(batch_size,3,224,224).cuda()
data.requires_grad = True
#optimizer = torch.optim.SGD([data], lr=6)#, momentum=0.99)
optimizer = torch.optim.Adam([data], lr=0.1, weight_decay=1e-6)
label = torch.tensor([clas]).cuda()
one_hot= torch.zeros((batch_size,num_classes), dtype=torch.bool).cuda()
label = label.reshape(-1,1)
one_hot.scatter_(1, label, 1)
for i in range(4001):
data1 = (data - data.min()) / (data.max() - data.min())
#data1 = data1 * mask
data1 = normalize(data1)
optimizer.zero_grad()
outputs = model(data1)
loss = - outputs[one_hot].sum()
loss.backward()
optimizer.step()
print('class:',outputs.max(1)[1].item())
print('time: %.2f'%(time.time()-t0))
data_i = data.clone()
data_i = (data_i - data_i.min()) / (data_i.max() - data_i.min())
#data_i = (data_i*mask)
data_i = data_i[0].permute(1,2,0).data.cpu().numpy()*255
data_i = data_i[...,::-1].astype('uint8') #注意cv2使用BGR顺序
cv2.imwrite('./class_impress/class_%d.png'%clas,data_i)
注: 損失関数が使用する対象カテゴリの出力値が最も大きく、従来の分類ネットワークと同様にクロスエントロピー CE を使用することも可能であると言われていますが、描画される可視化効果は良くなく、この損失を利用するのはあまり良くありません。
2. レンダリング
これらの生成された画像には、このカテゴリに対応する画像の影がいくつかあるように見えます。AlexNet の生成された画像にはまだ何かが見えますが、他のいくつかのネットワークの生成された画像は人間の目で認識するのが困難です。しかし、元のモデルを検証に使用すると、この生成されたグラフの対象カテゴリの認識確率は 100% に近いことがわかります。生成された画像を非常に鮮明で満足のいくレベルまで向上させるテクノロジーもいくつかありますが、これはこの記事の目的ではありません。興味がある場合は、私の他の記事
を読んでください。生成された画像はさらに優れています。 。
3. 小領域生成マップ
画像の小さな領域にのみ画像を生成するなど、入力に制約を課すこともできます。コードのマスク セクションを参照してください。この方法で生成された画像はごく一部にすぎませんが、認識ネットワークで 100% に近いターゲット カテゴリ認識確率を生成することができます。以下の図は、事前トレーニングされた ResNet18 によって生成された 100x100 および 24x24 サイズのカテゴリ生成グラフの例を示しています。
4. 攻撃的な敵対的なサンプルを生成する
なぜ狭いエリアでクラス印象マップを生成するのでしょうか? おそらく、これが攻撃対策のスキームであることは誰もがすでに推測しているでしょう。このような小さな画像はネットワーク認識の高い確率を生成する可能性があるため、この小さな画像を他の自然画像に追加すると、サンプル攻撃に対する方法が得られるのではないでしょうか? クラス 0 に対応する 100x100 で生成された画像と、クラス 8 に対応する 24x24 で生成された画像を元の画像に追加します。得られた敵対的サンプルの例を以下の図に示します。
100x100 のパッチ マップを使用して攻撃した場合、5000 枚の ImageNet 画像をテストしたところ、100% の攻撃率を達成しましたが、24x24 のパッチ マップを使用して攻撃した場合も、30% の攻撃率に達しました。
ただし、これはあくまでホワイトボックス攻撃手法であることに注意してください。上記の実験の小領域パッチ画像は ResNet18 で生成されたものであり、その攻撃画像は ResNet18 モデルでのみ有効です。他のモデルに置き換えると、攻撃は失敗します。これは、この方法で生成したクラス印象マップが、カテゴリのみに関連する普遍的なクラス印象マップではなく、モデルと強く相関する非常に過学習な結果であることも示しています。したがって、クラス インプレッション マップという用語は非常に正確で、特定のモデルによる特定のクラスの「印象」にすぎません。広大なニューラルネットワークの共通クラス印象を見つけることによってのみ、ブラックボックス攻撃手法を見つけることができるので、これは今後の課題です。