前言

1、机器学习中的大部分问题都是优化问题,而绝大部分优化问题都可以使用梯度下降法处理。

2、梯度下降法 = 梯度+下降

3、想要了解梯度,必须要了解方向导数,想要了解方向导数,就要了解偏导数,想要了解偏导数,就要了解导数,所以学习梯度需要依次学习导数、偏导数、方向导数和梯度。

基础知识

1、导数:函数在该点的瞬时变化率,针对一元函数而言

梯度下降的公式推导 梯度下降法公式推导_机器学习

2、偏导数:函数在坐标轴方向上的变化率 

梯度下降的公式推导 梯度下降法公式推导_梯度下降法_02

3、方向导数:函数在某点沿某个特定方向的变化率 

梯度下降的公式推导 梯度下降法公式推导_机器学习_03

4、梯度:函数在该点沿所有方向变化率最大的那个方向

梯度下降的公式推导 梯度下降法公式推导_优化问题_04

5、泰勒公式

直观认识

1、一元函数求极小值点

梯度下降的公式推导 梯度下降法公式推导_机器学习_05

如上图所示,曲线代表目标函数(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°在函数值上变化最快!

我们从一元函数即可推导出多元函数的计算公式,最快的方向就是


, ... ,

,该方向函数值变化最大:

梯度下降的公式推导 梯度下降法公式推导_梯度下降_06

公式认识

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()