ML02-邏輯回歸(上部分)

本文主題-邏輯回歸(上部分):

  1. 邏輯回歸的應(yīng)用背景
  2. 邏輯回歸的數(shù)學(xué)基礎(chǔ)
  3. 邏輯回歸的模型與推導(dǎo)
  4. 邏輯回歸算法推導(dǎo)
  5. 梯度下降算法
  6. 邏輯回歸梯度下降算法實(shí)現(xiàn)

一. 線性回歸在分類上存在的問題

  1. 線性回歸的條件

??在上述例子中,我們看到線性回歸可以做預(yù)測(cè),也可以做分類,一切結(jié)果看起來都是很完美。
??線性回歸模型:
??
??y^{(i)}=x^{(i)}W + b^{(i)} + \epsilon^{(i)}
??
??其中\epsilon^{(i)}的推導(dǎo)建立在一個(gè)假設(shè)之上:服從正態(tài)分布(Gaussian Distribution)
??
??p(x)=\dfrac{1}{\sqrt{2\pi} \sigma}exp(-\dfrac{(x- \mu)^2}{2 \sigma^2})????其中:μ表示期望(均數(shù)),σ表示標(biāo)準(zhǔn)差,σ2表示方差
??
??記正態(tài)分布為N(μ,σ) ,標(biāo)準(zhǔn)正態(tài)分布是N( 0,1 )
??
??下面可視化正態(tài)分布:

% matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
#  繪圖的坐標(biāo)軸
figure=plt.figure('正態(tài)分布可視化', figsize=(6, 4))
ax = figure.add_axes([0.1, 0.1, 0.8, 0.8], label='正態(tài)分布函數(shù)曲線')
ax.set_xlabel('x值')
ax.set_ylabel('隨機(jī)值:y')

# 設(shè)置繪制曲線范圍
ax.set_xlim(left=-10,right=10)    # x取值范圍
ax.set_ylim(bottom=0, top=0.5)    # 概率在[0, 1) 之間

# x取值范圍
x=np.linspace( -10 ,10, 100,  dtype=np.float32 )

# 系數(shù)-方差
sigma=1
# 系數(shù)-均值
mu=0

# 正態(tài)分布常數(shù)系數(shù)
coefficient = 1.0 / ( np.sqrt( 2 * np.pi) * sigma )
# 正態(tài)分布指數(shù)
exponent = -(x-mu)**2/(2*sigma**2)

y=coefficient * np.exp( exponent )

ax.plot(x, y,color='r',label='正態(tài)分布曲線')
ax.legend()

figure.show(warn=False)

正態(tài)分布曲線

??正態(tài)分布函數(shù)(概率密度函數(shù))從正無窮到負(fù)無窮積分的概率為1。即頻率的總和為100%
??隨機(jī)正態(tài)分布概率,就是其中一段區(qū)域的積分。

  1. 一個(gè)不適合使用線性回歸分類的例子

??使用隨機(jī)方式構(gòu)造一個(gè)數(shù)據(jù)集

% matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

cls1_data = np.random.uniform(low=10000,high=100000,size=50)
cls1_result = np.ones(shape=(50),dtype=np.int32)

cls2_data = np.random.uniform(low=0,high=30000,size=50)
cls2_result = np.zeros(shape=(50),dtype=np.int32)

# 繪制樣本
figure=plt.figure('用于線性回歸的分類樣本', figsize=(6, 4))
ax = figure.add_axes([0.1, 0.1, 0.8, 0.8], label='2類樣本')
ax.set_xlabel('取值區(qū)間')
ax.set_ylabel('分類:0與1')

# 設(shè)置繪制曲線范圍
ax.set_xlim(left=0,right=100000)    # x取值范圍
ax.set_ylim(bottom=-0.3, top=1.5)    # 概率在[0, 1) 之間

ax.scatter(cls1_data,cls1_result,color='r',marker='.')

ax.scatter(cls2_data,cls2_result,color='b',marker='.')

figure.show(warn=False)

隨機(jī)數(shù)據(jù)集可視化

??使用線性回歸分類

# 采用sklearn模塊來實(shí)現(xiàn)線性回歸
from sklearn.linear_model import *
import numpy as np
x=np.hstack((cls1_data,cls2_data))
y=np.hstack((cls1_result,cls2_result))
x=x.reshape(-1, 1)

regression=LinearRegression()
# 訓(xùn)練
# 數(shù)據(jù)格式整理
# Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample.
# 如果是一維特征,使用reshape處理單特征形狀(-1, 1),如果只有一個(gè)樣本,形狀reshape(1,-1)
regression.fit(x, y)
# 測(cè)試
print('評(píng)估:',regression.score(x, y))
# 斜率
print('斜率:',regression.coef_)
# 截距
print('截距:',regression.intercept_ )

# 使用訓(xùn)練數(shù)據(jù)統(tǒng)計(jì)分類正確率
pre=regression.predict(x)
print(pre)
cls_a=pre[0:50]
cls_a=cls_a>0.5
a_num=cls_a.sum()

# 第二類:后50
cls_b=pre[50:]
cls_b=cls_b<0.5
b_num=cls_b.sum()
# 統(tǒng)計(jì)正確率
a_pct=cls_a.mean()
b_pct=cls_b.mean()
print("A類識(shí)別正確數(shù):%d,識(shí)別正確率:%5.2f%%"%(a_num,a_pct*100))
print("B類識(shí)別正確數(shù):%d,識(shí)別正確率:%5.2f%%"%(b_num,b_pct*100))
# 可視化分類情況
figure=plt.figure('分類情況', figsize=(6, 4))
ax = figure.add_axes([0.1, 0.1, 0.8, 0.8], label='2類樣本')
ax.set_xlabel('取值區(qū)間')
ax.set_ylabel('分類:0與1')

# 設(shè)置繪制曲線范圍
ax.set_xlim(left=0,right=100000)    # x取值范圍
ax.set_ylim(bottom=-0.3, top=1.5)    # 概率在[0, 1) 之間

ax.scatter(cls1_data,cls1_result,color='r',marker='.')

ax.scatter(cls2_data,cls2_result,color='b',marker='.')

ax.plot(x, regression.predict(x),color='y', label='回歸直線')

ax.legend()

figure.show(warn=False)

評(píng)估: 0.555891654577714
斜率: [1.34255212e-05]
截距: 0.01655814267519684
[0.84828292 0.58331511 1.11550652 1.05660159 0.5944528  1.15643254
 1.14064579 0.94602928 0.48950987 0.48060621 0.5319122  0.71212052
 0.50981994 0.7330047  0.62845884 1.21112727 0.54341076 0.21257363
 0.26175963 1.02209569 1.23536988 0.53998925 0.98959512 0.17659679
 0.4907314  0.64503974 0.18405636 0.76383753 0.97628677 1.35292452
 0.20352834 0.98268824 1.06256155 1.32459732 0.99089918 0.46460692
 0.98906349 0.91117129 0.2198635  0.59830641 0.8756055  1.2736329
 0.83592414 1.06118727 0.65489012 0.8660766  0.61240252 1.33904091
 0.47394198 1.02521    0.05723705 0.37106916 0.33210881 0.33587503
 0.19013076 0.24586235 0.36920796 0.14182335 0.37130829 0.25797109
 0.2270329  0.27208044 0.15928228 0.1021966  0.17905334 0.22717218
 0.0948184  0.13249571 0.38909531 0.05946123 0.35638356 0.1328463
 0.0309184  0.41697969 0.08458613 0.11541662 0.08907712 0.02159664
 0.273264   0.13543039 0.27976214 0.38864573 0.02586998 0.35168836
 0.10483192 0.32039087 0.09642115 0.30624559 0.35838634 0.35280365
 0.15571477 0.38641816 0.11186056 0.14146531 0.38562691 0.06455996
 0.23412796 0.22797953 0.38572513 0.25240354]
A類識(shí)別正確數(shù):39,識(shí)別正確率:78.00%
B類識(shí)別正確數(shù):50,識(shí)別正確率:100.00%
隨機(jī)數(shù)據(jù)集的擬合可視化

????明顯的兩類樣本是可分的,使用線性回歸得到的分類效果明顯存在較大誤差。這是因?yàn)槲覀兊臉颖具`背了線性回歸的三個(gè)假設(shè):
??????|-自變量與因變量是線性關(guān)系;
??????|-自變量與誤差項(xiàng)相互獨(dú)立;
??????|-誤差項(xiàng)服從正態(tài)分布;

二、邏輯回歸的數(shù)學(xué)基礎(chǔ)

  1. 從分類開始談起
    ??某個(gè)樣本屬于A類還是B類,從結(jié)果上講就是值為0,還是值為1。但影響這個(gè)分類的是由一些因素決定的。我們從數(shù)學(xué)角度可以使用向量表示這些因素(這些因素就影響某個(gè)樣本屬于A類還是B類):
    ??
    ??x=(x_1,x_2,\dots,x_n)
    ??其中x就是表示一個(gè)樣本,樣本x具有n個(gè)影響分類的特征。如果考慮偏置項(xiàng),則可以增加一個(gè)份量1。
    ??x=(x_1,x_2,\dots,x_n,1)

  2. 建立分類的邏輯模型
    ??我們假設(shè)有兩套標(biāo)準(zhǔn)判定樣本所屬的分類,使用數(shù)學(xué)函數(shù)表示如下:
    ????|-?y_A=f(x) ?樣本x屬于A的可能性;
    ????|-?y_B=g(x) ?樣本x屬于B的可能性;
    ??
    ??這樣我們就可以建立一個(gè)分類模型:
    ??
    ??y=\begin{cases} 1,\quad y_A>y_B\\ 0,\quad y_A\leqslant y_B\\ \end{cases}
    ??
    ??當(dāng)y=1,則樣本x屬于A類;當(dāng)y=0,則樣本x屬于B類;
    ??
    ??可以把上述模型表示為:
    ??
    ??y=\begin{cases} 1,\quad y_A-y_B>0\\ 0,\quad 其他\\ \end{cases}

  1. 分類邏輯模型的概率分析基礎(chǔ)
    ??
    ?? 如果假設(shè)y_A,y_Bx是線性關(guān)系,同時(shí)考慮y_A,y_B的誤差都獨(dú)立服從正態(tài)分布,可以把y_A,y_B表示如下:
    ??
    ??|- y_A=xW_A+\epsilon_A
    ??|- y_B=xW_B+\epsilon_B
    ??
    ??其中\epsilon_A,\epsilon_B是服從獨(dú)立分布的誤差項(xiàng),可以假設(shè)服從正態(tài)分布。
    ??記z=y_A-y_B,則:
    ??|- z=x(W_A-W_B)+(\epsilon_A-\epsilon_B)
    ??
    ??從而分類邏輯模型可以表示如下:
    ??|- y=\begin{cases} 1,\quad z>0\\ 0,\quad 其他\\ \end{cases}
    ??其中W=W_A-W_B,\epsilon=\epsilon_A-\epsilon_B
    ??z=xW+\epsilon
    ??
    ??則樣本X屬于A的概率可以表示為:
    ??|- P(y=1)=P(z>0)=P(xW+\epsilon>0)=P(\epsilon>-xW)
    ??從正態(tài)分布可以繼續(xù)推導(dǎo):
    ??|- P(y=1)=1-P(\epsilon\leqslant-xW)=1-F_{\epsilon}(-xW)
    ??其中F_{\epsilon}是變量\epsilon的累積分布函數(shù);P(y=1)表示樣本屬于A的概率

  2. probit模型
    ??上述推導(dǎo)的公式在學(xué)術(shù)上稱為probit模型,建立的回歸模型也稱proit回歸。
    ??
    ??P(y=1)=1-F_{\epsilon}(-xW)
    ??
    ??F_{\epsilon}(-xW)是正態(tài)分布函數(shù)的累積函數(shù),上述累積分布函數(shù),在服從正態(tài)分布的時(shí)候比較麻煩,因?yàn)檎龖B(tài)分布的累積函數(shù)還沒有解析表達(dá)式能夠表達(dá)。 從而其參數(shù)估計(jì)非常麻煩,如果需要應(yīng)用,則需要簡(jiǎn)化( 做近似處理 )。
    ??為了解決正態(tài)分布累積函數(shù)的問題,正態(tài)分布的累積函數(shù)的計(jì)算居然是通過查表的形式提供運(yùn)算結(jié)果,大家如果想不起,可以查閱自己的高中數(shù)據(jù)或者大學(xué)數(shù)學(xué)書。

  3. 正態(tài)分布的近似處理
    ??正態(tài)分布表示:
    ??p(x)=\dfrac{1}{\sqrt{2\pi} \sigma}exp(-\dfrac{(x-\mu)^2}{2 \sigma^2})????其中:μ表示期望(均數(shù)),σ表示標(biāo)準(zhǔn)差,σ2表示方差
    ??
    ??記正態(tài)分布為N(μ,σ) ,標(biāo)準(zhǔn)正態(tài)分布是N( 0,1 )
    ??
    ?? 我們可以簡(jiǎn)化下正態(tài)分布累積函數(shù)的表示:
    ??F_{\epsilon}(x)=\phi(\dfrac{x-\mu}{\sigma})
    ??因?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=%5Cdfrac%7Bx-%5Cmu%7D%7B%5Csigma%7D" alt="\dfrac{x-\mu}{\sigma}" mathimg="1">是線性,所以只需要考慮標(biāo)準(zhǔn)正態(tài)分布。
    ??在數(shù)學(xué)上存在一個(gè)邏輯分布,與正態(tài)分布非常相似,

  4. 邏輯分布與標(biāo)準(zhǔn)正態(tài)分布
    ??下面使用可視化來認(rèn)識(shí)下邏輯分布函數(shù)與正態(tài)分布函數(shù)的近似度。
    ????|- 正態(tài)分布:p(x)=\dfrac{1}{\sqrt{2\pi}\sigma}exp(-\dfrac{(x-\mu)^2}{2\sigma^2})
    ????|- 邏輯分布:p(x)=\dfrac{e^{-x}}{(1+e^{-x})^2}
    ??
    ??邏輯分布函數(shù)與正態(tài)分布的區(qū)別就在于:邏輯分布有累積函數(shù),其累積函數(shù)如下:
    ????|- 邏輯分布累積函數(shù):S(x)=\dfrac{1}{1+e^{-x}}
    ??
    ??下面是邏輯分布函數(shù),正態(tài)分布函數(shù)的比較:

% matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
#  繪圖的坐標(biāo)軸
figure=plt.figure('正態(tài)分布與邏輯分布', figsize=(10, 4))
ax = figure.add_axes([0.1, 0.1, 0.8, 0.8], label='邏輯分布與正態(tài)分布')
ax.set_xlabel('x值')
ax.set_ylabel('y值')

# 設(shè)置繪制曲線范圍
ax.set_xlim(left=-10,right=10)    # x取值范圍
ax.set_ylim(bottom=0, top=0.5)    # 概率在[0, 1) 之間

# 標(biāo)準(zhǔn)正態(tài)分布函數(shù)--------------------
# x取值范圍
x_n=np.linspace( -10 ,10, 100,  dtype=np.float32 )
# 系數(shù)-方差
sigma=1
# 系數(shù)-均值
mu=0
# 正態(tài)分布常數(shù)系數(shù)
coefficient = 1.0 / ( np.sqrt( 2 * np.pi) * sigma )
# 正態(tài)分布指數(shù)
exponent = -(x_n-mu)**2/(2*sigma**2)
y_n=coefficient * np.exp( exponent )
ax.plot(x_n, y_n,color='r',label='正態(tài)分布')
# 邏輯分布函數(shù)--------------------
x_l=np.linspace( -10 ,10, 100,  dtype=np.float32 )
y_l=np.exp( -x_l ) / ( 1 + np.exp( -x_l ) )**2
ax.plot(x_l, y_l,color='b',label='邏輯分布')

ax.legend()

figure.show(warn=False)


正態(tài)分布與邏輯分布比較
  1. 邏輯分布與標(biāo)準(zhǔn)正態(tài)分布的累積函數(shù)
    ??標(biāo)準(zhǔn)正態(tài)分布沒有累積函數(shù),所以我們采用scipy的積分函數(shù)來繪制。
    ??使用積分表示正態(tài)分布累積函數(shù)的公式如下:
    ????|- F_{\epsilon}(x)=\int_{-\infty}^{x}\dfrac{1}{\sqrt{2\pi}\sigma}exp(-\dfrac{(t-\mu)^2}{2\sigma^2})\mathrmu0z1t8os t,
% matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import scipy.integrate as integrate

#  定義正態(tài)函數(shù),用于積分運(yùn)算
def  normal(t,m,s):
    # 系數(shù)-方差
    sigma=s
    # 系數(shù)-均值
    mu=m
    # 正態(tài)分布常數(shù)系數(shù)
    coefficient = 1.0 / ( np.sqrt( 2 * np.pi) * sigma )
    # 正態(tài)分布指數(shù)
    exponent = -(t-mu)**2/(2*sigma**2)
    re=coefficient * np.exp( exponent )
    return re

def cumulative(x):
    re=integrate.quad(     
        normal,         # 積分函數(shù)
        -np.inf,         # 積分下限
        x,              # 積分上限
        args=(0.0, 1.0)   # 傳遞給函數(shù)的參數(shù)(除第一個(gè)參數(shù)外,按照順序來)
    )
    return re[0]     #第一個(gè)是積分,第二個(gè)是誤差上限

#  繪圖的坐標(biāo)軸
figure=plt.figure('正態(tài)分布與邏輯分布', figsize=(10, 4))
ax = figure.add_axes([0.1, 0.1, 0.8, 0.8], label='邏輯分布與正態(tài)分布')
ax.set_xlabel('x值')
ax.set_ylabel('y值')

# 設(shè)置繪制曲線范圍
ax.set_xlim(left=-10,right=10)    # x取值范圍
ax.set_ylim(bottom=-0.1, top=1.1)    # 概率在[0, 1) 之間

# 標(biāo)準(zhǔn)正態(tài)分布函數(shù)--------------------
# x取值范圍
x_n=np.linspace( -10 ,10, 100,  dtype=np.float32 )
y_n=[cumulative(x) for  x in x_n ]
ax.plot(x_n, y_n,color='r',label='正態(tài)分布累積函數(shù)')
# 邏輯分布函數(shù)--------------------
x_l=np.linspace( -10 ,10, 100,  dtype=np.float32 )
y_l=1.0 / ( 1 + np.exp( -x_l ) )
ax.plot(x_l, y_l,color='b',label='邏輯分布累積函數(shù)')

ax.legend()
ax.grid(b=True)

figure.show(warn=False)
邏輯分布與正態(tài)分布的累積函數(shù)曲線
  1. 最佳的邏輯分布
    ??如果邏輯分布參數(shù)做一些調(diào)整,可以最佳接近。下面是最佳邏輯分布累積函數(shù)表示:
    ????|- S(x)=\dfrac{1}{1+e^{-1.702x}}
    ??下面是可視化后的直觀效果。
% matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import scipy.integrate as integrate

#  定義正態(tài)函數(shù),用于積分運(yùn)算
def  normal(t,m,s):
    # 系數(shù)-方差
    sigma=s
    # 系數(shù)-均值
    mu=m
    # 正態(tài)分布常數(shù)系數(shù)
    coefficient = 1.0 / ( np.sqrt( 2 * np.pi) * sigma )
    # 正態(tài)分布指數(shù)
    exponent = -(t-mu)**2/(2*sigma**2)
    re=coefficient * np.exp( exponent )
    return re

def cumulative(x):
    re=integrate.quad(     
        normal,         # 積分函數(shù)
        -np.inf,         # 積分下限
        x,              # 積分上限
        args=(0.0, 1.0)   # 傳遞給函數(shù)的參數(shù)(除第一個(gè)參數(shù)外,按照順序來)
    )
    return re[0]     #第一個(gè)是積分,第二個(gè)是誤差上限

#  繪圖的坐標(biāo)軸
figure=plt.figure('正態(tài)分布與邏輯分布', figsize=(10, 4))
ax = figure.add_axes([0.1, 0.1, 0.8, 0.8], label='邏輯分布與正態(tài)分布')
ax.set_xlabel('x值')
ax.set_ylabel('y值')

# 設(shè)置繪制曲線范圍
ax.set_xlim(left=-10,right=10)    # x取值范圍
ax.set_ylim(bottom=-0.1, top=1.1)    # 概率在[0, 1) 之間

# 標(biāo)準(zhǔn)正態(tài)分布函數(shù)--------------------
# x取值范圍
x_n=np.linspace( -10 ,10, 100,  dtype=np.float32 )
y_n=[cumulative(x) for  x in x_n ]
ax.plot(x_n, y_n,color='r',label='正態(tài)分布累積函數(shù) $F_{\epsilon}(x)=\int_{-\infty}^{x}\dfrac{1}{\sqrt{2\pi}\sigma}exp(-\dfrac{(t-\mu)^2}{2\sigma^2})\mathrmu0z1t8os t$')
# 邏輯分布函數(shù)--------------------
x_l=np.linspace( -10 ,10, 100,  dtype=np.float32 )
y_l=1.0 / ( 1 + np.exp( -1.702*x_l ) )
ax.plot(x_l, y_l,color='b',label='邏輯分布累積函數(shù)  $S(x)=\dfrac{1}{1+e^{-1.702x}}$ ')

ax.legend()
ax.grid(b=True)

figure.show(warn=False)
邏輯分布與正態(tài)分布累積函數(shù)的最佳逼近1.702

9.sigmoid函數(shù)
??S(x)=\dfrac{1}{1+e^{-1.702x}} 就是鼎鼎大名的sigmoid函數(shù),該函數(shù)具備許多良好的性質(zhì)。尤其是深度學(xué)習(xí)中的大殺器!經(jīng)常會(huì)用到。
??函數(shù)的特點(diǎn):
????|- 函數(shù)的導(dǎo)數(shù)可以用自身表示: S^\prime(x)=S(x)(1-S(x))
????|- 連續(xù)處處可微
????|- 值在[0,1)范圍
????|- 單調(diào)遞增
????|- 非線性
????|- 平滑性
????|- 原點(diǎn)附近近似identity(f(x)≈x)或者先線性性。
??函數(shù)的缺點(diǎn):
????|- 運(yùn)算量大(后面使用梯度下降算法可以提現(xiàn)出來,尤其誤差傳遞的時(shí)候)
????|- 容易出現(xiàn)梯度消失的情況,從而不利于樣本訓(xùn)練,甚至完不成梯度訓(xùn)練。(大家可以從邏輯分布函數(shù)看得出來,sigmoid函數(shù)的導(dǎo)數(shù)就是邏輯分布函數(shù),邏輯分布函數(shù)從0開始,就逐步趨向于0,容易產(chǎn)生梯度消失)

三、邏輯回歸模型與模型推導(dǎo)

  1. 邏輯回歸模型
    ??從上述邏輯分布與正態(tài)分布的相似性,可以得到邏輯回歸模型:
    ??
    ????|- (1)proit回歸模型: p(y=1)=1-F_{\epsilon}(-xW)
    ????|- (2)正態(tài)分布簡(jiǎn)寫模型:F_{\epsilon}(x)=\phi(\dfrac{x-\mu}{\sigma}) \qquad\to\qquad F_{\epsilon}(\sigma x+\mu)=\phi(x) \approx S(1.702x)
    ??
    ??在porit回歸模型基礎(chǔ)上,簡(jiǎn)單推導(dǎo),可以定義如下模型:
    ???? |- p(y=1) =\dfrac{1}{1+e^{-xW}}
    ????上上述公式就是邏輯回歸模型(省略了具體的推導(dǎo)還有一部分假設(shè))。

  2. 發(fā)生比
    ?? 我們可以定義\dfrac{p(y=1)}{1-p(y=1)}為發(fā)生比。 然后簡(jiǎn)單取自然對(duì)數(shù),得到如下公式:
    ?? ln \dfrac{p(y=1)}{1-p(y=1)}=xW
    ??
    ?? 邏輯回歸是建立在一個(gè)假設(shè)之上:事件發(fā)生比實(shí)際上是一個(gè)線性模型

  3. 似然函數(shù)
    ??邏輯回歸的算法還是要從模型參數(shù)的估計(jì)開始。
    ??從統(tǒng)計(jì)來說,數(shù)據(jù)出現(xiàn)的概率越大越好,這就是最大似然估計(jì)法,由于數(shù)據(jù)的取值是離散的0,1,從而數(shù)據(jù)取值的概率分布函數(shù)可以表示為(這里用到了二項(xiàng)分布概率累積函數(shù)的計(jì)算方法):
    ????|- p(y)={p(y=1)}^{y}{p(y=0)}^{1-y}
    ??取自然對(duì)數(shù):
    ????|-ln\ p(y)=y\ ln\ p(y=1) + (1-y)\ ln\ (1- p(y=1))
    ??
    ??考慮所有樣本,而且每個(gè)樣本獨(dú)立,所以可以對(duì)所有樣本形成下面公式:
    ????|-p(Y)=\prod\limits_ip(y_i) 其中i表示遍歷所有樣本,y_i表示其中第i個(gè)樣本。 ??
    ??把所有樣本的概率分布函數(shù)展開:
    ????|-p(Y)=\prod\limits_i {p(y_i=1)}^{y_i}{p(y_i=0)}^{1-y_i}
    ??替換為概率分布函數(shù):sigmoid函數(shù),可以得到如下公式:
    ????|-p(Y)=\prod\limits_i {h(X_i)}^{y_i}{(1-h(X_i))}^{1-y_i}
    ??????其中h(X_i)表示sigmoid函數(shù)h(X_i) =\dfrac{1}{1+e^{-X_iW}} ,X_i表示第i個(gè)樣本。
    ??上述公式就是W的似然函數(shù),可以更加明確的按照條件概率方式記為:
    ????|-L(W)=p(Y|W)=\prod\limits_i {h(X_i)}^{y_i}{(1-h(X_i))}^{1-y_i}

  4. 參數(shù)估計(jì)公式推導(dǎo)
    ??使用最大似然估計(jì)法,可以得到W的參數(shù)估計(jì)公式(求對(duì)數(shù)):
    ????|- l(W)=ln(L(W))=\sum\limits_{i}y_i\ ln(h(X_i)) +(1-y_i)\ln(1-h(X_i))

  5. 機(jī)器學(xué)習(xí)的損失函數(shù)定義
    ??由于使似然函數(shù)值最大,相反考慮,定義損失函數(shù)如下:
    ????Loss= - ln(L(W))=-l(W)
    ??這樣就使得問題編程求最小值,我們可以定義成邏輯回歸模型的損失函數(shù)。使用算法找到Loss的最小值即可。

四、邏輯回歸模型定義

  1. 決策函數(shù)
    ?? y_i=S(X_iW)
    ??
    ?? 其中S(x)= \dfrac{1}{1+e^{-x}}是sigmoid函數(shù)
    ?? 其中X_i=(x_1,x_2,\dots,x_n,1)是第i個(gè)樣本數(shù)據(jù)。
    ?? 其中W是樣本的線性系數(shù),也可以理解成樣本特征的重要性加權(quán)。

  2. 機(jī)器學(xué)習(xí)中的誤差定義
    ?? Loss=J(W)=-l(W)=-ln(L(W))=-\sum\limits_{i}y_i\ ln(h(X_i)) +(1-y_i)\ln(1-h(X_i))
    ??上述公式被稱為交叉熵(Cross Entropy)
    ??其中h(X_i)=S(X_iW)= \dfrac{1}{1+e^{-X_iW}}

五、邏輯回歸的算法推導(dǎo)

??邏輯回歸最終還是找到一個(gè)W,使得分類誤差最小,也就是使得損失函數(shù)最小,所以邏輯回歸屬于于廣義線性回歸的一種。
??邏輯回歸算法也是找到一個(gè)W,使得對(duì)所有樣本J(W)函數(shù)的值最小, 由于考慮問題的思路不同,這里的J(W)不再像線性回歸函數(shù)那樣:通過推導(dǎo)直接得到W的求解公式。
??下面我們嘗試使用求導(dǎo)的方式,來推導(dǎo)能否求解&J(W)&的最小值,從而得到W的解。

??推導(dǎo)前的一個(gè)已知知識(shí):sigmoid函數(shù)(也稱S曲線函數(shù))有一個(gè)顯著特性就是其導(dǎo)數(shù)可以使用自身表示。
????|- S^\prime(x)=S(x)(1-S(x))

  1. 求偏導(dǎo)數(shù)

\nabla_W J(W)=\nabla_W(-\sum\limits_{i}y_i\ ln(h(X_i)) +(1-y_i)\ln(1-h(X_i)))

\nabla_W J(W)=\dfrac{\partial J(W)}{\partial W}=-\sum\limits_i (\dfrac{y_i}{h(X_i)} + \dfrac{1-y_i}{1-h(Xi)} ) \dfrac{\partial h(X_i)}{\partial W}

\nabla_W J(W)=-\sum\limits_i (\dfrac{y_i}{h(X_i)} + \dfrac{1-y_i}{1-h(Xi)} ) (h(X_i)(1-h(X_i))) \dfrac{\partial X_iW)}{\partial W}

??上述推導(dǎo)基于一個(gè)數(shù)學(xué)知識(shí):鏈?zhǔn)角笃珜?dǎo)公式。下面繼續(xù)推導(dǎo):

\nabla_W J(W)=-\sum\limits_i (y_i(1-h(X_i)) - (1-y_i)h(X_i) ) X_i

??上述公式注意最后的推導(dǎo),我們直接采用了向量求導(dǎo),直接得到X_i。
??下面對(duì)前面幾項(xiàng)做多項(xiàng)式拆分,得到如下公式:

\nabla_W J(W)=-\sum\limits_i (y_i- y_i\ h(X_i) + y_i\ h(X_i) -h(X_i) ) X_i
\nabla_W J(W)=-\sum\limits_i (y_i -h(X_i) ) X_i
\nabla_W J(W)=\sum\limits_i (h(X_i)-y_i ) X_i

  1. 求解W
    ??按照原來的套路,利用極值求解W,由于其中h(X_i)是一個(gè)指數(shù)函數(shù),加上求和等線性因素,上述公式按照導(dǎo)數(shù)=0的方式求解非常麻煩,應(yīng)該說無法使用公式推導(dǎo)求的W的值。 下面我們來回顧下,數(shù)學(xué)中求極值算法。

  2. 從最大似然函數(shù)的推導(dǎo)結(jié)果看問題
    ??最大似然函數(shù)
    ????|-均方差(損失函數(shù))
    ??????|-線性(Closed-Form)
    ????????|-最小二乘法
    ??????|-非線性
    ????????|-梯度下降法
    ????????|-牛頓迭代法
    ????????|-擬牛頓法
    ????????|-坐標(biāo)下降法
    ????|-交叉熵(損失函數(shù))
    ??????|-非線性
    ????????|-梯度下降法
    ????????|-牛頓迭代法
    ????????|-擬牛頓法
    ????????|-坐標(biāo)下降法

??從機(jī)器學(xué)習(xí)的角度,通過建模的模型分析,得到一個(gè)評(píng)估學(xué)習(xí)模型好壞的標(biāo)準(zhǔn)-損失函數(shù),然后建立訓(xùn)練目標(biāo)。
??其中損失函數(shù)一般是損失最小,為了使得損失函數(shù)最小,就需要各種算法。
??下面列出在不同模型中常用的損失函數(shù)(后面逐步講解每個(gè)損失函數(shù)的來源)
??
??梯度下降法:
????|-全梯度下降法 (FG)
????|-隨機(jī)梯度下降算法 (SG)
????|-隨機(jī)平均梯度下降算法 (SAG)
????|-小批量梯度下降算法 (mini-bantch)
????|-隨機(jī)方差縮減法( SAGA)(STOCHASTIC VARIANCE REDUCTION METHODS)

  1. 常見的損失誤差:
    ??|-1. 鉸鏈損失(Hinge Loss):主要用于支持向量機(jī)(SVM) 中;
    ??|-2. 互熵?fù)p失 (Cross Entropy Loss,Softmax Loss ):用于Logistic 回歸與Softmax 分類中;
    ??|-3. 平方損失(Square Loss):主要是最小二乘法(OLS)中;
    ??|-4. 指數(shù)損失(Exponential Loss) :主要用于Adaboost 集成學(xué)習(xí)算法中;
    ??|-5. 其他損失(如0-1損失,絕對(duì)值損失)

六、梯度下降算法

  1. 梯度下降算法的前置條件
    ??|-梯度下降就是讓一個(gè)損失函數(shù)最小,所以梯度下降首先需要一個(gè)損失函數(shù)。
    ??|-梯度下降使得損失函數(shù)最小, 必須是因?yàn)槟硞€(gè)量,在我們的機(jī)器學(xué)習(xí)中, 這個(gè)量都是特征(X_i)權(quán)重的影響量; 在線性回歸與邏輯回歸中就是線性系數(shù)W。

??(1)線性回歸中,損失函數(shù)是:
????|-J(W)=\dfrac{1}{2}\sum\limits_{i=1}^{m}(x^{(i)}W-y^{(i)})^2
??(2)邏輯回歸中,損失函數(shù)是:
????|- J(W)=-l(W)=-ln(L(W))=-\sum\limits_{i}y_i\ ln(h(X_i)) +(1-y_i)\ln(1-h(X_i))
??????|-上述公式被稱為交叉熵(Cross Entropy)
??????|-其中h(X_i)=S(X_iW)= \dfrac{1}{1+e^{-X_iW}}

  1. 梯度下降的數(shù)學(xué)極值與凸優(yōu)化理論
    ??求最小值,大家第一個(gè)想到的就是極值定理。
    ????|-極大值與極小值就是函數(shù)在其定義域的某些局部區(qū)域所達(dá)到的相對(duì)最大值或相對(duì)最小值。當(dāng)函數(shù)在其定義域的某一點(diǎn)的值大于該點(diǎn)周圍 任何點(diǎn)的值時(shí),稱函數(shù)在該點(diǎn)有極大值; 當(dāng)函數(shù)在其定義域的某一點(diǎn)的值小于該點(diǎn)周圍任何點(diǎn)的值時(shí), 稱函數(shù)在該點(diǎn)有極小值。這里的極大和極小只具有局部意義。
    ????|-極值點(diǎn):極值點(diǎn)只能在函數(shù)不可導(dǎo)的點(diǎn)或?qū)?shù)為零的點(diǎn)上取得。

?? ??極值定理

對(duì)于一元可微函數(shù)??(??),它在某點(diǎn)x0有極值的充分必要條件是??(??)在??0的某鄰域上一階可導(dǎo),在??0處二階可導(dǎo),且??'(??0)=0,??' '(??0)≠0,那么:

       1)若??' '(??0)<0,則f在x0取得極大值;

       2)若??' '(??0)>0,則f在x0取得極小值。

求解極值,直接解?? ' (??0)=0方程,可以得到極值點(diǎn)。

??????最值與極值
??????因?yàn)闃O值是局部意義上的,最值是全局意義上的;在算法過程中,容易導(dǎo)致求出的極值在局部最大,在全局不是最大。為了保證極值就是最值,需要函數(shù)滿足凸性。

??????凸集

??對(duì)于集合X滿足:任給的x,y∈X,總有λx+(1?λ)y∈X,對(duì)于任意的λ∈(0,1),我們稱X是凸集。

?? ????凸函數(shù)

??對(duì)于一個(gè)函數(shù)f(x),滿足:任給的x,y∈XX是函數(shù)定義域)??傆?img class="math-inline" src="https://math.jianshu.com/math?formula=f(%CE%BBx%2B(1%E2%88%92%CE%BB)y))%E2%89%A4%CE%BBf(x)%2B(1%E2%88%92%CE%BB)f(y)" alt="f(λx+(1?λ)y))≤λf(x)+(1?λ)f(y)" mathimg="1">,對(duì)于任意的λ∈(0,1),我們稱f(x)為凸函數(shù)。
??換成幾何描述就是,函數(shù)的幾何圖形中任意兩個(gè)點(diǎn)的連線上的點(diǎn)都在函數(shù)的幾何圖形中。

  1. 均方差函數(shù)的可視化
    ??均方差函數(shù)本身是凸的, 如果從權(quán)重考慮,則發(fā)現(xiàn)該函數(shù)在邏輯回歸中是非凸的。
    ??從輸出的圖形來看是凸的。
%  matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure('3D可視化',figsize=(8,6))
# 創(chuàng)建3D圖形
# 方式一:
# ax = Axes3D(fig)
# 方式二:
ax = fig.add_subplot(111, projection='3d')
# J(W)對(duì)多個(gè)樣本繪制
# 年齡
x = np.loadtxt('ex2x.dat')
# 身高
y = np.loadtxt('ex2y.dat')


w = np.arange(-2, 2, 0.02)
b = np.arange(-2, 2, 0.02)
w, b = np.meshgrid(w, b)    # x-y 平面的網(wǎng)格

z=0
for i in range(len(x)):
    z += ( ( x[i]*w + b - y[i])**2 ) 
z/=len(x)

# rstride:行之間的跨度  cstride:列之間的跨度
ax.plot_surface(w, b, z, rstride=1, cstride=1, cmap=plt.get_cmap('rainbow'),label='三維拋物面')
# 設(shè)置圖像z軸的顯示范圍,x、y軸設(shè)置方式相同
#ax.set_xlim(-2,2)
#ax.set_ylim(-2,2)
#ax.set_zlim(0,4)

plt.show()


均方差函數(shù)的3D可視化
  1. 均方差采用S曲線函數(shù)輸出的可視化
    ??從輸出的圖形來看,非凸,所以在邏輯回歸的損失函數(shù),采用均方差公式訓(xùn)練會(huì)存在錯(cuò)誤收斂的問題。
%  matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm

fig = plt.figure('3D可視化',figsize=(8,6))
# 創(chuàng)建3D圖形
# 方式一:
# ax = Axes3D(fig)
# 方式二:
ax = fig.add_subplot(111, projection='3d')
# J(W)對(duì)多個(gè)樣本繪制
cls1_data = np.random.uniform(low=0,high=100,size=50)
cls1_result = np.ones(shape=(50),dtype=np.int32)

cls2_data = np.random.uniform(low=0,high=3,size=50)
cls2_result = np.zeros(shape=(50),dtype=np.int32)

x=np.hstack((cls1_data,cls2_data))
y=np.hstack((cls1_result,cls2_result))

w = np.arange(-1, 1, 0.04)
b = np.arange(-1, 1, 0.04)
w, b = np.meshgrid(w, b)    # x-y 平面的網(wǎng)格


s=lambda  p: 1.0/(1+np.exp(-p))

z=0
for i in range(len(x)):
    z += ( ( s(x[i]*w + b) - y[i] )**2 ) 
z/=len(x)
    
# rstride:行之間的跨度  cstride:列之間的跨度
ax.plot_surface(w, b, z, rstride=1, cstride=1, cmap=plt.get_cmap('rainbow'),label='三維拋物面')

#等高線繪制(直觀想象3D圖形)
cset = ax.contour(w, b, z, zdir='z', offset=-0.2, cmap=cm.coolwarm)
cset = ax.contour(w, b, z, zdir='x', offset=-1, cmap=cm.coolwarm)
cset = ax.contour(w, b, z, zdir='y', offset=1, cmap=cm.coolwarm)

ax.set_xlim(-1.1,1.1)
ax.set_xlim(-1.1,1.1)
ax.set_zlim(-0.2,0.6)
plt.show()


采用S曲線的均方差3D可視化
  1. 交叉熵函數(shù)的可視化
    ??J(W)=-ln(L(W))=-\sum\limits_{i}y_i\ ln(h(X_i)) +(1-y_i)\ln(1-h(X_i))
    ????|-其中h(X_i)=S(X_iW)= \dfrac{1}{1+e^{-X_iW}}
    ??
    ??在下面例子中,為了避免計(jì)算精度產(chǎn)生的問題,我們對(duì)樣本數(shù)據(jù)同比縮小,限制在0.1之間(一種正則化思維),這樣可以避免數(shù)據(jù)計(jì)算溢出的問題(無窮大與無窮小的問題)
    ?? 從下面可視化效果上,看的出損失函數(shù)是凸的。實(shí)際上從數(shù)學(xué)推理上也可以證明,上面的公式非凸,這個(gè)公式是凸的。
%  matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm

fig = plt.figure('3D可視化',figsize=(8,6))
# 創(chuàng)建3D圖形
# 方式一:
# ax = Axes3D(fig)
# 方式二:
ax = fig.add_subplot(111, projection='3d')
# J(W)對(duì)多個(gè)樣本繪制
cls1_data = np.random.uniform(low=0.0,high=1.0,size=50)
cls1_result = np.ones(shape=(50),dtype=np.float32)

cls2_data = np.random.uniform(low=0.01,high=0.04,size=50)
cls2_result = np.zeros(shape=(50),dtype=np.float32)

x=np.hstack((cls1_data,cls2_data))
y=np.hstack((cls1_result,cls2_result))

w = np.arange(-1, 1, 0.04,dtype=np.float64)
b = np.arange(-1, 1, 0.04,dtype=np.float64)
w, b = np.meshgrid(w, b)    # x-y 平面的網(wǎng)格

s=lambda  p: 1.0/(1.0+np.exp(-p))

for i in range(len(x)):
    z+=y[i]*np.log(s(x[i]*w+b))+(1.0-y[i])*(np.log(1.0-s(x[i]*w+b)))
z=-z
z/=len(x)

# rstride:行之間的跨度  cstride:列之間的跨度
ax.plot_surface(w, b, z, rstride=1, cstride=1, cmap=plt.get_cmap('rainbow'),label='三維拋物面')

#等高線繪制(直觀想象3D圖形)
cset = ax.contour(w, b, z, zdir='z', offset=0.5, cmap=cm.coolwarm)
cset = ax.contour(w, b, z, zdir='x', offset=-1.1, cmap=cm.coolwarm)
cset = ax.contour(w, b, z, zdir='y', offset=1.1, cmap=cm.coolwarm)

ax.set_xlim(-1.1,1.1)
ax.set_xlim(-1.1,1.1)
ax.set_zlim(0.5,1)

plt.show()


交叉熵3D可視化
  1. 交叉熵函數(shù)凸性證明
    ??為了證明交叉熵函數(shù)是凸的,只需要求二階導(dǎo)數(shù)就可以(這里用到凸優(yōu)定理):
    ??上面已經(jīng)求出一階導(dǎo)數(shù):\nabla_W J(W)=\sum\limits_i (h(X_i)-y_i ) X_i
    ????|-\dfrac{\partial^2J(w)}{\partial{W}\partial{W^T}}=\dfrac{\partial{\sum\limits_i (h(X_i)-y_i ) X_i}}{\partial{W^T}}
    ????|-\dfrac{\partial^2J(w)}{\partial{W}\partial{W^T}}=\sum\limits_i {\dfrac{\partial{(h(X_i)-y_i)}}{\partial{W^T}}X_i }
    ????|-\dfrac{\partial^2J(w)}{\partial{W}\partial{W^T}}=\sum\limits_i {\dfrac{\partial{(h(X_i)-y_i)}}{\partial{W^T}}X_i }
    ????|-\dfrac{\partial^2J(w)}{\partial{W}\partial{W^T}}=\sum\limits_i {\dfrac{\partial{h(X_i)}}{\partial{W^T}}X_i }
    ????|-\dfrac{\partial^2J(w)}{\partial{W}\partial{W^T}}=\sum\limits_i {\dfrac{e^{X_iW}{X_i}^T}{{(1+e^{X_iW})}^2}X_i}
    ????|-\dfrac{\partial^2J(w)}{\partial{W}\partial{W^T}}=\sum\limits_i {\dfrac{e^{X_iW}}{{(1+e^{X_iW})}^2}{X_i}^T X_i} ??
    ??由于\dfrac{\partial^2J(w)}{\partial{W}\partial{W^T}}是半負(fù)定矩陣,所以L(W)是凸函數(shù),有最小值。
  1. 最小值梯度下降求解
    ?? 由于J(W)函數(shù)我們從可視化直觀觀察,還是通過數(shù)學(xué)證明,都知道是凸函數(shù),并具有最小值( 注意對(duì)似然函數(shù)來講是最大值,我們添加了一個(gè)負(fù)號(hào)- )。 由于難以使用公式符號(hào)推導(dǎo)求解,所以這里采用梯度下降求解。
    ?? 梯度下降求解的原理
    ?? ?? |-(1)取一個(gè)初始隨機(jī)W(這里包含偏置項(xiàng));
    ?? ?? |-(2)根據(jù)邏輯回歸模型的決策函數(shù)y_i=S(X_iW) 計(jì)算出預(yù)測(cè)值;
    ?? ?? |-(3)如果預(yù)測(cè)值實(shí)際值有差異,則調(diào)整W的值;
    ?? ?? |-(4)調(diào)整值一定要往最小值點(diǎn)方向調(diào)整
    ?? ?? |-(5)n次以后,我們可以認(rèn)為W是使得損失函數(shù)最小的穩(wěn)定值。
  1. 梯度下降的方向與速度
    ??
    ?? 梯度下降的方向
    ????怎么保證調(diào)整的值是往最小值方向調(diào)整的呢? 用下圖的拋物線(凸函數(shù))來充分說明梯度方向的選擇(最小值情況)。
    ??????|- 為了趨向最小值點(diǎn),在最小值左邊應(yīng)該是增加W,在最小值右邊應(yīng)該是減少W(W是x軸)
    ??????|- 如果去J(W)的導(dǎo)數(shù)作為W的調(diào)整值,就可以很方便地決定方向,因?yàn)樵谧钚≈底筮厡?dǎo)數(shù)為負(fù),載最小值右邊導(dǎo)數(shù)為正。
    ??????|- 如果取導(dǎo)數(shù)作為調(diào)整值,則最小值左邊減去導(dǎo)數(shù)值(W增加),最小值右邊加上導(dǎo)數(shù)值(W減少)。
    ??
    ?? 梯度下降的速度
    ????從下圖可以看見,如果W的值調(diào)整過大,在最值點(diǎn)會(huì)擺動(dòng)很大,導(dǎo)致無法準(zhǔn)確得到最好的W,為了控制在最小值點(diǎn)擺動(dòng)產(chǎn)生的過擬合,可以對(duì)調(diào)整值加上一個(gè)參數(shù)\eta來控制。
    ??????|-參數(shù)\eta越大,訓(xùn)練速度快,取得的訓(xùn)練值容易過擬合。
    ??????|-參數(shù)\eta越小,訓(xùn)練速度慢,容易取得最好訓(xùn)練值。
%  matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure('梯度下降說明',figsize=(8,6))
ax = fig.add_subplot(111,label='梯度下降說明',xlabel='X-軸(W值)',ylabel='Y-軸(損失值:$J(W)$)')
x = np.linspace(-2.0, 2.0, 20)
y = x**2
ax.plot(x, y,label='二次凸曲線',color=(1,0,0,1),marker='.',markersize=10,markerfacecolor=(0,0,1,1),markeredgecolor=(0,0,1,1))
for i in range(9):
    ax.arrow(x=x[i],y=y[i],dx=x[i+1]-x[i],dy=y[i+1]-y[i],width=0.02,color=(0,0,0,1) ,head_width=0.1,head_length=0.05)

plt.show()
梯度下降示意圖

實(shí)現(xiàn)部分,限于篇幅,請(qǐng)閱讀下部分

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容