【Pytorch】Visualization of Feature Maps(5)——Deep Dream

news2025/1/24 4:53:47

在这里插入图片描述

学习参考来自:

  • PyTorch实现Deep Dream
  • https://github.com/duc0/deep-dream-in-pytorch

文章目录

  • 1 原理
  • 2 VGG 模型结构
  • 3 完整代码
  • 4 输出结果
  • 5 消融实验
  • 6 torch.norm()


1 原理

其实 Deep Dream大致的原理和【Pytorch】Visualization of Feature Maps(1)—— Maximize Filter 是有些相似的,前者希望整个 layer 的激活值都很大,而后者是希望某个 layer 中的某个 filter 的激活值最大。

在这里插入图片描述

这个图画的很好,递归只画了一层,下面来个三层的例子

在这里插入图片描述
CNN 处(def deepDream),指定网络的某一层,固定网络权重,开启输入图片的梯度,迭代指定层输出的负l2范数(相当于最大化该层激活),以改变输入图片。

loss = -out.norm() # 让负的变小, 正的变大

核心代码,loss 为指定特征图输出的二范数的负值,相当于放大了响应,负数负的更多,正数正的更多,二范数才越大,损失才越小

2 VGG 模型结构

VGG(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU(inplace=True)
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU(inplace=True)
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (6): ReLU(inplace=True)
    (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): ReLU(inplace=True)
    (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace=True)
    (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (13): ReLU(inplace=True)
    (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): ReLU(inplace=True)
    (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (18): ReLU(inplace=True)
    (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (20): ReLU(inplace=True)
    (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (22): ReLU(inplace=True)
    (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (25): ReLU(inplace=True)
    (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (27): ReLU(inplace=True)  # LAYER_ID 28
    (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (29): ReLU(inplace=True)  # LAYER_ID 30
    (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace=True)
    (2): Dropout(p=0.5, inplace=False)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace=True)
    (5): Dropout(p=0.5, inplace=False)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

(27): ReLU(inplace=True) # LAYER_ID 28
(29): ReLU(inplace=True) # LAYER_ID 30

3 完整代码

完整代码如下

# 导入使用的库
import torch
from torchvision import models, transforms
import torch.optim as optim
import numpy as np
from matplotlib import pyplot
from PIL import Image, ImageFilter, ImageChops

# 定义超参数
CUDA_ENABLED = True
LAYER_ID = 28  # the layer to maximize the activations through
NUM_ITERATIONS = 5  # number of iterations to update the input image with the layer's gradient
LR = 0.2

"we downscale the image recursively, apply the deep dream computation, scale up, and then" \
"blend with the original image"

NUM_DOWNSCALES = 20
BLEND_ALPHA = 0.5


# 定义好一些变量和图像的转换
class DeepDream:
    def __init__(self, image):
        self.image = image
        self.model = models.vgg16(pretrained=True)
        # print(self.model)
        if CUDA_ENABLED:
            self.model = self.model.cuda()
        self.modules = list(self.model.features.modules())

        # vgg16 use 224x224 images
        imgsize = 224
        self.mean = [0.485, 0.456, 0.406]
        self.std = [0.229, 0.224, 0.225]
        self.normalise = transforms.Normalize(
            mean=self.mean,
            std=self.std
        )

        self.transformPreprocess = transforms.Compose([
            transforms.Resize((imgsize, imgsize)),
            transforms.ToTensor(),
            self.normalise
        ])

        self.tensorMean = torch.Tensor(self.mean)
        if CUDA_ENABLED:
            self.tensorMean = self.tensorMean.cuda()

        self.tensorStd = torch.Tensor(self.std)
        if CUDA_ENABLED:
            self.tensorStd = self.tensorStd.cuda()

    def toimage(self, img):
        return img * self.tensorStd + self.tensorMean

    def deepDream(self, image, layer, iterations, lr):
        """核心代码
        :param image:
        :param layer:
        :param iterations:
        :param lr:
        :return:
        """
        transformed = self.transformPreprocess(image).unsqueeze(0)  # 前处理输入都会 resize 至 224x224
        if CUDA_ENABLED:
            transformed = transformed.cuda()
        input_img = torch.autograd.Variable(transformed, requires_grad=True)
        self.model.zero_grad()
        optimizer = optim.Adam([input_img.requires_grad_()], lr=lr)

        for _ in range(iterations):
            optimizer.zero_grad()
            out = input_img
            for layerid in range(layer):  # 28
                out = self.modules[layerid+1](out)  # self.modules[28] ReLU(inplace=True)
            # out, torch.Size([1, 512, 14, 14])
            loss = -out.norm()  # 负的变小,正的变大 -l2
            loss.backward()
            optimizer.step()
            # input_img.data = input_img.data + lr*input_img.grad.data
        # remove batchsize, torch.Size([1, 3, 224, 224]) ->torch.Size([3, 224, 224])
        input_img = input_img.data.squeeze()
        # c,h,w 转为 h,w,c 以便于可视化
        input_img.transpose_(0, 1)  # torch.Size([224, 3, 224])
        input_img.transpose_(1, 2)  # torch.Size([224, 224, 3])
        input_img = self.toimage(input_img)  # torch.Size([224, 224, 3])
        if CUDA_ENABLED:
            input_img = input_img.cpu()
        input_img = np.clip(input_img, 0, 1)
        return Image.fromarray(np.uint8(input_img*255))

    # 可视化中间迭代的过程
    def deepDreamRecursive(self, image, layer, iterations, lr, num_downscales):
        """
        :param image:
        :param layer:
        :param iterations:
        :param lr:
        :param num_downscales:
        :return:
        """
        if num_downscales > 0:
            # scale down the image
            image_gauss = image.filter(ImageFilter.GaussianBlur(2))  # 高斯模糊
            half_size = (int(image.size[0]/2), int(image.size[1]/2))  # 长宽缩放 1/2
            if (half_size[0]==0 or half_size[1]==0):
                half_size = image.size
            image_half = image_gauss.resize(half_size, Image.ANTIALIAS)

            # return deepDreamRecursive on the scaled down image
            image_half = self.deepDreamRecursive(image_half, layer, iterations, lr, num_downscales-1)

            print("Num Downscales: {}".format(num_downscales))
            print("====Half Image====", np.shape(image_half))
            # pyplot.imshow(image_half)
            # pyplot.show()

            # scale up the result image to the original size
            image_large = image_half.resize(image.size, Image.ANTIALIAS)
            print("====Large Image====", np.shape(image_large))
            # pyplot.imshow(image_large)
            # pyplot.show()

            # Blend the two image
            image = ImageChops.blend(image, image_large, BLEND_ALPHA)
            print("====Blend Image====", np.shape(image))
            # pyplot.imshow(image)
            # pyplot.show()

        img_result = self.deepDream(image, layer, iterations, lr)  # 迭代改变输入图片,max activation
        print(np.shape(img_result))
        img_result = img_result.resize(image.size)
        print(np.shape(img_result))
        # pyplot.imshow(img_result)
        # pyplot.show()
        return img_result

    def deepDreamProcess(self):
        return self.deepDreamRecursive(self.image, LAYER_ID, NUM_ITERATIONS, LR, NUM_DOWNSCALES)


if __name__ == "__main__":
    img = Image.open("cat.png").convert('RGB')
    # 生成
    img_deep_dream = DeepDream(img).deepDreamProcess()
    pyplot.title("Deep dream images")
    pyplot.imshow(img_deep_dream)
    pyplot.show()

4 输出结果

output

    """
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 1
    ====half Image==== (1, 1, 3)
    ====Large Image==== (1, 1, 3)
    ====Blend Image==== (1, 1, 3)
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 2
    ====half Image==== (1, 1, 3)
    ====Large Image==== (1, 1, 3)
    ====Blend Image==== (1, 1, 3)
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 3
    ====half Image==== (1, 1, 3)
    ====Large Image==== (1, 1, 3)
    ====Blend Image==== (1, 1, 3)
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 4
    ====half Image==== (1, 1, 3)
    ====Large Image==== (1, 1, 3)
    ====Blend Image==== (1, 1, 3)
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 5
    ====half Image==== (1, 1, 3)
    ====Large Image==== (1, 1, 3)
    ====Blend Image==== (1, 1, 3)
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 6
    ====half Image==== (1, 1, 3)
    ====Large Image==== (1, 1, 3)
    ====Blend Image==== (1, 1, 3)
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 7
    ====half Image==== (1, 1, 3)
    ====Large Image==== (1, 1, 3)
    ====Blend Image==== (1, 1, 3)
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 8
    ====half Image==== (1, 1, 3)
    ====Large Image==== (1, 1, 3)
    ====Blend Image==== (1, 1, 3)
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 9
    ====half Image==== (1, 1, 3)
    ====Large Image==== (1, 1, 3)
    ====Blend Image==== (1, 1, 3)
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 10
    ====half Image==== (1, 1, 3)
    ====Large Image==== (1, 1, 3)
    ====Blend Image==== (1, 1, 3)
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 11
    ====half Image==== (1, 1, 3)
    ====Large Image==== (1, 1, 3)
    ====Blend Image==== (1, 1, 3)
    (224, 224, 3)
    (1, 1, 3)
    Num Downscales: 12
    ====half Image==== (1, 1, 3)
    ====Large Image==== (2, 2, 3)
    ====Blend Image==== (2, 2, 3)
    (224, 224, 3)
    (2, 2, 3)
    Num Downscales: 13
    ====half Image==== (2, 2, 3)
    ====Large Image==== (5, 5, 3)
    ====Blend Image==== (5, 5, 3)
    (224, 224, 3)
    (5, 5, 3)
    Num Downscales: 14
    ====half Image==== (5, 5, 3)
    ====Large Image==== (11, 11, 3)
    ====Blend Image==== (11, 11, 3)
    (224, 224, 3)
    (11, 11, 3)
    Num Downscales: 15
    ====half Image==== (11, 11, 3)
    ====Large Image==== (23, 23, 3)
    ====Blend Image==== (23, 23, 3)
    (224, 224, 3)
    (23, 23, 3)
    Num Downscales: 16
    ====half Image==== (23, 23, 3)
    ====Large Image==== (47, 47, 3)
    ====Blend Image==== (47, 47, 3)
    (224, 224, 3)
    (47, 47, 3)
    Num Downscales: 17
    ====half Image==== (47, 47, 3)
    ====Large Image==== (94, 94, 3)
    ====Blend Image==== (94, 94, 3)
    (224, 224, 3)
    (94, 94, 3)
    Num Downscales: 18
    ====half Image==== (94, 94, 3)
    ====Large Image==== (188, 188, 3)
    ====Blend Image==== (188, 188, 3)
    (224, 224, 3)
    (188, 188, 3)
    Num Downscales: 19
    ====half Image==== (188, 188, 3)
    ====Large Image==== (376, 376, 3)
    ====Blend Image==== (376, 376, 3)
    (224, 224, 3)
    (376, 376, 3)
    Num Downscales: 20
    ====half Image==== (376, 376, 3)
    ====Large Image==== (753, 753, 3)
    ====Blend Image==== (753, 753, 3)
    (224, 224, 3)
    (753, 753, 3)
    """

在这里插入图片描述


部分结果展示

Num Downscales: 15
在这里插入图片描述
Num Downscales: 16
在这里插入图片描述
Num Downscales: 17
在这里插入图片描述
Num Downscales: 18
在这里插入图片描述
Num Downscales: 19
在这里插入图片描述
Num Downscales: 20
在这里插入图片描述

5 消融实验

NUM_DOWNSCALES = 50

在这里插入图片描述

NUM_ITERATIONS = 10

在这里插入图片描述

LAYER_ID = 23

在这里插入图片描述
LAYER_ID = 30

在这里插入图片描述

6 torch.norm()

torch.norm() 是 PyTorch 中的一个函数,用于计算输入张量沿指定维度的范数。具体而言,当给定一个输入张量 x 和一个整数 p 时,torch.norm(x, p) 将返回输入张量 x 沿着最后一个维度(默认为所有维度)上所有元素的 p 范数,p 默认为 2。

除了使用标量 p 之外,torch.norm() 还接受以下参数:

  • dim:指定沿哪个轴计算范数,默认对所有维度计算。
  • keepdim:如果设置为 True,则输出张量维度与输入张量相同,其中指定轴尺寸为 1;否则,将从输出张量中删除指定轴。
  • out:可选输出张量结果。

PyTorch中torch.norm函数详解

import torch

x = torch.tensor([[1, 2, 3, 4],
                 [5, 6, 7, 8],
                 [9, 10, 11, 12]], dtype=torch.float32)
print(x.norm())
print(x.norm(1))
print(x.norm(2))

output

tensor(25.4951)
tensor(78.)
tensor(25.4951)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1268291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3dMax导出glft和glb格式模型插件Max2Babylon教程

为了满足Autodesk提供自己的导出管道之前的迫切需要,Babylon.js导出器可用于3dMax。导出器可以将3dMax场景导出为.glTF文件、.glb文件或.babylon文件。 【适用版本】 3dMax2015 - 2024 【安装方法】 1.选择和自己电脑中3dMax所对应的插件版本,解压缩。…

JOSEF约瑟 逆功率继电器 GG-21 5a 100v 50hz

系列型号 GG-21逆功率继电器 GG-22过载继电器 1 用途 逆功率继电器GG-21/5A/100V 在出现逆功率时,从电网中断开交流发电机。 2 概述 逆功率继电器是基于感应式原理(具有旋转磁场)而工作。 继电器导磁体由两个磁路系统组成:上磁路系统和下磁路系统…

箭头函数与普通函数:谁更胜一筹?

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

数据结构 -- 图论之最小生成树

目录 1.最小生成树算法 1.Kruskal算法 2.Prim算法 1.最小生成树算法 定义:最小生成树算法:连通图有n个顶点组成,那么此时的图的每一个点都能相互连接并且边的个数为n-1条,那么此时该图就是最小生成树. 下面量算法有几个共同的特点: 1.只能使用图中权值最小的边来构造生成树 …

F. Magic Will Save the World

首先积攒了能量打了怪再积攒是没有意义的,可以直接积攒好,然后一次性进行攻击 那么怎么进行攻击了?可以尽量的多选怪物使用水魔法攻击剩余的再用火魔法进行攻击, 也就是只要存在合法的体积(即装入背包的怪物的体积之…

谷粒商城-商品服务三级分类功能·-后端代码

递归获取树形结构 CategoryController RequestMapping("/list/tree")public R list(){List<CategoryEntity> entities categoryService.listWithTree();return R.ok().put("data",entities);}CategoryServiceImpl 第一步&#xff1a; 1.查出所有分类…

MySQL 中的锁(三)

8.7. 死锁和空间锁 一般来说&#xff0c;只要有并发和加锁这两种情况的共同加持下&#xff0c;都会有死锁的身影。 死锁的具体成因&#xff0c;借用我们在并发编程中的内容&#xff1a; 8.7.1. 死锁 8.7.1.1. 概念 是指两个或两个以上的进程在执行过程中&#xff0c;由于竞…

史上最全接单平台集锦,程序员不容错过!

非典型程序员不是每天都累成狗&#xff0c;天天”996"甚至”007“。可能&#xff0c;面临着上班摸鱼没事干&#xff0c;下班躺尸打游戏的无聊境况。那么&#xff0c;如果你也是这样的程序员&#xff0c;有没有什么安排可以打发时间&#xff1f; 闲着还不如挣钱~心情好的时…

聚焦 6G 无线技术——目标和需求

从 3G 到 5G 乃至之后的每一种无线标准&#xff0c;都在设计时加入了推动行业发展的具体目标。例如&#xff0c;4G 专注于以 IP 为中心的灵活语音、数据和视频通信&#xff0c;而 5G 则在此基础上进行了改进。6G 的目标是提供更加无处不在、更高效、更身临其境的无线连接。6G 系…

记录一次YAMLException异常

记录一次YAMLException异常 ✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 报错以及B…

【从删库到跑路 | MySQL总结篇】表的增删查改(进阶下)

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】&#x1f388; 本专栏旨在分享学习MySQL的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、联合…

Linux常用命令----touch命令

文章目录 Linux操作系统中&#xff0c;touch 命令是一个常用且强大的工具&#xff0c;主要用于创建空文件或设置文件的时间戳。本文将详细介绍 touch 命令的各种参数及其用法&#xff0c;并通过实例演示来加深理解。 1. touch命令基础 touch 命令的基本语法格式为&#xff1a…

鸿蒙4.0开发笔记之ArkTS装饰器语法基础@Extend扩展组件样式与stateStyles多态样式(十一)

一、Extend扩展组件样式 1、作用 前文提到可以使用Styles用于样式的扩展&#xff0c;在Styles的基础上&#xff0c;ArkTS语法还提供了Extend&#xff0c;⽤于扩展原生组件样式&#xff0c;包括Text、Button等等。 2、定义语法 Extend(UIComponentName) function functionNam…

Flutter下拉框使用和可替换按钮的组件

前言 1、下拉框 在使用flutter框架完成项目的时候&#xff0c;有一个下拉框选择排序条件的需求&#xff0c;需要将下拉的选择内容&#xff0c;放在下拉按钮的下面&#xff0c;如Unity的Dropdown。下图是完整的需求。但是flutter系统自带的DropdownButtonFormField&#xff0c…

RabbitMQ消息模型之Work Queues

Work Queues Work Queues&#xff0c;也被称为&#xff08;Task Queues&#xff09;&#xff0c;任务模型&#xff0c;也是官网给出的第二个模型&#xff0c;使用的交换机类型是直连direct&#xff0c;也是默认的交换机类型。当消息处理比较耗时的时候&#xff0c;可能生产消息…

pkpmbs 建设工程质量监督系统 文件上传漏洞复现

0x01 产品简介 pkpmbs 建设工程质量监督系统是湖南建研信息技术股份有限公司一个与工程质量检测管理系统相结合的&#xff0c;B/S架构的检测信息监管系统。 0x02 漏洞概述 pkpmbs 建设工程质量监督系统 FileUpOrDown.aspx、/Platform/System/FileUpload.ashx、接口处存在任意文…

编程实现bf算法

BF算法&#xff08;Brute Force算法&#xff09;是一种朴素的字符串匹配算法&#xff0c;其基本思想是在文本串中不断地比较模式串和文本串中的子串&#xff0c;直到找到匹配的位置或者搜索完整个文本串。 下面是用Python实现BF算法的代码&#xff1a; def bf_search(text, p…

vuepress-----8、自定义域名

# 8、自定义域名 购买域名 [外链图片转存中…(img-0XcE3Zjv-1701236952478)] 填写域名、https # 自定义域名

【机器学习 | 可视化系列】可视化系列 之 决策树可视化

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

基于SSM的航空票务推荐系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…