python機器學習——邏輯迴歸方法
理論背景:
線性迴歸可以實現對連續結果的預測,但是現實生活中我們常見的另一種問題是分類問題,尤其是二分類問題,在這種情況下使用線性迴歸就不太合適了,我們實際上需要計算出的是一個在$[0,1]$之間的概率來告訴我們某樣本屬於某一類的概率,因此邏輯迴歸應運而生。
一般的邏輯迴歸就是線上性迴歸的基礎上巢狀一個邏輯函式,把線性迴歸的結果轉換成概率。
即我們定義$h_{\theta}(X)=P(y=1|X,\theta),1-h_{\theta}(X)=P(y=0|X,\theta)$,那麼我們希望最大化預測正確的概率,即我們要最大化:
$\prod_{i=1}^{m}P(y=y_{i}|X_{i},\theta)$
那麼也就是:
$\prod_{i=1}^{m}(h_{\theta}(X_{i})^{y_{i}}(1-h_{\theta}(X_{i}))^{1-y_{i}}$
這不好計算,兩側取對數再去取相反數就得到:
$J(\theta)=-\dfrac{1}{m}\sum_{i=1}^{m}y_{i}\log h_{\theta}(X_{i})+(1-y_{i})\log (1-h_{\theta}(X_{i}))$
這樣我們只需最小化這個損失函式就可以了,仍然使用梯度下降法確定引數,我們有:
$\hat{\theta_{j}}=\theta_{j}-\alpha \dfrac{\partial J(\theta)}{\partial \theta_{j}}$
對上式求偏導,最後我們得到:
$\hat{\theta_{j}}=\theta_{j}-\alpha \dfrac{1}{m}\sum_{i=1}^{m}(h_{\theta}(X_{i})-y_{i})x_{ij}$
而我們的操作是線上性模型的基礎上套上一個邏輯模型,也即我們的引數仍然是線性模型的引數$\theta$:
$z=\theta^{T}X$
在這個基礎上套上一個邏輯函式,這裡我們選擇的是sigmoid函式,即:
$g(z)=\dfrac{1}{1+e^{-z}}$
於是我們最後的函式即為:
$h_{\theta}=\dfrac{1}{1+e^{-\theta^{T}X}}$
程式碼實現:
import numpy as np import math from scipy import stats import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression def sigmoid(z): return 1/(1+math.exp(-z)) def logical_regression(X,Y,theta,siz,alpha,eps): delt=1 while delt>eps: new_theta=np.zeros(3) for i in range(0,3): r=theta[i] for j in range(0,siz): d=alpha/siz*(sigmoid(theta[0]*X[0][j]+theta[1]*X[1][j]+theta[2]*X[2][j])-Y[j])*X[i][j] r-=d new_theta[i]=r print(new_theta[i]) delta=new_theta-theta delt=delta[0]**2+delta[1]**2+delta[2]**2 theta=new_theta return theta x=np.arange(0.,10.,0.02) y=5-2*x/3+np.random.randn(500) now=0 dataset=[] for i in range(0,500): typ = 0 if 2*x[i]+3*y[i] <= 15: if abs(np.random.randn(1)[0])<2: typ = 1 else: typ = 0 else: if abs(np.random.randn(1)[0]) < 2: typ = 0 else: typ = 1 dataset.append([x[i],y[i],typ]) X=(np.array(dataset)[:,0:2]).T x0=np.ones(500) X=np.vstack([x0,X]) Y=(np.array(dataset)[:,2]) theta=np.array([1,1,1]) my_theta=logical_regression(X,Y,theta,500,1e-2,1e-7) print(my_theta) for i in range(0,500): if Y[i]==1: plt.scatter(X[1,i],X[2,i],c='r') else: plt.scatter(X[1,i],X[2,i],c='b') plt.plot(x,-my_theta[1]/my_theta[2]*x-my_theta[0]/my_theta[2],c='g',linewidth=3) plt.show()
這個程式碼生成了一組以直線$2x+3y-15=0$為分界的資料,並且加入了一定的隨機化,最後通過邏輯迴歸能夠找出這條直線,當然這裡的引數選取同樣也很重要
小結與優化:
邏輯迴歸中在一定程度上存在欠擬合的問題,因為很多時候分界線並不是直線而是曲線,此時單純的線性函式已經無法擬合邊界了,一個解決方案是引入更多維度,比如把$[x_{1},x_{2}]$擴充套件成$[x_{1},x_{2},x_{1}^{2},x_{2}^{2}]$,這樣就可以更好擬合二次曲線形成的邊界,以此類推等。
而精度問題則可能是由於資料特徵有缺失或資料空間太大等,遇到這種情況可以加入正則化的一項使模型縮減係數,有利於提高模型的泛化能力。