Numpy中np.repeat与np.broadcast_to的差异及等效实现问询
为什么你的代码返回False?
问题出在np.broadcast_to和np.repeat的核心逻辑完全不同,它们的维度扩展方式根本不是一回事:
np.broadcast_to是「广播视图」:它不会复制数据,只是基于numpy的广播规则,给原数组创建一个新的形状视图。你把Areshape成(n,1,d)后广播到(n,d-1,d),本质是把A的每一行(形状(d,))在第二个维度上重复d-1次。比如当n=2, d=3时,结果会是:[[[a,b,c], [a,b,c]], [[d,e,f], [d,e,f]]]np.repeat(A, d-1)是「元素级重复」:默认会先把数组展平,然后每个元素单独重复d-1次,再reshape回(n,d-1,d)。还是用n=2, d=3的例子,展平后的A是[a,b,c,d,e,f],重复后变成[a,a,b,b,c,c,d,d,e,e,f,f],reshape后的结果是:[[[a,a,b], [b,c,c]], [[d,d,e], [e,f,f]]]
这两个数组的元素排列完全不一样,自然np.all会返回False。
如何用np.broadcast_to复现np.repeat(A,k).reshape((n,k,d))的效果?
首先要明确:np.broadcast_to只能创建共享原数组内存的视图,而np.repeat的结果是完全复制数据的新数组(每个重复元素都是独立的内存块)。所以严格来说,你没法直接用np.broadcast_to得到和np.repeat完全一样的数组(因为后者是副本,前者是视图)。
但如果只是要得到数值上一致的结果,可以结合broadcast_to和reshape操作,不过这一步reshape会创建副本(因为需要改变元素排列顺序):
import numpy as np n = 100 d = 10 k = d-1 A = np.random.uniform(size=(n,d)) # 复现 np.repeat(A,k).reshape(n,k,d) # 1. 先把A的每个元素在第三个维度上广播k次 broadcasted = np.broadcast_to(A.reshape(n, d, 1), (n, d, k)) # 2. reshape成目标形状,这里会创建副本 result = broadcasted.reshape(n, k, d) # 验证结果一致 print(np.all(result == np.repeat(A,k).reshape(n,k,d))) # 输出True
不过如果你真正想要的是广播式的轴重复(也就是broadcast_to那种重复整行的效果),那对应的repeat写法应该是指定axis=1,而不是默认的展平重复:
# 这才是和broadcast_to结果一致的repeat写法 repeat_version = np.repeat(A.reshape(n,1,d), k, axis=1) print(np.all(repeat_version == np.broadcast_to(A.reshape(n,1,d), (n,k,d)))) # 输出True
内容的提问来源于stack exchange,提问作者lrnv

