pytorch简单代码实现deep dream图(即CNN特征可视化 features visualization)
??本文給出完整代碼實現CNN特征的可視化輸入圖像,也就是簡單的deep dream圖,有助于更好的理解CNN工作原理,并掌握用梯度上升法生成滿足要求輸入圖像的技術。更清晰美觀的deep dream圖需要加入一些其他技巧,可以參考我另一篇文章。
1,原理
??深度網絡的常規工作過程是,給定輸入樣本及標簽,前向處理后的輸出結果和標簽計算出某種損失函數,再由損失函數反向傳播求網絡各參數的梯度,根據此梯度更新參數,以使損失函數減小,逐漸訓練得到一個逼近標簽的網絡。
??有趣的是,我們也可以反向思維,固定網絡的參數不變,而是優化輸入圖像。根據某項指標求得輸入圖像的梯度,再根據此梯度優化輸入,就可以得到滿足要求的輸入圖像。由于往往需要最大化某種指標,與通常最小化損失函數的梯度下降法不同,所以這種方法也被稱為梯度上升法。在程序實現上,為了利用SGD,Adam等成熟的梯度下降優化算法,我們只需要給指標加個負號,也就變成和梯度下降一樣了。
??如果我們把特征圖的某個部分的均值作為最大化的指標,此時就可以得到使指定特征圖部分最大響應的輸入圖,也就能夠直觀的看出指定部分的特征圖到底處理的是什么類型的特征。這個指定的特征圖部分可以是某個層,也可以是某個層的某個通道,甚至也可以是某個通道上某個元素。我們先來看單個元素的情況:
2,指定特征圖單個元素的最大響應輸入圖像可視化
import torch import torchvision.models as models import cv2 import time t0 = time.time()model = models.resnet18(pretrained=True).cuda() batch_size = 1for params in model.parameters():params.requires_grad = False model.eval()def hook(module,inp,out):global featuresfeatures = outdata = torch.rand(batch_size,3,224,224).cuda() data.requires_grad=Truemu = 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#optimizer = torch.optim.SGD([data], lr=1, momentum=0.99) #參數需根據實際情況再調 optimizer = torch.optim.Adam([data], lr=0.1, weight_decay=1e-6) myhook = model.layer2.register_forward_hook(hook) n,h,w = 0,3,8 for i in range(4001):x = (data - data.min()) / (data.max() - data.min())x = normalize(x)_ = model(x)loss = - features[:,n,h,w].mean() #指定元素#loss = - features[:,n,:,:].mean() #指定通道#loss = - features.mean() #指定層optimizer.zero_grad()loss.backward()optimizer.step()if i%100==0:print('data.abs().mean():',data.abs().mean().item())print('loss:',loss.item())print('time: %.2f'%(time.time()-t0)) myhook.remove() data_i = data[0] data_i = (data_i - data_i.min()) / (data_i.max() - data_i.min()) data_i = data_i.permute(1,2,0).data.cpu().numpy()*255 data_i = data_i[...,::-1].astype('uint8') #注意cv2使用BGR順序 cv2.imwrite('./feature_visual/layer2_filter%d.png'%n,data_i)完整代碼如上,我們以torchvision中的預訓練resnet18為例,按照大的模塊劃分,resnet18中有4個layer,畫出每個layer中某個元素對應的輸入特征圖如下:
從圖中還可以看出,每個特征元素在輸入圖像上的感受野有多大,顯然越靠后層元素的感受野越大。
3,指定通道
圖2.resnet18不同層指定通道最大響應輸入圖像可以看出,前序層的輸入響應圖都是一些均勻的紋理圖,顯然是圖像的更基礎的組成要素;隨著網絡越深,輸入響應圖則逐漸呈現出更加全局性的一些圖像概念,以及更加高級和接近實物的一些圖像概念,有些似乎是某種實物的形狀特征。
我們還可以看出,單個通道的響應中可以看到多個類別的圖像的“影子”,所以通道并不是類別依賴的。
4,指定層
圖3.resnet18不同層最大響應輸入圖像5,其他一些網絡
圖4.其他網絡最末卷積層不同通道的最大響應輸入圖像可以看出,不同網絡的風格還是很不相同的,其中densenet不像別的那么惡心,還挺好看。
總結
以上是生活随笔為你收集整理的pytorch简单代码实现deep dream图(即CNN特征可视化 features visualization)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pytorch autograd整理
- 下一篇: pytorch制作CNN的类印象图 cl