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.
Что мы имеем: те же интерфейсные прототипы (имена функций в интерфейсе) и вызываем разные реализации.
Библиография: Прототипы - википедия
Кажется, вы делаете матричные умножения для каждого среза вдоль первой оси. Для этого вы можете использовать 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
Вам просто нужно выполнить операцию над первым измерением ваших тензоров, который помечен 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]
.
(2, 2, 2, 2)
вместо (10, 2, 2)
с вашим решением, поэтому что-то может быть неправильным.
– Holt
12 August 2015 в 08:03
einsum
. Есть ли что-то, что вы читали, это научило вас работать с синтаксисом? – rayryeng 12 August 2015 в 21:26permute
. Недавно выяснилось , как использоватьnp.einsum
для заменыnp.any
, снова, играя с ним. – Divakar 13 August 2015 в 04:44np.einsum
поддерживаемому NumPy? Я не совсем уверен, как заставить tensddd работать в этом случае. – Divakar 13 August 2015 в 04:56