Матричный матричный продукт [дубликат]

Q: - ... "Можно использовать любой класс, реализующий интерфейс?" A: - Да.

Q: -... «Когда вам это нужно?» A: - Каждый раз, когда вам нужен класс (ы), который реализует интерфейс (ы).

Примечание: мы не смогли создать интерфейс, не реализованный классом - Правда.

  • почему?
  • , потому что интерфейс имеет только прототипы методов, а не определения (просто имена функций, а не их логика)

AnIntf ​​anInst = new Aclass (); // мы могли бы сделать это, только если Aclass реализует AnIntf. // anInst будет иметь ссылку на Aclass.


Примечание: Теперь мы могли бы понять что происходит, если Bclass и Cclass реализуют один и тот же Dintf.

Dintf bInst = new Bclass();  
// now we could call all Dintf functions implemented (defined) in Bclass.

Dintf cInst = new Cclass();  
// now we could call all Dintf functions implemented (defined) in Cclass.

Что мы имеем: те же интерфейсные прототипы (имена функций в интерфейсе) и вызываем разные реализации.

Библиография: Прототипы - википедия

9
задан Divakar 12 August 2015 в 07:35
поделиться

2 ответа

Кажется, вы делаете матричные умножения для каждого среза вдоль первой оси. Для этого вы можете использовать np.einsum так же -

np.einsum('ijk,ikl->ijl',A,B)

Мы также можем использовать np.matmul -

np.matmul(A,B)

В Python 3.x эта операция matmul упрощается с помощью оператора @ -

A @ B

Бенчмаркинг

Подходы -

def einsum_based(A,B):
    return np.einsum('ijk,ikl->ijl',A,B)

def matmul_based(A,B):
    return np.matmul(A,B)

def forloop(A,B):
    N = A.shape[0]
    C = np.zeros((N,2,2))
    for i in range(N):
        C[i] = np.dot(A[i], B[i])
    return C

Сроки -

In [44]: N = 10000
    ...: A = np.random.rand(N,2,2)
    ...: B = np.random.rand(N,2,2)

In [45]: %timeit einsum_based(A,B)
    ...: %timeit matmul_based(A,B)
    ...: %timeit forloop(A,B)
100 loops, best of 3: 3.08 ms per loop
100 loops, best of 3: 3.04 ms per loop
100 loops, best of 3: 10.9 ms per loop
10
ответ дан Divakar 20 August 2018 в 21:25
поделиться
  • 1
    Спасибо Дивакар. Хотелось бы, чтобы я мог использовать это, но я несколько застрял в старой версии numpy, у которой нет einsum. Есть ли эквивалентный вызов с тендердотом? – Remy 12 August 2015 в 18:39
  • 2
    Я никогда не мог понять, как работает einsum. Есть ли что-то, что вы читали, это научило вас работать с синтаксисом? – rayryeng 12 August 2015 в 21:26
  • 3
    @rayryeng Только официальные документы и часы игры с ним. Есть еще много других вещей, которые я видел, когда люди делали с этим на SO, что мне нужно выяснить! Просто поиграйте с ним, как и с permute. Недавно выяснилось , как использовать np.einsum для замены np.any , снова, играя с ним. – Divakar 13 August 2015 в 04:44
  • 4
    @Remy Вы наконец-то получили доступ к np.einsum поддерживаемому NumPy? Я не совсем уверен, как заставить tensddd работать в этом случае. – Divakar 13 August 2015 в 04:56
  • 5
    @Divakar Да, я сделал это на своем собственном компьютере, и это действительно так намного быстрее, что я собираюсь укусить IT-пулю и обновить все остальные. Еще раз спасибо. – Remy 13 August 2015 в 08:25

Вам просто нужно выполнить операцию над первым измерением ваших тензоров, который помечен 0:

c = tensordot(a, b, axes=(0,0))

Это будет работать по вашему желанию. Также вам не нужен список осей, потому что это просто одно измерение, которое вы выполняете. С axes([1,2],[2,1]) вы перекрещиваетесь с 2-м и 3-м измерениями. Если вы пишете его в индексной нотации (соглашение об объединении Эйнштейна), это соответствует c[i,j] = a[i,k,l]*b[j,k,l], таким образом, вы сокращаете индексы, которые хотите сохранить.

EDIT: Хорошо, проблема в том, что тензорное произведение двух трехмерных объектов является объектом 6d. Поскольку сокращения связаны с парами индексов, вы не сможете получить 3D-объект с помощью операции tensordot. Трюк состоит в том, чтобы разбить ваш расчет на две части: сначала вы делаете tensordot в индексе для выполнения операции с матрицей, а затем вы берете диагональ тензора, чтобы уменьшить ваш 4d-объект до 3d. В одной команде:

d = np.diagonal(np.tensordot(a,b,axes=()), axis1=0, axis2=2)

В тензорной нотации d[i,j,k] = c[i,j,i,k] = a[i,j,l]*b[i,l,k].

0
ответ дан Mattia 20 August 2018 в 21:25
поделиться
  • 1
    Я получаю форму (2, 2, 2, 2) вместо (10, 2, 2) с вашим решением, поэтому что-то может быть неправильным. – Holt 12 August 2015 в 08:03
  • 2
    Извините, я дал вам неправильный ответ, пожалуйста, посмотрите на мой EDIT. – Mattia 12 August 2015 в 21:25
Другие вопросы по тегам:

Похожие вопросы: