机器学习 logistic算法

线性分类器

给定一些数据集合,他们分别属于两个不同的类别。例如对于广告数据来说,是典型的二分类问题,一般将被点击的数据称为正样本,没被点击的数据称为负样本。现在我们要找到一个线性分类器,将这些数据分为两类(当然实际情况中,广告数据特别复杂,不可能用一个线性分类器区分)。用X表示样本数据,Y表示样本类别(例如1与-1,或者1与0)。我们线性分类器的目的,就是找到一个超平面(Hyperplan)将两类样本分开。对于这个超平面,可以用以下式子描述:
在这里插入图片描述
对于logistic回归,有:
在这里插入图片描述
  其中 xx 为样本,x=[x1,x2,⋯,xn]x=[x1,x2,⋯,xn] 为n维向量,函数g为我们常说的logistic函数。g的更一般公式为:
g(z)=11+e−z
** g(z)图像 **
在这里插入图片描述
图像优点

  1. 他的输入范围是−∞→+∞ ,而之于刚好为(0,1),正好满足概率分布为(0,1)的要求。
  2. 他是一个单调上升的函数,具有良好的连续性,不存在不连续点。
g(z)函数求导

在这里插入图片描述

损失函数

https://blog.youkuaiyun.com/bitcarmanlee/article/details/51165444

对损失函数求导得出迭代公式
J(θ)=cost(hθ(x),y)=−yilog(hθ(x))−(1−yi)log(1−hθ(x))
则:
在这里插入图片描述
迭代公式向量化

样本矩阵表示:
在这里插入图片描述
将x*θ的乘积记为:
在这里插入图片描述
h(x)-y表示为
在这里插入图片描述
对于迭代公式,令j = 0
在这里插入图片描述
矩阵表达式
在这里插入图片描述

在这里插入图片描述

处理数据

def loadDataSet(filename):
    '''
        加载数据集
    :param filename: 数据集名称
    :return:
        dataMat : 文本数据集  类型 list
        labelMat: 标签数据集  类型 list
    '''
    dataMat = []
    labelMat = []
    fr = open(filename)
    for line in fr.readlines():
        lineArr = line.strip().split()
        if len(lineArr) == 1:
            continue
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
    return dataMat, labelMat

sigmoid函数

def sigmoid(inX):
    '''
    sigmoid: s型曲线图像
    tanh:类s型曲线图像 双曲正切
    :param inX: 参数X
    :return: 函数值Y
    '''
    return 2*1.0/(1+exp(-2*inX))-1

阶梯上升法

def gradAscent(dataMatIn,classLabels):
    '''

    :param dataMatIn: 文本集数组
    :param classLabels: 标签集列表
    :return:
    '''
    #转化为numpy矩阵
    dataMatrix = mat(dataMatIn)
    #转化为numpy矩阵并转置
    labelMat = mat(classLabels).transpose()
    #获取数据矩阵形状 m 文本数据量 n 特征量
    m, n = shape(dataMatrix)
    #步长
    alpha = 0.001
    #迭代次数
    maxCycles = 500
    #初始化回归系数
    weights = ones((n,1))
    for k in range(maxCycles):
        # h: m*1矩阵
        h = sigmoid(dataMatrix*weights)
        # error表示每一列上的误差情况
        error = (labelMat - h)
        #alpha * dataMatrix.transpose()*error表示 每一列的误差情况
        weights = weights + alpha * dataMatrix.transpose()*error
    return weights

接下来是随机梯度上升法,随机挑选一个样本进行梯度分析

def stocGradAscent0(dataMatrix,classLabels):
    '''
    随机梯度上升法
    :param dataMatrix:  文本集数组
    :param classLabels: 标签集列表
    :return:回归系数
    '''
    #获取形状
    m, n = shape(dataMatrix)
    alpha = 0.01
    #初始化矩阵
    weights = ones(n)
    for i in range(m):
        #求出f(x)的值
        h = sigmoid(sum(dataMatrix[i]* weights))
        #计算真实类别与预测类别之间的差值,调整回归系数
        error = classLabels[i] - h

        weights = weights + alpha * error * dataMatrix[i]

    return weights

由于处理数据时 可能遇到较大量数据,这时我们再一个一个处理数据会有较高的时间复杂度,批量化处理数据就是一个方法

def stocGradAscent1(dataMatrix, classLabels, numIter = 150):
    '''
        改进版的随机梯度下降,使用随机的一个样本来更新回归系数
    :param dataMatrix:
    :param classLabels:
    :param numIter: 迭代次数
    :return: weights 回归系数
    '''
    m, n = shape(dataMatrix)
    weights = ones(n)
    #随机梯度,循环150,观察是否收敛
    for j in range(numIter):
        dataIndex = [x for x in range(m)]
        for i in range(m):
            alpha = 4/(1.0 + j + i)+ 0.0001
            randIndex = int(random.uniform(0,len(dataIndex)))
            h = sigmoid(sum(dataMatrix[dataIndex[randIndex]]* weights))
            error = classLabels[dataIndex[randIndex]] - h
            weights = weights + alpha * error * dataMatrix[dataIndex[randIndex]]
            del (dataIndex[randIndex])
    return weights

数据可视化

def plotBestFit(dataArr, labelMat, weights):
    '''
        数据可视化
    :param dataArr:
    :param labelMat:
    :param weights:
    :return: none
    '''
    n = shape(dataArr)[0]
    xcord1 = []
    ycord1 = []
    xcord2 = []
    ycord2 = []
    for i in range(n):
        if int(labelMat[i]) == 1:
            xcord1.append(dataArr[i, 1])
            ycord1.append(dataArr[i, 2])
        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 = 's')
    ax.scatter(xcord2, ycord2, s=30, c='green')
    x = arange(-3.0, 3.0, 0.1)
    '''
    dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
    w0*x0+w1*x1+w2*x2=f(x)
    w0+w1*x+w2*y=0 => y = (-w0-w1*x)/w2   
    '''
    y = (-weights[0]-weights[1]*x)/weights[2]
    ax.plot(x,y)
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()

测试算法

def simpleTest():
    dataMat, labelMat = loadDataSet('../../testData/Logistic/TestSet.txt')

    dataArr = array(dataMat)

    weights = stocGradAscent1(dataArr, labelMat)
    # weights = stocGradAscent0(dataArr,labelMat)



    plotBestFit(dataArr, labelMat, weights)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值