機器學習學習筆記之一——用python實現簡單一元函式、二元函式的梯度下降
阿新 • • 發佈:2018-12-24
今天開始正正經經,好好的寫機器學習的筆記。
再一次從頭翻過來學機器學習,在有一些python和大學數學的基礎下,首先要搞的果然還是梯度下降,本篇記錄的是用jupyter完成的一次作業:python實現一維陣列和二維陣列的梯度下降,目的只在於熟悉梯度下降。
第一部分:一元函式的資料生成與影象呈現
import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl import math from mpl_toolkits.mplot3d import Axes3D import warnings # 解決中文顯示問題 mpl.rcParams['font.sans-serif'] = [u'SimHei'] mpl.rcParams['axes.unicode_minus'] = False %matplotlib inline """ 原影象: 1、構建一個函式為 y = 0.5 * (x-0.25) ** 2 的影象。 2、隨機生成X點,根據X點生成Y點。 3、畫出影象。 """ # 一維原始影象 # 原函式 def f1(x): return 0.5 * (x - 0.25) ** 2 # 構建資料 X = np.arange(-4,4,0.05) Y = np.array(list(map(lambda t: f1(t),X))) Y # 作圖 plt.figure(facecolor='w') plt.plot(X,Y,'r-',linewidth=2) plt.title(u'函式$y=0.5 * (x - 0.25)^2$') plt.show()
結果如圖:
第二部分:一元函式的梯度下降求解過程,以及求解過程影象呈現
""" 對當前一維原始影象求最小點: 1、隨機取一個點(橫座標為x),設定阿爾法引數值。 2、對這個點求導數 ,x =x - α*(dY/dx)。 3、重複第二步、設定迭代 y的變化量小於多少時 不再繼續迭代。 """ # 導數 def h1(x): return 0.5 * 2 * (x-0.25) x = 4 alpha = 0.5 f_change = f1(x) # y的變化量 iter_num = 0 # 迭代次數 GD_X = [x] #儲存梯度下降所經歷的點 GD_Y = [f1(x)] while(f_change > 1e-10) and iter_num<100: tmp = x - alpha * h1(x) f_change = np.abs(f1(x) - f1(tmp)) x = tmp GD_X.append(x) GD_Y.append(f1(x)) iter_num += 1 print(u"最終結果為:(%.5f,%.5f)"%(x,f1(x))) print(u"迭代過程中X的取值,迭代次數:%d" % iter_num) print(GD_X) %matplotlib inline plt.figure(facecolor='w') plt.plot(X,Y,'r-',linewidth=2) #第三個引數是顏色和形狀,red圈就是ro-,red直線就是r- plt.plot(GD_X, GD_Y, 'bo-', linewidth=2) plt.title(u'函式$ y = 0.5 * (x-0.25)^2$;\n學習率%.3f;最終解:(%.3f,%.3f),迭代次數:%d'%(alpha,x,f1(x),iter_num))
結果如圖:
第三部分:二元函式的資料生成、影象顯示
""" 二維原始影象 1、構建一個函式為 y = 0.5 (x1+x2)^2 - x1 x2 的影象。 2、隨機生成X1,X2點,根據X1,X2點生成Y點。 3、畫出影象。 """ def f2(x1,x2): return 0.5 * (x1+x2) ** 2 - x1 * x2 X1 = np.arange(-4,4,0.2) X2 = np.arange(-4,4,0.2) X1, X2 = np.meshgrid(X1, X2) # 生成xv、yv,將X1、X2變成n*m的矩陣,方便後面繪圖 Y = np.array(list(map(lambda t : f2(t[0],t[1]),zip(X1.flatten(),X2.flatten())))) Y.shape = X1.shape # 1600的Y圖還原成原來的(40,40) %matplotlib inline #作圖 fig = plt.figure(facecolor='w') ax = Axes3D(fig) ax.plot_surface(X1,X2,Y,rstride=1,cstride=1,cmap=plt.cm.jet) ax.set_title(u'$ y = 0.5 (x1+x2)^2 - x1 x2 $') plt.show()
結果如圖:
第四部分:二元函式的梯度下降求結果層
"""
對當前二維影象求最小點¶
1、隨機取一個點(x1,x2),設定α引數值
2、對這個點分別求關於x1、x2的偏導數,x1 =x1 - α*(dY/dx1),x2 =x2 - α*(dY/dx2)
3、重複第二補,設定 y的變化量 小於多少時 不再重複。
"""
# 二維原始影象
def f2(x, y):
return 0.15 * (x + 0.5) ** 2 + 0.25 * (y - 0.25) ** 2 + 0.35 * (1.5 * x - 0.2 * y + 0.35 ) ** 2
## 偏函式
def hx1(x, y):
return 0.15 * 2 * (x + 0.5) + 0.25 * 2 * (1.5 * x - 0.2 * y + 0.35 ) * 1.5
def hx2(x, y):
return 0.25 * 2 * (y - 0.25) - 0.25 * 2 * (1.5 * x - 0.2 * y + 0.35 ) * 0.2
x1 = 4
x2 = 4
alpha = 0.5
#儲存梯度下降經過的點
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'函式;\n學習率:%.3f; 最終解:(%.3f, %.3f, %.3f);迭代次數:%d' % (alpha, x1, x2, f2(x1,x2), iter_num))
plt.show()