对数几率回归

对数几率回归

简要介绍

利用回归解决分类问题,也就是用一个函数拟合数据,最终将函数值映射到0或1 。搞懂对数几率回归,对理解神经网络很有帮助。

具体原理

给定数据集 D = ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯ ( x n , y n ) . D=(x_1,y_1),(x_2,y_2),\cdots (x_n,y_n). D=(x1,y1),(x2,y2),(xn,yn).其中每个样本输入有 n n n个属性 ( x 11 , x 12 , ⋯ x 1 n ) (x_{11},x_{12},\cdots x_{1n}) (x11,x12,x1n),则会对应 n n n个权重 ( w 1 , w 2 , ⋯ w n ) (w_{1},w_{2},\cdots w_{n}) (w1,w2,wn),令 Z 1 = ∑ i = 1 n x 1 i w i + b Z_1=\sum_{i=1}^n x_{1i}w_{i}+b Z1=i=1nx1iwi+b,利用sigmod函数,最后分类结果为 1 1 + e − z \frac{1}{1+e^{-z}} 1+ez1

算法关键是如何选择参数,一个好的参数能使得对数损失函数
L ( w , b ) = − [ y i l o g 2 y i ^ + ( 1 − y i ) l o g 2 ( 1 − y i ^ ) ] 最 小 其 中 y i 是 第 i 个 样 本 的 类 别 , 有 0 和 1 两 种 取 值 , y i ^ 是 预 测 分 类 . L(w,b)=-[y_ilog_2\hat{y_i}+(1-y_i)log_2(1-\hat{y_i})]最小\\ 其中y_i是第i个样本的类别,有0和1两种取值,\hat{y_i}是预测分类. L(w,b)=[yilog2yi^+(1yi)log2(1yi^)]yii01yi^.
上面的损失函数其实只有 y i l o g 2 y i ^ y_ilog_2\hat{y_i} yilog2yi^有效或者 ( 1 − y i ) l o g 2 ( 1 − y i ^ ) (1-y_i)log_2(1-\hat{y_i}) (1yi)log2(1yi^)有效。当 y i = y i ^ y_i=\hat{y_i} yi=yi^时,损失函数为0最小,当 y i 与 y i ^ y_i与\hat{y_i} yiyi^是0和1的取值时,即结果完全相反,此时损失函数为正无穷大。

损失函数为什么不直接选取最小二乘 σ ( w , b ) = ∣ y i − y ^ i ∣ 2 \sigma(w,b)=|y_i-\hat{y}_i|^2 σ(w,b)=yiy^i2呢,因为最小二乘的损失函数不是凸的,而交叉熵 L ( w , b ) L(w,b) L(w,b)是严格凸的,这样梯度下降可以到达最优解而不是局部解

如何使得损失函数最小,这里使用梯度下降的办法,梯度下降有随机梯度下降和平均梯度下降,下面考虑一个样本的梯度下降,有点类似随机梯度下降

给出各参数之间的关系:

L ( w , b ) = − [ y l o g 2 y ^ + ( 1 − y ) l o g 2 ( 1 − y ^ ) ] . y i ^ = 1 1 + e − Z . Z i = ∑ j = 1 n x j w j + b . L(w,b)=-[ylog_2\hat{y}+(1-y)log_2(1-\hat{y})].\\ \hat{y_i}=\frac{1}{1+e^{-Z}}.\\ Z_i=\sum_{j=1}^nx_{j}w_j+b. L(w,b)=[ylog2y^+(1y)log2(1y^)].yi^=1+eZ1.Zi=j=1nxjwj+b.

从而求出梯度:

∂ L ∂ w = ∂ L ∂ y ^ ∗ ∂ y ^ ∂ Z ∗ ∂ z ∂ w = y ^ − y y ^ ( 1 − y ) ∗ 1 1 + e − z ( 1 − 1 1 + e − z ) ∗ x = ( y ^ − y ) x . 备 注 : 此 处 w 和 x 乃 同 维 度 的 向 量 。 同 理 , ∂ L ∂ b = y ^ − y . \frac{\partial L}{\partial w}=\frac{\partial L}{\partial \hat{y}}*\frac{\partial \hat{y}}{\partial Z}*\frac{\partial z}{\partial w}\\ =\frac{\hat{y}-y}{\hat{y}(1-y)}*\frac{1}{1+e^{-z}}(1-\frac{1}{1+e^{-z}})*x\\ =(\hat{y}-y)x.\\ 备注:此处w和x乃同维度的向量。\\ 同理,\frac{\partial L}{\partial b}=\hat{y}-y. wL=y^LZy^wz=y^(1y)y^y1+ez1(11+ez1)x=(y^y)x.wxbL=y^y.

则可以更新参数:

w = w − η ( y ^ − y ) x . b = b − η y ^ − y . w=w-\eta(\hat{y}-y)x.\\ b=b-\eta\hat{y}-y. w=wη(y^y)x.b=bηy^y.

代码实现

给出一部分数据格式

-0.017612 14.053064 0
-1.395634 4.662541 1
-0.752157 6.538620 0
-1.322371 7.152853 0
0.423363 11.054677 0
0.406704 7.067335 1
0.667394 12.741452 0
-2.460150 6.866805 1
0.569411 9.548755 0
-0.026632 10.427743 0

import numpy as npy
import matplotlib.pyplot as plt

# 读入数据函数
# 每一行前两个数字为x^1, x^2最后一个数据为标签y
# dataMat每一行为向量x = (1, x^1, x^2)
# labelMat只有一行,为对应的y
def loadDataSet():
    dataMat = []
    labelMat = []
    fr = open("testSet.txt")
    for line in fr.readlines():
        lineArr = line.strip().split()
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
    return dataMat, labelMat

# 返回sigmoid函数计算结果
# inX为w*x
def sigmoid(inX):
    return 1.0 / (1 + npy.exp(-inX))

def gradAscent(dataMatIn, classLabels):
    dataMatrix = npy.mat(dataMatIn)
    # 将labelMat变成m*1的矩阵
    labelMat = npy.mat(classLabels).transpose()
    # m行n列
    m, n = npy.shape(dataMatrix)
    alpha = 0.001
    maxCycles = 500
    # 生成n*1列的矩阵
    weights = npy.ones((n, 1))
    for k in range(maxCycles):
        # m*n的矩阵乘上n*1的矩阵,结果为m*1的矩阵
        forecastLabel = sigmoid(dataMatrix * weights)
        # 两个m*1的矩阵相减
        error = (labelMat - forecastLabel)
        # n*m矩阵乘上m*1矩阵,得到n*1矩阵,在这里就是2*1
        # 这就是梯度上升法的alpha * L'(w)
        weights = weights + alpha * dataMatrix.transpose() * error
    return weights

# 该函数画出所有的数据点和最优的分割线
def plotBestFit(weights):
    dataMat, labelMat = loadDataSet()
    dataArr = npy.array(dataMat)
    n = npy.shape(dataArr)[0]
    xcord1 = []
    ycord1 = []
    xcord2 = []
    ycord2 = []
    for i in range(n):
        # 如果数据标签是y = 1
        if int(labelMat[i]) == 1:
            xcord1.append(dataArr[i, 1])
            ycord1.append(dataArr[i, 2])
        # 如果数据标签是y = 0
        else:
            xcord2.append(dataArr[i, 1])
            ycord2.append(dataArr[i, 2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s = 30, c = "red", marker = "1")
    ax.scatter(xcord2, ycord2, s = 30, c = "green")

    # 画出分割线的图像即y = w * x
    # 原方程为0 = w0*x0 + w1*x1 + w2*x2
    x = npy.arange(-3.0, 3.0, 0.1)
    y = (-weights[0] - weights[1] * x) / weights[2]
    ax.plot(x, y)
    plt.xlabel("X1")
    plt.ylabel("X2")
    plt.show()

最终结果为:

[[ 4.12414349]
 [ 0.48007329]
 [-0.6168482 ]]

在这里插入图片描述
Z = 4.12414349 + 0.48007329 x 1 − 0.6168482 x 2 . Z=4.12414349+0.48007329 x_1-0.6168482 x_2. Z=4.12414349+0.48007329x10.6168482x2.

决策结果为 s i g m o d ( Z ) . sigmod(Z). sigmod(Z).


以上内容参考《机器学习实战》Peter Harriongton著《机器学习》周志华著.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值