loss下降auc下降_梯度下降算法 线性回归拟合(附Python/Matlab/Julia源代码)
梯度下降
梯度下降法的原理
梯度下降法(gradient descent)是一種常用的一階(first-order)優(yōu)化方法,是求解無約束優(yōu)化問題最簡單、最經(jīng)典的方法之一。
梯度下降最典型的例子就是從山上往下走,每次都尋找當(dāng)前位置最陡峭的方向小碎步往下走,最終就會(huì)到達(dá)山下(暫不考慮有山谷的情況)。
首先來解釋什么是梯度?這就要先講微分。對(duì)于微分,相信大家都不陌生,看幾個(gè)例子就更加熟悉了。
先來看單變量的微分:
再看多變量的微分:
補(bǔ)充:導(dǎo)數(shù)和微分的區(qū)別
導(dǎo)數(shù)是函數(shù)在某一點(diǎn)處的斜率,是Δy和Δx的比值;而微分是指函數(shù)在某一點(diǎn)處的切線在橫坐標(biāo)取得增量Δx以后,縱坐標(biāo)取得的增量,一般表示為dy。
梯度就是由微分結(jié)果組成的向量,令
有
那么,函數(shù)f(x,y,z)在(1,2,3)處的微分為
因此,函數(shù)f(x,y,z)在(1,2,3)處的梯度為(6,11,6)。
梯度是一個(gè)向量,對(duì)于一元函數(shù),梯度就是該點(diǎn)處的導(dǎo)數(shù),表示切線的斜率。對(duì)于多元函數(shù),梯度的方向就是函數(shù)在該點(diǎn)上升最快的方向。
梯度下降法就是每次都尋找梯度的反方向,這樣就能到達(dá)局部的最低點(diǎn)。
那為什么按照梯度的反方向能到達(dá)局部的最低點(diǎn)呢?這個(gè)問題直觀上很容易看出來,但嚴(yán)禁起見,我們還是給出數(shù)學(xué)證明。
對(duì)于連續(xù)可微函數(shù)f(x),從某個(gè)隨機(jī)點(diǎn)出發(fā),想找到局部最低點(diǎn),可以通過構(gòu)造一個(gè)序列
能夠滿足
那么我們就能夠不斷執(zhí)行該過程即可收斂到局部極小點(diǎn),可參考下圖。
那么問題就是如何找到下一個(gè)點(diǎn)
并保證 呢?我們以一元函數(shù)為例來說明。對(duì)于一元函數(shù)來說,x是會(huì)存在兩個(gè)方向:要么是正方向 , 要么是負(fù)方向 ,如何選擇每一步的方向,就需要用到大名鼎鼎的泰勒公式,先看一下下面這個(gè)泰勒展式:其中
表示f(x)在x處的導(dǎo)數(shù)。若想
,就需要保證 ,令步長 是一個(gè)較小的正數(shù),從而有
因此,有
每一步我們都按照
更新x,這就是梯度下降的原理。這里再對(duì)
解釋一下,α在梯度下降算法中被稱作為學(xué)習(xí)率或者步長,意味著我們可以通過α來控制每一步走的距離。既要保證步子不能太小,還沒下到山底太陽就下山了;也要保證步子不能跨的太大,可能會(huì)導(dǎo)致錯(cuò)過最低點(diǎn)。在梯度前加負(fù)號(hào)就是朝梯度的反方向前進(jìn),因?yàn)樘荻仁巧仙羁斓姆较?#xff0c;所以方向就是下降最快的方向。
梯度下降的實(shí)例
一元函數(shù)的梯度下降
設(shè)一元函數(shù)為
函數(shù)的微分為
設(shè)起點(diǎn)為
,步長 ,根據(jù)梯度下降的公式經(jīng)過4次迭代:
多元函數(shù)的梯度下降
設(shè)二元函數(shù)為
函數(shù)的梯度為
設(shè)起點(diǎn)為(2,3),步長
,根據(jù)梯度下降的公式,經(jīng)過多次迭代后,有loss function(損失函數(shù))
損失函數(shù)也叫代價(jià)函數(shù)(cost function),是用來衡量模型預(yù)測(cè)出來的值h(θ)與真實(shí)值y之間的差異的函數(shù),如果有多個(gè)樣本,則可以將所有代價(jià)函數(shù)的取值求均值,記做J(θ)。代價(jià)函數(shù)有下面幾個(gè)性質(zhì):
最常見的代價(jià)函數(shù)是均方誤差函數(shù),即
其中,
- m為訓(xùn)練樣本的個(gè)數(shù)
- 表示估計(jì)值,表達(dá)式如下
- y是原訓(xùn)練樣本中的值
我們需要做的就是找到θ的值,使得J(θ)最小。代價(jià)函數(shù)的圖形跟我們上面畫過的圖很像,如下圖所示。
看到這個(gè)圖,相信大家也就知道了我們可以用梯度下降算法來求可以使代價(jià)函數(shù)最小的θ值。
先求代價(jià)函數(shù)的梯度
這里有兩個(gè)變量
和 ,為了方便矩陣表示,我們給x增加一維,這一維的值都是1,并將會(huì)乘到 上。那么cost function的矩陣形式為:這么看公式可能很多同學(xué)會(huì)不太明白,我們把每個(gè)矩陣的具體內(nèi)容表示出來,大家就很容易理解了。
矩陣
為:矩陣X為:
矩陣y為:
這樣寫出來后再去對(duì)應(yīng)上面的公式,就很容易理解了。
下面我們來舉一個(gè)用梯度下降算法來實(shí)現(xiàn)線性回歸的例子。有一組數(shù)據(jù)如下圖所示,我們嘗試用求出這些點(diǎn)的線性回歸模型。
首先產(chǎn)生矩陣X和矩陣y
# generate matrix X按照上面的公式定義梯度函數(shù)
def gradient_function(theta, X, y):diff = np.dot(X, theta) - yreturn (1./m) * np.dot(np.transpose(X), diff)接下來就是最重要的梯度下降算法,我們?nèi)?
和 的初始值都為1,再進(jìn)行梯度下降過程。def gradient_descent(X, y, alpha):theta = np.array([1, 1]).reshape(2, 1)gradient = gradient_function(theta, X, y)while not np.all(np.absolute(gradient) <= 1e-5):theta = theta - alpha * gradientgradient = gradient_function(theta, X, y)return theta通過該過程,最終求出的
, ,線性回歸的曲線如下附錄 source code
matlab一元函數(shù)的梯度下降程序
clc; close all; clear all; %% delta = 1/100000; x = -1.1:delta:1.1; y = x.^2; dot = [1, 0.2, 0.04, 0.008]; figure;plot(x,y); axis([-1.2, 1.2, -0.2, 1.3]); grid on hold on plot(dot, dot.^2,'r'); for i=1:length(dot)text(dot(i),dot(i)^2,['theta_{',num2str(i),'}']); end title('一元函數(shù)的梯度下降過程');python一元函數(shù)的梯度下降程序
import numpy as np import matplotlib.pyplot as pltdelta = 1/100000 x = np.arange(-1.1, 1.1, delta) y = x ** 2 dot = np.array([1, 0.2, 0.04, 0.008]) plt.figure(figsize=(7,5)) plt.plot(x,y) plt.grid(True) plt.xlim(-1.2, 1.2) plt.ylim(-0.2, 1.3) plt.plot(dot, dot**2, 'r') for i in range(len(dot)):plt.text(dot[i],dot[i]**2,r'$theta_%d$' % i) plt.title('一元函數(shù)的梯度下降過程') plt.show()julia一元函數(shù)的梯度下降程序
using PyPlot delta = 1/100000 x = -1.1:delta:1.1 y = x.^2 dot = [1, 0.2, 0.04, 0.008] plot(x, y) grid(true) axis("tight") plot(dot, dot.^2, color="r") for i=1:length(dot)text(dot[i], dot[i]^2, "$theta_$i$") end title("Single variable function gradient descent")matlab二元函數(shù)的梯度下降程序
pecision = 1/100; [x,y] = meshgrid(-3.1:pecision:3.1); z = x.^2 + y.^2; figure; mesh(x,y,z); dot = [[2,3];[1.6,2.4];[1.28,1.92];[5.09e-10, 7.64e-10]]; hold on scatter3(dot(:,1),dot(:,2),dot(:,1).^2+dot(:,2).^2,'r*'); for i=1:4text(dot(i,1)+0.4,dot(i,2),dot(i,1).^2+0.2+dot(i,2).^2+0.2,['theta_{',num2str(i),'}']); end title('二元函數(shù)的梯度下降過程')python二元函數(shù)的梯度下降程序
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D x = np.linspace(-3.1,3.1,300) y = np.linspace(-3.1,3.1,300) x,y = np.meshgrid(x, y) z = x**2 + y**2 dot = np.array([[2,3],[1.6,2.4],[1.28,1.92],[5.09e-10, 7.64e-10]]) fig = plt.figure(figsize = (10,6)) ax = fig.gca(projection = '3d') cm = plt.cm.get_cmap('YlGnBu') surf = ax.plot_surface(x, y, z, cmap=cm) fig.colorbar(surf,shrink=0.5, aspect=5) ax.scatter3D(dot[:,0], dot[:,1], dot[:,0]**2 + dot[:,1]**2, marker='H',c='r') for i in range(len(dot)-1):ax.text(dot[i,0]+0.4, dot[i,1], dot[i,0]**2 + dot[i,1]**2, r'$Theta_%d$' % i) ax.text(dot[3,0]+0.4, dot[3,1]+0.4, dot[3,0]**2 + dot[3,1]**2-0.4, r'min') plt.show()julia二元函數(shù)的梯度下降程序
這個(gè)圖的text死活標(biāo)不上,希望知道的朋友可以告知一下。再多說一句,雖然我之前出了個(gè)Julia的教程,里面也包含4種繪圖工具(Plots,GR,Gadfly & PyPlot),但沒有畫過3維的圖形,今天為了畫這個(gè)圖可真是費(fèi)盡周折,Julia官網(wǎng)上的3D繪圖的程序基本沒有一個(gè)可以直接使用的,具體的繪圖過程和調(diào)試中碰到的問題我還會(huì)整理篇文章到知乎和公眾號(hào),大家可以看一下。
using Plots Plots.plotlyjs() n = 50 x = range(-3, stop=3, length=n) y= x z = zeros(n,n) for i in 1:n, k in 1:nz[i,k] = x[i]^2 + y[k]^2 endsurface(x, y, z) dot = [[2 3]; [1.6 2.4]; [1.28 1.92]; [5.09e-10 7.64e-10]] scatter!(dot[:,1], dot[:,2], dot[:,1].^2 .+ dot[:,2].^2)matlab梯度下降的線性回歸
m = 18; X0 = ones(m,1); X1 = (1:m)'; X = [X0, X1]; y = [2,3,3,5,8,10,10,13,15,15,16,19,19,20,22,22,25,28]'; alpha = 0.01; theta = gradient_descent(X, y, alpha, m);function [grad_res] = gradient_function(theta, X, y, m)diff = X * theta - y;grad_res = X' * diff / m; endfunction [theta_res] = gradient_descent(X, y, alpha, m)theta = [1;1];gradient = gradient_function(theta, X, y, m);while sum(abs(gradient)>1e-5)>=1theta = theta - alpha * gradient;gradient = gradient_function(theta, X, y, m);endtheta_res = theta; endpython梯度下降的線性回歸
import numpy as np import matplotlib.pyplot as plt # y = np.array([2,3,3,5,8,10,10,13,15,15,16,19,19,20,22,22,25,28]) # x = np.arange(1,len(y)+1) # plt.figure() # plt.scatter(x,y) # plt.grid(True) # plt.show()# sample length m = 18# generate matrix X X0 = np.ones((m, 1)) X1 = np.arange(1, m+1).reshape(m, 1) X = np.hstack((X0, X1))# matrix y y = np.array([2,3,3,5,8,10,10,13,15,15,16,19,19,20,22,22,25,28]).reshape(m,1)# alpha alpha = 0.01def cost_function(theta, X, y):diff = np.dot(X, theta) - yreturn (1./2*m) * np.dot(np.transpose(diff), diff)def gradient_function(theta, X, y):diff = np.dot(X, theta) - yreturn (1./m) * np.dot(np.transpose(X), diff)def gradient_descent(X, y, alpha):theta = np.array([1, 1]).reshape(2, 1)gradient = gradient_function(theta, X, y)while not np.all(np.absolute(gradient) <= 1e-5):theta = theta - alpha * gradientgradient = gradient_function(theta, X, y)return theta[theta0, theta1] = gradient_descent(X, y, alpha) plt.figure() plt.scatter(X1,y) plt.plot(X1, theta0 + theta1*X1, color='r') plt.title('基于梯度下降算法的線性回歸擬合') plt.grid(True) plt.show()julia梯度下降的線性回歸
m = 18 X0 = ones(m,1) X1 = Array(1:m) X = [X0 X1]; y = [2,3,3,5,8,10,10,13,15,15,16,19,19,20,22,22,25,28]; alpha = 0.01; theta = gradient_descent(X, y, alpha, m)function gradient_function(theta, X, y, m)diff = X * theta .- y;grad_res = X' * diff / m; endfunction gradient_descent(X, y, alpha, m)theta = [1,1]gradient = gradient_function(theta, X, y, m)while all(abs.(gradient) .>1e-5)==truetheta = theta - alpha * gradientgradient = gradient_function(theta, X, y, m)endtheta_res = theta end最后附上我出過的免費(fèi)的Julia教學(xué)視頻鏈接:
Julia 教程 從入門到進(jìn)階 - 網(wǎng)易云課堂?study.163.com微信公眾號(hào):Quant_Times
總結(jié)
以上是生活随笔為你收集整理的loss下降auc下降_梯度下降算法 线性回归拟合(附Python/Matlab/Julia源代码)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win10时间和linux不同步时间,u
- 下一篇: python环境配置opencv_Pyt