1

I'm working with a 3D array of which the index array is a 200x200 binary array (for classification). This array contains either 0 or 1 and I need to use this array select a random 1000 locations of 0 and a random 1000 locations of 1 in the 3D array. I've gotten to the point where I can make a list of integers and their location and I cannot figure out how to randomize that list and use it to slice the 3D array.

What follows is my code.

index = file.read(1) #a 200 x 200 2D array. it's binary and only contains 1s and 0s in varying clusters.
array1 = file.read(1) #a 200x 200 2D array #first array in the stack this is repeated for the remaining 3
stack = np.dstack((array1, array2, array3, array4, index)) #Note location of 'index'. Also this is now a 3d array.

Printing 'stack' provides this.

print(stack)

[[[0.5580524  0.4883823  0.45231035 0.48734677 0.48952746 0.5680048
   0.61111915 0.7087597  0.68731683 0.7544603  0.74395233 0.76797485
   0.6963369  0.551183   1.        ]

...

[0.4401738  0.3988781  0.35379404 0.36442786 0.36919853 0.46986657
   0.4414228  0.4944533  0.47824454 0.5220391  0.56117916 0.6202841
   0.6201752  0.64005166 0.        ]]]

Now to generate a list of values and their positions from 'index' 2D array using numpy.where

class_indexes = {}
for class_ in np.unique(index):
    class_indexes[class_] = np.where(index == class_)

The results of calling class_indexes is below

class_indexes
{0: (array([   1,    1,    1, ..., 1511, 1511, 1511]),
  array([1797, 1798, 1799, ..., 2001, 2002, 2003])),
 1: (array([   1,    1,    1, ..., 1511, 1511, 1511]),
  array([1833, 1834, 1835, ..., 1962, 1963, 1964]))}

additionally

len(class_indexes[0][0])
280000

len(class_indexes[1][1])
120000

Matches

np.unique(index, return_counts = True)
(array( 0,  1], dtype=int16), array([280000, 120000]))

I can select/slice a specific location in the 3D array using

print(stack[50:51,75:76])
[[[0.444261   0.43989536 0.47133848 0.4160257  0.5548938  0.44350675
   0.6010795  0.48953462 0.6352046  0.5407316  0.72074664 0.69200116
   0.58779025 0.5807785  1.        ]]]

or

print(stack[50,75])
[0.444261   0.43989536 0.47133848 0.4160257  0.5548938  0.44350675
 0.6010795  0.48953462 0.6352046  0.5407316  0.72074664 0.69200116
 0.58779025 0.5807785  1.        ]

This is where I get stuck. To reiterate, I want to randomly slice 1000 of the ones that end in 1 and 1000 of the ones that end in 0 from the 3D array and I cannot for the life of me figure out how to use the 'class_indexes' I've generated to do this.

4

2 回答 2

0

I suppose you want to create a batch and iterate over them?

You can create a permutation of each class and then select the batch you want:

p1 = np.random.permutation(280000) // use the length of the class instead of the fixed value
p2 = np.random.permutation(120000)

for i in range(0, batch_size, 120000):
   class_indexes[0][p1[i:i+batch_size]]
   class_indexes[1][p2[i:i+batch_size]]

Of course, this is a little bit waste full because of the discarded 160000 elements, but you could still use this data by having two indexes and create a new permutation when required.

Check each element of the indexing to see what it does:

p1[i:i+batch_size]

And then

class_indexes[0][p1[i:i+batch_size]]
于 2018-12-06T15:44:43.373 回答
0

This should work with two classes. If you have more than two classes it becomes a problem.

import numpy as np

allindices = np.mgrid[0:200, 0:200].swapaxes(0, 2).swapaxes(0, 1)
allzeroes = allindices[index2 == 0]
randomzeroes = allzeroes[np.random.randint(0, allzeroes.shape[0], size=2000), :] #size = sample size.
newarray = index[randomzeroes[:,0], randomzeroes[:,1], :]

np.set_printoptions(threshold=np.nan) #removes truncation during print
print(newarray)
于 2018-12-07T10:10:49.073 回答