梯度下降算法
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 星期六