numpy.random.rand 与 numpy.random.randn 在 Python 中的区别
Differences between numpy.random.rand vs numpy.random.randn in Python
numpy.random.rand
和numpy.random.randn
有什么区别?
从文档中,我知道它们之间的唯一区别是每个数字的概率分布,但总体结构(维度)和使用的数据类型(浮点数)是相同的。因此,我很难调试神经网络。
具体来说,我正在尝试重新实现 Neural Network and Deep Learning book by Michael Nielson. The original code can be found here 中提供的神经网络。我的实现和原来的一样;但是,我在 init
函数中使用 numpy.random.rand
定义和初始化了权重和偏差,而不是像原始函数中所示的 numpy.random.randn
函数。
但是,我的使用 random.rand
初始化 weights and biases
的代码不起作用。网络不会学习,权重和偏差也不会改变。
导致这种怪异的两个随机函数之间有什么区别?
首先,正如您从文档中看到的那样,numpy.random.randn
从正态分布生成样本,而 numpy.random.rand
从均匀分布(在 [0,1) 范围内)生成样本。
第二,统一分配为什么不行?主要原因是激活函数,特别是在您使用 sigmoid 函数的情况下。 sigmoid 曲线如下所示:
所以你可以看到,如果你的输入远离 0,函数的斜率下降得非常快,结果你得到一个微小的梯度和微小的权重更新。如果你有很多层——这些梯度在反向传递中会乘以很多次,所以即使是“适当的”梯度在乘法之后也会变小并且不再产生任何影响。因此,如果你有很多权重将你的输入带到那些区域,你的网络就很难训练。这就是为什么通常的做法是将网络变量初始化为零值。这样做是为了确保您获得合理的梯度(接近 1)来训练您的网络。
不过,均匀分布也不是完全不可取的,你只需要让范围更小,更接近于零即可。一种好的做法是使用 Xavier 初始化。在这种方法中,您可以使用以下方法初始化权重:
正态分布。其中 mean 为 0 且 var = sqrt(2. / (in + out))
,其中 in - 是神经元的输入数量,out - 输出数量。
均匀分布[-sqrt(6. / (in + out)), +sqrt(6. / (in + out))]
np.random.rand
用于均匀分布(在 half-open 区间 [0.0, 1.0)
)
np.random.randn
用于标准正态(又名高斯)分布(均值 0 和方差 1)
您可以很容易地直观地探索这两者之间的区别:
import numpy as np
import matplotlib.pyplot as plt
sample_size = 100000
uniform = np.random.rand(sample_size)
normal = np.random.randn(sample_size)
pdf, bins, patches = plt.hist(uniform, bins=20, range=(0, 1), density=True)
plt.title('rand: uniform')
plt.show()
pdf, bins, patches = plt.hist(normal, bins=20, range=(-4, 4), density=True)
plt.title('randn: normal')
plt.show()
产生:
和
1) numpy.random.rand
来自 uniform(范围 [0,1))
2) numpy.random.randn
从 正态分布
生成样本
numpy.random.rand
和numpy.random.randn
有什么区别?
从文档中,我知道它们之间的唯一区别是每个数字的概率分布,但总体结构(维度)和使用的数据类型(浮点数)是相同的。因此,我很难调试神经网络。
具体来说,我正在尝试重新实现 Neural Network and Deep Learning book by Michael Nielson. The original code can be found here 中提供的神经网络。我的实现和原来的一样;但是,我在 init
函数中使用 numpy.random.rand
定义和初始化了权重和偏差,而不是像原始函数中所示的 numpy.random.randn
函数。
但是,我的使用 random.rand
初始化 weights and biases
的代码不起作用。网络不会学习,权重和偏差也不会改变。
导致这种怪异的两个随机函数之间有什么区别?
首先,正如您从文档中看到的那样,numpy.random.randn
从正态分布生成样本,而 numpy.random.rand
从均匀分布(在 [0,1) 范围内)生成样本。
第二,统一分配为什么不行?主要原因是激活函数,特别是在您使用 sigmoid 函数的情况下。 sigmoid 曲线如下所示:
所以你可以看到,如果你的输入远离 0,函数的斜率下降得非常快,结果你得到一个微小的梯度和微小的权重更新。如果你有很多层——这些梯度在反向传递中会乘以很多次,所以即使是“适当的”梯度在乘法之后也会变小并且不再产生任何影响。因此,如果你有很多权重将你的输入带到那些区域,你的网络就很难训练。这就是为什么通常的做法是将网络变量初始化为零值。这样做是为了确保您获得合理的梯度(接近 1)来训练您的网络。
不过,均匀分布也不是完全不可取的,你只需要让范围更小,更接近于零即可。一种好的做法是使用 Xavier 初始化。在这种方法中,您可以使用以下方法初始化权重:
正态分布。其中 mean 为 0 且
var = sqrt(2. / (in + out))
,其中 in - 是神经元的输入数量,out - 输出数量。均匀分布
[-sqrt(6. / (in + out)), +sqrt(6. / (in + out))]
np.random.rand
用于均匀分布(在 half-open 区间[0.0, 1.0)
)np.random.randn
用于标准正态(又名高斯)分布(均值 0 和方差 1)
您可以很容易地直观地探索这两者之间的区别:
import numpy as np
import matplotlib.pyplot as plt
sample_size = 100000
uniform = np.random.rand(sample_size)
normal = np.random.randn(sample_size)
pdf, bins, patches = plt.hist(uniform, bins=20, range=(0, 1), density=True)
plt.title('rand: uniform')
plt.show()
pdf, bins, patches = plt.hist(normal, bins=20, range=(-4, 4), density=True)
plt.title('randn: normal')
plt.show()
产生:
和
1) numpy.random.rand
来自 uniform(范围 [0,1))
2) numpy.random.randn
从 正态分布