魔法师の高塔

梯度下降算法

梯度下降算法基于一个不言自喻的事实,极值处于梯度下降的方向。
$f(x,y)=2x^2+y^2-2xy+x-3y+7$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
fn function(x: (f32, f32)) -> f32 {
return 2.0 * x.0 * x.0 + x.1 * x.1 - 2.0 * x.0 * x.1 + x.0 - 3.0 * x.1 + 7.0;
}
fn derivative_function(x: (f32, f32)) -> (f32, f32) {
return (4.0 * x.0 - 2.0 * x.1 + 1.0, 2.0 * x.1 - 2.0 * x.0 - 3.0);
}
fn main() {
let e = 0.000001;
let alpha = 0.3;
let mut x0 = (0.0, 0.0);
let mut y0 = function(x0);
loop {
x0 = (x0.0 - alpha * derivative_function(x0).0, x0.1 - alpha * derivative_function(x0).1);
let y1 = function(x0);
if (y1 - y0).abs() < e {
break;
}
y0 = y1;
}
println!("{}", y0);
println!("{:?}", x0);
}

在线性回归中,梯度下降算法也是非常重要的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
fn main() {
//训练数据集
// 自变量x (x0,x1)
let x = vec![(1.0, 1.05), (1.0, 1.9), (1.0, 3.06), (1.0, 4.66), (1.0, 6.84), (1.0, 7.95)];
// 假设函数 h(x) = theta0 + theta1*x
let y = vec![10.7, 18.7, 29.8, 49.3, 70.2, 80.2];
let epsilon = 0.0000001;//收敛精度
let alpha = 0.005; //迭代步长
let mut error0 = 0.0;
let mut error1 = 0.0;
let m = x.len();
let mut theta = (0.0, 0.0);
loop {
// 遍历数据集,不断更新theta值
for i in 0..m {
//带入,计算并更新系数
let diff = theta.0 + theta.1 * x[i].1 - y[i];
theta.0 = theta.0 - alpha * diff * x[i].0;
theta.1 = theta.1 - alpha * diff * x[i].1;
}
let diff0: f32 = theta.0 - error0;
let diff1: f32 = theta.1 - error1;
if diff0.abs() < epsilon && diff1.abs() < epsilon {
break;
}
error0 = theta.0;
error1 = theta.1;
}
println!("{:?}", theta);
}

明白了梯度下降算法,那么神经网络中的BP算法便不是问题。
BP算法的本质,依旧是梯度下降,按照链式求导的法则,依次求得各个层的权重对损失函数的影响。
这个值得进一步说明,以前不明白BP算法,那大概是因为我没认真看,畏于各种数学符号,实在是对不起我的头脑。
现在再看,就很疑惑,为什么我以前不明白BP算法。