一、梯度下降法(GD,Gradient Descent)
Ⅰ、得到目标函数J(θ),求解使得J(θ)最小时的θ值
当然,这里只是取了俩特征而已,实际上会有m个特征维度
通过最小二乘法求目标函数最小值
令偏导为0即可求解出最小的θ值,即
Ⅱ、判定为凸函数
凸函数有需要判断方法,比如:定义、一阶条件、二阶条件等。利用正定性判定使用的是二阶条件。
半正定一定是凸函数,开口朝上,半正定一定有极小值
在用二阶条件进行判定的时候,需要得到Hessian矩阵,根据Hessian的正定性判定函数的凹凸性。比如Hessian矩阵半正定,函数为凸函数;Hessian矩阵正定,函数为严格凸函数
Hessian矩阵:黑塞矩阵(Hessian Matrix),又称为海森矩阵、海瑟矩阵、海塞矩阵等,是一个多元函数的二阶偏导数构成的方阵,描述了函数的局部曲率。
Ⅲ、Hessian矩阵
黑塞矩阵是由目标函数在点x处的二阶偏导数组成的对称矩阵
正定:对A的特征值全为正数,那么A一定是正定的
不正当:非正定或半正定
若A的特征值≥0,则半正定,否则,A为非正定。
对J(θ)损失函数求二阶导,之后得到的一定是半正定的,因为自己和自己做点乘。
Ⅳ、解析解
数值解是在一定条件下通过某种近似计算得出来的一个数值,能在给定的精度条件下满足方程,解析解为方程的解析式(比如求根公式之类的),是方程的精确解,能在任意精度下满足方程。
Ⅴ、梯度下降法
这个课程跟其他课程讲的差不多,这里我就不再赘述了。梯度下降法
梯度下降法:是一种以最快的速度找到最优解的方法。
流程:
1,初始化θ,这里的θ是一组参数,初始化也就是random一下即可
2,求解梯度gradient
3,θ(t+1) = θ(t) - grand*learning_rate
这里的learning_rate常用α表示学习率,是个超参数,太大的话,步子太大容易来回震荡;太小的话,迭代次数很多,耗时。
4,grad < threshold时,迭代停止,收敛,其中threshold也是个超参数
超参数:需要用户传入的参数,若不传使用默认的参数。
Ⅵ、代码实现
导包
import numpy as np
import matplotlib.pyplot as plt
初始化样本数据
# 这里相当于是随机X维度X1,rand是随机均匀分布
X = 2 * np.random.rand(100, 1)
# 人为的设置真实的Y一列,np.random.randn(100, 1)是设置error,randn是标准正太分布
y = 4 + 3 * X + np.random.randn(100, 1)
# 整合X0和X1
X_b = np.c_[np.ones((100, 1)), X]
print(X_b)
"""
[[1. 1.01134124][1. 0.98400529][1. 1.69201204][1. 0.70020158][1. 0.1160646 ][1. 0.42502983][1. 1.90699898][1. 0.54715372][1. 0.73002827][1. 1.29651341][1. 1.62559406][1. 1.61745598][1. 1.86701453][1. 1.20449051][1. 1.97722538][1. 0.5063885 ][1. 1.61769812][1. 0.63034575][1. 1.98271789][1. 1.17275471][1. 0.14718811][1. 0.94934555][1. 0.69871645][1. 1.22897542][1. 0.59516153][1. 1.19071408][1. 1.18316576][1. 0.03684612][1. 0.3147711 ][1. 1.07570897][1. 1.27796797][1. 1.43159157][1. 0.71388871][1. 0.81642577][1. 1.68275133][1. 0.53735427][1. 1.44912342][1. 0.10624546][1. 1.14697422][1. 1.35930391][1. 0.73655224][1. 1.08512154][1. 0.91499434][1. 0.62176609][1. 1.60077283][1. 0.25995875][1. 0.3119241 ][1. 0.25099575][1. 0.93227026][1. 0.85510054][1. 1.5681651 ][1. 0.49828274][1. 0.14520117][1. 1.61801978][1. 1.08275593][1. 0.53545855][1. 1.48276384][1. 1.19092276][1. 0.19209144][1. 1.91535667][1. 1.94012402][1. 1.27952383][1. 1.23557691][1. 0.9941706 ][1. 1.04642378][1. 1.02114013][1. 1.13222297][1. 0.5126448 ][1. 1.22900735][1. 1.49631537][1. 0.82234995][1. 1.24810189][1. 0.67549922][1. 1.72536141][1. 0.15290908][1. 0.17069838][1. 0.27173192][1. 0.09084242][1. 0.13085313][1. 1.72356775][1. 1.65718819][1. 1.7877667 ][1. 1.70736708][1. 0.8037657 ][1. 0.5386607 ][1. 0.59842584][1. 0.4433115 ][1. 0.11305317][1. 0.15295053][1. 1.81369029][1. 1.72434082][1. 1.08908323][1. 1.65763828][1. 0.75378952][1. 1.61262625][1. 0.37017158][1. 1.12323188][1. 0.22165802][1. 1.69647343][1. 1.66041812]]
"""
# 常规等式求解theta
theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
print(theta_best)
"""
[[3.9942692 ][3.01839793]]
"""
# 创建测试集里面的X1
X_new = np.array([[0], [2]])
X_new_b = np.c_[(np.ones((2, 1))), X_new]
print(X_new_b)
y_predict = X_new_b.dot(theta_best)
print(y_predict)
"""
[[1. 0.][1. 2.]]
[[ 3.9942692 ][10.03106506]]
"""
绘图
plt.plot(X_new, y_predict, 'r-')
plt.plot(X, y, 'b.')
plt.axis([0, 2, 0, 15])
plt.show()
Ⅶ、完整代码
import numpy as np
import matplotlib.pyplot as plt# 这里相当于是随机X维度X1,rand是随机均匀分布
X = 2 * np.random.rand(100, 1)
# 人为的设置真实的Y一列,np.random.randn(100, 1)是设置error,randn是标准正太分布
y = 4 + 3 * X + np.random.randn(100, 1)# 整合X0和X1
X_b = np.c_[np.ones((100, 1)), X]
print(X_b)# 常规等式求解theta
theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
print(theta_best)# 创建测试集里面的X1
X_new = np.array([[0], [2]])
X_new_b = np.c_[(np.ones((2, 1))), X_new]
print(X_new_b)
y_predict = X_new_b.dot(theta_best)
print(y_predict)#绘图
plt.plot(X_new, y_predict, 'r-')
plt.plot(X, y, 'b.')
plt.axis([0, 2, 0, 15])
plt.show()
二、批量梯度下降法(BGD,Batch Gradient Descent)
Ⅰ、梯度下降法流程
梯度下降法流程:
1,初始化theta,w0…wn
2,接着求梯度gradient
3,theta_t+1 = theta_t - grad * learning_rate
learning_rate是个超参数,太大容易来回振荡,太小步子太短,需要走很长时间,不管太大还是太小,
都会迭代次数很多,耗时很长
4,等待grad < threshold,迭代停止,收敛,threshold是个超参数
推导线性回归的loss function的导函数,目的是可以更快的求解梯度!
grad_j = (1/m) * (Xj)^Transpose * (Xtheta - y)
grads = (1/m) * X^Transpose * (Xtheta - y)
上面就是批量梯度下降的时候,去求解gradients梯度的公式!
不管是批量梯度下降,还是随机梯度下降,流程里面的1,3,4都是一样的,只有第二步求梯度稍有不同!
Ⅱ、批量梯度下降法(BGF)
初始化W,随机W,进行赋初始值
沿着负梯度方向迭代,更新后的W使得J(W)更小
Ⅲ、完整代码
import numpy as npX = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X]
# print(X_b)learning_rate = 0.1
n_iterations = 10000
m = 100# 1,初始化theta,w0...wn
theta = np.random.randn(2, 1)
count = 0# 4,不会设置阈值,之间设置超参数,迭代次数,迭代次数到了,我们就认为收敛了
for iteration in range(n_iterations):count += 1# 2,接着求梯度gradientgradients = 1/m * X_b.T.dot(X_b.dot(theta)-y)# 3,应用公式调整theta值,theta_t + 1 = theta_t - grad * learning_ratetheta = theta - learning_rate * gradientsprint(count)
print(theta)
三、随机梯度下降法(SGD,Stochastic Gradient Descent)
批量梯度下降法中考虑了所有的样本的梯度,找到最优梯度然后再往下走,很慢。
随机梯度下降则从所有的样本中随机找一个样本的梯度,然后按这个梯度向下走
完整代码
import numpy as npdef learning_schedule(t):#随着迭代次数的增加,会相应的减小学习率return t0 / (t+t1)X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X]
# print(X_b)n_epoches = 500
t0,t1 = 5,50#超参数m = 100
theta = np.random.randn(2,1)#随机初始化θ值for epoch in range(n_epoches):#执行500次迭代for i in range(m):random_index = np.random.randint(m)#从m个样本中随机抽取一个,作为索引xi = X_b[random_index:random_index+1]#根据索引取出值yi = y[random_index:random_index+1]gradients = 2*xi.T.dot(xi.dot(theta)-yi)#得到梯度learning_rate = learning_schedule(epoch*m+i)#随着迭代次数的增加,会相应的减小学习率theta = theta - learning_rate * gradients#根据梯度下降公式调整θprint(theta)
上面代码里面除了随机抽取一条数据来求解梯度,还随着迭代次数的增多,不断减小learning_rate,最终减小步长!
总结
Ⅰ随机梯度下降,怎么随机的呢?
答:其实就是在求梯度的时候,不再用所有的m个样本数据来计算,而是随机的选择一条数据来计算梯度!
Ⅱ随机梯度下降的好处是什么?缺点是什么?
答:在求梯度的时候快,迭代次数有可能更多,最终可能落不到全局最优解上
ⅢMini-Batch GD是什么?
答:就是在求梯度的时候做了一个折中,不用所有的数据,而是随机选择一部分数据来求梯度!
Ⅳ为什么要不断的调整步长?
答:就是为了让越接近最优解的时候,调整的幅度越小,避免来回震荡!
Ⅴ如果我们不人为的调小步长,会不会随着迭代的次数增多,调整的幅度自动减小?
答:调整的幅度取决于谁?取决于学习率和梯度,梯度事实上越接近最优解,梯度的绝对值越小
四、小批量梯度下降法(MBGD,Mini-Batch Gradient Descent)
随机梯度下降法是随机抽取一个样本的梯度作为整体梯度进行下降,速度上去了,但是样本的随机选取很容易抽到不好的样本导致最终的结果偏差很大。批量梯度下降法考虑了所有样本的梯度,选择最优,但是速度太慢。
小批量梯度下降法随机选取一小部分样本的梯度,选择其中最优的解作为最终的梯度。随着迭代次数的增加学习率会降低,步长减小。