mxnet有两种模式,可以像tensorFlow一样预先建立网络图结构,是symbol模块。也可以像pytorch一样,动态的建立网络图结构,属于gluon模块。
mxnet在建立动态图结构的时候,在with autograd.record()之下的网络层计算,据此建立的计算图用于后向传播。说明这一点的关键是:如果有时候我们会遇到只需要变量(NDArray)的一小部分。比如只需要第一个batch传入多分类中的其中一个分支;或者更复杂的情况,只使用波段(或channel通道)的部分元素。这种情况不过通过单纯的slicing 的情况,计算图会出错。
对于需要slicing索引的情况,即只取得有限的元素的情况: with autograd.record(): val1 = val * 2 a = [nd.dot(val1[0, :], w1), nd.dot(val1[1, :], w1)] a[1] = val1[1, :] res = nd.stack(*a) 对于某些属性元素的情况,我这儿也没有想到太好的可以自由选取元素的办法,只有下面的方式: threshold = top_k_values.pick(idx) # top_k_values是配合用去取不同channel下的某个阈值 threshold = threshold.reshape((-1, 1, 1, 1)) seeds = (x > threshold) * 5.0 # 我的方法就是选取大于某个阈值下的元素 但是不管是什么样的操作,必须是要变量级别的运算,这样才能在后向传播的时候将梯度反传递到前面。这是自定义某些操作时,出现了上面所说的违反建立计算图原则的情况,需要设置bypass的方式,逐一定位错误出现的地方。
其中一种错误是 mxnet.gluon.parameter.DeferredInitializationError,mxnet一些网络层是可以自动的推算输入输出,如FC层,可以不需要指定输入的大小,所以需要先经历一次forward前传,建立计算图,mxnet才能后向传播。可是有些情况,比如多分类会有多个分支,可能训练时不会所有的分支都用到,就会出现这种错误了。对于这种错误,给的建议还是比较明了的,比如我的:Parameter dense0_weight has not been initialized yet because initialization was deferred. Actual initialization happens during the first forward pass. Please pass one batch of data through the network before accessing Parameters. You can also avoid deferred initialization by specifying in_units, num_features, etc., for network layers.是说第一个FC层没有指定输入大小,如果还想反向传播,可以指定它的输入层数。