numpy 随机播放一小部分子数组
numpy shuffle a fraction of sub-arrays
我在 ndim = 3
的数组中有未定义形状的单热编码数据,例如:
import numpy as np
arr = np.array([ # Axis 0
[ # Axis 1
[0, 1, 0], # Axis 2
[1, 0, 0],
],
[
[0, 0, 1],
[0, 1, 0],
],
])
我想要的是沿 axis=2
.
打乱已知部分子数组的值
如果这个分数是0.25
,那么结果可能是:
arr = np.array([
[
[1, 0, 0], # Shuffling happened here
[1, 0, 0],
],
[
[0, 0, 1],
[0, 1, 0],
],
])
我知道如何使用迭代方法来做到这一点,例如:
for i in range(arr.shape[0]):
for j in range(arr.shape[1]):
if np.random.choice([0, 1, 2, 3]) == 0:
np.random.shuffle(arr[i][j])
但这是非常低效的。
编辑:正如评论中所建议的,已知分数的随机选择应遵循统一的规律。
您的迭代方法很棒,就所涉及的逻辑操作数而言绝对是最佳解决方案。据我所知,做得更好的唯一方法是利用 numpy 的矢量化加速。以下代码为示例
def permute_last_maybe(x):
N, M, K = x.shape
y = np.transpose(x, [2, 0, 1])
y = np.random.permutation(y)
y = np.transpose(y, [1, 2, 0])
mask = (np.random.random((N, M, 1)) > 0.25) * np.ones([N, M, K])
return np.where(mask, x, y)
timeit 魔术显示 300 us 而不是 4.2 ms,数组大小为 (40, 40, 30)
。
请注意,此代码不使用 numpy 中的新 random Generators(我尝试过,但创建 class 实例的重载很重要)。
我可能还应该提到这个函数不会改变给定的数组 x 而是 returns 它的一个副本。
一种方法:
import numpy as np
np.random.seed(42)
fraction = 0.25
total = arr.shape[0] * arr.shape[1]
# pick arrays to be shuffled
indices = np.random.choice(np.arange(total), size=int(total * fraction), replace=False)
# convert the each index to the corresponding multi-index
multi_indices = np.unravel_index(indices, arr.shape[:2])
# create view using multi_indices
selected = arr[multi_indices]
# shuffle select by applying argsort on random values of the same shape
shuffled = np.take_along_axis(selected, np.argsort(np.random.random(selected.shape), axis=1), axis=1)
# set the array to the new values
arr[multi_indices] = shuffled
print(arr)
输出(单个运行)
[[[0 1 0]
[0 0 1]]
[[0 0 1]
[0 1 0]]]
我在 ndim = 3
的数组中有未定义形状的单热编码数据,例如:
import numpy as np
arr = np.array([ # Axis 0
[ # Axis 1
[0, 1, 0], # Axis 2
[1, 0, 0],
],
[
[0, 0, 1],
[0, 1, 0],
],
])
我想要的是沿 axis=2
.
如果这个分数是0.25
,那么结果可能是:
arr = np.array([
[
[1, 0, 0], # Shuffling happened here
[1, 0, 0],
],
[
[0, 0, 1],
[0, 1, 0],
],
])
我知道如何使用迭代方法来做到这一点,例如:
for i in range(arr.shape[0]):
for j in range(arr.shape[1]):
if np.random.choice([0, 1, 2, 3]) == 0:
np.random.shuffle(arr[i][j])
但这是非常低效的。
编辑:正如评论中所建议的,已知分数的随机选择应遵循统一的规律。
您的迭代方法很棒,就所涉及的逻辑操作数而言绝对是最佳解决方案。据我所知,做得更好的唯一方法是利用 numpy 的矢量化加速。以下代码为示例
def permute_last_maybe(x):
N, M, K = x.shape
y = np.transpose(x, [2, 0, 1])
y = np.random.permutation(y)
y = np.transpose(y, [1, 2, 0])
mask = (np.random.random((N, M, 1)) > 0.25) * np.ones([N, M, K])
return np.where(mask, x, y)
timeit 魔术显示 300 us 而不是 4.2 ms,数组大小为 (40, 40, 30)
。
请注意,此代码不使用 numpy 中的新 random Generators(我尝试过,但创建 class 实例的重载很重要)。
我可能还应该提到这个函数不会改变给定的数组 x 而是 returns 它的一个副本。
一种方法:
import numpy as np
np.random.seed(42)
fraction = 0.25
total = arr.shape[0] * arr.shape[1]
# pick arrays to be shuffled
indices = np.random.choice(np.arange(total), size=int(total * fraction), replace=False)
# convert the each index to the corresponding multi-index
multi_indices = np.unravel_index(indices, arr.shape[:2])
# create view using multi_indices
selected = arr[multi_indices]
# shuffle select by applying argsort on random values of the same shape
shuffled = np.take_along_axis(selected, np.argsort(np.random.random(selected.shape), axis=1), axis=1)
# set the array to the new values
arr[multi_indices] = shuffled
print(arr)
输出(单个运行)
[[[0 1 0]
[0 0 1]]
[[0 0 1]
[0 1 0]]]