4
\$\begingroup\$

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_X = X[mask,:]
        curr_y = y[mask]
        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]
\$\endgroup\$
  • \$\begingroup\$ Could you please edit the title of your question to be less generic? \$\endgroup\$ – Seanny123 Jan 23 '18 at 0:48
3
\$\begingroup\$

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)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.