# Eliminate for loops in numpy implementation

I have the following dataset in numpy

indices | real data (X)    |targets (y)
|                  |
0   0   | 43.25 665.32 ... |2.4      } 1st block
0   0   | 11.234           |-4.5     }
0   1     ...               ...      } 2nd block
0   1                                }
0   2                                } 3rd block
0   2                                }
1   0                                } 4th block
1   0                                }
1   0                                }
1   1                       ...
1   1
1   2
1   2
2   0
2   0
2   1
2   1
2   1
...


Theses are my variables

idx1 = data[:,0]
idx2 = data[:,1]
X = data[:,2:-1]
y = data[:,-1]


I also have a variable W which is a 3D array.

What I need to do in the code is loop through all the blocks in the dataset and return a scalar number for each block after some computation, then sum up all the scalars, and store it in a variable called cost. Problem is that the looping implementation is very slow, so I'm trying to do it vectorized if possible. This is my current code. Is it possible to do this without for loops in numpy?

IDX1 = 0
IDX2 = 1

# get unique indices
idx1s = np.arange(len(np.unique(data[:,IDX1])))
idx2s = np.arange(len(np.unique(data[:,IDX2])))

# initialize global sum variable to 0
cost = 0
for i1 in idx1s:
for i2 in idx2:

# for each block in the dataset
mask = np.nonzero((data[:,IDX1] == i1) & (data[:,IDX2] == i2))

# get variables for that block
curr_W = W[:,i2,i1]

# calculate a scalar
pred = np.dot(curr_X,curr_W)
sigm = 1.0 / (1.0 + np.exp(-pred))
loss = np.sum((sigm- (0.5)) * curr_y)

# add result to global cost
cost += loss


Here is some sample data

data = np.array([[0,0,5,5,7],
[0,0,5,5,7],
[0,1,5,5,7],
[0,1,5,5,7],
[1,0,5,5,7],
[1,1,5,5,7]])
W = np.zeros((2,2,2))
idx1 = data[:,0]
idx2 = data[:,1]
X = data[:,2:-1]
y = data[:,-1]

• Could you please edit the title of your question to be less generic? Jan 23, 2018 at 0:48

That W was tricky... Actually, your blocks are pretty irrelevant, apart from getting the right slice of W to do the np.dot with the corresponding X, so I went the easy route of creating an aligned_W array as follows:

aligned_W = W[:, idx2, idx1]


This is an array of shape (2, rows) where rows is the number of rows of your data set. You can now proceed to do your whole calculation without any for loops as:

from numpy.core.umath_tests import inner1d
pred = inner1d(X, aligned_W.T)
sigm = 1.0 / (1.0 + np.exp(-pred))
loss = (sigm - 0.5) * curr_y
cost = np.sum(loss)