Задача 6
Вычисление свертки
Предположим, у нас есть два 2D-массива arr и arr_filter:
arr = np.array([
[0.15, 0.71, 0.26, -0.11, -2.03],
[0.13, 0.44, -0.11, -0.23, 0.19],
[-1.44, 0.51, 0.42, 2.58, -0.88],
[-1.18, 2.73, 2.35, 0.21, -0.29],
[-1.64, -0.37, 0.27, 0.57, 1.82]
])

arr_filter = np.array([
[0.08, 0.27, -0.24],
[-0.25, -0.11, -0.18],
[0.44, 1.87, 1.18]
])
Свертка (конволюция) массива arr с массивом arr_filter с шагом свертки, равным 2 означает, что фильтр будет скользить по массиву arr с шагом 2, и на каждом шаге код будет вычислять скалярное произведение между фильтром и соответствующей областью массива arr:
Вам предстоит решить более сложную задачу — вычислить свертку двух многомерных массивов:
  • arr — массив размером 33x33x3, который можно рассматривать как 33x33 сетку, где каждая ячейка содержит 3-канальные данные (например, как в изображениях с тремя цветными каналами — RGB).
  • arr_filter — массив размером 5x5x3, который представляет собой фильтр для свертки.
import numpy as np

rng = np.random.default_rng(123)
arr = rng.normal(size=(33,33,3)).round(2)


print(arr)

# [

#     [[-0.99 -0.37  1.29]
#      [ 0.19  0.92  0.58]
#      [-0.64  0.54 -0.32]
#      ...
#      [ 1.23  0.15  0.48]
#      [-0.15  1.32 -1.22]

#      [-0.3  -1.17  0.83]]
# 
#     [[ 0.85 -0.52  1.66]
#      [-0.3  -1.38 -0.28]
#      [ 0.36 -0.23  2.27]
#      ...

#      [ 1.52  0.49  0.7 ]
#      [ 0.85 -0.91  0.12]
#      [ 0.15 -0.16 -1.09]]
# 
#     ...
# 

#     [[-0.38 -0.45  1.  ]
#      [-0.58  2.18  0.36]
#      [-0.44 -2.77  0.82]
#      ...
#      [-1.58 -0.5  -0.52]
#      [-0.86 -0.54 -0.26]
#      [ 0.23  0.81 -0.4 ]]
# 
#     [[-1.98 -0.22 -0.79]
#      [-0.01 -1.47 -0.83]
#      [-0.87  0.3  -0.82]
#      ...
#      [ 1.42  0.7  -0.75]
#      [-0.81  1.68 -0.82]
#      [-0.93  0.28 -1.61]]
# ]

filter = rng.normal(size=(5,5,3)).round(2)

print(filter)
#[

#      [[-1.47  0.74  0.58]

#      [ 0.46  2.37  0.79]
#      [ 1.15 -1.11 -0.29]
#      [-0.98  0.29  0.44]
#      [-0.44 -0.03  0.69]]
# 
#     [[ 0.34  0.67 -0.11]
#      [-0.71 -1.   -0.88]
#      [ 0.61  0.49 -0.27]
#      [ 0.12 -1.56  0.11]
#      [ 0.32 -0.98  0.46]]
#
#     [[-1.03  0.58  0.08]
#      [ 0.89  0.86  1.49]
#      [-0.4   0.86 -0.29]
#      [ 0.07 -0.09 -0.87]
#      [ 0.2   1.22 -0.27]]
# 
#     [[ 1.1  -2.61  1.64]
#      [-1.15  0.47  1.44]
#      [-1.45  0.39  1.37]
#      [ 0.13 -0.1   0.04]
#      [ 0.27  0.57  0.57]]
# 
#     [[-0.61 -0.41  0.93]
#      [ 1.47 -0.07 -0.29]
#      [ 0.49  1.02  0.2 ]
#      [ 0.16  0.95  0.52]
#      [ 1.11  0.13 -0.17]]
# ]

Решение 1
mport numpy as np

def convolution_3d(arr, arr_filter, stride=2):

arr_height, arr_width, arr_depth = arr.shape
arr_filter_height, arr_filter_width, _ = arr_filter.shape

output_height = (arr_height - arr_filter_height) // stride + 1
output_width = (arr_width - arr_filter_width) // stride + 1
output = np.zeros((output_height, output_width))

for i in range(output_height):
for j in range(output_width):
h_start = i * stride
h_end = h_start + arr_filter_height
w_start = j * stride
w_end = w_start + arr_filter_width

arr_slice = arr[h_start:h_end, w_start:w_end, :]
output[i, j] = np.sum(arr_slice * arr_filter)

return output

rng = np.random.default_rng(123)
arr = rng.normal(size=(33,33,3)).round(2)
arr_filter = rng.normal(size=(5,5,3)).round(2)

result = convolution_3d(arr, arr_filter, stride=2)
print(f"Результат свертки: \n{result}") 
            
Решение 2
import numpy as np

rng = np.random.default_rng(123)
arr = rng.normal(size=(33,33,3)).round(2)
arr_filter = rng.normal(size=(5,5,3)).round(2)
stride = 2
result_size = 15
result = np.zeros((result_size, result_size))

for i in range(result_size):
for j in range(result_size):
x_start = i * stride
y_start = j * stride
x_end = x_start + arr_filter.shape[0]
y_end = y_start + arr_filter.shape[1]

sub_array = arr[x_start:x_end, y_start:y_end, :]
result[i, j] = np.sum(sub_array * arr_filter)

print(f"Результат свертки: \n{result}")
Результат 💡
Результат свертки: [[ 1.6365 -3.2203 -2.4356 5.4776 5.0641 -11.4295 -0.57 3.0129 3.3447 -0.1092 9.8129 -18.7139 -5.593 -1.3115 11.4256] [ -3.7278 -3.1691 3.4618 6.5913 3.0866 -9.5214 -5.9602 -17.0158 -0.737 5.2471 -5.2445 0.9407 5.9824 -1.8073 -9.8402] [ 6.6744 5.4541 -4.0907 -7.7306 0.4615 7.2214 -13.1941 -0.3735 -4.1624 1.6707 5.9313 -11.2847 3.9481 -0.5967 -0.1432] [ -3.1864 10.1817 -3.741 -1.825 5.3938 -11.1009 7.4304 11.0491 -9.4815 6.9975 -6.4231 2.4402 -0.259 3.5262 -2.1071] [ -1.9811 -4.4298 16.1514 3.7657 -2.1691 15.8734 -8.1102 3.5816 13.8944 -2.9477 -2.3477 8.3166 -13.1247 7.7287 5.6404] [ -8.3384 -3.2206 -5.1079 -11.6662 -12.481 17.2997 5.7164 -0.9965 5.5737 2.1679 -9.0249 -6.2392 -0.1176 9.1014 -1.4912] [ 17.9393 3.9332 -1.7492 11.8316 5.3351 -9.5632 -3.6986 11.2727 9.8814 3.8074 -0.2027 -0.903 3.2166 -11.9336 6.539 ] [ 5.2101 -5.0775 -17.2767 9.5459 -13.1335 -5.3796 16.4167 4.2472 -0.419 -17.9 -8.0877 0.4413 -3.4333 12.5416 3.2737] [ 13.0626 4.448 4.3355 8.6428 -4.8645 -8.7404 5.9076 6.8848 11.9746 15.3114 -12.5516 -3.2627 0.8234 -0.6925 3.8171] [ 12.8567 11.4424 -7.1229 3.9673 -2.6499 -5.6442 1.4895 -1.2306 0.9072 14.5911 -2.9622 -9.0077 2.6915 5.0552 -6.6603] [ 9.6347 -5.3504 -4.6228 -16.5698 11.7627 -2.8633 -3.9296 -3.4898 -10.1173 -6.0982 -8.0761 -8.3843 0.2656 2.0927 -5.3165] [ 1.6311 -2.2514 -1.7042 11.7879 18.5396 -2.0368 4.8912 8.1521 -6.5893 -2.3582 -15.8512 3.6679 -14.4281 1.2029 1.1821] [ 16.9196 1.5067 -11.0525 4.5525 7.4842 3.3549 -1.0631 -0.915 4.3023 -2.4144 -5.1141 2.0733 -0.6937 14.4476 -2.1554] [ -9.0089 -1.1905 -4.8269 -2.0663 4.3727 2.8398 5.1798 14.1138 -11.8306 3.4416 0.9471 12.4693 6.4678 -0.6475 -7.7998] [ 2.3013 10.048 11.6956 -3.1206 -0.7687 -11.8323 10.3904 -8.4125 -11.6443 2.9512 -4.2575 2.1336 6.6034 2.801 -1.169 ]]