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

在这里插入图片描述

学习参考来自:

  • 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)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一起学docker系列之十七Docker Compose 与手动操作的比较与优势分析

目录 1 前言2 不使用 Docker Compose2.1 启动 MySQL 容器2.2 启动 Redis 容器2.3 启动微服务容器 3 使用 Docker Compose4 使用 Docker Compose 的优势5 结语参考地址 1 前言 在当今容器化应用的开发与部署中,容器编排工具的选择对于简化流程、提高效率至关重要。本…

蓝桥杯第1037题子串分值和 C++ 字符串 逆向思维 巧解

题目 思路和解题方法 方案一——遍历哈希表 仅能过60%样例,大多数同学都用的该方法&#xff0c;就不过多赘述 #include <iostream> #include <unordered_map> using namespace std; int main() {string s;cin >> s;int n s.size();int res n;for (int i 0…

未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序报错的解决办法

当在本地计算机上使用Microsoft Office相关库时&#xff0c;可能会出现“未在本地计算机上注册microsoft.ACE.oledb.12.0”提供程序的报错。这是由于缺少相关的驱动程序或者未安装相应的软件所导致的。下面是解决该问题的完整攻略。 可能是因为没有安装数据访问组件&#xff0…

反序列化漏洞(二)

目录 pop链前置知识&#xff0c;魔术方法触发规则 pop构造链解释&#xff08;开始烧脑了&#xff09; 字符串逃逸基础 字符减少 字符串逃逸基础 字符增加 实例获取flag 字符串增多逃逸 字符串减少逃逸 延续反序列化漏洞(一)的内容 pop链前置知识&#xff0c;魔术方法触…

树基本概念+前中后序遍历二叉树

&#x1f308;一、树的基本概念 ☀️1.树的定义&#xff1a;树是一种非线性结构&#xff0c;看起来像一棵倒挂的树&#xff0c;根朝上&#xff0c;而叶朝下。 ☀️2.相关术语 1.根节点&#xff1a;图中的A&#xff0c;无前驱结点 2.叶节点&#xff08;终端节点&#xff09;&a…

iptables——建立linux安全体系

目录 一. 安全技术类型 二. linux防火墙 1. 按保护范围划分&#xff1a; 2. 按实现方式划分&#xff1a; 3. 按网络协议划分&#xff1a; 4. 防火墙原理 三. 防火墙工具——iptables 1. netfilter 中五个勾子函数和报文流向 数据包传输过程&#xff1a; ① .五表四链…

设计模式-结构型模式之外观设计模式

文章目录 七、外观模式 七、外观模式 外观模式&#xff08;Facade Pattern&#xff09;隐藏系统的复杂性&#xff0c;并向客户端提供了一个客户端可以访问系统的接口。它向现有的系统添加一个接口&#xff0c;来隐藏系统的复杂性。 这种模式涉及到一个单一的类&#xff0c;该类…

爬虫-xpath篇

1.xpath的基础语法 表达式描述nodename选中该元素/从根节点选取、或者是元素和元素间的过渡//从匹配选择的当前节点选择文档中的节点&#xff0c;而不考虑它们的位置.选取当前节点…选取当前节点的父节点选取属性text()选取文本 举例&#xff1a; 路径表达式结果html选择html元…

使用java批量生成Xshell session(*.xsh)文件

背景 工作中需要管理多套环境, 有时需要同时登陆多个节点, 且每个环境用户名密码都一样, 因此需要一个方案来解决动态的批量登录问题. XShell Xshell有session管理功能: 提供了包括记住登录主机、用户名、密码及登录时执行命令或脚本(js,py,vbs)的功能 session被存储在xsh文…

6-49.自定义的学生类

本题要求定义一个简单的学生类&#xff0c;数据成员仅需要定义学号和姓名&#xff0c;函数成员的原型见给出的代码&#xff0c;请给出函数成员的类外完整实现。 其中m_id和m_name分别表示学生的学号和姓名&#xff0c;类型已经定义好。类内声明了3个成员函数&#xff0c;分别表…

Linux docker批量安装软件

1.前提 具备docker-compose.yml 和 prometheus.yml 文件 常见报错&#xff1a; 1.没有配置network 配置network即可&#xff1a; 2.缺少相关依赖 docker-compose.yml加入相关配置 3.重复项 删除掉重复的 最后 执行 等待完成 下载后相当于有了这些软件包的镜像 启动的每…

大数据Hadoop-HDFS_架构、读写流程

大数据Hadoop-HDFS 基本系统架构 HDFS架构包含三个部分&#xff1a;NameNode&#xff0c;DataNode&#xff0c;Client。 NameNode&#xff1a;NameNode用于存储、生成文件系统的元数据。运行一个实例。 DataNode&#xff1a;DataNode用于存储实际的数据&#xff0c;将自己管理…

OpenHarmony亮相MTSC 2023 | 质量效率共进,赋能应用生态发展

11月25日&#xff0c;MTSC 2023第十二届中国互联网测试开发大会在深圳登喜路国际大酒店圆满举行。大会以“软件质量保障体系和测试研发技术交流”为主要目的&#xff0c;旨在为行业搭建一个深入探讨和交流的桥梁和平台。OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&a…

Langchain-Chatchat的安装过程

参考&#xff1a;LLMs之RAG&#xff1a;LangChain-Chatchat(一款中文友好的全流程本地知识库问答应用)的简介(支持 FastChat 接入的ChatGLM-2/LLaMA-2等多款主流LLMs多款embe_一个处女座的程序猿的博客-CSDN博客 1、安装过程中出现了 GPU驱动版本 是11.8 而 python -c "…

文心版吴恩达课程:语义核心(Semantic Kernel)插件的商业应用

文心版吴恩达课程&#xff1a;语义核心&#xff08;Semantic Kernel&#xff09;插件的商业应用 Semantic Kernel is an SDK that integrates Large Language Models (LLMs) like OpenAI, Azure OpenAI, and Hugging Face with conventional programming languages like C#, P…

HTTP 基本概念(计算机网络)

一、HTTP 是什么&#xff1f; HTTP(HyperText Transfer Protocol) &#xff1a;超文本传输协议。 HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」。 「HTTP 是用于从互联网服务器传输超文本到本地浏览器的协议…

【海思SS528 | VDEC】MPP媒体处理软件V5.0 | VDEC的使用总结

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

SQL简介

目录 一、SQL 简史 二、数据库简史 1、Dr. Codds 对关系型数据库系统的十二条规则 2、设计数据库的结构 3、数据库的前景 4、对于什么是客户机/服务器型电脑系统 BernardH.Boar的定义如下&#xff1a; 5、交互式语言 6、易于实现 7、SQL 总览 三、流行的 SQL 开发工具…

QT 中 QProgressDialog 进度条窗口 备查

基础API //两个构造函数 QProgressDialog::QProgressDialog(QWidget *parent nullptr, Qt::WindowFlags f Qt::WindowFlags());QProgressDialog::QProgressDialog(const QString &labelText, const QString &cancelButtonText, int minimum, int maximum, QWidget *…

Vue安装及环境配置详细教程

一、下载node.js 访问node.js官网&#xff1a;Download | Node.js 选择Windows Installer (.msi)的64-bit进行下载。 在E盘新建一个文件夹&#xff0c;取名为nodejs&#xff0c;也可以在其他盘符新建。 在安装node.js时&#xff0c;点击Change...&#xff0c;进行切换盘符安…