Numpys setdiff1d не работает? - PullRequest
       35

Numpys setdiff1d не работает?

1 голос
/ 16 апреля 2020

Чтобы выбрать данные для обучения и проверки в моих проектах машинного обучения, я обычно использую функцию маскировки numpys. Таким образом, типичный повторный блок кода для выбора индексов для проверки и проверки данных выглядит следующим образом:

import numpy as np

validation_split = 0.2

all_idx = np.arange(0,100000)
idxValid = np.random.choice(all_idx, int(validation_split * len(all_idx)))
idxTrain = np.setdiff1d(all_idx, idxValid)

Теперь всегда должно быть верно следующее:

len(all_idx) == len(idxValid)+len(idxTrain)

К сожалению, я нашел Выходит, что как-то это не всегда так. Поскольку я увеличиваю количество элементов, которые выбираются из массива all_idx, результирующие числа не складываются должным образом. Вот еще один автономный пример, который ломается, как только я увеличиваю количество случайно выбранных индексов проверки выше 1000:

import numpy as np

all_idx = np.arange(0,100000)
idxValid = np.random.choice(all_idx, 1000)
idxTrain = np.setdiff1d(all_idx, idxValid)

print(len(all_idx), len(idxValid), len(idxTrain))

Это приводит к -> 100000, 1000, 99005

Я запутался? ! Пожалуйста, попробуйте сами. Я был бы рад понять это.

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

Рассмотрим следующий пример:

all_idx = np.arange(0, 100)
print(all_idx)
>>> [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
 96 97 98 99]

Теперь, если вы распечатаете свой проверочный набор данных:

idxValid = np.random.choice(all_idx, int(validation_split * len(all_idx)))
print(idxValid)
>>> [31 57 55 45 26 25 55 76 33 69 49 90 46 14 18 30 89 73 47 82]

На самом деле вы можете заметить, что в результирующем наборе есть дубликаты и, таким образом,

len(all_idx) == len(idxValid)+len(idxTrain)

не приведет к True.

Что вам нужно сделать, это убедиться, что np.random.choice делает выборку без перестановки, передав replace=False:

idxValid = np.random.choice(all_idx, int(validation_split * len(all_idx)), replace=False)

Теперь результаты должны быть такими, как ожидалось:

import numpy as np

validation_split = 0.2

all_idx = np.arange(0, 100)
print(all_idx)

idxValid = np.random.choice(all_idx, int(validation_split * len(all_idx)), replace=False)
print(idxValid)

idxTrain = np.setdiff1d(all_idx, idxValid)
print(idxTrain)

print(len(all_idx) == len(idxValid)+len(idxTrain))

, а результат:

[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
 96 97 98 99]

[12 85 96 64 48 21 55 56 80 42 11 92 54 77 49 36 28 31 70 66]

[ 0  1  2  3  4  5  6  7  8  9 10 13 14 15 16 17 18 19 20 22 23 24 25 26
 27 29 30 32 33 34 35 37 38 39 40 41 43 44 45 46 47 50 51 52 53 57 58 59
 60 61 62 63 65 67 68 69 71 72 73 74 75 76 78 79 81 82 83 84 86 87 88 89
 90 91 93 94 95 97 98 99]

True

Рассмотрите возможность использования train_test_split из scikit-learn, который просто:

from sklearn.model_selection import train_test_split


train, test = train_test_split(df, test_size=0.2)
1 голос
/ 16 апреля 2020
idxValid = np.random.choice(all_idx, 10, replace=False)

Осторожно, вам нужно указать, что вы не хотите иметь дубликаты в idxValid. Для этого вам просто нужно иметь replace=False в np.random.choice

replace boolean, optional
    Whether the sample is with or without replacement
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...