dw = x * sigma 传上来的梯度
原先fc层的卷积是把grad与weight分块,然后两者做卷积
FC层这里
grad weight 30x4096
fc_input 30x9216
detafc 30x4096
weight 4096x9216
30是就是batch_size我给改了
不过grad weight
这里mm为矩阵乘法,.T为对后面的矩阵进行变换
现在需要把grad与
前一层层是256x3x3,输出也是256层,代表的是有256个filter。为了加速计算,需要考虑上一层与下一层的DSP分配。看下面这段程序。
with open("weight_conv5.coe","w") as f:
f.write("memory_initialization_radix=2;\n")
f.write("memory_initialization_vector =\n")
for p in range(16):
for k in range(128):
for x in range(3):
for y in range(3):
for i in range(16):
for j in range(2):
f.write(d2b((net_new.features[14].weight.data[2*k+j,16*p+i,x,y]*(2**8)).numpy()))
f.write(',\n')
其中存储的顺序是[2*k+j, 16*p+i, x, y]
循环最底层的是i和j,相当于取了两个filter的16个深度,然后是x与y,把这个3x3的filter完整地遍历,接下来是改变k,也就是找接下来两个filter,最后再增加深度。其中i的16是由上一层的输出决定的,2是决定下一层DSP的使用。
DSP分配回去看看这个基于FPGA的卷积神经网络实现(三)资源分配(1)_MasJilwei的博客-CSDN博客
这里关于缓存的计算是256*100*1这里的256*100指的是输入图片为256*100的矩形。
关于缓存的大小可以看这个图像卷积和池化操作后的特征图大小计算方法_ZJE-CSDN博客_卷积特征图大小计算
weight 和fconv5的存储方式对应verilog中DSP的分配
net_new.features[14].weight.data = torch.round(net_new.features[14].weight.data*(2**net_new.features[14].lmd_shift))/(2**net_new.features[14].lmd_shift)
# with open("weight_conv5.coe","w") as f:
# f.write("memory_initialization_radix=2;\n")
# f.write("memory_initialization_vector =\n")
# for p in range(16):
# for k in range(128):
# for x in range(3):
# for y in range(3):
# for i in range(16):
# for j in range(2):
# f.write(d2b((net_new.features[14].weight.data[2*k+j,16*p+i,x,y]*(2**8)).numpy()))
# f.write(',\n')
f_conv5 = F.conv2d(f_conv4_relu_q, net_new.features[14].weight, None, 1, 1)
f_conv5_q = torch.round(f_conv5)
f_conv5_relu = f_conv5_q.clamp(min=0)
# with open("f_conv5.coe","w") as f:
# f.write("memory_initialization_radix=2;\n")
# f.write("memory_initialization_vector =\n")
# for k in range(13):
# for x in range(13):
# for y in range(128):
# for i in range(2):
# for j in range(2):
# f.write(d2b(torch.round((f_conv5_relu.data[i,y*2+j,k,x]*(2**0))).numpy()))
# f.write(',\n')