根据DCT特征训练CNN

记录一次改代码的挣扎经历:
        看了几篇关于DCT频域的深度模型文献,尤其是21年FcaNet:基于DCT 的attention model,咱就是说想试试将我模型的输入改为分组的DCT系数,然后就开始下面的波折了。

第一次尝试:

        我直接调用了库函数,然后出现问题了:这个库函数是应用在numpy数组上,得在CPU上处理。

from scipy.fftpack import dct, idct
...
dct_block = dct(dct(block, axis=2, norm='ortho'), axis=3, norm='ortho')   # [B,C,k,k]
...
block = idct(idct(dct_block, axis=2, norm='ortho'), axis=3, norm='ortho')    # [B,C,k,k]

第二次尝试:
        好吧,我先把数据调回CPU,处理后,再调回GPU,又有新问题了:这样做(将block从GPU转移至CPU)torch类型张量转换为numpy数组时,torch张量的梯度无法保存。

# 图像分块
...
# 将块转移到 CPU
block_cpu = block.cpu()        # [B,C,k,k]
# 在 CPU 上对块应用 DCT
dct_block_np = dct(dct(block_cpu.numpy(), axis=2, norm='ortho'), axis=3, norm='ortho')   # [B,C,k,k]
# 将结果传输回 GPU
dct_block = torch.from_numpy(dct_block_np).to(image.device)     # [B,C,k,k]...# 将块转移到 CPU
dct_block_cpu = dct_block.cpu()
# 在 CPU 上对块应用逆 DCT
block_np = idct(idct(dct_block_cpu.numpy(), axis=2, norm='ortho'), axis=3, norm='ortho')
# 将结果传输回 GPU
block = torch.from_numpy(block_np).to(dct_block.device)    # [B,C,k,k]

 第三次尝试:

        根据报错提醒,我进行以下改进,将block_cpu.numpy -> block_cpu.detach.numpy(),即忽略掉torch类型张量带着的梯度信息,哈哈,这样一改,梯度就丢失了,模型就不能反向传播进行更新训练了。

# 图像分块
...
# 将块转移到 CPU
block_cpu = block.cpu()        # [B,C,k,k]
# 在 CPU 上对块应用 DCT
dct_block_np = dct(dct(block_cpu.numpy(), axis=2, norm='ortho'), axis=3, norm='ortho')   # [B,C,k,k]
# 将结果传输回 GPU
dct_block = torch.from_numpy(dct_block_np).to(image.device)     # [B,C,k,k]...# 将块转移到 CPU
dct_block_cpu = dct_block.cpu()
# 在 CPU 上对块应用逆 DCT
block_np = idct(idct(dct_block_cpu.detach.numpy(), axis=2, norm='ortho'), axis=3, norm='ortho')
# 将结果传输回 GPU
block = torch.from_numpy(block_np).to(dct_block.device)    # [B,C,k,k]

第四次尝试:
        CPU上库函数不好用,那我自己写(借鉴)DCT变换的函数嘛,DCT就是输入k*k图像关于k*k个余弦基函数的加权和嘛:

 别人写的的8 x 8d的DCT和IDCT的实现:


class DCT8X8(nn.Module):""" Discrete Cosine TransformationInput:image(tensor): batch x height x widthOutput:dcp(tensor): batch x height x width"""def __init__(self):super(DCT8X8, self).__init__()tensor = np.zeros((8, 8, 8, 8), dtype=np.float32)for x, y, u, v in itertools.product(range(8), repeat=4):tensor[x, y, u, v] = np.cos((2 * x + 1) * u * np.pi / 16) * np.cos((2 * y + 1) * v * np.pi / 16)alpha = np.array([1. / np.sqrt(2)] + [1] * 7)self.tensor = nn.Parameter(torch.from_numpy(tensor).float())self.scale = nn.Parameter(torch.from_numpy(np.outer(alpha, alpha) * 0.25).float())def forward(self, image):image = image - 128result = self.scale * torch.tensordot(image, self.tensor, dims=2)result.view(image.shape)return resultclass IDCT8X8(nn.Module):""" Inverse discrete Cosine TransformationInput:dcp(tensor): batch x height x widthOutput:image(tensor): batch x height x width"""def __init__(self):super(IDCT8X8, self).__init__()alpha = np.array([1. / np.sqrt(2)] + [1] * 7)self.alpha = nn.Parameter(torch.from_numpy(np.outer(alpha, alpha)).float())tensor = np.zeros((8, 8, 8, 8), dtype=np.float32)for x, y, u, v in itertools.product(range(8), repeat=4):tensor[x, y, u, v] = np.cos((2 * u + 1) * x * np.pi / 16) * np.cos((2 * v + 1) * y * np.pi / 16)self.tensor = nn.Parameter(torch.from_numpy(tensor).float())def forward(self, image):image = image * self.alpharesult = 0.25 * torch.tensordot(image, self.tensor, dims=2) + 128result.view(image.shape)return result

我根据上述改的任意block_size的DCT和IDCT:

class DCTCustom(nn.Module):"""Customizable Discrete Cosine TransformationInput:image(tensor): batch x height x widthOutput:dct(tensor): batch x height x width"""def __init__(self, input_size=8):super(DCTCustom, self).__init__()self.input_size = input_sizetensor = np.zeros((input_size, input_size, input_size, input_size), dtype=np.float32)for x, y, u, v in itertools.product(range(input_size), repeat=4):tensor[x, y, u, v] = np.cos((2 * x + 1) * u * np.pi / (2 * input_size)) * np.cos((2 * y + 1) * v * np.pi / (2 * input_size))alpha = np.array([1. / np.sqrt(2)] + [1] * (input_size - 1))self.tensor = nn.Parameter(torch.from_numpy(tensor).float())self.scale = nn.Parameter(torch.from_numpy(np.outer(alpha, alpha) * 0.25).float())def forward(self, image):image = image - 128result = self.scale * torch.tensordot(image, self.tensor, dims=2)result = result.view(image.shape)  # Corrected linereturn resultclass IDCTCustom(nn.Module):""" Inverse discrete Cosine TransformationInput:dcp(tensor): batch x height x widthOutput:image(tensor): batch x height x width"""def __init__(self, block_size=8):super(IDCTCustom, self).__init__()self.block_size = block_size# Compute alpha coefficientsalpha = np.array([1. / np.sqrt(2)] + [1] * (block_size - 1))self.alpha = nn.Parameter(torch.from_numpy(np.outer(alpha, alpha)).float())# Compute tensor for IDCTtensor = np.zeros((block_size, block_size, block_size, block_size), dtype=np.float32)for x, y, u, v in itertools.product(range(block_size), repeat=4):tensor[x, y, u, v] = np.cos((2 * u + 1) * x * np.pi / (2 * block_size)) * np.cos((2 * v + 1) * y * np.pi / (2 * block_size))self.tensor = nn.Parameter(torch.from_numpy(tensor).float())def forward(self, image):if image.shape[-2] % self.block_size != 0 or image.shape[-1] % self.block_size != 0:raise ValueError("Input dimensions must be divisible by the block size.")# Apply IDCTimage = image * self.alpharesult = 0.25 * torch.tensordot(image, self.tensor, dims=2) + 128result = result.view(image.shape)return result

        不出意外的话,问题又出现了,我对一个torch.ones((2,3,k,k))的张量进行DCT,再IDCT恢复。当k=8时(即block_size=8x8)时,能够完全恢复,但当k!=8(=16、32)时,经IDCT后无法恢复原始输入,懵。

第五次尝试(hh):
        突然!我发现了torch内置的DCT函数!可以再GPU上实现DCT。

torch-dct · PyPI

import torch_dct as dct# 图像分块    # [B,C,H,W]...        # [B,C,k,k]# dctblock = dct.dct_2d(block)     # [B,C,k,k]...# idctblock = dct.idct_2d(block)        # [B,C,k,k]

 然后又有问题了:
        我的模型开始训练后,我发现我的每个epoch的loss都为NAN...

        然后我打印了DCT输出,发现DCT系数长这个样子,CNN不高兴好好训练吧。

        我们再想想办法将输入数据归一化到范围[0, 1]或[-1, 1]之间,再喂给CNN吧。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】自定义类型:结构体深入解析(三)结构体实现位段最终篇

文章目录 📝前言🌠什么是位段?🌉 位段的内存分配🌉VS怎么开辟位段空间呢?🌉位段的跨平台问题🌠 位段的应⽤🌠位段使⽤的注意事项🚩总结 📝前言 本…

【K8S 二进制部署】部署Kurbernetes的网络组件、高可用集群、相关工具

目录 一、K8S的网络类型: 1、K8S中的通信模式: 1.1、、pod内部之间容器与容器之间的通信 1.2、同一个node节点之内,不同pod之间的通信方式: 1.3、不同node节点上的pod之间是如何通信的呢? 2、网络插件一&#xff…

linux 下批量重放流量

目录 介绍实操linux方式1,2linux 方式3 介绍 这里介绍的是,如何在 linux 环境下让IDP设备告警 这里linux下流量重放的工具是:tcpreplay 工具的作用:将PCAP包重新发送,用于性能或者功能测试工具的使用与参数&#xff…

【电商项目实战】基于SpringBoot完成首页搭建

🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的专栏《电商项目实战》。🎯🎯 &am…

Linux:jumpserver工作台操作(7)

工作台在用户和管理那章就早有接触 概览 这里可以看到登录的时间以及来自哪里 我的资产 这里就能看到当前账户有哪些资产可以使用 web终端 这里就能选择我们的资产让后对其连接 文件管理——批量传输 在这我们在前面选择要上传的资产,让后把东西拖拽进去&#xff…

Intel FPGA 技术开放日

概要 时间:2023.11.14 全天 ( 9:00 - 16: 20) 地点:北京望京. 凯悦酒店 主题内容:分享交流了Intel FPGA 产品技术优势和落地实践方案。 会议的议程 开场致词: FPGA业务,是几年前intel收购而…

Uncaught ReferenceError: VueRouter is not defined

没有引入完全,报缺什么就引入什么 import * as VueRouter from vue-router;

istio 示例程序 bookinfo 快速部署

官网 文档位置 相关 yaml 资源下载 Bookinfo 应用分为四个单独的微服务: productpage:这个微服务会调用 details 和 reviews 两个微服务,用来生成页面details:这个微服务中包含了书籍的信息reviews:这个微服务中包含了…

【Redis刨析】知识图谱的构建与实现

前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 ChatGPT体验地址 文章目录 前言引用构建过程Redis的知识图谱构建过程Redis介绍快的原因持久化 引用 对于编程的学习,过了初级阶段,我认为应该减少对视频的依赖&am…

制造业数字化转型的核心不止是技术

一、制造业的数字化转型意味着什么? 在当今的制造业领域,数字化转型意味着通过集成数字技术来增强传统的制造方法、产品和劳动力的过程。这些技术包括一系列创新,如自动化软件、电子商务系统、传感器、工业机器人等。 二、制造业数字化转型的…

操作系统“文艺复兴”,云数智融合涌现“美第奇效应”

操作系统作为信息技术中的基础软件,是现代计算机的“灵魂”。随着大模型AI推动云计算、大数据、人工智能、物联网和5G等新一代数字技术的飞速融合,现代计算机体系结构和软件架构面临着重大创新机遇期。图灵奖获得者John Hennessy和David Patterson早在20…

jsp页面bootstrap表格设置页面跳转一直在底部

首先介绍一下bootStrap和bootStrap table: bootStrap: Bootstrap是Twitter推出的一个用于前端开发的开源工具包。 它由Twitter的设计师Mark Otto和Jacob Thornton合作开发,是一个CSS/HTML框架。 bootStrap table: Bootstrap table 是一款基于 Bootstrap 的 jQue…