第5章:通用梯度下降
本章主要内容:
- 多输入的梯度下降学习
- 冻结权重的意义和用途
- 多输出梯度下降学习
- 多输入多输出梯度下降学习
- 可视化权重
- 可视化点积
5.1 多输入的梯度下降学习
在上一章中,我们已经学会了对于单输入的神经网络进行基于最小化误差原理的梯度学习,学习的目的是找到合适的权重。在本节中,我们将展示如何使用相同的技术来更新一个包含多个权重的神经网络。
digraph G {
rankdir=LR
splines=line
nodesep=.3;
ranksep = 0.9;
node [fontname="Inconsolata, Consolas", fontsize=14, penwidth=0.5];
subgraph cluster_0 {
color=white;
node [style=solid,color=blue4, shape=rectangle];
原料成本 销售成本 人工成本 生产成本;
label = "输入层";
}
subgraph cluster_1 {
color=white;
node [style=solid,color=red2, shape=circle];
零售价格;
label = "输出层";
}
原料成本 -> 零售价格 [arrowhead=vee]
销售成本 -> 零售价格 [arrowhead=vee]
人工成本 -> 零售价格 [arrowhead=vee]
生产成本 -> 零售价格 [arrowhead=vee]
}
比如上面就是一个工厂生产的产品的价格预测神经网络的示意图。这个神经网络的代码如下:
import numpy as np
cost_of_material = np.array([38.3, 35, 31.2, 43.2, 44.2, 41.2])
cost_of_sales = np.array([12.3, 11.2, 10.1, 9.2, 9.1, 9.6])
cost_of_human = np.array([22,21.3,23.7,23.2,20.5,24.2])
cost_of_product = np.array([7.2, 7.8, 8.3, 8.6, 8.8, 9.3])
sell_price = np.array([100.1, 102, 99.2, 101.2, 103.8, 100.5])
# 数据正规化,由于都是钱计价的,所以可以用同一个单位来正规化,比如这里使用100
cost_of_material /= 100
cost_of_sales /= 100
cost_of_human /= 100
cost_of_product /= 100
sell_price /= 100
# 预设权重
weights = np.array([0.6,0.2,0.8,0.9])
inputs = np.array(
[cost_of_material[0],
cost_of_sales[0],cost_of_human[0], cost_of_product[0]]
)
learning_rate = [0.5,0.5,0.5,0.5]
# 预测函数
def neural_network(inputs,weights):
prediction = inputs.dot(weights)
return prediction
# 代价函数
def error_function(inputs, weights, real_value):
prediction = neural_network(inputs,weights)
return pow(prediction - real_value,2)
# 梯度下降乘子
def grad_descent_multiplier(inputs, weights, real_value):
multiplier = (
neural_network(inputs,weights) -
real_value)*inputs
return multiplier
# 上面的2因子来源于求导数
times = 0
# 当误差小于10的-20次方,即(1e-20),即停止运算。
while error_function(inputs,weights,sell_price[0]) > 1e-20:
times += 1
gdm = list(grad_descent_multiplier(inputs,weights,sell_price[0]))
if min(np.abs(gdm)) > max(np.abs(weights)):
gdm /= 10*min(np.abs(gdm))/max(np.abs(weights))
# 下降因子相对于权重过大,此时应将它缩小,否则极易引起误差发散。
factor = np.diag(gdm)
weights -= np.matmul(learning_rate,factor)
error = error_function(inputs,weights,sell_price[0])
print("计算了%d 次\n" %times, "权重为:", weights)
print("最终误差为:", error)
print("梯度下降因子:", gdm)
check = weights.dot(inputs)*100
print("预测价格:", check)
运行后,上面的代码应该显示
计算了197 次
权重为: [1.4993482 0.48882462 1.31659687 1.06906807]
最终误差为: 8.11071631421852e-21
梯度下降因子: [-3.865607856035069e-11, -1.241435421128756e-11, -2.2204535987668805e-11, -7.266939050509792e-12]
预测价格: 100.09999999099404
上面的代码实际上就是多元线性回归算法的实现。我们使用了学习率是0.5,仅仅197步,误差已经小到10的负20次方以下。可以看出梯度下降学习的威力。在上面的代码中,如果不对权重的梯度下降加以正规化,很容易导致误差发散的结果,这是因为下降的梯度值相对于权重本身的变化过大,使得权重变化越过了最优位置,这样的步长不满足微扰的条件,必须要使它相对于前值权重比较小。这样的梯度发散通常在回归问题中比较常见,但在概率和识别问题中比较少见。
网友评论