论文阅读1:addernet(1)
提出了加法网络(AdderNets)来交换深度神经网络中的这些大规模乘法,特别是卷积神经网络(CNNs),以获得更简易的加法以降低计算成本。
用L1距离代替欧氏距离,使得用减法代替卷积操作
本文主要解析adder2d_function,减法操作。

知识点复习:
1.torch.nn.functional.unfold()函数,unfold函数的输入数据是四维,但输出是三维的。
首先看一下参数
def unfold(input, kernel_size, dilation=1, padding=0, stride=1):
"""
input: tensor数据,四维, Batchsize, channel, height, width
kernel_size: 核大小,决定输出tensor的数目。稍微详细讲
dilation: 输出形式是否有间隔,稍后详细讲。
padding:一般是没有用的必要
stride: 核的滑动步长。稍后详细讲
"""
假设有一个张量特征图

在连续的在分辨率维度(H和W)维度取出特征

假设输入数据是[N, C, H, W],输出为[N, C* kH * kW, L],若stride= 1,padding = 0,则输出中的L为

一般情况下L计算公式为 (ㄒoㄒ)

另外dilation参数的含义为选择的像素间隔
dilation = 0

dilation = 1

2.X_col = X_col.permute(1,2,0).contiguous().view(X_col.size(1),-1)操作
permute(dims)功能是将tensor的维度换位
比如原来的矩阵x(x,y,z),经过x.permute(1,2,0)后将第0维变换到第三维,即矩阵变为x(y,z,x),注意permute不改变原矩阵x,仅在计算中有用。
因为不能保存,一般在permute后,接着进行contiguous(),来返回一个contiguous copy,后续才能view()。
一种可能的解释:有些tensor并不是占用一整块内存,而是由不同的数据块组成,而tensor的view()操作依赖于内存是整块的,这时只需要执行contiguous()这个函数,把tensor变成在内存中连续分布的形式。
后续不用多说,view变化矩阵为(X_col_first_dim, _)形式。
3.adder.apply(W_col,X_col)
不太清楚,我觉得和class adder(Function): 有关,使用自己构建的类,过两天再看看吧,目前没有明确答案,先记录一下。

4.squeeze()和unsqueeze()
X.unsqueeze(1)在X(2, 3)的第二维增加一个维度,使其维度变为(2,1,3),如果需要在倒数第1个维度上增加一个维度,那么使用b.unsqueeze(-1),变为(2,3,1)。
所以squeeze()即为减少维度,注意只有维度为1时才会去掉,比如Y(1,2,3),Y.squeeze(0)或者Y.squeeze(-3)后,Y变成(2, 3)。
5.ctx.save_for_backward和ctx.saved_tensors
按照图中写就好了,ctx.save_for_backward(W_col,X_col)保存反向传播的参数,
W_col,X_col = ctx.saved_tensors加载反向传播参数。
水平有限,有问题欢迎指正^ ^
参考:https://blog.csdn.net/b15040915/article/details/105601027
https://blog.csdn.net/qq_34914551/article/details/102940368
https://blog.csdn.net/qq_40231500/article/details/90606872
https://www.zhihu.com/question/366882609/answer/982196400