Подтвердить что ты не робот

Умножение в массив numpy

Я пытаюсь умножить каждое из терминов в 2D-массиве на соответствующие члены в 1D-массиве. Это очень просто, если я хочу умножить каждый столбец на массив 1D, как показано в numpy.multiply. Но я хочу сделать наоборот, умножить каждый член в строке. Другими словами, я хочу умножить:

[1,2,3]   [0]
[4,5,6] * [1]
[7,8,9]   [2]

и получим

[0,0,0]
[4,5,6]
[14,16,18]

но вместо этого я получаю

[0,2,6]
[0,5,12]
[0,8,18]

Кто-нибудь знает, есть ли элегантный способ сделать это с помощью numpy? Большое спасибо, Alex

4b9b3361

Ответ 1

Нормальное умножение, как вы показали:

>>> import numpy as np
>>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> c = np.array([0,1,2])
>>> m * c
array([[ 0,  2,  6],
       [ 0,  5, 12],
       [ 0,  8, 18]])

Если вы добавите ось, она будет умножаться так, как вы хотите:

>>> m * c[:, np.newaxis]
array([[ 0,  0,  0],
       [ 4,  5,  6],
       [14, 16, 18]])

Вы также можете транспонировать дважды:

>>> (m.T * c).T
array([[ 0,  0,  0],
       [ 4,  5,  6],
       [14, 16, 18]])

Ответ 2

Вы также можете использовать матричное умножение (aka dot product):

a = [[1,2,3],[4,5,6],[7,8,9]]
b = [0,1,2]
c = numpy.diag(b)

numpy.dot(c,a)

Что более элегантно, вероятно, дело вкуса.

Ответ 3

Еще один трюк (по версии 1.6)

A=np.arange(1,10).reshape(3,3)
b=np.arange(3)

np.einsum('ij,i->ij',A,b)

Я разбираюсь в вещании numpy (newaxis), но я все еще нахожу свой путь вокруг этого нового инструмента einsum. Поэтому я немного поиграл, чтобы найти это решение.

Сроки (с использованием Ipython timeit):

einsum: 4.9 micro
transpose: 8.1 micro
newaxis: 8.35 micro
dot-diag: 10.5 micro

Кстати, при изменении a i до j, np.einsum('ij,j->ij',A,b) получается матрица, которую Алекс не хочет. И np.einsum('ji,j->ji',A,b) делает, по сути, двойную транспонирование.

Ответ 4

Я сравнивал различные варианты скорости и обнаружил, что, к моему удивлению, все опции (кроме diag) одинаково быстрые:

введите описание изображения здесь


Код для воспроизведения сюжета:

import numpy
import perfplot


def newaxis(data):
    A, b = data
    return A * b[:, numpy.newaxis]


def double_transpose(data):
    A, b = data
    return (A.T * b).T


def double_transpose_contiguous(data):
    A, b = data
    return numpy.ascontiguousarray((A.T * b).T)


def diag_dot(data):
    A, b = data
    return numpy.dot(numpy.diag(b), A)


def einsum(data):
    A, b = data
    return numpy.einsum('ij,i->ij', A, b)


perfplot.show(
    setup=lambda n: (numpy.random.rand(n, n), numpy.random.rand(n)),
    kernels=[
        newaxis, double_transpose, double_transpose_contiguous, diag_dot,
        einsum
        ],
    n_range=[2**k for k in range(10)],
    logx=True,
    logy=True,
    xlabel='len(A), len(b)'
    )

Ответ 5

Почему бы вам просто не сделать

>>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> c = np.array([0,1,2])
>>> (m.T * c).T

??