随机拆分一个numpy数组

kon*_*tin 7 python numpy

我有一个numpy数组的大小46928x28x28,我想随机将该数组分成两个大小(41928x28x28)和子矩阵(5000x28x28).因此,要从初始数组中随机选择行.到目前为止我尝试的代码(计算两个子数组的索引)如下:

ind = np.random.randint(input_matrix.shape[0], size=(5000,))
rest = np.array([i for i in range(0,input_matrix.shape[0]) if i not in ind])
rest = np.array(rest)
Run Code Online (Sandbox Code Playgroud)

然而,令人惊讶的是,ind (5000,)的形状是其余的形状(42192,).在那种情况下,我做错了什么?

Gia*_*chi 7

错误是randint给出了一些重复的索引.你可以通过打印测试它len(set(ind)),你会发现它小于5000.

要使用相同的想法,只需将第一行替换为

ind = np.random.choice(range(input_matrix.shape[0]), size=(5000,), replace=False)
Run Code Online (Sandbox Code Playgroud)

话虽这么说,你的代码的第二行很慢,因为列表上的迭代.使用布尔值向量定义所需的索引会快得多,这将允许您使用否定运算符~.

choice = np.random.choice(range(matrix.shape[0]), size=(5000,), replace=False)    
ind = np.zeros(matrix.shape[0], dtype=bool)
ind[choice] = True
rest = ~ind
Run Code Online (Sandbox Code Playgroud)

在我的机器上,这个方法与实现scikit.learn的速度一样快train_test_split,这让我觉得两者做的完全相同.


stu*_*ent 7

一种方式可以是使用尝试train_test_splitsklearn 文档:

import numpy as np
from sklearn.model_selection import train_test_split

# creating matrix
input_matrix = np.arange(46928*28*28).reshape((46928,28,28))
print('Input shape: ', input_matrix.shape)
# splitting into two matrices of second matrix by size
second_size = 5000/46928

X1, X2 = train_test_split(input_matrix, test_size=second_size)

print('X1 shape: ', X1.shape)
print('X2 shape: ', X2.shape)
Run Code Online (Sandbox Code Playgroud)

结果:

Input shape:  (46928, 28, 28)
X1 shape:  (41928, 28, 28)
X2 shape:  (5000, 28, 28)
Run Code Online (Sandbox Code Playgroud)


sac*_*cuL 5

我同意train_test_split可能是要走的路的评论。但是,由于这是标记为numpy,因此这是一种numpy非常快的处理方式:

# recreate random array:
x = np.random.random((46928,28,28))

# pick your indices for sample 1 and sample 2:
s1 = np.random.choice(range(x.shape[0]), 41928, replace=False)
s2 = list(set(range(x.shape[0])) - set(s1))

# extract your samples:
sample1 = x[s1, :, :]
sample2 = x[s2, :, :]
Run Code Online (Sandbox Code Playgroud)

你的输出:

>>> sample1.shape
(41928, 28, 28)
>>> sample2.shape
(5000, 28, 28)
Run Code Online (Sandbox Code Playgroud)

时间:

出于好奇,我对这种numpy方法进行了计时,sklearn.model_selection.train_test_split并且几乎没有区别。train_test_split更快,但只有一点点。无论如何,我坚持train_test_split成为更好的选择。

numpy方法:平均 0.26082248413999876 秒

train_test_split方法:平均 0.22217219217000092 秒


小智 5

只是快速更新一下,可以使用以下方法轻松解决此问题shuffle

rng = np.random.default_rng()
rng.shuffle(data, axis = 0)
split1 = data[:41928]
split2 = data[41928:]
Run Code Online (Sandbox Code Playgroud)

如果您将其用于 ML 应用程序,那么它还有一个额外的好处,即随机化训练集和测试集的顺序,这通常是可取的。如果您需要保留两个分割数组上的给定顺序,您可以改为随机排列索引并重新排序:

idx = np.arange(data.shape[0])
rng.shuffle(idx)
idx1 = np.sort(idx[:41928])
idx2 = np.sort(idx[41928:])
split1 = data[idx1, ...]
split2 = data[idx2, ...]
Run Code Online (Sandbox Code Playgroud)