人工智能筆記---梯度下降算法,牛頓法

梯度下降算法

1.梯度下降算法的基本原理

梯度下降究竟爲何方神聖?我來用最通俗的語言來介紹下: 假設你站在華山之巔,你現在想以最快速度下山,那你肯定是找一條最陡峭的路走。你環顧四周,找到了一條路線,恩,這個方向是最陡的。於是你就出發了,走了一會發現,這個方向不是最陡的路了。你就停下來,換了個最陡的方向,繼續往下走。重複這個步驟,你最終到達了山腳下。 那麼,你從山頂到山腳的整個下山的過程,就是梯度下降。

2.多元線性迴歸分析

採用梯度法求解漫畫書中“店鋪多元迴歸”的問題。並與之前的結果做對比
爲求得某個地區的商品店的月營業額是與店鋪的面積相關性大,還是與該店距離車站距離的相關性大,需要我們以店鋪面積、距離車站的距離、以及月營業額建立線性迴歸方程,並求解該方程,和相關係數

導入數據

import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
data=np.genfromtxt('面積距離車站數據.csv',delimiter=',')
x_data=data[:,:-1]
y_data=data[:,2]

定義學習率、斜率、截據,設方程爲y=theta1x1+theta2x2+theta0定義學習率、斜率、截據,設方程爲y=theta1x1+theta2x2+theta0

lr=0.00001
theta0=0
theta1=0
theta2=0
#定義最大迭代次數,因爲梯度下降法是在不斷迭代更新k與b
epochs=10000
#定義最小二乘法函數-損失函數(代價函數)
def compute_error(theta0,theta1,theta2,x_data,y_data):
    totalerror=0
    for i in range(0,len(x_data)):#定義一共有多少樣本點
        totalerror=totalerror+(y_data[i]-(theta1*x_data[i,0]+theta2*x_data[i,1]+theta0))**2
    return totalerror/float(len(x_data))/2

梯度下降算法求解參數

def gradient_descent_runner(x_data,y_data,theta0,theta1,theta2,lr,epochs):
    m=len(x_data)
    for i in range(epochs):
        theta0_grad=0
        theta1_grad=0
        theta2_grad=0
        for j in range(0,m):
            theta0_grad-=(1/m)*(-(theta1*x_data[j,0]+theta2*x_data[j,1]+theta2)+y_data[j])
            theta1_grad-=(1/m)*x_data[j,0]*(-(theta1*x_data[j,0]+theta2*x_data[j,1]+theta0)+y_data[j])
            theta2_grad-=(1/m)*x_data[j,1]*(-(theta1*x_data[j,0]+theta2*x_data[j,1]+theta0)+y_data[j])
        theta0=theta0-lr*theta0_grad
        theta1=theta1-lr*theta1_grad
        theta2=theta2-lr*theta2_grad
    return theta0,theta1,theta2

進行迭代求解,畫圖,生成網格矩陣

theta0,theta1,theta2=gradient_descent_runner(x_data,y_data,theta0,theta1,theta2,lr,epochs)
print('結果:迭代次數:{0} 學習率:{1}之後 a0={2},a1={3},a2={4},代價函數爲{5}'.format(epochs,lr,theta0,theta1,theta2,compute_error(theta0,theta1,theta2,x_data,y_data)))
print("多元線性迴歸方程爲:y=",theta1,"X1+",theta2,"X2+",theta0)
#畫圖
ax=plt.figure().add_subplot(111,projection='3d')
ax.scatter(x_data[:,0],x_data[:,1],y_data,c='r',marker='o')
x0=x_data[:,0]
x1=x_data[:,1]
#生成網格矩陣
x0,x1=np.meshgrid(x0,x1)
z=theta0+theta1*x0+theta2*x1

畫圖

ax.plot_surface(x0,x1,z)
ax.set_xlabel('area')
ax.set_ylabel('distance')
ax.set_zlabel("Monthly turnover")
plt.show()

總體代碼

import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
data=np.genfromtxt('面積距離車站數據.csv',delimiter=',')
x_data=data[:,:-1]
y_data=data[:,2]
#定義學習率、斜率、截據
#設方程爲y=theta1x1+theta2x2+theta0
lr=0.00001
theta0=0
theta1=0
theta2=0
#定義最大迭代次數,因爲梯度下降法是在不斷迭代更新k與b
epochs=10000
#定義最小二乘法函數-損失函數(代價函數)
def compute_error(theta0,theta1,theta2,x_data,y_data):
    totalerror=0
    for i in range(0,len(x_data)):#定義一共有多少樣本點
        totalerror=totalerror+(y_data[i]-(theta1*x_data[i,0]+theta2*x_data[i,1]+theta0))**2
    return totalerror/float(len(x_data))/2
#梯度下降算法求解參數

def gradient_descent_runner(x_data,y_data,theta0,theta1,theta2,lr,epochs):
    m=len(x_data)
    for i in range(epochs):
        theta0_grad=0
        theta1_grad=0
        theta2_grad=0
        for j in range(0,m):
            theta0_grad-=(1/m)*(-(theta1*x_data[j,0]+theta2*x_data[j,1]+theta2)+y_data[j])
            theta1_grad-=(1/m)*x_data[j,0]*(-(theta1*x_data[j,0]+theta2*x_data[j,1]+theta0)+y_data[j])
            theta2_grad-=(1/m)*x_data[j,1]*(-(theta1*x_data[j,0]+theta2*x_data[j,1]+theta0)+y_data[j])
        theta0=theta0-lr*theta0_grad
        theta1=theta1-lr*theta1_grad
        theta2=theta2-lr*theta2_grad
    return theta0,theta1,theta2
#進行迭代求解
theta0,theta1,theta2=gradient_descent_runner(x_data,y_data,theta0,theta1,theta2,lr,epochs)
print('結果:迭代次數:{0} 學習率:{1}之後 a0={2},a1={3},a2={4},代價函數爲{5}'.format(epochs,lr,theta0,theta1,theta2,compute_error(theta0,theta1,theta2,x_data,y_data)))
print("多元線性迴歸方程爲:y=",theta1,"X1+",theta2,"X2+",theta0)
#畫圖
ax=plt.figure().add_subplot(111,projection='3d')
ax.scatter(x_data[:,0],x_data[:,1],y_data,c='r',marker='o')
x0=x_data[:,0]
x1=x_data[:,1]
#生成網格矩陣
x0,x1=np.meshgrid(x0,x1)
z=theta0+theta1*x0+theta2*x1
#畫3d圖
ax.plot_surface(x0,x1,z)
ax.set_xlabel('area')
ax.set_ylabel('distance')
ax.set_zlabel("Monthly turnover")
plt.show()


本文章參考別處,具體請參考這裏
2020-04-04 20:47:47 星期六


使用Python3D圖像繪製

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import math
from mpl_toolkits.mplot3d import Axes3D

設置在jupyter中matplotlib展示圖片,非內嵌顯示 tk:顯示出來,inline:內嵌顯示

get_ipython().run_line_magic('matplotlib', 'tk') 

解決中文顯示問題

mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False

二維原始圖像

ef f2(x, y):
    return x**2+2*(y)**2 - 4*(x)-2*(x)*(y)

偏函數

def hx1(x, y):
    return 2*x-4-2*y
def hx2(x, y):
    return 4*y-2*x

X1 = np.arange(-4,4,0.2)
X2 = np.arange(-4,4,0.2)
# 生成xv、yv,將X1、X2變成n*m的矩陣,方便後面繪圖
X1, X2 = np.meshgrid(X1, X2) 
Y = np.array(list(map(lambda t : f2(t[0],t[1]),zip(X1.flatten(),X2.flatten()))))
# 1600的Y圖還原成原來的(40,40)
Y.shape = X1.shape 
x1 = 1
x2 = 1
alpha = 0.1

保存梯度下降經過的點

GD_X1 = [x1]
GD_X2 = [x2]
GD_Y = [f2(x1,x2)]

定義y的變化量和迭代次數

y_change = f2(x1,x2)
iter_num = 0
while(y_change < 1e-10 and iter_num < 100) :
    tmp_x1 = x1 - alpha * hx1(x1,x2)
    tmp_x2 = x2 - alpha * hx2(x1,x2)
    tmp_y = f2(tmp_x1,tmp_x2)
    f_change = np.absolute(tmp_y - f2(x1,x2))
    x1 = tmp_x1
    x2 = tmp_x2
    GD_X1.append(x1)
    GD_X2.append(x2)
    GD_Y.append(tmp_y)
    iter_num += 1
print(u"最終結果爲:(%.5f, %.5f, %.5f)" % (x1, x2, f2(x1,x2)))
print(u"迭代過程中X的取值,迭代次數:%d" % iter_num)
print(GD_X1)

作圖

fig = plt.figure(facecolor='w',figsize=(20,18))
ax = Axes3D(fig)
ax.plot_surface(X1,X2,Y,rstride=1,cstride=1,cmap=plt.cm.jet)
ax.plot(GD_X1,GD_X2,GD_Y,'ko-')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.set_title(u'$ y = x1^2+2(x2)^2 - 4(x1)-2(x1) (x2) $')
 
ax.set_title(u'函數;\n學習率:%.3f; 最終解:(%.3f, %.3f, %.3f);迭代次數:%d' % (alpha, x1, x2, f2(x1,x2), iter_num))
plt.show()

效果:

參考csdn的博客連接
2020-04-04 23:08:28 星期六

牛頓法

牛頓法用來迭代的求解一個方程的解,原理如下:
對於一個函數f(x),它的泰勒級數展開式是這樣的

當使用牛頓法來求一個方程解的時候,它使用泰勒級數前兩項來代替這個函數,即用ϕ(x)代替f(x),其中:

令ϕ(x)=0,則 x=x0−f(x0)/f′(x0)。
所以,牛頓法的迭代公式是

牛頓法求解n的平方根
求解n的平方根,其實是求方程x2−n=0的解
利用上面的公式可以得到:

編程的時候核心的代碼是:x = (x + n/x)/2

最優化的牛頓法

應用於最優化的牛頓法是以迭代的方式來求解一個函數的最優解,常用的優化方法還有梯度下降法。
取泰勒展開式的二次項,即用ϕ(x)來代替f(x):

最優點的選擇是ϕ′(x)=0的點,對上式求導

令ϕ′(x)=0,則x=x0−f′(x0)/f′′(x0)
所以,最優化的牛頓迭代公式是

和梯度下降法相比,在使用牛頓迭代法進行優化的時候,需要求Hessien矩陣的逆矩陣,這個計算是很大的。


參考鏈接在這裏
2020-04-04 23:09:26 星期六

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章