本文给出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完整代码)相关推荐

  1. 好玩的Deep Dream

    参照<21个项目玩转深度学习>第4章实现的,Deep Dream是google公司在2015年公布的一项有趣技术,通过读取训练模型中某一层的结果值,添加噪声而得到一张结果图,deep Dr ...

  2. 生成式对抗网络实战(一)——手写数字生成(CPU本地版)完整代码加详解

    [注1]代码的原文来自以下网址,修改部分及增添注释(基本上都注释了).修改版整体见最后,原版下方链接,均可以跑通,有问题欢迎交流.生成对抗网络GAN---生成mnist手写数字图像示例( 附代码)_陶 ...

  3. 【深度强化学习】(4) Actor-Critic 模型解析,附Pytorch完整代码

    大家好,今天和各位分享一下深度强化学习中的 Actor-Critic 演员评论家算法,Actor-Critic 算法是一种综合了策略迭代和价值迭代的集成算法.我将使用该模型结合 OpenAI 中的 G ...

  4. 【深度强化学习】(6) PPO 模型解析,附Pytorch完整代码

    大家好,今天和各位分享一下深度强化学习中的近端策略优化算法(proximal policy optimization,PPO),并借助 OpenAI 的 gym 环境完成一个小案例,完整代码可以从我的 ...

  5. 【深度强化学习】(5) DDPG 模型解析,附Pytorch完整代码

    大家好,今天和各位分享一下深度确定性策略梯度算法 (Deterministic Policy Gradient,DDPG).并基于 OpenAI 的 gym 环境完成一个小游戏.完整代码在我的 Git ...

  6. 【图像分类案例】(10) Vision Transformer 动物图像三分类,附Pytorch完整代码

    大家好,今天和各位分享一下如何使用 Pytorch 构建 Vision Transformer 网络模型,并使用 权重迁移学习方法 训练模型并预测. Vision Transformer 的原理和 T ...

  7. 通用版!完整代码,单链表SingleLinkedList增删改查,反转,逆序,有效数据等Java实现

    文章目录 节点类 链表类(主要) 测试类 小结 节点类 可以根据需要,对节点属性进行修改.注意重写toString()方法,以便后续的输出操作. //节点类 class Node {public in ...

  8. C语言——简易版通讯录完整代码

    目录 一.Contact.h 二.Contact.c 三.test.c 一.Contact.h #pragma once #include <stdio.h> #include <s ...

  9. 近期风靡互联网的Deep Dream人工智能图像识别软件

    code: https://github.com/google/deepdream/blob/master/dream.ipynb 声明:本译文包含六篇以上原外文内容,现汇合一处,附有大量的链接.实际 ...

最新文章

  1. 基于Hash的消息认证码HMAC简介及在OpenSSL中使用举例
  2. 10分钟完成一个业务流程的发布
  3. voxelnet_ue4商城资源Voxel Sandbox Toolkit体素沙盒工具箱
  4. python3urllib常见使用_Python3 urllib常用操作
  5. 从天而降的文字,文字掉落效果
  6. hadoop 3.x 关闭安全模式
  7. java linux ping ip,java linux ping命令
  8. Java报错 -- The public type c must be defined in its own file
  9. c++ primer plus 内存模型和名称空间
  10. linux python-3.10.4 安装
  11. Discuz网站地图在线生成
  12. 备战数学建模2——MATLAB导入数据,处理缺失值
  13. ASCII码与16进制的互相转换(表)
  14. 获取硬件序列号(注册机)
  15. 关于tink的碰撞检测类【1】
  16. CAPA换届大会召开,发布信息无障碍最新报告及“可及APP”
  17. python运维工具开源_开源运维自动化平台-opendevops
  18. MFC简单自学图形绘制1
  19. 四位二进制、十进制、四位十六进制相互转换(高位补零)python
  20. Open-falcon技术系列文章——安装部署open-falcon

热门文章

  1. 如何优化页面的响应速度 以及如何减少项目初次加载时间(转https://www.cnblogs.com/MarcoHan/p/5295398.html)...
  2. 关于cookie 跨页面处理
  3. 第四章 源代码的下载和编译
  4. 数据结构——HDU1312:Red and Black(DFS)
  5. 逼出的成功,强迫的辉煌
  6. 扩展方法的定义及使用
  7. POJ 1047 Round and Round We Go
  8. 官方公布94本预警期刊名单,其中5本高风险
  9. 撰写科技奖励申报材料的“思路”“要点”与“技巧”
  10. java自定义jsp标签_深入浅出javaWeb实战第17讲自定义JSP标签(上)