1 梯度下降分类
1、本章描述的交通信号灯问题是一个多个输入一个输出的神经网络
2、随机梯度下降:它分别为每个训练样例执行预测和权重更新。它先拿到第一条信号灯的数据,尝试基于它进行预测,计算权重增量 weight_delta,并更新权重。然后继续读取第二条信号灯数据,以此类推。它循环遍历整个数据集多次,直到找到适合所有训练用例的权重配置
3、完全梯度下降:它每次为整个数据集更新权重。在训练示例中,网络针对整个数据集计算 weight_delta 的平均值,并在均值计算完成之后更新权重,而非对每个训练用例更新权重
4、批量梯度下降:它每次针对每 n 个样例更新权重。选择确定批次大小(通常在8到256之间)的样例子,然后更新权重
5、下面的结果中,中间信号灯的 weight 非常接近 1 ,而最左边和最右边的权重非常接近 0 。整个神经网络的训练学习过程,完成了相当简单的事情:让神经网络确认了中间的输入和输出的相关性。任何权重数值高的位置都具有高相关性
6、深度学习的最大弱点是过拟合。所有的权值都有误差。如果某个特定的权重配置意外地在预测数据集和输出数据集之间创建了完美的吻合(error=0),而此时并没有给真正最重要的输入赋予最大权重,那么神经网络将停止学习
7、正则化的目的是使得只有真正强相关性的权重才能保持不变,其他的一切都会被压制,因为它们会产生噪声
#交通信号灯实例,训练全部数据
import numpy as np
weights = np.array([0.5,0.48,-0.7])
alpha = 0.1
streetlights = np.array([[1,0,1],
[0,1,1],
[0,0,1],
[1,1,1],
[0,1,1],
[1,0,1]
])
walk_vs_stop = np.array([0,1,0,1,1,0])
input = streetlights[0]
goal_prediction = walk_vs_stop[0]
#随机梯度下降
for iteration in range(40):#训练40轮
error_for_all_lights = 0
for row_index in range(len(walk_vs_stop)):#一次性训练所有数据
input = streetlights[row_index]
goal_prediction = walk_vs_stop[row_index]
prediction = input.dot(weights)
error = (prediction - goal_prediction)**2
error_for_all_lights += error
delta = prediction - goal_prediction
weights = weights - (input * delta) * alpha
print('Weights: ' + str(weights))
print("Prediction: " + str(prediction))
print("Error: " + str(error_for_all_lights))
2 堆叠神经网络
1、如果数据没有相关性,那么创建具有相关性的中间数据。在现实中,神经网络搜索它们的输入层和输出层之间的相关性
2、如果输入数据集和输出数据集不相关,所以你可以使用输入数据集创建一个与输出相关的中间数据集。如下图所示,目标是训练这个网络使得即使在输入数据集和输出数据集(layer_0 和 layer_2)之间没有相关性的情况下,用 layer_0 创建的数据集 layer_1 仍与 layer_2 相关
3、下面这个 “堆叠神经网络” ,第一个神经网络的输出是第二个神经网络的输入。神经网络的上半层 (layer_1 到 layer_2 层)与前一章训练的网络没有什么区别。这章新的部分是layer_0 到 layer_1 之间的权重
3 反向传播
1、如果 layer_2 以 x(+0.25)的误差偏高,layer_1 中权重较高的值(weights_1_2)会贡献更多的误差,权重较低的值会贡献较少的误差。取一个极端的例子,最左边节点的权重是0,该节点对误差的贡献就是 0。从 layer_1 到 layer_2 的权重准确描述了 layer_1 节点对 layer_2 预测的贡献,这些权重也能准确的描述 layer_1 节点对 layer_2 的误差的贡献
2、layer_2 的 delta 乘以 layer_1 的各个权重,就可以获得layer_1 的 delta。 这就像反向的预测逻辑。这种反向传递增量信号的过程叫做 反向传播
3、对于每一个权重,将它的输出增量乘以它自身layer_1_delta=layer_2_delta.dot(weights_1_2.T)*relu2deriv(layer_1),然后将权重调整这么多
4、由于输入和输出之间不存在相关性,中间层只是把一些已经没用的相关性混合在一起,真正需要的是使中间层能够选择性地与输入节点相关联。 中间层的作用是只在想要和某个输入节点产生 x% 的关联的时候,才关联到它,而其他时候根本不关联。这称为条件相关,或者选择相关
5、如果中间层节点的值低于 0 ,这个节点与输入具有一定的相关性,只是这个相关性是负的而已。如果将其设置为 0 ,那么它与任何输入的相关性都会为 0 。这意味着节点可以在它想要的时候选择性地关联相应的对象,这就解决了第 4 点的问题
6、神经网络中间层节点的值如果是负的设置为 0,这实际上就是 ReLU(Rectified Linear Unit 修正线性单元)激活函数的操作。它的目的是引入非线性,并且改善网络的训练效率。f(x)=max(0,x)
7、layer_1_delta=layer_2_delta.dot(weights_1_2.T)*relu2deriv(layer_1) ; 如果 layer_1 的数值因为 Relu 设置为 0 ,则不会对误差产生任何影响,在这个前提下需要将这个节点的 delta 设置为 0 。将 layer_1 节点乘以 relu2deriv 函数就能做到这点。relu2deriv 的返回值是 1 还是 0 ,取决于 layer_1 的值是否大于0.
import numpy as np
np.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]]).T
def relu(x):
return (x>0) * x
#当输入大于0时,返回1;当输入小于0时,返回0
#relu2deriv 是relu函数的导数(斜率)
def relu2deriv(output):
return output>0
alpha = 0.2
hidden_size = 4
#两组权重经过随机初始化之后,将三层网络连接在一起
weights_0_1 = 2*np.random.random((3,hidden_size)) -1
weights_1_2 = 2*np.random.random((hidden_size,1)) -1
for iteration in range(60):
layer_2_error = 0
for i in range(len(streetlights)):
layer_0 = streetlights[i:i+1]
#relu 函数实现非线性
layer_1 = relu(np.dot(layer_0,weights_0_1))
layer_2 = np.dot(layer_1,weights_1_2)
layer_2_error += np.sum((layer_2 - walk_vs_stop[i:i+1])**2)
#之前的向前传播 delta 是prediction - goal_prediction
#目前的 delta 是goal_prediction - prediction
layer_2_delta = walk_vs_stop[i:i+1] - layer_2
#反向传播
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("Error: " + str(layer_2_error))
8、附一张numpy 中 1D、2D、3D数组的区别
9、深度学习就是创建从数据集到预测结果的中间层,中间层中的每个节点表示输入数据中不同类型的组合模式是否存在。对于猫的图形数据集,没有任何一个单独的像素与照片中是否有猫有相关性。相反,中间层将尝试识别不同的像素组合模式,这些像素组合在一起可能与猫相关(比如猫的耳朵、眼睛),也可能与猫无关
4 参考资料
《深度学习图解》