http://zh.diveintodeeplearning.org/chapter_convolutional-neural-networks/conv-layer.html
这一节的作业完全蒙了, 请教一下:
作业2:
试着对我们构造的Conv2D进行自动求导,会有什么样的错误信息?
问题1:
请问此处的"对我们构造的Conv2D进行自动求导"是什么意思?
我注意到原题中采用的是nn自带的Conv2D实例, 所以我按以下方式修改并采用了我们自己定义的实例
#conv2d = nn.Conv2D(1, kernel_size=(1, 2))
conv2d = Conv2D(kernel_size=(1, 2))
请问这就是"对我们构造的Conv2D进行自动求导"吗?
问题2:
我在此处得到了以下错误信息:
MXNetError: [20:42:15] c:\projects\mxnet-distro-win\mxnet-build\src\imperative\./imperative_utils.h:107: Check failed: infershape[attrs.op](attrs, &in_shapes, &out_shapes)
请问这个错误信息是正确的吗? 我的理解是因为目前X的shape是1x1x6x8, 所以无法直接使用corr2d造成的, 请问这个理解对吗?
作业3:
在Conv2D的forward函数里,将corr2d替换成nd.Convolution使得其可以求导。
问题1:
请问如何将corr2d替换成nd.Convolution?
我有尝试写法1:
#return corr2d(x, self.weight.data()) + self.bias.data()
return nd.Convolution(x,self.weight.data(),self.bias.data())
得到错误: MXNetError: Required parameter kernel of Shape(tuple) is not presented, in operator Convolution(name="")
考虑到Convolution的接口定义如下:
mxnet.ndarray.Convolution(data=None, weight=None, bias=None, kernel=_Null,...)
我有尝试写法2:
return nd.Convolution(x, None, None, self.weight.data())
得到错误:
MXNetError: Invalid Parameter format for kernel expect Shape(tuple) but value='[[ 0.0238893 -0.04607266]] <NDArray 1x2 @cpu(0)>', in operator Convolution(name="", kernel="[[ 0.0238893 -0.04607266]]<NDArray 1x2 @cpu(0)>")
请问正确的写法是什么呢?
请问哪里有类似参考答案之类的东西吗? 谢谢
对于作业2的理解有些进展,
受到5.3节提示, 多修改了两行,
#X = X.reshape((1, 1, 6, 8))
#Y = Y.reshape((1, 1, 6, 7))
X = X.reshape((6, 8))
Y = Y.reshape((6, 7))
得到以下错误:
MXNetError: [21:46:57] C:\projects\mxnet-distro-win\mxnet-build\src\imperative\imperative.cc:250: Check failed: AGInfo::IsNone(*(outputs[i])) Inplace operations (+=, -=, x[:]=, etc) are not supported when recording with autograd.
这和教程原文中的以下内容比较切合了,应该是正确了
虽然我们之前构造了Conv2D类,但由于corr2d使用了对单个元素赋值([i, j]=)的操作会导致无法自动求导,下面我们使用Gluon提供的Conv2D类来实现这个例子。
请多指教, 谢谢
对于作业3,
做了以下修改(这段代码好奇怪,斗胆抛砖引玉,期待漂亮的解决方法), 执行通过,
#return corr2d(x, self.weight.data()) + self.bias.data()
data = x.reshape((1,1,)+x.shape)
weight = self.weight.data()
weight = weight.reshape((1,1,)+weight.shape)
bias = self.bias.data()
kernel = self.weight.shape
return nd.Convolution(data, weight, bias, kernel, stride=(1,1), dilate=(1,1), pad=(0,0), num_filter=1)
这里的实现参考了MXNET的ndarray.Convolution文档
你理解没问题。corr2d因为用了[i,j]=导致自动求导失败,这是由于autograd目前还有局限性。
改成 nd.Convolution 会没问题,因为它手动实现了backward函数。
非常感谢回复,看到沐神很激动
# e.x.3 在 Conv2D 的 forward 函数⾥,将 corr2d 替换成 nd.Convolution 使得其可以求导。
class Conv2D_ex3(nn.Block):
"""
- **data**: *(batch_size, channel, height, width)*
- **weight**: *(num_filter, channel, kernel[0], kernel[1])*
- **bias**: *(num_filter,)*
- **out**: *(batch_size, num_filter, out_height, out_width)*.
"""
def __init__(self, channels, kernel_size, **kwargs):
super(Conv2D_ex3, self).__init__(**kwargs)
self.weight = self.params.get(
'weight', shape=(
channels,
1,
) + kernel_size)
self.bias = self.params.get('bias', shape=(channels, ))
self.num_filter = channels
self.kernel_size = kernel_size
def forward(self, x):
return nd.Convolution(
data=x, weight=self.weight.data(), bias=self.bias.data(), num_filter=self.num_filter, kernel=self.kernel_size)
print('\ne.x.3:')
X = X.reshape((1, 1, 6, 8))
Y = Y.reshape((1, 1, 6, 7))
conv2d = Conv2D_ex3(10, kernel_size=(1, 2))
conv2d.initialize()
for i in range(10):
with autograd.record():
Y_hat = conv2d(X)
l = (Y_hat - Y)**2
if i % 2 == 1:
print('batch %d, loss %.3f' % (i, l.sum().asscalar()))
l.backward()
conv2d.weight.data()[:] -= 3e-2 * conv2d.weight.grad()
练习最后一题:如何构造⼀个全连接层来进⾏物体边缘检测?
能否给些提示?
针对“试着将 conv2d 的核构造成(2, 2),会学出什么样的结果?”这题:
X3
K3
Y3
训练
我不知道错在哪里?
可以参考caffe的卷积实现
Y 默认定义在cpu上
Label是什么呢,如何知道哪里是边缘
请教一下,使用教材中定义的Conv2D进行前向计算,为什么输出是一个1x0大小?
代码如下:
conv2d = Conv2D(kernel_size=(1, 2))
conv2d.initialize()
Y_hat = conv2d(X)
Y_hat
关键是你的X的shape是什么?
调用corr2d,声明Y= nd.zeros()时,Y存入了内存里,虽然X,k在显存里,但计算Y的时候,因为Y在内存,所以将X,k复制到了内存,再进行计算。
你试试Y=nd.zeros(, ctx=mx.gpu()),最终结果就会用GPU计算
多谢回复。
确实是忘记检查X的shape了
作业二。我改完之后也还是可以自动求梯度的。。。为何
这个没问题呀,你看PDF上的例程,也是这样,是因为原图像没有padding,你继续看下一节就知道怎么回事了,如果是斜着检测边缘的话,创建的检测子起码就需要是2*2的了,比如说罗伯特检测算子(这些都是图像的基本知识,可以直接自网上找边缘检测算子)