Я новичок, пытающийся понять обратное распространение 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)
Буду очень признателен, если кто-нибудь найдет мою ошибку.