第8章 Logistic回归(算法原理+手编实现+库调用)


俯视机器学习


我想我还是不习惯,从看不懂数学公式到轻松推导整个算法!


第8章 Logistic回归(Logistic Regression)

1. Logistic 函数

f ( x ) = 1 1 + e − x f(x) = \frac{1}{1+e^{-x}} f(x)=1+ex1

2. Logistic回归

考虑二分类任务,对给定的样本 x x x,输出类别 f ( x ) ∈ 0 , 1 f(x)\in {0,1} f(x)0,1,构造函数
f ( x ) = 1 1 + e − ( w T x + b ) f(x) = \frac{1}{1+e^{-(w^Tx + b)}} f(x)=1+e(wTx+b)1

为了方便讨论,把 x x x 改为扩展形式,即最后增加一个元素 1 1 1 w , x w, x w,x 采用同样的记号
f ( x ) = 1 1 + e − w T x (2) f(x) = \frac{1}{1 + e^{-w^T x}} \tag{2} f(x)=1+ewTx1(2)

通过学习获得权重 w w w,当 x x x 真实类别为 0 0 0(或 1 1 1) 时,希望输出 f ( x ) f(x) f(x) 也接近 0 0 0(或 1 1 1)。
给定 x ∈ R n x\in R^n xRn,定义期望函数
p ( x ; w ) = y f ( x ) + ( 1 − y ) ( 1 − f ( x ) ) (3) p(x;w) = yf(x) + (1-y)(1-f(x)) \tag{3} p(x;w)=yf(x)+(1y)(1f(x))(3)
其中 y y y x x x 的真实类别, p ( x ; w ) p(x;w) p(x;w) 可以看成是样本的预测概率。则希望所有样本的预测概率之积最大(最大似然估计),即最大化
Π x p ( x ; w ) \mathop{\Pi}_x p(x;w) Πxp(x;w)
其中 m m m 表示样本数。通常乘积结果很小,通过取对数,不改变最优解。取对数后的期望记为 P ( w ) P(w) P(w) ,有
P ( w ) = ∑ x ln ⁡ p ( x ; w ) (4) P(w) = \sum_x \ln p(x;w) \tag{4} P(w)=xlnp(x;w)(4)
其中 ∑ x \sum_x x 表式遍历所有样本 x x x 求和。

( 2 ) , ( 3 ) (2),(3) (2),(3) 式代入式 ( 4 ) (4) (4) ,可得
P ( w ) = ∑ x [ y w T x − ln ⁡ ( 1 + e w T x ) ] (5) P(w) = \sum_x \left[y w^T x - \ln (1+e^{w^T x})\right] \tag{5} P(w)=x[ywTxln(1+ewTx)](5)
通常要处理的式最小化问题,定义 l ( w ) = − P ( w ) l(w)=-P(w) l(w)=P(w)。最大化 P ( w ) P(w) P(w),相当于最小化 l ( w ) l(w) l(w)
可解得
l ( w ) = ∑ x [ − y w T x + ln ⁡ ( 1 + e w T x ) ] (5) l(w) = \sum_x \left[-y w^T x + \ln (1+e^{w^T x})\right] \tag{5} l(w)=x[ywTx+ln(1+ewTx)](5)
这里 x , y x, y x,y 分别代表扩展的样本及其真实类别,两者均随样本不同而不同。

3. 牛顿法求解最优化目标

根据式 ( 1 ) (1) (1),第 ( t + 1 ) (t+1) (t+1) 轮迭代解的更新公式为
w t + 1 = w t − ( ∂ 2 l ( w ) ∂ w ∂ w T ) − 1 ∂ l ( w ) ∂ w w^{t+1} = w^t - \left(\frac{\partial^2 l(w)}{\partial w \partial w^T} \right)^{-1}\frac{\partial l(w)}{\partial w} wt+1=wt(wwT2l(w))1wl(w)
或写为
w t + 1 = w t − [ ∇ 2 l ( w ) ] − 1 ∇ l ( w ) (6) w^{t+1} = w^t - \left[\nabla^2 l(w) \right]^{-1}\nabla l(w) \tag{6} wt+1=wt[2l(w)]1l(w)(6)
计算可得
∇ l ( w ) = ∑ x ( − y x + e w T x 1 + e w T x x ) [ ∇ 2 l ( w ) ] i j = ∑ x x i x j e − w T x ( 1 + e − w T x ) 2 (7) \nabla l(w) = \sum_x \left(-y x + \frac{e^{w^T x}}{1+e^{w^T x}}x \right) \\ [\nabla^2 l(w)]_{ij} = \sum_x \frac{x_i x_j e^{-w^T x}}{(1+ e^{-w^T x})^2} \tag{7} l(w)=x(yx+1+ewTxewTxx)[2l(w)]ij=x(1+ewTx)2xixjewTx(7)
∇ 2 l ( w ) = ∑ x x x T e − w T x ( 1 + e − w T x ) 2 (8) \nabla^2 l(w) = \sum_x \frac{xx^T e^{-w^T x}}{(1+ e^{-w^T x})^2} \tag{8} 2l(w)=x(1+ewTx)2xxTewTx(8)

这里 x i x_i xi(或 x j x_j xj) 分别代表 x x x 的第 i i i或( j j j) 个属性。

4. 实战:鸢尾花分类

对鸢尾花数据集的类别进行分类。

数据集介绍:

  • 数据来源:R.A. Fisher

  • 150 个样本点,3 类鸢尾花,每类 50 个样本点。

  • 4 个属性,分别为花萼长度、花萼宽度、花瓣长度、花瓣宽度。

  • 目的:根据属性判断鸢尾花类别。

编程实现

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris

# 数据准备
X, y = load_iris(return_X_y=True)
X = X[(y==0) | (y==1)]  # / X.max(axis=0) 
X = X[:, [0,1]]        # 只取前两个属性
X = np.c_[X, np.ones((len(X), 1))]

yy = y[(y==0) | (y==1)]
y = y[(y==0) | (y==1)].reshape((-1, 1))

# 牛顿法求解 logistic 回归

def get_loss(X, y, w):
    return np.sum(-y * (X @ w) + np.log(1 + np.exp(X @ w)))


def get_grad(X, y, w):
    G = np.zeros(X.shape[1]).reshape(-1, 1)
    for i in range(len(X)):
        x = X[i, :].reshape(-1,1)
        G += -y[i] * x + np.exp(w.T @ x)/(1 + np.exp(w.T @ x)) * x
    return G
        
    
def get_hessian(X, y, w):
    H = np.zeros((X.shape[1], X.shape[1]))
    for x in X:
        x = x.reshape(-1, 1)
        H += x @ x.T * (np.exp(-w.T @ x)) / (1 + np.exp(-w.T @x))**2
    return H


# 牛顿法求解
it    = 0 # 迭代次数
maxIt = 20
w     = np.zeros((X.shape[1], 1))
ep    = 1e-5
G     = 1000.
loss  = []
while np.linalg.norm(G) > ep and it < maxIt:
    G = get_grad(X, y, w)
    H = get_hessian(X, y, w)
    w   = w - (np.linalg.inv(H) @ G).reshape(-1,1)
    loss.append(get_loss(X, y, w))
    it += 1 
    
print(f'iter = {it}')
print(f'w = \n{w}')

# 可视化
x1min, x1max = X[:,0].min()-.5, X[:,0].max()+.5
x2min, x2max = X[:,1].min()-.5, X[:,1].max()+.5
xx1, xx2 = np.meshgrid(np.linspace(x1min, x1max, 100),
                       np.linspace(x2min, x2max, 100))

X2 = np.c_[xx1.ravel(), xx2.ravel(), np.ones(len(xx1.ravel()))]
y2 = 1. / (1 + np.exp(-X2 @ w))
y2[y2  > 0.5] = 1
y2[y2 <= 0.5] = 0
Z = y2.reshape(xx1.shape)
plt.pcolormesh(xx1, xx2, Z, shading='auto', cmap=plt.cm.binary_r)

plt.scatter(X[yy==0][:,0], X[yy==0][:,1], c='r', marker='o')
plt.scatter(X[yy==1][:,0], X[yy==1][:,1], c='g', marker='+')
plt.show()

5. 实战:Sklearn中的Logistic回归

class sklearn.linear_model.LogisticRegression(penalty=’l2’, *, dual=False, tol=0.0001,C=1.0, fit_intercept=True, intercept_scaling=1, class_weight=None,random_state=None, solver=’lbfgs’,max_iter=100, multi_class=’auto’, verbose=0, warm_start=False,n_jobs=None, l1_ratio=None)

  • 参数
    • penalty [{‘l1’, ‘l2’, ‘elasticnet’, ‘none’}, default=’l2’] 惩罚
    • dual [bool, default=False] 对偶问题或是原问题形式
    • tol [float, default=1e-4] 提前停止的阈值
    • C [float, default=1.0] 正则化系数,越小正则化能力越强!
  • 属性
    • classes_
    • coef_
    • intercept_
  • 方法
    • fit(X, y[, sample_weight])
    • predict(X)
    • score(X, y[, sample_weight])
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression

X, y = load_iris(return_X_y=True)
X = X[:, :2] # 取前两个特征
X = X[(y==0) | (y==1)]
y = y[(y==0) | (y==1)]

lr = LogisticRegression()
lr.fit(X, y)

ypred = lr.predict(X)
acc = np.sum(ypred == y) / len(y)
print(f"Accurancy = {acc}")

版权申明:本教程版权归创作人所有,未经许可,谢绝转载!


交流讨论QQ群:784117704

部分视频观看地址:b站搜索“火力教育”

课件下载地址:QQ群文件(有最新更新) or 百度网盘PDF课件及代码

链接:https://pan.baidu.com/s/1lc8c7yDc30KY1L_ehJAfDg
提取码:u3ls


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值