根据我上一个博文:使用矩阵乘法实现卷积“博文“”的的基础上分享一下对于转置卷积的心得。
博文参考:
转置卷积(Transposed Convolution)_太阳花的小绿豆的博客-CSDN博客_转置卷积
1.使用矩阵乘法实现卷积运算
1) 分别对输入矩阵和卷积核进行展平、补充零展平拼接操作得到新的矩阵。(我上一个博客“使用矩阵乘法实现卷积“有讲解)
2) 进行矩阵运算,然后Reshape形状得到卷积后的结果
2 .对上述的卷积运算进行逆向过程的操作,从而实现转置卷积的从输出的2X2形状上采样到3X3
1)下面这里采用矩阵的转置来实现上采样
2)与上面的正向卷积输出的结果进行逆过程的上采样
3)下面这种方法的计算效果和上面2)这种方法是一致的
3.转置卷积输出尺寸大小计算
代码实现
import numpy as np
# ----------------Convolution Transposed -----------------------
# 数据预处理
def Data_rashape(image: np, kernel:np):
# 将输入矩阵进行横向展平处理
image_ = np.reshape(image,-1)
# 用于存储卷积核填零展平拼接后的矩阵
dd_ = None
# 填充零这里使用的是,直接替换全零矩阵的值实现
'''
首先需要计算卷积后的到的矩阵大小(w,h)
通过模仿滑动窗口的样子,依次填充卷积核,最后将它们拼接起来就是一个卷积核矩阵
:return
输入矩阵展平之后的矩阵和卷积核填充0后的矩阵
'''
for i in range(image.shape[0]-kernel.shape[0]+1):
for j in range(image.shape[1]-kernel.shape[1]+1):
dd = np.zeros(image.shape) # 根据输入矩阵的大小,来建立全零矩阵
dd[i:i + kernel.shape[0], j:j + kernel.shape[1]]=kernel # 全零矩阵对应位置被卷积核替换
if i==0 and j==0: # 第一个卷积核记录为起点
dd_ = dd.reshape(-1)[None,:]
else:
# 从第二个卷积核开始,进行按行的堆叠
dd_ = np.concatenate((dd_, dd.reshape(-1)[None,:]),axis=0)
print("kernels形状:",dd_.T.shape)
print("image_的形状:",image_.T.shape)
# 这里通过转置转换为想要的形状
return dd_.T , image_.T
if __name__ == '__main__':
Image = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
kernel = np.array([[1,2],
[3,4]])
# 输入矩阵展平之后的矩阵和卷积核填充0后的矩阵
C, I = Data_rashape(Image,kernel)
O = I @ C
result1 = O.reshape(Image.shape[0]-kernel.shape[0]+1,Image.shape[1]-kernel.shape[1]+1)# 按照最后的卷积的大小,进行还原
print("result1:\n",result1)
print("==================卷积的逆向过程======================")
print(O.shape,C.shape)
I_ = O @ C.T
result2 = I_.reshape(Image.shape)# 按照最后的卷积的大小,进行还原
print("result2:\n",result2)