1. 程式人生 > >ml課程:線性迴歸、邏輯迴歸入門(含程式碼實現)

ml課程:線性迴歸、邏輯迴歸入門(含程式碼實現)

以下是我的學習筆記,以及總結,如有錯誤之處請不吝賜教。

本文主要介紹簡單的線性迴歸、邏輯迴歸先關推倒,以及案例程式碼。

昨天做專案發現K-means都忘了,想想之前很多基礎都忘了,於是決定重新開始學一遍ml的基礎內容,順便記錄一下,也算是梳理自己的知識體系吧。

機器學習:目前包括有監督、無監督、強化學習三個大的方向,昨天說過了,就不詳細展開。

幾個基本概念

資料集,樣本(samples)、特徵(features)、標籤(labels)、輸入空間、特徵空間(feature vector),輸出空間,如下圖。

 

下面開始講重點:線性迴歸和邏輯迴歸。

在說這兩個初級演算法之前,首先要知道演算法包含的三個基本模組:目標函式、損失函式、優化演算法。

線性迴歸:

簡單說就是我們都學過的,線性方程:y=kx+b,輸入一個x,得到一個y。

那麼我們將它寫成向量形式更好計算:

因此它的目標函式就是:

損失函式:是最簡單的平方損失,即:預測點與實際點的差值平方/樣本點個數。具體表示為:

其中:\Theta為權重,_{h\Theta}表示預測值,y表示實際值,m表示樣本點個數,除以2是為了方便計算求導。

由於該損失函式為凸函式:

(二元情況)

(多元情況)

因此得到其優化函式為:梯度下降,即Gradient descent,沿梯度下降的方向逐漸減小其損失。為什麼不直接對原方程求逆舉證呢?因為第一計算資源有限,第二是因為有些矩陣並沒有逆矩陣,因此我們用了這種啟發式的函式。

函式形式如下:

其中:\alpha表示學習率,即選擇下降步子的大小,負號表示按照梯度下降方向。

(二元情況)

(多元情況)

這裡還有一個正則化的問題:現實中我們處理的資料可能特徵會很多,因此我們的模型可能會遇到以下兩個問題:

  • 欠擬合

  • 過擬合

一般情況下,我們遇到的都是過擬合現象,因為目前有很多高階的演算法可以擬合出任何想要的曲線空間。所以我們加入正則化:

其中:\lambda表示正則化的權重,權重過小無法限制過擬合的情況,過大則會限制函式的擬合能力,下面程式碼階段會舉例說明。

線性迴歸實現核心程式碼

# 計算損失函式
def computeCost(X, y, theta=[[0],[0]]):
    m = y.size
    J = 0
    
    h = X.dot(theta)
    
    J = 1.0/(2*m)*(np.sum(np.square(h-y)))
    
    return J

# 梯度下降
def gradientDescent(X, y, theta=[[0],[0]], alpha=0.01, num_iters=1500): #學習率設定為0.01
    m = y.size
    J_history = np.zeros(num_iters)
    
    for iter in np.arange(num_iters):
        h = X.dot(theta)
        theta = theta - alpha*(1.0/m)*(X.T.dot(h-y))
        J_history[iter] = computeCost(X, y, theta)  #返回損失函式
    return(theta, J_history)

具體程式碼可以看我之前碼過得:python簡單實現線性迴歸案例

邏輯迴歸:

邏輯迴歸名字及中是迴歸,其實是用來做分類,用來預測概率。

目標函式:sigmod函式,g_{z}=\frac{1}{(1+e^{-z})}。將y=kx+b閾值為(-\infty,+\infty)對映到(0,1)之間的概率,因為sigmod函式擁有很好的數學特性,g^{'}=g_{z}(1-g_{z})

損失函式:log損失函式,由於平方損失在sigmod上為非凸函式,且由於目標函式h_{\Theta }(x)為一個p概率範圍在(0,1)之間的數,我們想要得到p越大越好,就是-p越小越好,但是我們要對p求乘積時越來越小,因此我們加入log函式,使其變為加法,而且log函式為單調遞增或遞減的函式,不改變其單調性。具體函式如下:

合併後:

加正則化項後:

                                       J(\theta) = \frac{1}{m}\sum_{i=1}^{m}\big[-y^{(i)}\, log\,( h_\theta\,(x^{(i)}))-(1-y^{(i)})\,log\,(1-h_\theta(x^{(i)}))\big]$$+\frac{\lambda }{2m}\sum_{i=1}^{m}\Theta _{j}^{2}

向量化的公式:

                                           J(\theta) =- \frac{1}{m}\big((\,log\,(g(X\theta))^Ty+(\,log\,(1-g(X\theta))^T(1-y)\big) + \frac{\lambda}{2m}\sum_{j=1}^{n}\theta_{j}^{2}

優化方法:依然還是梯度下降。

求偏倒:

                                                                      \frac{\delta J(\theta)}{\delta\theta_{j}} = \frac{1}{m}\sum_{i=1}^{m} ( h_\theta (x^{(i)})-y^{(i)})x^{(i)}_{j} + \frac{\lambda}{m}\theta_{j}

向量化的偏導公式:

                                                                          \frac{\delta J(\theta)}{\delta\theta_{j}} = \frac{1}{m} X^T(g(X\theta)-y) + \frac{\lambda}{m}\theta_{j}

核心程式碼:

#定義sigmod函式
def sigmod(z):
    return (1/(1+np.exp(-z))

#定義損失函式
def costFunction(theta, reg, *args):
    m = y.size
    h = sigmoid(X.dot(theta))
    
    J = -1.0*(1.0/m)*(np.log(h).T.dot(y)+np.log(1-h).T.dot(1-y)) +(reg/(2.0*m))*np.sum(np.square(theta[1:]))
               
    if np.isnan(J[0]):
        return(np.inf)  #np.inf表示無窮大的一個數
    return J[0]

#梯度下降
def gradinet(theta, reg, *args):
    m=y.size
    h=sigmod(X.dot(theta.reshape(-1,1)))
    grad = (1.0/m)*X.T.dot(h-y) + (reg/m)*np.r_[[[0]],theta[1:].reshape(-1,1)]
    return(grad.flatten())

應用:根據上面的學習,我們知道了演算法的超引數,主要有:正則化係數、迭代輪次、學習率。因此我們在演算法調優:

 

具體實現程式碼可以關注:我的github


未完,待續。