高数

  1. 导数定义 函数某一点的变化率 det(y)/det(x)
  2. 微分定义 当x增加时,y会相应增加,使用微分近似的表示增加的值(即保留主要值,忽略误差值)
  3. 积分定义 任意x属于I,存在F(x)’=f(x),则称F(x)是f(x)的原函数。全体原函数称为不定积分。sf(x)dx=F(x)
  4. 偏导数 某一点对于某个变量的变化率

监督学习所想要解决的问题:
使用已有的数据集进行训练,获取一个函数对数据集外的数据进行预测。

评判标准

函数预测值与真实值之间的误差总和最小,那么就认为这个函数和实际的函数越拟合。使用cost function计算误差之和。

所用公式

  1. 拟合函数
  2. cost function
  3. 更新参数
  4. 偏导计算

梯度下降

如何使用梯度下降获得目标函数:

  1. 首先我们的目标就是使得函数预测的值和真实值的误差最小。
  2. 为了达成这个目标我们总是依据当前的情况去判断下一步的情况。
  3. 使用某个变量的偏导数来判断该变量下一步变化的方向。
  4. 使用学习速率描述在方向上移动的快慢。
  5. 最终函数会逼近局部最低点,即偏导数为0的点,此时得到一个目标函数。

注意的问题

  1. 学习速率的选取:过大会发散,过小会导致迭代次数太多,所以计算时尝试使用不同的学习速率,每次取值大约隔三倍。
  2. 特征值的范围:如果特征值之间的范围差距较大,那么可能一个特征值的大小变化会显著影响目标函数的误差,使得函数收敛的很慢。解决的方法是使用特征缩放的方式,使得特征值的范围差距不太大。

python模拟

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import numpy as np
import random

# 随机函数
def random_list(start, end, length):
list = []
for i in range(length):
list.append(random.uniform(start, end))
return list

# 取值范围
start = 0
end = 100
# 样本个数
length = 100

#函数参数
theta0 = 20
theta1 = 14
theta2 = 5

#自变量
x = np.array(random_list(start, end, length))
y = np.array(random_list(start, end, length))

# 函数值
z = int(theta0) + int(theta1) * x + int(theta2) * y

# 加入的误差
s = np.array(random_list(-10, 10, length))

#真实值 = 函数值 + 误差
zz = z + s

# 循环次数
loop_time = 10000

#允许误差
epsilon = 3000

#学习速率
alpha = 0.0001

#计算的参数
ctheta0 = 0
ctheta1 = 0
ctheta2 = 0
count = 0
m = len(x)


def h(x, y):
return ctheta0 + ctheta1 * x + ctheta2 * y


diff = np.array([0, 0, 0])

while count < loop_time:
count += 1
for i in range(m):
diff[0] += (h(x[i], y[i]) - zz[i]) # 偏导数和
diff[1] += (h(x[i], y[i]) - zz[i]) * x[i]
diff[2] += (h(x[i], y[i]) - zz[i]) * y[i]
ctheta0 -= alpha * diff[0] / m # 更新特征值
ctheta1 -= alpha * diff[1] / m
ctheta2 -= alpha * diff[2] / m

err = 0
for i in range(m):
err += (h(x[i], y[i]) - zz[i]) ** 2 # 计算error
if err < epsilon:
print("theta0: %f theta1: %f theta2: %f \nctheta0: %f ctheta1: %f ctheta2: %f" % (
theta0, theta1, theta2, ctheta0, ctheta1, ctheta2))
print("count: %f error: %f" % (count, err))
break;
diff[0] = 0
diff[1] = 0
diff[2] = 0


if count >= loop_time:
print("-------loop out of time-------")
print("theta0: %f theta1: %f theta2: %f \nctheta0: %f ctheta1: %f ctheta2: %f" % (theta0, theta1, theta2, ctheta0,
ctheta1, ctheta2))
print("error: %f" % err)
loop_time alpha result
10000 0.0001 ctheta0=2.02 ctheta1=14.12 ctheta2=5.18
10000 0.0003 ctheta0=5.07 ctheta1=14.16 ctheta2=5.07
100000 0.0003 chteta0=18.04 ctheta1=14.01 ctheta2=5.02

一开始alpha较小时,迭代次数过多,导致迭代超过次数时ctheta0的值依然很小;随后加大alpha的值,ctheta0的值确实增加,继续增大步长会导致溢出,即发散,因此确定alpha的值为0.03。继续增加循环次数,ctheta0逐渐逼近设定值。