我正在阅读一本书,书中包含以下代码:
import numpy as npnp.random.seed(1)streetlights = np.array([[1, 0, 1], [0, 1, 1], [0, 0, 1], [1, 1, 1]])walk_vs_stop = np.array([[1, 1, 0, 0]]).Tdef relu(x): return (x > 0) * xdef relu2deriv(output): return output > 0alpha = 0.2hidden_layer_size = 4# random weights from the first layer to the secondweights_0_1 = 2*np.random.random((3, hidden_layer_size)) -1# random weights from the second layer to the outputweights_1_2 = 2*np.random.random((hidden_layer_size, 1)) -1for iteration in range(60): layer_2_error = 0 for i in range(len(streetlights)): layer_0 = streetlights[i : i + 1] layer_1 = relu(np.dot(layer_0, weights_0_1)) layer_2 = relu(np.dot(layer_1, weights_1_2)) layer_2_error += np.sum((layer_2 - walk_vs_stop[i : i + 1])) ** 2 layer_2_delta = layer_2 - walk_vs_stop[i : i + 1] layer_1_delta = layer_2_delta.dot(weights_1_2.T) * relu2deriv(layer_1) weights_1_2 -= alpha * layer_1.T.dot(layer_2_delta) weights_0_1 -= alpha * layer_0.T.dot(layer_1_delta) if iteration % 10 == 9: print(f"Error: {layer_2_error}")
输出结果为:
# Error: 0.6342311598444467# Error: 0.35838407676317513# Error: 0.0830183113303298# Error: 0.006467054957103705# Error: 0.0003292669000750734# Error: 1.5055622665134859e-05
我理解大部分内容,但这一部分没有解释,我不确定为什么是这样:
weights_0_1 = 2*np.random.random((3, hidden_layer_size)) -1weights_1_2 = 2*np.random.random((hidden_layer_size, 1)) -1
我不理解的是:
- 为什么整个矩阵要乘以
2*
,以及为什么要减去-1
- 如果我将
2
改为3
,我的误差会大大降低# Error: 5.616513576418916e-13
- 我尝试将
2
改为许多其他数字,同时将-1
改为许多其他数字,大多数时候我得到# Error: 2.0
,或者误差远比3
和-1
的组合差很多。
我似乎无法理解将随机权重乘以一个数字然后减去一个数字的关系和目的。
P.S. 这个网络的目的是理解街道灯光模式,根据streetlight
中灯光的开关组合来判断人们应该走还是停。
回答:
初始化神经网络的方法有很多,这是当前的研究主题,因为它对性能和训练时间有很大影响。一些经验法则是:
- 避免所有权重都只有一个值,因为它们会以相同的方式更新
- 避免权重过大,可能会使梯度过高
- 避免权重过小,可能会使梯度消失
在你的案例中,目标只是让权重在[-1;1]之间:
- np.random.random 会给你一个在[0;1]之间的浮点数
- 乘以2会得到[0;2]之间的数
- 减去1会得到[-1;1]之间的数