numpys setdiff1d 坏了吗?
Is numpys setdiff1d broken?
为了 select 在我的机器学习项目中用于训练和验证的数据,我通常使用 numpys 屏蔽功能。因此,select 验证和测试数据索引的典型重复代码块如下所示:
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-array 中选择的元素数量时,结果数字加起来不正确。这是另一个独立示例,一旦我将随机选择的验证索引的数量增加到 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
我糊涂了?!请自己尝试。我很乐意理解这一点。
idxValid = np.random.choice(all_idx, 10, replace=False)
注意,您需要表明您不想在 idxValid
中出现重复项。为此,您只需要 replace=False
in np.random.choice
replace boolean, optional
Whether the sample is with or without replacement
考虑以下示例:
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
考虑直接使用 scikit-learn
中的 train_test_split
:
from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.2)
为了 select 在我的机器学习项目中用于训练和验证的数据,我通常使用 numpys 屏蔽功能。因此,select 验证和测试数据索引的典型重复代码块如下所示:
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-array 中选择的元素数量时,结果数字加起来不正确。这是另一个独立示例,一旦我将随机选择的验证索引的数量增加到 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
我糊涂了?!请自己尝试。我很乐意理解这一点。
idxValid = np.random.choice(all_idx, 10, replace=False)
注意,您需要表明您不想在 idxValid
中出现重复项。为此,您只需要 replace=False
in np.random.choice
replace boolean, optional
Whether the sample is with or without replacement
考虑以下示例:
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
考虑直接使用 scikit-learn
中的 train_test_split
:
from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.2)