1. 问题
为什么 np.random.randn(*images_example.shape)
中的 images_example.shape
前面需要加 *
?
2. 解决问题
在 Python 里面,*
表示解包(一般是用于 List 和 Tuple),**
也是解包,但它用于 字典 Dict 的解包。因此,images_example.shape
前面的 *
其实也是解包的意思。
对于一个 tensor,它的属性 .shape
返回的是一个 Tuple(元组),但 np.random.randn()
的里面要的参数不能是一个 Tuple
对象,而应该是 int
。所以这里的 *
其实就是把 Tuple
拆成了 int
。
3. 例子
example_list = [1, 2, 3]
print(f"{example_list = }")
print(f"{type(example_list) = }")
print("*example_list:", *example_list)
print()
example_tuple = (1, 2, 3)
print(f"{example_list = }")
print(f"{type(example_list) = }")
print("*example_tuple:", *example_list)
结果如下:
example_list = [1, 2, 3]
type(example_list) = <class 'list'>
*example_list: 1 2 3
example_list = [1, 2, 3]
type(example_list) = <class 'list'>
*example_tuple: 1 2 3
这个例子中,我们看到:
[1, 2, 3]
经过*
后变为了1 2 3
这样很诡异的样子(1, 2, 3)
经过*
后变为了1 2 3
这样很诡异的样子
为什么说它"诡异"呢?
因为它的类型是不能求的,会报错:
tuple = (1, 2, 3)
print("type(*tuple):", type(*tuple))
结果如下:
Traceback (most recent call last):
File "C:\Users\Leovin\Desktop\Desktop\pytorch\books\src\leovin\Encoder & Decoder\Exp_3.py", line 2, in <module>
print("type(*tuple):", type(*tuple))
TypeError: type.__new__() argument 1 must be str, not int
那么 1 2 3
这种诡异的形式放到 np.random.randn()
中会怎么样?那么是分批放入,还是一起放入?我们做一个验证就可以知道了:
import numpy as np
a = (1, 2, 3)
np.random.seed(42)
A = np.random.randn(*a)
np.random.seed(42)
B = np.random.randn(1, 2, 3)
print(f"{A = }")
print(f"{B = }")
结果如下:
A = array([[[ 0.49671415, -0.1382643 , 0.64768854],
[ 1.52302986, -0.23415337, -0.23413696]]])
B = array([[[ 0.49671415, -0.1382643 , 0.64768854],
[ 1.52302986, -0.23415337, -0.23413696]]])
那么,答案很清晰了。(1, 2, 3)
这个 Tuple 被拆成了 1 2 3
,是按照 1, 2, 3
这样的样子放进 np.random.randn()
当中的,即 np.random.randn(*(1, 2, 3)) <=> np.random.randn(1, 2, 3)
。