当前位置: 首页 > 知识库问答 >
问题:

ND卷积反积

璩华辉
2023-03-14

对于我的教育,我正在尝试在卷积神经网络中实现一个N维卷积层。

我想实现一个反向传播html" target="_blank">函数。然而,我不确定这样做最有效的方式。

目前,我正在使用信号。fftconvolve收件人:

>

在反向传播步骤中,使用数组卷积导数(在所有维度上使用FlipAllAxes函数进行反转)(https://jefkine.com/general/2016/09/05/backpropagation-in-convolutional-neural-networks/)对所有筛选器进行汇总。我的输出是每个图像与每个滤波器的每个导数的卷积之和。

我对如何卷积导数特别困惑。使用下面的类进行反向传播会导致权重大小爆炸。

编程导数与输出和滤波器的卷积的正确方法是什么?

编辑:

根据这篇论文(通过FFTs快速训练卷积网络),这篇论文正是我想要做的:

>

  • 前一层的导数由当前层的导数与权重的卷积给出:

    dL/dy\U f=dL/dx*w\U f^T

    权重的导数是导数与原始输入的卷积的分段和:

    dL/dy=dL/dx*x

    我已经尽我所知最好地实现了以下内容。然而,这似乎并没有给出预期的结果,因为我使用这一层编写的网络在训练期间表现出剧烈的波动。

        import numpy as np
        from scipy import signal
    
        class ConvNDLayer:
            def __init__(self,channels, kernel_size, dim):
    
                self.channels = channels
                self.kernel_size = kernel_size;
                self.dim = dim
    
                self.last_input = None
    
                self.filt_dims = np.ones(dim+1).astype(int)
                self.filt_dims[1:] =  self.filt_dims[1:]*kernel_size
                self.filt_dims[0]= self.filt_dims[0]*channels 
                self.filters = np.random.randn(*self.filt_dims)/(kernel_size)**dim
    
    
            def FlipAllAxes(self, array):
    
                sl = slice(None,None,-1)
                return array[tuple([sl]*array.ndim)] 
    
            def ViewAsWindows(self, array, window_shape, step=1):
                 # -- basic checks on arguments
                 if not isinstance(array, cp.ndarray):
                     raise TypeError("`array` must be a Cupy ndarray")
                 ndim = array.ndim
                 if isinstance(window_shape, numbers.Number):
                      window_shape = (window_shape,) * ndim
                 if not (len(window_shape) == ndim):
                       raise ValueError("`window_shape` is incompatible with `arr_in.shape`")
    
                 if isinstance(step, numbers.Number):
                      if step < 1:
                      raise ValueError("`step` must be >= 1")
                      step = (step,) * ndim
                 if len(step) != ndim:
                       raise ValueError("`step` is incompatible with `arr_in.shape`")
    
                  arr_shape = array.shape
                  window_shape = np.asarray(window_shape, dtype=arr_shape.dtype))
    
                  if ((arr_shape - window_shape) < 0).any():
                       raise ValueError("`window_shape` is too large")
    
                  if ((window_shape - 1) < 0).any():
                        raise ValueError("`window_shape` is too small")
    
                   # -- build rolling window view
                        slices = tuple(slice(None, None, st) for st in step)
                        window_strides = array.strides
                        indexing_strides = array[slices].strides
                        win_indices_shape = (((array.shape -window_shape)
                        // step) + 1)
    
                     new_shape = tuple(list(win_indices_shape) + list(window_shape))
                     strides = tuple(list(indexing_strides) + list(window_strides))
    
                      arr_out = as_strided(array, shape=new_shape, strides=strides)
    
                      return arr_out
    
            def UnrollAxis(self, array, axis):
                 # This so it works with a single dimension or a sequence of them
                 axis = cp.asnumpy(cp.atleast_1d(axis))
                 axis2 = cp.asnumpy(range(len(axis)))
    
                 # Put unrolled axes at the beginning
                 array = cp.moveaxis(array, axis,axis2)
                 # Unroll
                 return array.reshape((-1,) + array.shape[len(axis):])
    
            def Forward(self, array):
    
                 output_shape =cp.zeros(array.ndim + 1)    
                 output_shape[1:] =  cp.asarray(array.shape)
                 output_shape[0]= self.channels 
                 output_shape = output_shape.astype(int)
                 output = cp.zeros(cp.asnumpy(output_shape))
    
                 self.last_input = array
    
                 for i, kernel in enumerate(self.filters):
                        conv = self.Convolve(array, kernel)
                        output[i] = conv
    
                 return output
    
    
            def Backprop(self, d_L_d_out, learn_rate):
    
                d_A= cp.zeros_like(self.last_input)
                d_W = cp.zeros_like(self.filters)
    
    
               for i, (kernel, d_L_d_out_f) in enumerate(zip(self.filters, d_L_d_out)):
    
                    d_A += signal.fftconvolve(d_L_d_out_f, kernel.T, "same")
                    conv = signal.fftconvolve(d_L_d_out_f, self.last_input, "same")
                    conv = self.ViewAsWindows(conv, kernel.shape)
                    axes = np.arange(kernel.ndim)
                    conv = self.UnrollAxis(conv, axes)  
                    d_W[i] = np.sum(conv, axis=0)
    
    
               output = d_A*learn_rate
               self.filters =  self.filters - d_W*learn_rate
               return output
    
  • 共有1个答案

    范瀚昂
    2023-03-14

    将梯度与learn\u rate相乘通常是不够的。

    为了更好的性能和减少严重的波动,使用优化器通过除以过去的几个梯度(RMSprop)等方法缩放梯度。

    更新还取决于错误,如果您单独传递每个样本的错误,通常会产生噪音,因此最好对多个样本(小批量)进行平均。

     类似资料:
    • 图像的卷积(Convolution)定义为 $$f(x) = act(\sum{i, j}^n \theta{(n - i)(n - j)} x_{ij}+b)$$ 其计算过程为 示例1 import tensorflow as tf import numpy as np sess = tf.InteractiveSession() input_batch = tf.constant([

    • 卷积神经网络有一个批量过滤器, 持续不断的在图片上滚动收集图片里的信息,每一次收集的时候都只是收集一小块像素区域, 然后把收集来的信息进行整理, 这时候整理出来的信息有了一些实际上的呈现, 比如这时的神经网络能看到一些边缘的图片信息, 然后在以同样的步骤, 用类似的批量过滤器扫过产生的这些边缘信息, 神经网络从这些边缘信息里面总结出更高层的信息结构,比如说总结的边缘能够画出眼睛,鼻子等等. 再经过

    • Convolution1D层 keras.layers.convolutional.Convolution1D(nb_filter, filter_length, init='uniform', activation='linear', weights=None, border_mode='valid', subsample_length=1, W_regularizer=None, b_regu

    • Conv1D层 keras.layers.convolutional.Conv1D(filters, kernel_size, strides=1, padding='valid', dilation_rate=1, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zero

    • 下午好在第一阶段,在卷积神经网络(输入层)的输入上,我们接收一个源图像(因此是手写英文字母的图像)。首先,我们使用一个从左到右的nxn窗口来扫描图像并在内核(卷积矩阵)上乘法来构建特征映射?但没有人写过内核应该具有什么样的精确值(换句话说,我应该将从n*n窗口检索到的数据相乘到什么样的内核值)。是否适合在这个用于边缘检测的卷积核上乘以数据?有许多卷积核(浮雕、高斯滤波器、边缘检测、角度检测等)?但

    • 该网络用于预测包含移动方块的人工生成的电影的下一帧。 from keras.models import Sequential from keras.layers.convolutional import Conv3D from keras.layers.convolutional_recurrent import ConvLSTM2D from keras.layers.normalization