Reputation: 43
I'm working on a project where I have a set of samples for gesture recognition (ChaLearn dataset).
The input is a (10000,6,32,64,64) array. I have 10000 examples, 6 featuremaps (body, l-hand, r-hand in depth and rgb images), 32 frames of 64 by 64.
I have to select only the depth images (which are indices 1, 3 and 5) and 4 frames out of 32 (indices 8,13,18,25)
I'm not that familiar with python so I was messing around and I think my solution is fine but it is really slow. Mostly the two selections take up alot of time (70-80 seconds for this bit).
samples.shape gives me (10000,6,32,64,64) at the start
samples = samples[0:samples.shape[0],0:samples.shape[1],(7,13,18,25)]
samples = samples[0:samples.shape[0],(1,3,5)]
samples = floatX(samples.reshape((samples.shape[0],12,64,64)))/255.
samples.shape gives me (10000,12,64,64) at the end.
Is there a more efficient way of accomplishing my goal? Or am I completely wrong here?
ignore the floatx part for now :)
Upvotes: 2
Views: 3023
Reputation: 88198
Is there a more efficient way of accomplishing my goal?
If you are willing to look into another layer of abstraction, you might want to consider a format that is designed for larger data. Personally, I use HDF which has a few nice python modules like h5py
and pytables
.
Two main advantages I see, you'll be able to store much larger datasets at once (since you don't have to load the entire set into memory) and you'll be able to apply meta-data to the data (with .attrs
). When you build the hdf data set you can organize it so your "query" of something like "indices 1, 3 and 5" can be much more logical.
Upvotes: 1
Reputation: 67447
As mentioned in the other answer, there are some discussions in numpy about making this easier, but in your case, since the two axes you want to index along are adjacent in the shape, things aren't so bad. This should get you what you are after avoiding that intermediate copy altogether:
depth_idx = np.array([1, 3, 5], dtype=np.intp)
frame_idx = np.array([8, 13, 18, 25], dtype=np.intp)
samples = samples[:, depth_idx[:, None], frame_idx].reshape(-1, 12, 64, 64)
Actually, since your depth_idx
happens to be writeable as a slice, for this particular case you will actually be better off doing:
samples = samples[:, 1::2, frame_idx].reshape(-1, 12, 64, 64)
Upvotes: 2
Reputation: 10308
First, you can just do samples[:,:,(7,13,18,25)]
. However, the reason this is slow is because you are doing you are doing 2 copy operations. You can't currently get around this, although you can simplify stuff somewhat using take
:
samples = np.take(np.take(samples, [7,13,18,25], axis=2), [1,3,4], axis=1)
There is actually work going on to make the operation you are trying to do much easier, but it isn't ready yet.
If you aren't using numpy
1.9, you should definitely upgrade to it, since the "fancy" indexing you are doing is much faster. The take
version will be faster in earlier versions.
Upvotes: 1