Numpy 和 TensorFlow 中 repeat()
和 tile()
都能对输入数组进行重复, 那么它们的区别是什么呢? 本小节将以numpy为例详细介绍它们.
(tensorflow的版本与numpy的完全相同.)
将数组 a
中的元素重复 repeats
次.
注意: 重复的是a
中的元素, 最终返回展平的(flattened)数组, 或其维度与 a
相同.
函数定义:
def repeat(a, repeats, axis=None):
"""
Repeat elements of an array.
Parameters
----------
a : array_like
Input array.
repeats : int or array of ints
The number of repetitions for each element. `repeats` is broadcasted
to fit the shape of the given axis.
axis : int, optional
The axis along which to repeat values. By default, use the
flattened input array, and return a flat output array.
"""
说明:
repeats
表示元素被重复的次数, 可以是 int
, 也可以是 int array
. 如果是 int array
, 那么它必须可以在 axis
方向上进行 广播 (broadcasting)
注: 如果读者还不太明白 broadcasting, 强烈建议读者把其弄明白后再往下学习此文)
axis
表示在指定轴方向上进行重复, int
类型. 给定的轴方向必须存在, 否则报错.下面以几个示例加以说明:
repeats
为 int
类型, 每个元素被重复 repeats
次>>> a = np.array([1,2,3]) # 1维数组
>>> np.repeat(a, 2) # axis=None; 默认返回展平后的数组
>>> array([1, 1, 2, 2, 3, 3])
>>> b = np.array([[1,2], [3,4]]) # 2维数组
>>> np.repeat(b, 2) # axis=None; 默认返回展平后的数组
>>> array([1, 1, 2, 2, 3, 3, 4, 4])
>>> np.repeat(b, 2, axis=0) # axis=0; 元素在0轴上重复2次
>>> array([[1, 2], # 注: 在0轴上, 元素为 [1,2] 和 [3, 4]
[1, 2],
[3, 4],
[3, 4]])
>>> np.repeat(b, 2, axis=1) # axis=1; 元素在1轴上重复2次
>>> array([[1, 1, 2, 2], # 注: 在1轴上, 元素为 [1, 3] 和 [2, 4]
[3, 3, 4, 4]])
repeats
为 int array
类型, 则repeats
必须能在给定 axis
上 传播>>> a = np.array([[1,2],[3,4]) # 2维数组
>>> np.repeat(a, [1,2]) # 报错:默认展平数组[shape=(4,)], 而repeats[shape=(2,)], 传播失败
>>> np.repeat(a, [1,2], axis=0) # axis=0; repeats[shape=(2,)]在0轴上[shape=(2,)]传播
>>> array([[1, 2], # 传播后repeats=[1,2], 因此在0轴上对应元素重复[1次, 2次]
[3, 4],
[3, 4]])
>>> np.repeat(a, [1,2], axis=1) # axis=1; 同理, repeats在1轴上[shape=(2,)]传播
>>> array([[1, 2, 2], # 传播后repeats=[1,2], 因此在1轴上对应元素重复[1次, 2次]
[3, 4, 4]]) # 注: 1轴上对应元素为 [1, 3] 和 [2, 4]
将数组 A
重复reps
次
A
这个整体(想像一下场景: 把 A
看成一个 tile (瓦片), 根据 reps
在不同的轴(方向)上进行重复铺设)def tile(A, reps):
"""
Construct an array by repeating A the number of times given by reps.
If `reps` has length ``d``, the result will have dimension of
``max(d, A.ndim)``.
If ``A.ndim < d``, `A` is promoted to be d-dimensional by prepending new
axes. So a shape (3,) array is promoted to (1, 3) for 2-D replication,
or shape (1, 1, 3) for 3-D replication. If this is not the desired
behavior, promote `A` to d-dimensions manually before calling this
function.
If ``A.ndim > d``, `reps` is promoted to `A`.ndim by pre-pending 1's to it.
Thus for an `A` of shape (2, 3, 4, 5), a `reps` of (2, 2) is treated as
(1, 1, 2, 2).
Parameters
----------
A : array_like
The input array.
reps : array_like
The number of repetitions of `A` along each axis.
Returns
-------
c : ndarray
The tiled output array.
"""
reps
为 int
或 int array
, 表示在指定维度上重复的次数A
或 reps
将根据 A.ndim
和 len(reps)
进行改变, 函数定义中已作了详细说明, 请参见示例进一步理解c
的维度为 A.ndim
和 len(reps)
中较大的那一个下面是具体示例, 需注意每个实例中 reps
和 A
的变化情况:
reps
为 int
类型. 此时很好理解, 将 A
重复 reps
次, 但要视 A
的维度决定该如何重复.>>> A = np.array([1,2,3]) # 1维数组
>>> np.tile(A, 2) # reps=2,等价于reps=[2]; 此时A.ndim == len(reps)
>>> array([1, 2, 3, 1, 2, 3] # A和reps无须改变, 将A在0轴上重复2次
>>> A = np.array([[1,2],[3,4]]) # 2维数组
>>> np.tile(A, 2) # resp=2,等价于reps=[2]; 此时A.ndim > len(reps)
>>> array([[1, 2, 1, 2], # reps改变:在前面补1, 使得A.ndim == len(reps), 即
[3, 4, 3, 4]]) # reps=[1,2], 最终将A在0轴和1轴上分别重复[1次, 2次]
# 对于3维和更高维度也一样, 读者可以自己尝试
reps
为 int array
类型, 其中每个元素代表每个轴上应该重复的次数>>> A = np.array([1,2,3]) # 1维数组
>>> np.tile(A, [2,2]) # reps=[2,2]; 此时A.ndim < len(reps)
>>> array([[1, 2, 3, 1, 2, 3], # A的shape改变:在其前面补1, 使得A.ndim == len(reps), 即
[1, 2, 3, 1, 2, 3]]) # A=[[1,2,3]], 最终将A在0轴和1轴上分别重复[2次, 2次]
>>> A = np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
>>> A
>>> array([[[1, 2], # 3维数组
[3, 4]],
[[5, 6],
[7, 8]]])
>>> np.tile(A, [2,2]) # reps=[2,2]; 此时A.ndim > len(reps)
>>> array([[[1, 2, 1, 2], # reps改变, 在其前面补1, 变为 reps=[1, 2, 2]
[3, 4, 3, 4], # 因此最终结果为:
[1, 2, 1, 2], # A在0轴,1轴,2轴上分别重复[1次,2次,2次]
[3, 4, 3, 4]],
[[5, 6, 5, 6],
[7, 8, 7, 8],
[5, 6, 5, 6],
[7, 8, 7, 8]]])
后记:
在使用 np.tile()
时, 不管是 A
的改变, 还是 reps
改变, 都特别容易让人迷糊. 因此, 为了方便, 直接传入与 A
维度相同的长度的 pres
即可, 这样就能很清楚的明白在哪个维度上重复多少次了, 例如: np.tile(A, [2, 2, 2])
表示将 A
在 0,1,2 轴全部重复2次.