机器学习个人笔记——(二)Logistic回归

分类算法——Logistic回归

  • 一、Logistic回归概念
    • 1. 主要思想
    • 2. 一般:
  • 二、原理
    • 1. Sigmoid 函数
    • 2.构建似然函数
    • 3.梯度上升
    • 4. 随机梯度上升
  • 三、代码实现

一、Logistic回归概念

1. 主要思想

回归 : 用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称作回归。
逻辑回归: 是一种适用于二分类(非0即1)的分类算法

根据现有数据对分类边界线建立回归公式,以此进行分类。
目标:找到最佳拟合参数集

例如:下图所示,在一个平面中存在2个类别的数据,红色为:1,蓝色为0机器学习个人笔记——(二)Logistic回归_第1张图片
此时画一条直线,平面上的点将被为两个部分,而我们所要求的就是这一条直线方程
假设这条直线方程为w0+w1*x1+w2*x2=0,而平面中的点是已知的,如:(x1, x2)=(1.0 , 0.6),带入该方程中,得w0+w1*1.0+w2*0.6=z,若z>0,则在直线的上方,若z<0,类别1,则在直线的下方,类别0
问题即为:求一个最佳的的w0,w1,w2,使分类器尽可能地准确
机器学习个人笔记——(二)Logistic回归_第2张图片

数据处理过程中,通常会对原数据加入一个特征值1,原数据(x1,x2)=>(1,x1,x2)=(1, 1.0 ,0.6)
此时点向量为 x T = [ x 0 x 1 x 2 ] = [ 1.0 1.0 0.6 ] \begin{aligned} \mathbf{ x^{T}}&=\begin{bmatrix}x_{0}&x_{1}&x_{2}\\\end{bmatrix}\\ &=\begin{bmatrix}1.0&1.0&0.6\\\end{bmatrix} \end{aligned} xT=[x0x1x2]=[1.01.00.6]

参数w0,w1,w2为
w T = [ w 0 w 1 w 2 ] \begin{aligned} \mathbf{ w^{T}} &=\begin{bmatrix}w_{0}&w_{1}&w_{2}\end{bmatrix} \end{aligned} wT=[w0w1w2]

此时方程为
z = w 0 ∗ 1.0 + w 1 ∗ x 1 + w 2 ∗ x 2 = w 0 ∗ 1.0 + w 1 ∗ 1.0 + w 2 ∗ 0.6 = w T x ( 向 量 相 乘 ) \begin{aligned} z&=w_{0}*1.0+w_{1}*x_{1}+w_{2}*x_{2} \\ &=w_{0}*1.0+w_{1}*1.0+w_{2}*0.6\\ &=\mathbf{w^{T}}\mathbf{x} {(向量相乘)} \end{aligned} z=w01.0+w1x1+w2x2=w01.0+w11.0+w20.6=wTx()

2. 一般:

存在一个点(x1,x2,…xn), n为特征值的个数,对应的向量为
x T = [ x 0 x 1 x 2 . . . x n ] = [ 1 x 1 x 2 . . . x n ] \begin{aligned} \mathbf{ x^{T}}&=\begin{bmatrix}x_{0}&x_{1}&x_{2}&...&x_{n}\\\end{bmatrix}\\ &=\begin{bmatrix}1&x_{1}&x_{2}&...&x_{n}\\\end{bmatrix} \end{aligned} xT=[x0x1x2...xn]=[1x1x2...xn]
参数为:
w T = [ w 0 w 1 w 2 . . . w n ] \begin{aligned} \mathbf{ w^{T}} &=\begin{bmatrix}w_{0}&w_{1}&w_{2}&...&w_{n}\end{bmatrix} \end{aligned} wT=[w0w1w2...wn]
因此:
z = w 0 ∗ 1 + w 1 ∗ x 1 + w 2 ∗ x 2 + . . . + w n ∗ x n = w T x \begin{aligned} z&=w_{0}*1+w_{1}*x_{1}+w_{2}*x_{2} +...+w_{n}*x_{n}\\ &=\mathbf{w^{T}} \mathbf{x} \end{aligned} z=w01+w1x1+w2x2+...+wnxn=wTx

二、原理

1. Sigmoid 函数

Sigmoid 函数具体公式如下所示:
h ( x ) = 1 1 + e − x h(x)=\frac{1}{1+e^{-x} } h(x)=1+ex1
函数图像如图所示:
机器学习个人笔记——(二)Logistic回归_第3张图片
x>0时,1>Sigmoid(x)>0.5
x<0时,0
x=0时,Sigmoid(x)=0.5

因为:
z = w 0 ∗ 1 + w 1 ∗ x 1 + w 2 ∗ x 2 + . . . + w n ∗ x n = w T x \begin{aligned} z&=w_{0}*1+w_{1}*x_{1}+w_{2}*x_{2} +...+w_{n}*x_{n}\\ &=\mathbf{w^{T}} \mathbf{x} \end{aligned} z=w01+w1x1+w2x2+...+wnxn=wTx

z代入Sigmoid函数中,进而得到一个范围在0~1 之间的数值。
h ( w T x ) = 1 1 + e − w T x h(\mathbf{w^{T}} \mathbf{x} )=\frac{1}{1+e^{-\mathbf{w^{T}} \mathbf{x} } } h(wTx)=1+ewTx1
大于0.5的数据被分入1 类,小于0.5即被归入0 类。

Sigmoid函数求导,将在后面的推导中用到:
h ′ ( x ) = d 1 1 + e − x d x = h ( x ) ( 1 − h ( x ) ) \begin{aligned} h ^{'}(x) & = \frac{d{\frac{1}{1+e^{-x} }}}{d{x}}\\ &=h(x)(1-h(x)) \end{aligned} h(x)=dxd1+ex1=h(x)(1h(x))

2.构建似然函数

通过sigmoid函数 ,输出的值 p= h ( w T x ) h(\mathbf{w^{T}} \mathbf{x} ) h(wTx)
p的值表示结果为1的概率,1-p则表示结果为0的概率**
在一个数据集中(m表示样本数,n表示特征值个数):
x = [ x 10 x 20 . . . x m 0 x 11 x 21 . . . x m 1 . . . x 1 n x 2 n . . . x m n ] \mathbf{x}=\begin{bmatrix} x_{10}&x_{20}&...&x_{m0}\\ x_{11}&x_{21}&...&x_{m1}\\ ...\\ x_{1n}&x_{2n}&...&x_{mn} \end{bmatrix} x=x10x11...x1nx20x21x2n.........xm0xm1xmn,则任意一个输入向量 x i = [ x i 0 x i 1 . . . x i n ] \mathbf{x_{i}}=\begin{bmatrix}x_{i0}\\x_{i1}\\...\\x_{in}\end{bmatrix} xi=xi0xi1...xin
分类结果为类别1和类别0的概率分别为

P i ( y = 1 ∣ x i ) = h ( w T x i ) ( 当 该 类 别 标 签 y = 1 时 ) P i ( y = 0 ∣ x i ) = 1 − h ( w T x i ) ( 当 该 类 别 标 签 y = 0 时 ) \begin{aligned} P_{i}(y & = 1| \mathbf{x_{i}}) = h(\mathbf{w^{T}} \mathbf{x_{i}} ){(当该类别标签 y=1时)}\\ P_{i}(y & = 0| \mathbf{x_{i}}) = 1-h(\mathbf{w^{T}} \mathbf{x_{i}} ){(当该类别标签 y=0时)} \end{aligned} Pi(yPi(y=1xi)=h(wTxi)(y=1)=0xi)=1h(wTxi)(y=0)

对以上式子进行合并,得到
P i ( y i ∣ x i ) = ( h ( w T x i ) ) y i ∗ ( 1 − h ( w T x i ) ) ( 1 − y i ) \begin{aligned} P_{i}(y_{i}|\mathbf{x_{i}})=(h(\mathbf{w^{T}}\mathbf{x_{i}}))^{y_{i}}*(1-h(\mathbf{w^{T}}\mathbf{x_{i}}))^{(1-y_{i})} \end{aligned} Pi(yixi)=(h(wTxi))yi(1h(wTxi))(1yi)

构建似然函数:若训练样本相互独立,则似然函数为:
L ( w ) = ∏ i = 1 m P i ( y i ∣ x i ) = ∏ i = 1 m ( h ( w T x i ) ) y i ∗ ( 1 − h ( w T x i ) ) ( 1 − y i ) \begin{aligned} L(\mathbf{w})&=\prod_{i= 1}^{m} P_{i}(y_{i}|\mathbf{x_{i}})\\ &=\prod_{i= 1}^{m}(h(\mathbf{w^{T}}\mathbf{x_{i}}))^{y_{i}}*(1-h(\mathbf{w^{T}}\mathbf{x_{i}}))^{(1-y_{i})} \end{aligned} L(w)=i=1mPi(yixi)=i=1m(h(wTxi))yi(1h(wTxi))(1yi)

对似然函数进行一个转换,两边取log,将乘法运算转换为加法运算:
l n L ( w ) = ∑ i = 1 m y i ln ⁡ h ( w T x i ) + ( 1 − y i ) l n ( 1 − h ( w T x i ) ) = l ( w ) \begin{aligned} ln_{}{L(\mathbf{w})}&=\sum_{i=1}^{m}{y_{i}}\ln_{}{h(\mathbf{w^{T}}\mathbf{x_{i}})} +{(1-y_{i})}ln_{}{(1-h(\mathbf{w^{T}}\mathbf{x_{i}}))}\\&=l(\mathbf{w}) \end{aligned} lnL(w)=i=1myilnh(wTxi)+(1yi)ln(1h(wTxi))=l(w)

似然函数是一种关于统计模型中的参数的函数,表示模型参数中的似然性,可以理解为条件概率的逆反
以盒子中抓黑白球为例:
比如个一盒子中只有黑色白色两种球,但不知道他们的数量是多少
现在从中抓10次(每次都放回),得到了3次黑球,7次白球。
假设取到黑球的概率为P,则取到白球的概率为1-P
则 构建似然函数为
L ( P ) = P 3 ∗ ( 1 − P ) 7 L(P)=P^3*(1-P)^7 L(P)=P3(1P)7

此时,若存在一个参数值P, 即抓到黑球的概率,使得它的函数值L(P)达到最大的话,那么这个值P就是最为合理的参数值。
一般对L(P)进行求导,令导数为0,求得P所取的值

同理在逻辑回归中,也是二分类问题,当存在w使得L(w)取最大值时,那么此时的w即为合适的值,在当前问题中, w = [ w 0 , w 1 , w 2 , . . . , w n ] w=[w_{0}, w_{1}, w_{2}, ... , w_{n}] w=[w0,w1,w2,...,wn]是一个n+1维的向量,即参数值

3.梯度上升

似然函数为:
l ( w ) = ∑ i = 1 m y i ln ⁡ h ( w T x i ) + ( 1 − y i ) l n ( 1 − h ( w T x i ) ) \begin{aligned} l(\mathbf{w})&=\sum_{i=1}^{m}{y_{i}}\ln_{}{h(\mathbf{w^{T}}\mathbf{x_{i}})} +{(1-y_{i})}ln_{}{(1-h(\mathbf{w^{T}}\mathbf{x_{i}}))} \end{aligned} l(w)=i=1myilnh(wTxi)+(1yi)ln(1h(wTxi))
l ( w ) l(\mathbf{w}) l(w)求最大值,使用梯度上升

梯度:
一般来说,梯度可以定义为一个函数的全部偏导数构成的向量
指向函数值增长最快的方向

梯度上升:沿着增长最快的方向,移动 α \alpha α 的步长,迭代公式如下
w = w + α ∇ f \large w=w+\alpha \nabla {f} w=w+αf

即求 l ( w ) l(\mathbf{w}) l(w)的梯度, 需分别对对 w i w_{i} wi求偏导

∇ f = [ ∂ l ( w ) ∂ w 0 ∂ l ( w ) ∂ w 1 ∂ l ( w ) ∂ w 2 . . . ∂ l ( w ) ∂ w n ] \large \nabla {f}=\begin{bmatrix} \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{0}}\\ \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{1}}\\ \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{2}}\\ ...\\ \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{n}}\\ \end{bmatrix} f=w0l(w)w1l(w)w2l(w)...wnl(w)

对以上公式进行拆分,拿出一个来看
∂ l ( w ) ∂ w 0 = ∑ i = 1 m ∂ h ( w T x i ) ∂ w 0 ( y i h ( w T x i ) + 1 − y i 1 − h ( w T x i ) ) {\large \begin{aligned} \frac{\partial l(\mathbf{w})}{\partial w_{0}} &=\sum_{i=1}^{m} \frac{\partial\mathrm h(\mathbf{w^{T}x_{i}})}{\partial\mathrm w_{0}}(\frac{y_{i}}{h(\mathbf{w^{T}x_{i}})} +\frac{1-y_{i}}{1-h(\mathbf{w^{T}x_{i}})}) \end{aligned}} w0l(w)=i=1mw0h(wTxi)(h(wTxi)yi+1h(wTxi)1yi)

其中

∵ h ′ ( x ) = d h ( x ) d x = h ( x ) ( 1 − h ( x ) ) ∴ ∂ h ( w T x i ) ∂ w 0 = h ( w T x i ) ( 1 − h ( w T x i ) ) ∗ ∂ ( w T x i ) ∂ w 0 = . . . ∗ ∂ ( w 0 x 0 + w 1 x 1 + . . . + w n x n ) ∂ w 0 = . . . ∗ x 0 = h ( w T x i ) ( 1 − h ( w T x i ) ) ∗ x 0 . . . . 以 此 类 推 ∴ ∂ h ( w T x i ) ∂ w j = h ( w T x i ) ( 1 − h ( w T x i ) ) ∗ x j ( x j = 第 j 个 特 征 值 ) {\large \begin{aligned} &\because h^{'}(x) =\frac{\mathrm{d} h(x)}{\mathrm{d} x} = h(x)(1-h(x))\\\\ &\therefore \frac{\partial\mathrm h(\mathbf{w^{T}x_{i}})}{\partial\mathrm w_{0}} = h(\mathbf{w^{T}x_{i}})(1-h(\mathbf{w^{T}x_{i}})) *\frac{\partial\mathrm (\mathbf{w^{T}x_{i}})}{\partial\mathrm w_{0}}\\&=...*\frac{\partial\mathrm (w_{0}x_{0}+w_{1}x_{1}+...+w_{n}x_{n})}{\partial\mathrm w_{0}}\\&=...* x_{0}\\ &=h(\mathbf{w^{T}x_{i}})(1-h(\mathbf{w^{T}x_{i}}))*x_{0}\\\\&....{以此类推}\\ &\therefore \frac{\partial\mathrm h(\mathbf{w^{T}x_{i}})}{\partial\mathrm w_{j}}=h(\mathbf{w^{T}x_{i}})(1-h(\mathbf{w^{T}x_{i}}))*x_{j}{(x_{j}=第j个特征值)} \end{aligned}} h(x)=dxdh(x)=h(x)(1h(x))w0h(wTxi)=h(wTxi)(1h(wTxi))w0(wTxi)=...w0(w0x0+w1x1+...+wnxn)=...x0=h(wTxi)(1h(wTxi))x0....wjh(wTxi)=h(wTxi)(1h(wTxi))xj(xj=j)

代入原方程中得

∂ l ( w ) ∂ w 0 = ∑ i = 1 m ( h ( w T x i ) ( 1 − h ( w T x i ) ) ∗ x 0 ) ( y i h ( w T x i ) + 1 − y i 1 − h ( w T x i ) ) 整 理 得 = ∑ i = 1 m ( y i − h ( w T x i ) ) x i 0 {\large \begin{aligned} \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{0}}&=\sum_{i=1}^{m}(h(\mathbf{w^{T}x_{i}}) (1-h(\mathbf{w^{T}x_{i}}))*x_{0})(\frac{y_{i}}{h(\mathbf{w^{T}x_{i}})} +\frac{1-y_{i}}{1-h(\mathbf{w^{T}x_{i}})})\\{整理得}\\ &=\sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i0} \end{aligned}} w0l(w)=i=1m(h(wTxi)(1h(wTxi))x0)(h(wTxi)yi+1h(wTxi)1yi)=i=1m(yih(wTxi))xi0
所以:
∂ l ( w ) ∂ w j = ∑ i = 1 m ( y i − h ( w T x i ) ) x i j ( x i j = 第 i 个 样 本 的 第 j 个 特 征 值 ) {\large \begin{aligned} \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{j}}&=\sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{ij}{(x_{ij}=第i个样本的第j个特征值)} \end{aligned}} wjl(w)=i=1m(yih(wTxi))xij(xij=ij)

梯度可以表示为:
∇ f = 1 m [ ∑ i = 1 m ( y i − h ( w T x i ) ) x i 0 ∑ i = 1 m ( y i − h ( w T x i ) ) x i 1 ∑ i = 1 m ( y i − h ( w T x i ) ) x i 2 . . . . . . ∑ i = 1 m ( y i − h ( w T x i ) ) x i n ] \large \nabla {f}=\frac{1}{m} \begin{bmatrix} \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i0}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i1}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i2}\\ ......\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{in}\\ \end{bmatrix} f=m1i=1m(yih(wTxi))xi0i=1m(yih(wTxi))xi1i=1m(yih(wTxi))xi2......i=1m(yih(wTxi))xin

梯度上升算法的迭代过程: α \alpha α 为步长
w = w + α ∇ f = [ w 0 w 1 w 2 . . . w n ] + α 1 m [ ∑ i = 1 m ( y i − h ( w T x i ) ) x i 0 ∑ i = 1 m ( y i − h ( w T x i ) ) x i 1 ∑ i = 1 m ( y i − h ( w T x i ) ) x i 2 . . . . . . ∑ i = 1 m ( y i − h ( w T x i ) ) x i n ] \begin{aligned} \mathbf{w} &=\mathbf{w} +\alpha \nabla f\\\\&=\begin{bmatrix} w_{0}\\ w_{1}\\ w_{2}\\...\\w_{n} \end{bmatrix}+\alpha \frac{1}{m}\begin{bmatrix} \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i0}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i1}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i2}\\ ......\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{in}\\ \end{bmatrix} \end{aligned} w=w+αf=w0w1w2...wn+αm1i=1m(yih(wTxi))xi0i=1m(yih(wTxi))xi1i=1m(yih(wTxi))xi2......i=1m(yih(wTxi))xin
经过上述不断迭代的过程,最终得到一个合适的 w \mathbf{w} w参数

4. 随机梯度上升

当数据量达到上亿或更多数据以后,梯度上升算法中的矩阵乘法等操作显然耗时将上升到非常高的程度
他通过随机取数据集中的部分数据,来代表整体数据集,从而实现对数据样本集的缩小,达到减少计算量,降低算法时间复杂度的目的。

三、代码实现

import numpy as np
import matplotlib.pyplot as plt
from random import randint


def sigmoid(in_x):
    """
    对列向量中的每个元素都执行一次sigmoid(x)函数

    :param in_x: 输入列向量
    :return: 函数值,列向量

    样例输入:
    [[0],
     [1],
     [2]]
     样例输出:
     [[sigmoid(0)],
      [sigmoid(1)],
      [sigmoid(2)]]
    """
    if in_x.any() >= 0:
        return 1.0/(1+np.exp(-in_x))
    else:
        return float(np.exp(in_x))/(1+np.exp(in_x))



def autoNorm(dataMat):
    """
    对数据进行归一化

    :param dataMat: 数据集
    :return: 数据集(归一化后)
    """
    minVals=np.min(dataMat, axis=0)
    maxVals=np.max(dataMat, axis=0)
    ranges=maxVals-minVals
    normDataSet=dataMat-minVals
    normDataSet=normDataSet/ranges#[0,1]
    return normDataSet


def load_data(filename):
    """
    从文件中加载数据

    :param filename:文件名称/路径
    :return: 数据集矩阵,数据类别标签向量
    """
    data_mat=[]
    data_labels=[]
    w0=[]
    with open(filename,'r')  as fr:
        for line in fr:
            currline=line.strip().split('\t')
            w0.append(1.0)
            data_mat.append(list(map(float, currline[:-1])))
            data_labels.append(float(currline[-1]))
        data_mat=autoNorm(np.mat(data_mat))
        data_mat=np.insert(data_mat, 0, values=np.mat(w0), axis=1)
    return data_mat, np.mat(data_labels).T


def get_weight_0(in_data_mat, in_data_labels, alph=0.01, r=500):
    """
    梯度上升算法

    :param in_data_mat: 输入训练集
    :param in_data_labels: 训练集标签
    :param alph: 移动步长
    :param r: 迭代多少次
    :return: w参数向量
    """
    shape=in_data_mat.shape
    weights = np.ones((shape[1], 1))
    for i in range(r):
        h_wx=sigmoid(in_data_mat*weights)
        err=in_data_labels-h_wx
        weights=weights+alph*in_data_mat.T*err
    return weights


def get_weight_1(in_data_mat, in_data_labels, c=0.01, r=50):
    """
    随机梯度上升(优化)

    :param in_data_mat: 输入训练集
    :param in_data_labels: 训练集标签
    :param c: 移动步长
    :param r: 迭代多少次
    :return: w参数向量
    """
    shape=in_data_mat.shape
    weights = np.ones((shape[1], 1))
    for j in range(r):
        index_list = list(range(shape[0]))
        for i in range(shape[0]):
            ran_num=randint(0, len(index_list)-1)
            index =index_list[ran_num]
            alph=4/(1.0+j+i)+c
            h_wx=float(sigmoid(in_data_mat[index]*weights))
            err=in_data_labels[index]-h_wx
            weights=weights+(alph*err*in_data_mat[index]).T
            del index_list[ran_num]
    return weights


def plot_fig(weights, in_data_mat, in_data_labels):
    """
    画出点集和所求的直线

    :param weights: w参数向量
    :param in_data_mat: 训练数据集
    :param in_data_labels: 训练集标签
    :return: None
    """
    size=in_data_mat.shape[0]
    for i in range(size):
        if int(in_data_labels[i]) == 0:
            plt.scatter(in_data_mat[i, 1], in_data_mat[i, 2], color='r', linewidth=5, marker='.')
        else:
            plt.scatter(in_data_mat[i, 1], in_data_mat[i, 2], color='b', linewidth=5, marker='.')
    weights=list(map(float, np.array(weights)))
    y=-(weights[0]+weights[1]*in_data_mat[:, 1])/weights[2]
    plt.plot(in_data_mat[:, 1], y, linewidth=5, linestyle='solid')
    plt.xlabel('x1')
    plt.ylabel('x2')
    plt.show()


def example_test():
    """
    测试函数

    :return:None
    """
    data_mat, data_labels=load_data('testSet.txt')
    weights=get_weight_0(data_mat, data_labels)
    plot_fig(weights, data_mat, data_labels)



example_test()

你可能感兴趣的:(个人笔记)