maxpooling
import numpy as np
import torch
class MaxPooling2D:
def __init__(self, kernel_size=(2, 2), stride=2):
self.kernel_size = kernel_size
self.w_height = kernel_size[0]
self.w_width = kernel_size[1]
self.stride = stride
self.x = None
self.in_height = None
self.in_width = None
self.out_height = None
self.out_width = None
self.arg_max = None
def __call__(self, x):
self.x = x
self.in_height = np.shape(x)[0]
self.in_width = np.shape(x)[1]
self.out_height = int((self.in_height - self.w_height) / self.stride) + 1
self.out_width = int((self.in_width - self.w_width) / self.stride) + 1
out = np.zeros((self.out_height, self.out_width))
self.arg_max = np.zeros_like(out, dtype=np.int32)
for i in range(self.out_height):
for j in range(self.out_width):
start_i = i * self.stride
start_j = j * self.stride
end_i = start_i + self.w_height
end_j = start_j + self.w_width
out[i, j] = np.max(x[start_i: end_i, start_j: end_j])
self.arg_max[i, j] = np.argmax(x[start_i: end_i, start_j: end_j])
self.arg_max = self.arg_max
return out
def backward(self, d_loss):
dx = np.zeros_like(self.x)
for i in range(self.out_height):
for j in range(self.out_width):
start_i = i * self.stride
start_j = j * self.stride
end_i = start_i + self.w_height
end_j = start_j + self.w_width
index = np.unravel_index(self.arg_max[i, j], self.kernel_size)
dx[start_i:end_i, start_j:end_j][index] = d_loss[i, j] #
return dx
np.set_printoptions(precision=8, suppress=True, linewidth=120)
x_numpy = np.random.random((1, 1, 6, 9))
x_tensor = torch.tensor(x_numpy, requires_grad=True)
max_pool_tensor = torch.nn.MaxPool2d((2, 2), 2)
max_pool_numpy = MaxPooling2D((2, 2), stride=2)
out_numpy = max_pool_numpy(x_numpy[0, 0])
out_tensor = max_pool_tensor(x_tensor)
d_loss_numpy = np.random.random(out_tensor.shape)
d_loss_tensor = torch.tensor(d_loss_numpy, requires_grad=True)
out_tensor.backward(d_loss_tensor)
dx_numpy = max_pool_numpy.backward(d_loss_numpy[0, 0])
dx_tensor = x_tensor.grad
# print('input \n', x_numpy)
print("out_numpy \n", out_numpy)
print("out_tensor \n", out_tensor.data.numpy())
print("dx_numpy \n", dx_numpy)
print("dx_tensor \n", dx_tensor.data.numpy())
結(jié)果對比:
input
[[[[0.23154623 0.39067432 0.1935981 0.57404555 0.45836731 0.17431257 0.73531471 0.15065228 0.24519314]
[0.03184393 0.23829775 0.56975363 0.35438115 0.33226485 0.4235955 0.20789183 0.6806974 0.38405406]
[0.03310472 0.99881498 0.94234671 0.04932191 0.42538918 0.86215804 0.68977391 0.76811963 0.41257792]
[0.57807187 0.14109779 0.34925223 0.9519405 0.82116835 0.04807382 0.8303489 0.81035534 0.95730942]
[0.24868524 0.39256031 0.11658718 0.51279824 0.37514214 0.23667244 0.29587014 0.1269187 0.96846764]
[0.95877717 0.64374607 0.05483185 0.08409835 0.99503626 0.57803468 0.29041625 0.15926311 0.16737524]]]]
out_numpy
[[0.39067432 0.57404555 0.45836731 0.73531471]
[0.99881498 0.9519405 0.86215804 0.8303489 ]
[0.95877717 0.51279824 0.99503626 0.29587014]]
out_tensor
[[[[0.39067432 0.57404555 0.45836731 0.73531471]
[0.99881498 0.9519405 0.86215804 0.8303489 ]
[0.95877717 0.51279824 0.99503626 0.29587014]]]]
dx_numpy
[[0. 0.9304535 0. 0.15515155 0.65241189 0. 0.45043355 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0.26357898 0. 0. 0. 0.75194057 0. 0. 0. ]
[0. 0. 0. 0.65124641 0. 0. 0.84716348 0. 0. ]
[0. 0. 0. 0.49120861 0. 0. 0.01629701 0. 0. ]
[0.91338436 0. 0. 0. 0.31244633 0. 0. 0. 0. ]]
dx_tensor
[[[[0. 0.9304535 0. 0.15515155 0.65241189 0. 0.45043355 0. 0. ]
[0. 0. 0. 0. 0. 0. 0. 0. 0. ]
[0. 0.26357898 0. 0. 0. 0.75194057 0. 0. 0. ]
[0. 0. 0. 0.65124641 0. 0. 0.84716348 0. 0. ]
[0. 0. 0. 0.49120861 0. 0. 0.01629701 0. 0. ]
[0.91338436 0. 0. 0. 0.31244633 0. 0. 0. 0. ]]]]
avgpooling
import numpy as np
import torch
class AvgPooling2D:
def __init__(self, kernel_size=(2, 2), stride=2):
self.stride = stride
self.kernel_size = kernel_size
self.w_height = kernel_size[0]
self.w_width = kernel_size[1]
def __call__(self, x):
self.x = x
self.in_height = x.shape[0]
self.in_width = x.shape[1]
self.out_height = int((self.in_height - self.w_height) / self.stride) + 1
self.out_width = int((self.in_width - self.w_width) / self.stride) + 1
out = np.zeros((self.out_height, self.out_width))
for i in range(self.out_height):
for j in range(self.out_width):
start_i = i * self.stride
start_j = j * self.stride
end_i = start_i + self.w_height
end_j = start_j + self.w_width
out[i, j] = np.mean(x[start_i: end_i, start_j: end_j])
return out
def backward(self, d_loss):
dx = np.zeros_like(self.x)
for i in range(self.out_height):
for j in range(self.out_width):
start_i = i * self.stride
start_j = j * self.stride
end_i = start_i + self.w_height
end_j = start_j + self.w_width
dx[start_i: end_i, start_j: end_j] = d_loss[i, j] / (self.w_width * self.w_height)
return dx
np.set_printoptions(precision=8, suppress=True, linewidth=120)
x_numpy = np.random.random((1, 1, 6, 9))
x_tensor = torch.tensor(x_numpy, requires_grad=True)
avg_pool_tensor = torch.nn.AvgPool2d((2, 2), 2)
avg_pool_numpy = AvgPooling2D((2, 2), stride=2)
out_numpy = avg_pool_numpy(x_numpy[0, 0])
out_tensor = avg_pool_tensor(x_tensor)
d_loss_numpy = np.random.random(out_tensor.shape)
d_loss_tensor = torch.tensor(d_loss_numpy, requires_grad=True)
out_tensor.backward(d_loss_tensor)
dx_numpy = avg_pool_numpy.backward(d_loss_numpy[0, 0])
dx_tensor = x_tensor.grad
# print('input \n', x_numpy)
print("out_numpy \n", out_numpy)
print("out_tensor \n", out_tensor.data.numpy())
print("dx_numpy \n", dx_numpy)
print("dx_tensor \n", dx_tensor.data.numpy())
結(jié)果對比:
input
[[[[0.67762597 0.784904 0.1742022 0.77898319 0.51368794 0.08239002 0.81457734 0.02356839 0.22477326]
[0.96088153 0.06949592 0.73221965 0.66271638 0.00440624 0.78853139 0.89342955 0.89005521 0.91831133]
[0.29421028 0.8554962 0.05581848 0.71596048 0.70460538 0.63569891 0.01734993 0.13829778 0.30057628]
[0.75630389 0.73970589 0.38891535 0.18060703 0.8896449 0.19123307 0.38337412 0.48160742 0.49614005]
[0.36208588 0.13197825 0.110713 0.0618705 0.01305788 0.17365524 0.34396082 0.67473201 0.0877381 ]
[0.13336738 0.88374808 0.49674372 0.62228087 0.73629159 0.04834309 0.99103707 0.93708058 0.39369763]]]]
out_numpy
[[0.62322686 0.58703035 0.3472539 0.65540762]
[0.66142906 0.33532534 0.60529557 0.25515731]
[0.3777949 0.32290202 0.24283695 0.73670262]]
out_tensor
[[[[0.62322686 0.58703035 0.3472539 0.65540762]
[0.66142906 0.33532534 0.60529557 0.25515731]
[0.3777949 0.32290202 0.24283695 0.73670262]]]]
dx_numpy
[[0.05336788 0.05336788 0.01867329 0.01867329 0.0331215 0.0331215 0.11753746 0.11753746 0. ]
[0.05336788 0.05336788 0.01867329 0.01867329 0.0331215 0.0331215 0.11753746 0.11753746 0. ]
[0.02911582 0.02911582 0.12474389 0.12474389 0.18454687 0.18454687 0.24717661 0.24717661 0. ]
[0.02911582 0.02911582 0.12474389 0.12474389 0.18454687 0.18454687 0.24717661 0.24717661 0. ]
[0.09239687 0.09239687 0.11108155 0.11108155 0.12044172 0.12044172 0.12191826 0.12191826 0. ]
[0.09239687 0.09239687 0.11108155 0.11108155 0.12044172 0.12044172 0.12191826 0.12191826 0. ]]
dx_tensor
[[[[0.05336788 0.05336788 0.01867329 0.01867329 0.0331215 0.0331215 0.11753746 0.11753746 0. ]
[0.05336788 0.05336788 0.01867329 0.01867329 0.0331215 0.0331215 0.11753746 0.11753746 0. ]
[0.02911582 0.02911582 0.12474389 0.12474389 0.18454687 0.18454687 0.24717661 0.24717661 0. ]
[0.02911582 0.02911582 0.12474389 0.12474389 0.18454687 0.18454687 0.24717661 0.24717661 0. ]
[0.09239687 0.09239687 0.11108155 0.11108155 0.12044172 0.12044172 0.12191826 0.12191826 0. ]
[0.09239687 0.09239687 0.11108155 0.11108155 0.12044172 0.12044172 0.12191826 0.12191826 0. ]]]]