神经网络中快速傅立叶变换(FFT)的梯度传递

本文介绍了在神经网络中如何处理快速傅立叶变换(FFT)的梯度传递问题。作者通过复习离散傅立叶变换(DFT)和雅可比矩阵,详细探讨了在实数和复数领域的梯度计算。傅立叶变换矩阵被证明是一个按比例缩放的酉矩阵,其逆矩阵是其共轭转置的1/N。因此,FFT的反向传播可以用其逆变换完成,而FFT逆变换的反向传播则用FFT本身。

最近需要在神经网络中构造复数酉矩阵做权重系数,使用了快速傅立叶变换和反变换.
但是FFT不是theano的现成操作模块(有人写过对应的代码,所以应该会很快加进去了),所以想自己去写梯度传递来彻底搞清楚这件事.
重新学一遍离散Fourier transform再加找梯度相关的文献学习,整整花了一周时间.从本科一毕业DFT就忘光了...
在此总结了下,不得不说推倒的结果出来以后,真是出乎意料的漂亮,所以实现起来更是异常简单.



傅立叶变换是线性变换.所以可以写成F(x)=Fx的形式, F是复矩阵,x是向量.
如果是实数,根据d/dx (Ay)=A * d/dx (y). 大白话说,矩阵F乘向量x这种运算的雅可比矩阵(雅可比矩阵是函数的一阶偏导数以一定方式排列成的矩阵)就是F矩阵本身.
雅可比矩阵乘以输出端梯度就可以由F和向量的乘法实现了.
ok,拓展到复数领域,用的是F的共轭转置,这里有个简单的例子大概理解一下https://math.stackexchange.com/questions/828689/complex-function-and-jacobian-matrix.
然而傅立叶变换矩阵不只如此,傅立叶变换矩阵F本身是个按比例(1/sqrt(N))缩放过的酉矩阵(scaled unitary matrix),其逆矩阵就是其共轭转置的1/N, 具体的请看多伦多大学的论文证明11页23式(http://www.cs.toronto.edu/~jepson/csc320/notes/fourier.pdf)
这么一来,求傅立叶变换的梯度反向传播,就是用傅立叶逆变换完成.注意,我们乎略1/N这个比例系数.因为如果把傅立叶变换矩阵用sqrt(N)缩放一下编成酉矩阵的话,比例系数就是1了.
反之,傅立叶逆变换的梯度反向传播,就是用傅立叶变换了来实现了.
奇妙~!


参考:

斯坦福大学快速傅立叶变换课堂视频  http://open.163.com/movie/2008/2/A/L/M7Q4BLENR_M7QDNTVAL.html

傅立叶变换的在线教程  http://fourier.eng.hmc.edu/e161/lectures/fourier/fourier.html

西电DFT与FFT课件  http://web.xidian.edu.cn/kywang/files/20121027_164737.pdf

酉矩阵  https://zh.wikipedia.org/wiki/%E9%85%89%E7%9F%A9%E9%98%B5

谷歌群组的讨论  https://groups.google.com/forum/#!topic/theano-dev/ZqSf3lBH89U

import torch import torch.nn as nn import torch.optim as optim import numpy as np import torchvision.transforms as transforms from PIL import Image import os from torch.utils.data import DataLoader, Dataset import torch.nn.functional as F from torchvision.utils import save_image import matplotlib matplotlib.use('TkAgg') # 或者使用 'Agg',如果你只需要保存图片 import matplotlib.pyplot as plt # ============================ # 光学前向传播 (角谱法) # ============================ def angular_spectrum_propagation(E0, z, wavelength, pixel_size): k = 2 * np.pi / wavelength N, M = E0.shape[-2:] fx = np.fft.fftfreq(N, d=pixel_size) fy = np.fft.fftfreq(M, d=pixel_size) FX, FY = np.meshgrid(fx, fy) # 计算角谱传播 H = np.exp(1j * k * z * np.sqrt(1 - (wavelength * FX)**2 - (wavelength * FY)**2)) E0_ft = np.fft.fft2(E0) E_z_ft = E0_ft * H E_z = np.fft.ifft2(E_z_ft) return E_z # ============================ # 模拟光学传播过程 # ============================ class OpticalForwardModel(nn.Module): #定义了一个神经网络类OF,继承自tnM,所有神经网络必须继承 def __init__(self): super(OpticalForwardModel, self).__init__() self.thickness = nn.Parameter(torch.rand(5) * 300) #可变参数 """ self.thickness:可训练的参数 nn.P 它是包含5个随机值的张量(torch.rand(5)),初始值(0,1) """ def forward(self, x): #前向传输,x是传入的原始图片 x_np = x.detach().cpu().numpy().squeeze() E0 = x_np """ x 是原始输入图片(格式是 torch.tensor) .detach():阻断该张量的计算图,防止梯度回传,因为光场传输不是反向传播的一部分。 .cpu():如果图片在GPU上,将其搬运回CPU,便于用Numpy计算 .numpy():将 torch.Tensor 转换成 Numpy数组,方便进行光场传输模拟 它是包含5个随机值的张量(torch.rand(5)),初始值(0,1) .squeeze():去除所有维度为1的通道, """ for i in range(5): #光场的传播模拟 E0 = angular_spectrum_propagation( E0, z=self.thickness[i].item() * 1e-9, wavelength=532e-9, pixel_size=0.5e-6 ) #调用函数 #确保输出是一个Tensor,并需要计
最新发布
03-13
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值