#python #numpy #numpy-ndarray #tensor #array-broadcasting
Вопрос:
У меня есть массив 3D NumPy размером (9,9,200)
и массив 2D размером (200,200)
. Я хочу взять каждый канал форму (9,9,1)
и создать массив (9,9,200)
, каждый канал умноженной в 200 раз по 1 скаляр в один ряд, и средний ее так, чтобы результирующий массив (9,9,1)
.
В принципе, если есть n
каналы в массиве ввода, я хочу, чтобы каждый канал умножается n
раза и составила в среднем — и это должно произойти для всех каналов. Есть ли эффективный способ сделать это?
Пока что у меня есть вот это —
import numpy as np
arr = np.random.rand(9,9,200)
nchannel = arr.shape[-1]
transform = np.array([np.random.uniform(low=0.0, high=1.0, size=(nchannel,)) for i in range(nchannel)])
for channel in range(nchannel):
# The below line needs optimization
temp = [arr[:,:,i] * transform[channel][i] for i in range(nchannel)]
arr[:,:,channel] = np.sum(temp, axis=0)/nchannel
Редактировать :
Пример изображения, демонстрирующего то, что я ищу. Здесь nchannel
= 3.
Входное изображение есть arr
. Конечный образ — это трансформированный arr
.
Комментарии:
1. можете ли вы опубликовать минимальный исполняемый пример? Я не уверен, что такое arr и nchannel…
2. Я не уверен, что понимаю, чего вы хотите, для чего нужен 2D-массив? Откуда берутся n скаляров?
3. Возможно, чтобы добавить к комментарию sehan2 , было бы очень полезно, если бы это был игрушечный пример, которого нет
9 x 9 x 200
, но что-то вроде2 x 2 x 3
ожидаемого результата: -) Я, к сожалению, не понимаю вашей проблемы из вопроса..4. Спасибо, что указали на это @sehan2. @user16648691 двумерный массив представляет собой
nxn
матрицу, каждая строка которой соответствует n скалярам, на которые будет умножен один канал.5. Если я правильно понял, это тензорное умножение на матрицу, а затем усреднение по оси -1?
Ответ №1:
Редактировать:
import numpy as np
n_channels = 3
scalar_size = 2
t = np.ones((n_channels,scalar_size,scalar_size)) # scalar array
m = np.random.random((n_channels,n_channels)) # letters array
print(m)
print(t)
m_av = np.mean(m, axis=1)
print(m_av)
for i in range(n_channels):
t[i] = t[i]*m_av1[i]
print(t)
выход:
[[0.04601533 0.05851365 0.03893352]
[0.7954655 0.08505869 0.83033369]
[0.59557455 0.09632997 0.63723506]]
[[[1. 1.]
[1. 1.]]
[[1. 1.]
[1. 1.]]
[[1. 1.]
[1. 1.]]]
[0.04782083 0.57028596 0.44304653]
[[[0.04782083 0.04782083]
[0.04782083 0.04782083]]
[[0.57028596 0.57028596]
[0.57028596 0.57028596]]
[[0.44304653 0.44304653]
[0.44304653 0.44304653]]]
Комментарии:
1. Привет @user16648691, я не думаю, что это правильное решение. Я добавил диаграмму, чтобы лучше подчеркнуть то, что я ищу.
2. итак, здесь у нас есть скалярный массив 2x2x3 и массив 3×3, содержащий каналы, верно? Сначала для каждого канала размера 3 мы получаем массив 2x2x3, который в основном является элементом умножения скалярного массива на каждый элемент канала ? Таким образом, вы в конечном итоге получаете массив 2x2x3x3, который вы, наконец, усреднили на последнем axxis, чтобы получить массив 2x2x3 ? Поправьте меня, если я ошибаюсь
3. Если это так, я бы сначала усреднил каждый канал, чтобы вы получили массив 1D размером n_channel, который вы можете поэлементно умножить на свой скалярный массив. Я отредактирую свой ответ.
Ответ №2:
То, о чем вы просите, — это простое матричное умножение вдоль последней оси:
import numpy as np
arr = np.random.rand(9,9,200)
transform = np.random.uniform(size=(200, 200)) / 200
arr = arr @ transform