机器学习分类算法之逻辑回归

一、概念

逻辑回归(Logistic Regression,LR)是一种广义的线性回归分析模型,属于监督学习算法,需要打标数据,可以用在回归、二分类和多分类等问题上,最常用的是二分类。

线性回归就是通过一条曲线区分不同的数据集,在二分类问题上会有一条直线对其进行区分,如下:

逻辑回归需要每组数据都是都是数值型的,因为需要对其进行运算,得到直线系数,打标数据一般是0和1。

 

二、计算

逻辑回归的输出是一组特征系数,使用了 y=wx+b这种函数来进行线性拟合,这个问题的y值不是0,就是1。使用上述函数很难快速逼近0-1。为了解决这个问题,我们给出一个激活函数Sigmoid函数:

他在z趋向于无穷小时,逼近于0 ,在t趋向于无穷大时逼近于1。

,函数就变为了:

,这样,W的存在就将原本的数据集转换为了一组值在0-1之间的数,我们通过调整W的值,尽可能让数据集的值贴近目标值,即0和1。

由上面介绍可知,y=0.5时刚好是x=0;

y越趋近于0,x越小,且为负数,到负无穷时为0;

反之,y越趋近于1,x越大,且为正数,到正无穷时为1。

逻辑回归会算出一组系数,使样本的值向目标值0或1趋近,越接近目标值越好,预测就会越准确。

 

这里用梯度下降法来实现逻辑回归。

梯度下降法(Gradient Descent)就是每一次迭代都向目标结果接近一点,直到计算收敛。

梯度下降法的基本思想可以类比为一个下山的过程,以当前的所处的位置为基准,寻找这个位置最陡峭的地方,然后朝着山的高度下降的地方走,同理,如果我们的目标是上山,也就是爬到山顶,那么此时应该是朝着最陡峭的方向往上走。然后每走一段距离,都反复采用同一个方法,最后就能成功的抵达山谷。

梯度下降公式为:

其中是权重系数每次需要调整的值,

alpha被称之为步长,也叫乘积系数,是为了限制每次调整的大小,调整太大会错过关键信息,调整太小会迭代次数过多,所以要反复调整,

error被称之为梯度,error = sigmoid(XW) - Y,Y是目标列,

我们一般会指定一个初始特征系数,一般设为全是1,即 W=(1,1,1.....,1),

常数项我们作为增广向量添加到数据集中,增广向量我们全部设为1,同样的,目标列也增加一个1,

最后我们还有设置一个阈值,来作为预测结果的依据,根据上面的描述,梯度下降法可选用sigmoid(XW)和0.5的比较来判断,因为小于0.5,x为负,趋近于0,大于0.5,x为正,趋近于1。

 

三、实现

# !/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt


def sigmoid(x):
    return 1.0 / (1 + np.exp(-x))


def grad_ascent(data_mat, class_label, alpha):
    data_matrix = np.mat(data_mat)
    label_mat = np.mat(class_label).transpose()
    m, n = np.shape(data_matrix)
    data_matrix = augment(data_matrix)  # 增广
    n += 1
    weight = np.ones((n, 1))
    while True:
        error = sigmoid(data_matrix * weight) - label_mat
        cha = alpha * data_matrix.transpose() * error
        if np.abs(np.sum(cha)) < 0.0001:
            break
        weight = weight - cha
    return weight


def create_sample():
    np.random.seed(10)  # 随机数种子,保证随机数生成的顺序一样
    n_dim = 2
    num = 100
    a = 3 + 5 * np.random.randn(num, n_dim)
    b = 18 + 4 * np.random.randn(num, n_dim)
    data_mat = np.concatenate((a, b))
    ay = np.zeros(num)
    by = np.ones(num)
    label = np.concatenate((ay, by))
    return {'data_mat': data_mat, 'label': label}


def plot_data(samples, plot_type='o'):
    data_mat = samples['data_mat']
    label = samples['label']
    n = data_mat.shape[0]
    cs = ['r', 'g']
    dd = np.arange(n)
    for i in range(2):
        index = label == i
        xx = data_mat[dd[index]]
        plt.plot(xx[:, 0], xx[:, 1], plot_type, markerfacecolor=cs[i], markersize=14)


def augment(data_matrix):
    n, n_dim = data_matrix.shape
    a = np.mat(np.ones((n, 1)))
    return np.concatenate((data_matrix, a), axis=1)


def classify(data_mat, weight):
    data_matrix = np.mat(data_mat)
    data_matrix = augment(data_matrix)
    d = sigmoid(data_matrix * weight)
    print(d)
    r = np.zeros((data_matrix.shape[0], 1))
    r[d > 0.5] = 1
    return r


def plot(weight, data):
    lx = [0, -weight[2] / weight[0]]
    ly = [-weight[2] / weight[1], 0]
    plot_data(data)
    plt.plot(lx, ly)
    plt.show()


def main():
    data = create_sample()
    final_weight = grad_ascent(data['data_mat'], data['label'], 0.001)
    print(final_weight)
    plot(final_weight, data)
    pred = classify(data['data_mat'], final_weight)
    label = np.mat(data['label']).T
    diff = np.sum(pred != label)
    print(diff, len(label), 1.0 * diff / len(label))


if __name__ == '__main__':
    main()

 

四、结果:

weight:

[[ 0.3236568 ]
[ 0.30234029]
[-7.00232679]]

  图形:

准确率:

预测不一致:4个

总数:200个

错误率:2%

调整迭代跳出条件为np.abs(np.sum(cha)) < 0.00001,则:

weight:

[[ 1.52741071]
[ 1.08976556]
[-32.00925101]]

 图形:

 

准确率:

预测不一致:3个

总数:200个

错误率:1.5%

posted @ 2019-01-07 08:45  Small_office  阅读(620)  评论(0编辑  收藏  举报