Невозможно правильно рассчитать градиенты Conv1D - PullRequest
0 голосов
/ 07 ноября 2019

Я новичок, пытающийся понять обратное распространение Conv1D. Я реализую это и сравниваю мои градиенты с градиентами Pytorch. Тем не менее, шаг backprop кажется неправильным. Я разместил полный реализованный класс.

class Conv1D:
    def __init__(self, input_channel, output_channel, kernel_size, stride):
        self.input_channel = input_channel
        self.output_channel = output_channel
        self.kernel_size = kernel_size
        self.stride = stride
        self.W = np.random.normal(0, 1, [output_channel, input_channel, kernel_size])
        self.b = np.random.normal(0, 1, [output_channel])
        self.dW = np.zeros(shape=self.W.shape)
        self.db = np.zeros(shape=self.b.shape)
        self.dx = np.zeros(shape=self.b.shape)
        self.input = np.array([])

    def forward(self, x):
        output_width = int(np.floor(len(x[0][0])-self.kernel_size)/self.stride) + 1
        y = np.zeros(shape=[len(x), self.output_channel, output_width])
        self.input = np.copy(x)
        for i in range(len(x)):
            for j in range(self.output_channel):
                k_ = 0
                for k in range(output_width):
                    input_piece = x[i, :, k_:k_+self.kernel_size]
                    y[i][j][k] = np.sum(np.multiply(input_piece, self.W[j])) + self.b[j]
                    k_ += self.stride
        return y

    def backward(self, dl):
        output_width = int(np.floor(len(dl[0][0])-self.kernel_size)/self.stride) + 1
        self.dW = np.zeros(shape=self.W.shape)
        self.db = np.zeros(shape=self.b.shape)
        self.dx = np.zeros(shape=self.input.shape)
        for i in range(len(dl)):
            for j in range(self.output_channel):
                k_ = 0
                for k in range(output_width):
                    input_piece = self.input[i][:, k_:k_+self.kernel_size]
                    self.dx[i][:, k_:k_+self.kernel_size] += dl[i][j][k] * self.W[j]
                    self.dW[j] += dl[i][j][k] * input_piece
                    self.db[j] += dl[i][j][k] 
                    k_ += self.stride
        return self.dx



    def __call__(self, x):
        return self.forward(x)

Буду очень признателен, если кто-нибудь найдет мою ошибку.

...