Разделите большую матрицу numpy на 10 независимых подматриц стратифицированным образом

#python #numpy #matrix

#python #numpy #матрица

Вопрос:

У меня есть две переменные numpy с 32000 записями, которые выглядят следующим образом:

 >>> files
array(['GAN_0.npy', 'GAN_1.npy', 'GAN_10.npy', ..., 'GAN_822.npy',
       'GAN_8220.npy', 'GAN_8221.npy'], dtype='<U13')
>>> files.shape
(32000,)

>>> labels
array([1, 1, 1, ..., 1, 1, 1])
>>> np.unique(labels)
array([0, 1])
>>> labels.shape
(32000,)
  

Другими словами, первая переменная представляет собой числовую матрицу строк, а другая — числовую матрицу целых чисел. В первой матрице у меня есть строковый список имен изображений, а в другой матрице — целые числа в качестве меток, которые я использую для их идентификации (изображения, начинающиеся с имен GAN_, равны 1, тогда как изображения с именами RAW_ равны 0).

Я хотел бы знать, могу ли я разделить эти 32000 записей на 10 подмножеств по 3200 изображений в каждом без повторения, то есть 1600 записей, имена которых начинаются с RAW_, и другие 1600, имена которых начинаются с GAN_ . Имена и метки изображений перемешиваются, поэтому я не могу просто разделить большую матрицу на 10 подматриц. Поэтому, существует ли какой-либо метод в Numpy, который мог бы создать 10 стратифицированных и независимых подматриц образцов из 2 классов в Python?

P.s: эти два файла можно найти здесь

Комментарии:

1. вы имели в виду 32000 вместо 16000?

2. Спасибо. почему бы не разделить их, а затем разделить и объединить?

3. Именно поэтому я именно сейчас и делаю. Как только я закончу, я опубликую это здесь. Спасибо.

Ответ №1:

Вот возможное решение:

 arrays = [np.concatenate((g, r))
          for g, r in zip(np.array_split(files[labels==1], 10), 
                          np.array_split(files[labels==0], 10))]
  

Это решение сохраняет относительный порядок файлов ‘GAN *’ и ‘RAW *’. Кроме того, массивы создаются таким образом, что начальные позиции заполняются файлами ‘GAN *’, а остальные — файлами ‘RAW *’. если вас не устраивает такая сортировка, вы всегда можете перетасовать каждый массив после их создания.

Комментарии:

1. Спасибо за ваш ответ. Итак, для каждого подмножества я никогда не найду те же элементы в другом подмножестве, правильно?

2. @mad Да, точно

3. не используйте циклы в numpy. измените форму и сложите и измените форму обратно.

4. @CrazyCoder Я не использую никакого цикла в numpy. Массив разделяется дважды, а затем я повторяю результат (который не является массивом numpy). если у вас есть более быстрое решение, пожалуйста, не стесняйтесь предлагать что-то или отправлять другой ответ 🙂

5. @RiccardoBucco Я добавил решение без циклов. Я думаю, что Crazy Coder имеет в виду нечто подобное.

Ответ №2:

Вот решение без циклов (предложенное @Crazy Coder в комментариях к другим ответам):

 labels = np.array(labels, dtype=bool)
np.split(np.vstack((files[labels],files[~labels])).T.reshape(-1,1), 10)
  

Ответ №3:

Мое собственное решение (основанное на предложении @CrazyCoder)

 import numpy as np

#Read file names
file_names=np.genfromtxt('test_files.txt',dtype='str')
   
raw_vector=[]
gan_vector=[]

for i in range(0,file_names.shape[0]):

    image_name=file_names[i]

    #Separate RAW and GAN files
    if("RAW_" in image_name):
        raw_vector.append(image_name)

    if("GAN_" in image_name):
        gan_vector.append(image_name)
    
raw_vector=np.array(raw_vector)
gan_vector=np.array(gan_vector)

#Split into 10 subsets each
raw_vector_divided=np.split(raw_vector,10)
gan_vector_divided=np.split(gan_vector,10)

for j in range(0,10):
    x=raw_vector_divided[j]
    y=gan_vector_divided[j]
    
    x=x.reshape(x.shape[0],1)
    y=y.reshape(y.shape[0],1)
    
    #merge
    experiment_data=np.vstack((x,y))
    
    #Save subset as file
    np.savetxt( 'experiment-'   str(j 1)   '-data.txt',  experiment_data, fmt='%s')

print("finished")