梯度下降法公式推导(不用泰勒展开式)

前言

什么是AI?
The theory and development of computer systems able to perform tasks normally requiring human intelligence.(–Oxford Dictionary)
Using data to solve problems.(–cy)

公式推导

其实不用泰勒展开式也是可以简单方便的得出梯度下降法的结论的,在高数书本(同济)的微分的定义里就有讲到(我看的是同济7版第113页和117页)。见下图:
在这里插入图片描述
以上就是梯度下降法的原理吧,只不过在机器学习与深度学习要设置好适当的学习率(即f(x)的导数前面乘以一个常数)。

举例

求下面求函数的最小值。
在这里插入图片描述
代码以及运行效果如下:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['KaiTi']#显示中文字体
mpl.rcParams['font.serif'] = ['KaiTi']
mpl.rcParams['font.size'] =8
plt.rcParams['axes.unicode_minus'] = False#解决matplotlib画图坐标轴负号乱码问题

# 画图 x迭代找到最小值(图像最低点)的过程
x = 3#这里设置x的初始值是3
lr = 0.25#这个是学习率

# 原函数
def fx(x):
    fx = x * x + 2 * x + 2
    return fx

#优化过程
def optmize(learning_rate):
    global x
    gx=2 * x + 2
    x=x-learning_rate*gx
    
plt.grid()
print("迭代次数\t    x\t      f(x)\t  导数df(x)\t学习率*导数\tx-学习率*导数(即下一步x)")
for i in range(20):
    f_x=fx(x)
    plt.plot(np.linspace(-5, 3, 10000), [fx(x) for x in np.linspace(-5, 3, 10000)],color='black')
    plt.scatter(x,f_x, color='r')#, ,
    plt.title('迭代次数:'+str(i)+"  x:"+str('%.4f'%x)+"  f(x):"+str('%.4f'%f_x))

    #下面这几行代码是改变显示的坐标轴的范围 因为迭代到后期数字太小的时候不改变坐标轴的范围 看的不明显 跟没有动一样
    if x<-0.8:
        plt.xlim(-1.15,-0.85)
        plt.ylim(0.99,1.02)  # 坐标系y轴范围
    if x<-0.998:
        plt.xlim(-1.002,-0.998)
        plt.ylim(0.998,1.002)  # 坐标系y轴范围

    plt.pause(1)#间隔1s再进行下一步 要不是太快了 瞬间就完了
    print(" {:0>3d}\t {:.4f}     {:.4f}\t   {:.4f}\t {:.4f}\t\t\t{:.4f}".
          format(i, x, f_x,2 * x + 2,lr*(2 * x + 2),x-lr*(2 * x + 2)))#,2 * x + 2,lr*(2 * x + 2),x-lr*(2 * x + 2)    导数df(x)的值:{.4f}\t\t学习率*导数:{.4f}\t\tx-lr*df(x)(下一个x):{.4f}
    optmize(lr)#优化
plt.show()

在这里插入图片描述
在这里插入图片描述

神经网络中运用

在神经网络中 一般是对LOSS函数求最小值 然后对数据的权重w求偏导 下面改成这种形式

#需要优化的函数
def loss_fn():
    loss=w1**2+2*w1+w2**2+w2
    return loss

#优化函数
def optmize(lr):
    global w1,w2
    dw1=2*w1+2#求偏导
    dw2=2*w2+1
    #然后梯度下降
    w1=w1-lr*dw1
    w2=w2-lr*dw2

w1,w2=0,1
lr=0.03
for i in range(201):
    lossData=loss_fn()
    if i%5==0:
        print("迭代次数:{:0>3d},  loss值:{:.4f},  w1:{:.4f},  w2:{:.4f}".format(i,lossData,w1,w2))
    optmize(lr)

迭代次数:000, loss值:2.0000, w1:0.0000, w2:1.0000
迭代次数:005, loss值:0.5005, w1:-0.2661, w2:0.6009
迭代次数:010, loss值:-0.3072, w1:-0.4614, w2:0.3079
迭代次数:015, loss值:-0.7422, w1:-0.6047, w2:0.0929
迭代次数:020, loss值:-0.9765, w1:-0.7099, w2:-0.0648
迭代次数:025, loss值:-1.1027, w1:-0.7871, w2:-0.1806
迭代次数:030, loss值:-1.1706, w1:-0.8437, w2:-0.2656
迭代次数:035, loss值:-1.2073, w1:-0.8853, w2:-0.3280
迭代次数:040, loss值:-1.2270, w1:-0.9158, w2:-0.3738
迭代次数:045, loss值:-1.2376, w1:-0.9382, w2:-0.4074
迭代次数:050, loss值:-1.2433, w1:-0.9547, w2:-0.4320
迭代次数:055, loss值:-1.2464, w1:-0.9667, w2:-0.4501
迭代次数:060, loss值:-1.2481, w1:-0.9756, w2:-0.4634
迭代次数:065, loss值:-1.2490, w1:-0.9821, w2:-0.4731
迭代次数:070, loss值:-1.2494, w1:-0.9868, w2:-0.4803
迭代次数:075, loss值:-1.2497, w1:-0.9903, w2:-0.4855
迭代次数:080, loss值:-1.2498, w1:-0.9929, w2:-0.4894
迭代次数:085, loss值:-1.2499, w1:-0.9948, w2:-0.4922
迭代次数:090, loss值:-1.2500, w1:-0.9962, w2:-0.4943
迭代次数:095, loss值:-1.2500, w1:-0.9972, w2:-0.4958
迭代次数:100, loss值:-1.2500, w1:-0.9979, w2:-0.4969
迭代次数:105, loss值:-1.2500, w1:-0.9985, w2:-0.4977
迭代次数:110, loss值:-1.2500, w1:-0.9989, w2:-0.4983
迭代次数:115, loss值:-1.2500, w1:-0.9992, w2:-0.4988
迭代次数:120, loss值:-1.2500, w1:-0.9994, w2:-0.4991
迭代次数:125, loss值:-1.2500, w1:-0.9996, w2:-0.4993
迭代次数:130, loss值:-1.2500, w1:-0.9997, w2:-0.4995
迭代次数:135, loss值:-1.2500, w1:-0.9998, w2:-0.4996
迭代次数:140, loss值:-1.2500, w1:-0.9998, w2:-0.4997
迭代次数:145, loss值:-1.2500, w1:-0.9999, w2:-0.4998
迭代次数:150, loss值:-1.2500, w1:-0.9999, w2:-0.4999
迭代次数:155, loss值:-1.2500, w1:-0.9999, w2:-0.4999
迭代次数:160, loss值:-1.2500, w1:-0.9999, w2:-0.4999
迭代次数:165, loss值:-1.2500, w1:-1.0000, w2:-0.4999
迭代次数:170, loss值:-1.2500, w1:-1.0000, w2:-0.5000
迭代次数:175, loss值:-1.2500, w1:-1.0000, w2:-0.5000
迭代次数:180, loss值:-1.2500, w1:-1.0000, w2:-0.5000
迭代次数:185, loss值:-1.2500, w1:-1.0000, w2:-0.5000
迭代次数:190, loss值:-1.2500, w1:-1.0000, w2:-0.5000
迭代次数:195, loss值:-1.2500, w1:-1.0000, w2:-0.5000
迭代次数:200, loss值:-1.2500, w1:-1.0000, w2:-0.5000

线性回归举例

下面生成一堆数据进行线性回归试试 一般在AI项目中,数据都是一条一条的,也就是离散的.这个时候损失函数就是一条一条的数据预测值与实际值的偏差累加起来的.对于一个有确定表达式的函数(连续型),我们用求导公式能够很快的写出来,对于离散型的变量求偏导,好像见得不多哦,无非是求偏导的时候把累加符号带上求偏导就可以了(我看的是同济高数第7版第136页讲最小二乘法的时候,那里出现了离散型的数据求偏导)

import random
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import warnings
warnings.filterwarnings("ignore")#忽略下面frame有些方法的警告

##### 首先生成数据并且可视化
x=np.linspace(1,10,50)#先生成横坐标
y=[3*i+8+random.randint(-1,1) for i in x]#y大致是x的一次函数y=3*x+8 不过我加上了随机数 不是完全的一次函数的点
df=pd.DataFrame()
for i in range(len(x)):
    df=df.append(pd.DataFrame({'x':[x[i]],'y':[y[i]]}))
df=df.reset_index(drop=True)#索引重新排号
print(df)
plt.scatter(df['x'],df['y'])
plt.show()

序号  x      y
0 1.000000 11.000000
1 1.183673 10.551020
2 1.367347 13.102041
3 1.551020 11.653061
4 1.734694 12.204082
5 1.918367 14.755102
6 2.102041 15.306122
7 2.285714 13.857143
8 2.469388 14.408163
9 2.653061 15.959184
10 2.836735 16.510204
11 3.020408 18.061224
12 3.204082 16.612245
13 3.387755 18.163265
14 3.571429 17.714286
15 3.755102 20.265306
16 3.938776 20.816327
17 4.122449 19.367347
18 4.306122 19.918367
19 4.489796 21.469388
20 4.673469 21.020408
21 4.857143 22.571429
22 5.040816 24.122449
23 5.224490 22.673469
24 5.408163 23.224490
25 5.591837 25.775510
26 5.775510 24.326531
27 5.959184 24.877551
28 6.142857 27.428571
29 6.326531 26.979592
30 6.510204 26.530612
31 6.693878 27.081633
32 6.877551 27.632653
33 7.061224 28.183673
34 7.244898 28.734694
35 7.428571 30.285714
36 7.612245 30.836735
37 7.795918 30.387755
38 7.979592 32.938776
39 8.163265 31.489796
40 8.346939 33.040816
41 8.530612 33.591837
42 8.714286 35.142857
43 8.897959 34.693878
44 9.081633 36.244898
45 9.265306 36.795918
46 9.448980 36.346939
47 9.632653 37.897959
48 9.816327 36.448980
49 10.000000 37.000000
在这里插入图片描述

w=random.randint(-10,10)
b=random.randint(-10,10)
print('随机初始的w:',w,'\t随机初始的b:',b)

def loss_fn(y,y_predict):
    loss=np.mean((y_predict-y)*(y_predict-y))#均方误差
    return loss

## 准备函数:更新参数
def optimize(learning_rate):
    global w,b    
    dfw=2*np.mean((w*df['x']+b-df['y'])*df['x'])#均方误差对w求偏导
    dfb=2*np.mean((w*df['x']+b-df['y']))#均方误差对b求偏导

    w-=learning_rate*dfw#梯度下降
    b-=learning_rate*dfb

for i in range(3001):    
    y_predict=df['x']*w+b#用初始的w和b进行预测值    
    loss=loss_fn(y,y_predict)#3计算损失 
    
    if i%300==0:
        print('迭代次数:',i,'\t误差:',loss)
    ## 4更新参数w和b
    optimize(0.01)

print("训练完之后的w:",w,"\t训练完之后的b:",b)
plt.scatter(df['x'],df['y'])
plt.plot(df['x'],w*df['x']+b,color='r')
plt.show()

随机初始的w: -9 随机初始的b: -6
迭代次数: 0 误差: 7422.177551020408
迭代次数: 300 误差: 3.378002459873165
迭代次数: 600 误差: 0.9540268221912477
迭代次数: 900 误差: 0.6900677102960657
迭代次数: 1200 误差: 0.6613238517896634
迭代次数: 1500 误差: 0.6581937859400552
迭代次数: 1800 误差: 0.6578529370515627
迭代次数: 2100 误差: 0.6578158202717991
迭代次数: 2400 误差: 0.657811778435705
迭代次数: 2700 误差: 0.6578113382994895
迭代次数: 3000 误差: 0.6578112903708038
训练完之后的w: 3.0771502250843357 训练完之后的b: 7.555641370093037
在这里插入图片描述
蓝色点是前面生成的点,红色的线是训练出来的w和b生成的一次函数曲线。
同样 这里只有一个特征x 如果有多个特征x1 x2 x3依次加上w1 w2 w3,如果是逻辑回归的话 就改一下损失函数和求偏导就OK了

总结

(如果您发现我写的有错误,欢迎在评论区批评指正)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值