How to express c[i,j,k] = a[i,j] * b[i,k] in Numpy/Theano? - numpy

The definition
c[i,j,k] = a[i,j] * b[i,k] for any i, j, k
is an element-wise product with respect to i, and an outer product with respect to j and k. Is there any way to express this in NumPy/Theano without loops?

I found a solution that works with both Numpy and Theano:
c = a[:, :, np.newaxis] * b[:, np.newaxis, :]

Related

Sympy simplify sum of Kronecker delta

How does one simplify sums of Kronecker delta expressions in sympy?
For example consider Sum(KroneckerDelta(i,j),(i,0,n-1)) or Sum(KroneckerDelta(i, j, (0, n - 1)), (i, 0, n - 1)):
from sympy import *
from sympy.concrete.delta import _simplify_delta
n = symbols('n')
j = tensor.Idx('j')
i = tensor.Idx('i')
_simplify_delta(simplify(Sum(KroneckerDelta(i,j),(i,0,n-1))))
_simplify_delta(simplify(Sum(KroneckerDelta(i,j,(0,n-1)),(i,0,n-1))))
Outputs Sum(KroneckerDelta(i, j), (i, 0, n - 1)) and Sum(KroneckerDelta(i, j, (0, n - 1)), (i, 0, n - 1))
If j is constrained to be between 0 and n-1 (how do I tell the sympy that?), then this should reduce to 1, which occurs at i==j. Moreover if the sum is more complicated, I would expect it to remove the sum and replace the sum variable i with the variable j.
Moreover, I would be interested in a resource for all sorts of simplifications in sympy for KroneckerDelta functions. I recently found out how to perform implicit matrix differentiation in sympy and KroneckerDelta functions appear everywhere.
Edit: I found a solution, kind of. Its not automated.
I found more functions inside of sympy.concrete.delta using help(sympy.concrete.delta). If we copy the resulting expression and replace Sum with sympy.concrete.delta.deltasummation then the desired simplification happens. I am still curious if there is a delta simplification package that tries all these things automatically.
You can evaluate summations using Sum().doit() or summation:
In [1]: from sympy import *
...: from sympy.concrete.delta import _simplify_delta
...:
...: n = symbols("n")
...: j = tensor.Idx("j")
...: i = tensor.Idx("i")
In [2]: s = Sum(KroneckerDelta(i, j), (i, 0, n - 1))
In [3]: s
Out[3]:
n - 1
___
╲
╲ δ
╱ i,j
╱
‾‾‾
i = 0
In [4]: s.doit()
Out[4]:
⎧1 for j ≥ 0 ∧ j ≤ n - 1
⎨
⎩0 otherwise
In [5]: summation(KroneckerDelta(i, j), (i, 0, n - 1))
Out[5]:
⎧1 for j ≥ 0 ∧ j ≤ n - 1
⎨
⎩0 otherwise
There isn't currently a way to specify in assumptions that j<=n-1 although you can use j = symbols('j', nonnegative=True) to specify that j>=0. You can also manually replace those conditions with true though e.g.:
In [8]: s.doit().subs({j >= 0: True, j <= n-1: True})
Out[8]: 1
The second summation where you give bounds for the KroneckerDelta will compute automatically:
In [11]: s2 = Sum(KroneckerDelta(i, j, (0, n - 1)), (i, 0, n - 1))
In [12]: s2
Out[12]:
n - 1
___
╲
╲ δ
╱ i,j
╱
‾‾‾
i = 0
In [13]: s2.doit()
Out[13]: 1

Efficient way to calculate 3D matrix multiplication using numpy

How can I efficiently write and calculate this multiplication using numpy:
for k in range(K):
for i in range(SIZE):
for j in range(SIZE):
for i_b in range(B_SIZE):
for j_b in range(B_SIZE):
for k_b in range(k+1):
data[k, i * w + i_b, j * h + j_b] += arr1[k_b, i_b, j_b] * arr2[k_b, i, j]
For example:
SIZE, B_SIZE = 32, 8
arr1.shape -> (8, 8, 8)
arr2.shape -> (8, 32, 32)
data.shape -> (K, 256, 256)
Thank you.
You can use Numba for such kind of non-trivial case and rework the loops to use efficiently the CPU cache. Here is an example:
import numba as nb
#nb.njit
def compute(data, arr1, arr2):
for k in range(K):
for k_b in range(k+1):
for i in range(SIZE):
for j in range(SIZE):
tmp = arr2[k_b, i, j]
for i_b in range(B_SIZE):
for j_b in range(B_SIZE):
data[k, i * w + i_b, j * h + j_b] += arr1[k_b, i_b, j_b] * tmp
If you do this operation once, then you can pre-compile the Numba code by providing the types of the arrays. If K is big, then you can parallelize the code using #nb.njit(parallel=True) and use for k in nb.prange(K) rather than for k in range(K). This should be several order of magnitude fater.

Multiplying multidimensional array in python

I have two arrays:
L, M, N = 6, 31, 500
A = np.random.random((L, M, N))
B = np.random.random((L, L))
I am trying to get an array C such that:
C = B * A
C has dimension [L, M, N]
I tried answer posted at this link but it hasn't given me the desired output.
A for loop version of above code is:
L, M, N = 6, 31, 500
A = np.random.random((L, M, N))
B = np.random.random((L, L))
z1 = []
for j in range(M):
a = np.squeeze(A[:, j, :])
z1.append(np.dot(B, a))
z2 = np.stack(z1)
I think you are looking for numpy.tensordot() where you can specify along which axes to sum:
np.tensordot(B,A,axes=(1,0))

Pick random tensors from another one in Tensorflow

I have a Tensor X whith shape [B, L, E] (let's say, B batches of L vectors of length E). From this Tensor X, I want to randomly pick N vectors in each batch, and so create Y with shape [B, N, E].
I tried to combine tf.random_uniform and tf.gather but I really struggle with the dimension and can't get Y.
You can use something like this:
import tensorflow as tf
import numpy as np
B = 3
L = 5
E = 2
N = 3
input = np.array(range(B * L * E)).reshape([B, L, E])
print(input)
print("#################################")
X = tf.constant(input)
batch_range = tf.tile(tf.reshape(tf.range(B, dtype=tf.int32), shape=[B, 1, 1]), [1, N, 1])
random = tf.random_uniform([B, N, 1], minval = 0, maxval = L - 1, dtype = tf.int32)
indices = tf.concat([batch_range, random], axis = 2)
output = tf.gather_nd(X, indices)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(indices))
print("#################################")
print(sess.run(output))

Printing the equation of the best fit line

I have created the best fit lines for the dataset using the following code:
fig, ax = plt.subplots()
for dd,KK in DATASET.groupby('Z'):
fit = polyfit(x,y,3)
fit_fn = poly1d(fit)
ax.plot(KK['x'],KK['y'],'o',KK['x'], fit_fn(KK['x']),'k',linewidth=4)
ax.set_xlabel('x')
ax.set_ylabel('y')
The graph displays the best fit line for each group of Z. I want print the equation of the best fit line on top of the line.Please suggest what can i do out here
So you need to write some function that convert a poly parameters array to a latex string, here is an example:
import pylab as pl
import numpy as np
x = np.random.randn(100)
y = 1 + 2 * x + 3 * x * x + np.random.randn(100) * 2
poly = pl.polyfit(x, y, 2)
def poly2latex(poly, variable="x", width=2):
t = ["{0:0.{width}f}"]
t.append(t[-1] + " {variable}")
t.append(t[-1] + "^{1}")
def f():
for i, v in enumerate(reversed(poly)):
idx = i if i < 2 else 2
yield t[idx].format(v, i, variable=variable, width=width)
return "${}$".format("+".join(f()))
pl.plot(x, y, "o", alpha=0.4)
x2 = np.linspace(-2, 2, 100)
y2 = np.polyval(poly, x2)
pl.plot(x2, y2, lw=2, color="r")
pl.text(x2[5], y2[5], poly2latex(poly), fontsize=16)
Here is the output:
Here's a one liner.
If fit is the poly1d object, while plotting the fitted line, just use label argument as bellow,
label='y=${}$'.format(''.join(['{}x^{}'.format(('{:.2f}'.format(j) if j<0 else '+{:.2f}'.format(j)),(len(fit.coef)-i-1)) for i,j in enumerate(fit.coef)]))