Частично векторизовано
Мы можем сократить его до одного цикла -
m,s = X[:a_size].mean(1),X[:a_size].std(1)
L = (m-s).astype(int)
H = (m+s).astype(int)
out = np.empty((a_size,X.shape[0]),dtype=int)
for i,(l,h) in enumerate(zip(L,H)):
out[i] = np.random.choice(np.arange(l,h),X.shape[0],replace=False)
Основная идея:
Вычислить средние и стандартные значения вдольвторая осьПеред этим нам нужно нарезать X
, чтобы ограничить его a_size
строками, если a_size
не является количеством строк в X
.
В оригиналезацикленная версия, мы используем random.randint
со средним-стандартным и средним + стандартным в качестве пределов.Таким образом, для предложенной версии получите нижний и верхний пределы, используя средние и стандартные значения из шага № 1.
Запустите цикл с np.random.choice(np.arange(l,h),X.shape[0],replace=False)
с этими низкими и высокими значениями для настройкидиапазон значений на выбор и выбор случайных значений размером X.shape[0]
и уникальных значений с replace=False
.
полностью векторизация
Мы могли бы сделать его полностью векторизованнымс трюком, как указано в 1 & 2 , чтобы дать нам что-то вроде следующего, который заменяет зацикленный шаг, перечисленный ранее:
R = H-L
MX = R.max()
n = X.shape[0]
unqIDs = np.random.rand(len(L),MX).argpartition(axis=1,kth=n)[:,:n]
out = unqIDs%R[:,None] + L[:,None]
Обратите внимание, что это будет иметьбольше места в памяти.