日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

好玩的deep dream(清晰版,pytorch完整代码)

發布時間:2025/3/8 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 好玩的deep dream(清晰版,pytorch完整代码) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??本文給出pytorch完整代碼實現deep dream,加入了圖像金字塔處理和高斯平滑處理,使生成圖更加清晰美觀。文中還討論了各種因素對生成圖的影響。

1, 完整代碼

??Deep dream圖是反向生成的使某層輸出特征最大化的輸入圖像,可以認為是特征的可視化圖,可以幫助我們理解每層網絡學到了什么東西,deep dream圖也很好玩,可以生成一些漂亮有趣的圖片。在上一篇文章中我們已經就主要原理進行了介紹,但是上篇使用的簡單方法生成的圖不美觀。我這次加入了在github上找到的圖像金字塔處理和高斯平滑處理代碼,使生成結果更加漂亮了,上完整代碼:

import torch import torchvision.models as models import torch.nn.functional as F import torch.nn as nn import numpy as np import numbers import math import cv2 from PIL import Image from torchvision.transforms import Compose, ToTensor, Normalize, Resize, ToPILImage import time t0 = time.time()model = models.vgg16(pretrained=True).cuda() batch_size = 1for params in model.parameters():params.requires_grad = False model.eval()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)/stdtransform_test = Compose([Resize((500,600)),ToTensor(),Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), ])class CascadeGaussianSmoothing(nn.Module):"""Apply gaussian smoothing separately for each channel (depthwise convolution).Arguments:kernel_size (int, sequence): Size of the gaussian kernel.sigma (float, sequence): Standard deviation of the gaussian kernel."""def __init__(self, kernel_size, sigma):super().__init__()if isinstance(kernel_size, numbers.Number):kernel_size = [kernel_size, kernel_size]cascade_coefficients = [0.5, 1.0, 2.0] # std multipliers, hardcoded to use 3 different Gaussian kernelssigmas = [[coeff * sigma, coeff * sigma] for coeff in cascade_coefficients] # isotropic Gaussianself.pad = int(kernel_size[0] / 2) # assure we have the same spatial resolution# The gaussian kernel is the product of the gaussian function of each dimension.kernels = []meshgrids = torch.meshgrid([torch.arange(size, dtype=torch.float32) for size in kernel_size])for sigma in sigmas:kernel = torch.ones_like(meshgrids[0])for size_1d, std_1d, grid in zip(kernel_size, sigma, meshgrids):mean = (size_1d - 1) / 2kernel *= 1 / (std_1d * math.sqrt(2 * math.pi)) * torch.exp(-((grid - mean) / std_1d) ** 2 / 2)kernels.append(kernel)gaussian_kernels = []for kernel in kernels:# Normalize - make sure sum of values in gaussian kernel equals 1.kernel = kernel / torch.sum(kernel)# Reshape to depthwise convolutional weightkernel = kernel.view(1, 1, *kernel.shape)kernel = kernel.repeat(3, 1, 1, 1)kernel = kernel.cuda()gaussian_kernels.append(kernel)self.weight1 = gaussian_kernels[0]self.weight2 = gaussian_kernels[1]self.weight3 = gaussian_kernels[2]self.conv = F.conv2ddef forward(self, input):input = F.pad(input, [self.pad, self.pad, self.pad, self.pad], mode='reflect')# Apply Gaussian kernels depthwise over the input (hence groups equals the number of input channels)# shape = (1, 3, H, W) -> (1, 3, H, W)num_in_channels = input.shape[1]grad1 = self.conv(input, weight=self.weight1, groups=num_in_channels)grad2 = self.conv(input, weight=self.weight2, groups=num_in_channels)grad3 = self.conv(input, weight=self.weight3, groups=num_in_channels)return (grad1 + grad2 + grad3) / 3#data = torch.ones(batch_size,3,500,600).cuda()*0.5 #data = normalize(data) n = 0 #某層特征的第n個通道 data = Image.open('./feature_visual/gray.jpg')#使用一張初始圖片 data = transform_test(data).unsqueeze(0).cuda()H,W = data.shape[2],data.shape[3] #data.requires_grad=True input_tensor = data.clone()def hook(module,inp,out):global featuresfeatures = out myhook = model.features[22].register_forward_hook(hook)levels, ratio = 4, 1.8 lr=0.2 IMAGENET_MEAN_1 = np.array([0.485, 0.456, 0.406], dtype=np.float32) IMAGENET_STD_1 = np.array([0.229, 0.224, 0.225], dtype=np.float32) LOWER_IMAGE_BOUND = torch.tensor((-IMAGENET_MEAN_1 / IMAGENET_STD_1).reshape(1, -1, 1, 1)).cuda() UPPER_IMAGE_BOUND = torch.tensor(((1 - IMAGENET_MEAN_1) / IMAGENET_STD_1).reshape(1, -1, 1, 1)).cuda() for pyramid_level in range(levels):#使用圖像金字塔方法,逐漸放大分辨率data = input_tensor.detach()h = int(np.round(H*(1.8**(pyramid_level - levels + 1))))w = int(np.round(W*(1.8**(pyramid_level - levels + 1))))input_tensor = F.interpolate(data,(h,w),mode='bilinear')input_tensor.requires_grad=Truefor i in range(20):_ = model(input_tensor)loss = features[:,n,:,:].mean() #指定通道#loss = features.mean() #指定層loss.backward()grad = input_tensor.gradsigma = ((i + 1) / 20) * 2.0 + 0.5smooth_grad = CascadeGaussianSmoothing(kernel_size=9, sigma=sigma)(grad) # "magic number" 9 just works wellg_std = torch.std(smooth_grad)g_mean = torch.mean(smooth_grad)smooth_grad = smooth_grad - g_meansmooth_grad = smooth_grad / g_stdinput_tensor.data += lr * smooth_gradinput_tensor.grad.zero_()input_tensor.data = torch.max(torch.min(input_tensor, UPPER_IMAGE_BOUND), LOWER_IMAGE_BOUND)print('data.mean():',input_tensor.mean().item(),input_tensor.std().item())print('loss:',loss.item())print('time: %.2f'%(time.time()-t0)) myhook.remove() data_i = input_tensor.clone() data_i = unnormalize(data_i) data_i = torch.clamp(data_i,0,1) data_i = data_i[0].permute(1,2,0).data.cpu().numpy()*255 data_i = data_i[...,::-1].astype('uint8') #注意cv2使用BGR順序 cv2.imwrite('./feature_visual/densenet161block3denselayer36relu2/filter%d.jpg'%n,data_i)

2, 效果

我們先看看使用torchvision預訓練模型vgg16和densenet161的某些層特征圖的某個通道(如下圖第一幅是指vgg16網絡relu4_3層的第2個通道)進行反推得到的生成圖。

圖1.vgg16的22層(relu4_3層)和densenet161的block3層部分通道生成的deep dream圖

??從這些圖可以看出某個特定的特征層到底提取的是哪種特征,而且它們像藝術圖一樣漂亮!
??下圖再給出網絡不同層的deep dream圖:

圖2.densenet161各層的deep dream圖

??可以看出,淺層輸出生成的deep dream圖呈現出一些簡單的條紋和色彩特征,隨著網絡加深,生成的deep dream圖逐漸變得豐富。最漂亮的一般是中間偏后的層,例如上面的block3,再往后的層,信息會更豐富但也更雜亂一些,視覺效果不是很好。
??下面再給出從最后層輸出(也就是分類的類別)反推得到的生成圖,這種圖也可以稱之為類印象圖,類印象圖的概念在我另一篇文章中有介紹。我們使用ImageNet的第0類丁鱥魚,觀察在幾種不同預訓練網絡上的類印象圖。

圖3.幾種網絡的類印象圖,ImageNet編號0類:丁鱥魚

??感覺AlexNet的類印象圖更直觀一些,而更深的網絡的類印象圖反而不是很直觀。
??使用上面的代碼并不受網絡輸入圖片分辨率的限制,可以生成任意分辨率的圖片,都很清晰!下面感受一下生成的一張1024 x 1024大圖的效果。

圖4.大分辨率deep dream圖, resnet18.layer3 filter2, 1024x1024

3,圖像金字塔的作用

圖5.分別使用1~4級圖像金字塔的生成圖, resnet18.layer3 filter37

??使用圖像金字塔的作用是使圖像中出現有大有小不同尺寸的紋路,使圖片顯得有層次感,看起來更加美觀而不單調。

4, 高斯平滑的作用

圖6.使用和不使用高斯平滑的效果對比,左邊不使用,右邊使用

??不使用高斯平滑時生成圖會有一些高頻噪點,顯得圖像不夠清晰,使用高斯平滑可以去掉。

5, 初始圖像的作用

??初始圖像好比是一顆種子,隨著每次迭代生成圖在初始圖的基礎上不斷發展,初始圖的輪廓則在生成圖中持續存在,這一點很有趣,使我們可以更靈活的按照需要引導生成圖。

圖7.各種初始圖的生成圖

總結

以上是生活随笔為你收集整理的好玩的deep dream(清晰版,pytorch完整代码)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。