前言
1、机器学习中的大部分问题都是优化问题,而绝大部分优化问题都可以使用梯度下降法处理。
2、梯度下降法 = 梯度+下降
3、想要了解梯度,必须要了解方向导数,想要了解方向导数,就要了解偏导数,想要了解偏导数,就要了解导数,所以学习梯度需要依次学习导数、偏导数、方向导数和梯度。
基础知识
1、导数:函数在该点的瞬时变化率,针对一元函数而言
2、偏导数:函数在坐标轴方向上的变化率
3、方向导数:函数在某点沿某个特定方向的变化率
4、梯度:函数在该点沿所有方向变化率最大的那个方向
5、泰勒公式
直观认识
1、一元函数求极小值点
如上图所示,曲线代表目标函数(loss函数),如何在给定的初始x值情况下,找到目标函数极小值的坐标x?
1)若初始点为x0,此点的导数值从给定的曲线来看必然大于0,此时我们可以尝试:x0 := x0 - 导数值(为什么是减号,这里就体现了梯度下降),那么x0必然往左移动,记为x0',再在此点做第二条切线,按照此步骤进行训练计算。
2)若初始点为x1,此点的导数值从给定的曲线来看必然小于0,此时我们可以尝试:x1 := x1 + 导数值(为什么是加号,这里就体现了梯度下降),那么x1必然往右移动,记为x1',再在此点做第二条切线,按照此步骤进行训练计算。
按照上述办法,我们最后得到的x值有可能就在目标x点左右徘徊,可是我们担心导数值过大,使得x0或x1计算后并没有向目标x点移动,而是离它越来越远,所以我们可以尝试如下计算方式:
x0 := x0 - a*导数值 x1 := x1 + a*导数值 (可通过泰勒一阶展开式证明)
这里的a代表学习率,即步长,如果导数值过大,我们可以根据经验将a变小,反之则变大
2、多元函数求极小值点
若一个人站在半山腰,他的前面有四条路,如何才能使得自己下山的速度最快呢?
1)上山的路
2)较为平缓的环形下山公路
3)45°的下山阶梯
4)90°的悬崖绝壁
小伙伴你们选什么,欢迎留言!
博主给出的回答是直接跳崖,自由落体比什么都快,这里不要笑,因为梯度就是这么想的。
回到问题,如何找到多元函数的极小值点呢?从上面的理论中我们可以看出,梯度表示函数在该点沿所有方向变化率最大的那个方向,你们说是不是选择直接跳崖呢,因为90°在函数值上变化最快!
我们从一元函数即可推导出多元函数的计算公式,最快的方向就是
,
, ... ,
,该方向函数值变化最大:
公式认识
1、前向函数
2、loss函数
3、梯度下降初始定义
4、梯度计算
5、梯度下降最终定义
代码认识
#!usr/bin/python3
# coding:utf-8
import numpy as np
import random
def batchGradientDescent(x, y, theta, alpha, m, maxInteration):
x_train = x.transpose()
for i in range(0, maxInteration):
hypothesis = np.dot(x, theta)
# 损失函数
loss = hypothesis - y
# 下降梯度
gradient = np.dot(x_train, loss) / m
# 求导之后得到theta
theta = theta - alpha * gradient
return theta
def main():
trainData = np.array([[1, 4, 2], [2, 5, 3], [5, 1, 6], [4, 2, 8]])
trainLabel = np.array([19, 26, 19, 20])
print(trainData)
print(trainLabel)
m, n = np.shape(trainData)
theta = np.ones(n)
print(theta.shape)
maxInteration = 500
alpha = 0.01
theta = batchGradientDescent(trainData, trainLabel, theta, alpha, m, maxInteration)
print(theta)
return
if __name__ == "__main__":
main()