ivanxy

logistic regression (逻辑回归算法)

下面的函数与图为logistic regression的核心

LR算法解决主要解决分类问题的判别概率问题。现在常用在垃圾邮件判别、推荐系统、疾病预测等场景中。一般用来判决某件 事情属于某个分类的概率来确定类别。如:一封邮件是垃圾邮件概率是90%,则判定这封邮件是垃圾邮件;某个用户可能概率最大的三类产品为:华为手机80%,iPhone75%,魅族73%,其余的都小于73%,则给这个用户推荐的产品就是华为、iPhone、魅族;一个病人,根据他的年龄、患病历史、疼痛部位、疼痛状态等特征得出他得咽喉癌的概率是79%,则判定这个病人可能是咽喉癌。

 

逻辑回归算法计算公式

sigmoid函数,俗称激活函数

 

 

说了这么多,下面进入正题,pyhton的代码实现

初始化线性函数参数为1

构造sigmoid函数

重复循环I次

    计算数据集梯度

    更新线性函数参数

确定最终的sigmoid函数

输入训练(测试)数据集

运用最终sigmoid函数求解分类
伪代码
# -*- coding:utf-8 -*-

import numpy as np

import matplotlib.pyplot as plt

import random

 

 

def text2num(string):

    """

    :param string: string

    :return: list

    """

    str_list = string.replace("\n", " ").split(" ")

    while \'\' in str_list:

        str_list.remove(\'\')

    num_list = [float(i) for i in str_list]

    return num_list

 

 

def sigmoid(x):

    """

    :param x: 输入需要计算的值

    :return: 

    """

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

 

 

def data_plot(data_list, weight):

    """

    :param data_list:数据点集合 

    :param weight: 参数集合

    :return: null

    """

    x_data = [list(i[0:2]) for i in data_list if i[2] == 0.0]

    y_data = [list(i[0:2]) for i in data_list if i[2] == 1.0]

    x_data = np.reshape(x_data, np.shape(x_data))

    y_data = np.reshape(y_data, np.shape(y_data))

    linear_x = np.arange(-4, 4, 1)

    linear_y = (-weight[0] - weight[1] * linear_x) / weight[2]

    print(linear_y)

    plt.figure(1)

    plt.scatter(x_data[:, 0], x_data[:, 1], c=\'r\')

    plt.scatter(y_data[:, 0], y_data[:, 1], c=\'g\')

    print(linear_x)

    print(linear_y.tolist()[0])

    plt.plot(linear_x, linear_y.tolist()[0])

    plt.show()

 

 

def grad_desc(data_mat, label_mat, rate, times):

    """

    :param data_mat: 数据特征

    :param label_mat: 数据标签

    :param rate: 速率

    :param times: 循环次数

    :return: 参数

    """

    data_mat = np.mat(data_mat)

    label_mat = np.mat(label_mat)

    m,n = np.shape(data_mat)

    weight = np.ones((n, 1))

    for i in range(times):

        h = sigmoid(data_mat * weight)

        error = h - label_mat

        weight = weight - rate * data_mat.transpose() * error

    return weight

 

 

def random_grad_desc(data_mat, label_mat, rate, times):

    """

    :param data_mat: 数据特征

    :param label_mat: 数据标签

    :param rate: 速率

    :param times: 循环次数

    :return: 参数

    """

    data_mat = np.mat(data_mat)

    m,n = np.shape(data_mat)

    weight = np.ones((n, 1))

    for i in range(times):

        for j in range(m):

            h = sigmoid(data_mat[j] * weight)

            error = h - label_mat[j]

            weight = weight - rate * data_mat[j].transpose() * error

    return weight

 

 

def improve_random_grad_desc(data_mat, label_mat, times):

    """

    :param data_mat: 数据特征

    :param label_mat: 数据标签

    :param rate: 速率

    :param times: 循环次数

    :return: 参数

    """

    data_mat = np.mat(data_mat)

    m,n = np.shape(data_mat)

    weight = np.ones((n, 1))

    for i in range(times):

        index_data = [i for i in range(m)]

        for j in range(m):

            rate = 0.0001 + 4 / (i + j + 1)

            index = random.sample(index_data, 1)

            h = sigmoid(data_mat[index] * weight)

            error = h - label_mat[index]

            weight = weight - rate * data_mat[index].transpose() * error

            index_data.remove(index[0])

    return weight

 

 

def main():

    file = open("/Users/chenzu/Documents/code-machine-learning/data/LR", "rb")

    file_lines = file.read().decode("UTF-8")

    data_list = text2num(file_lines)

    data_len = int(len(data_list) / 3)

    data_list = np.reshape(data_list, (data_len, 3))

    data_mat_temp = data_list[:, 0:2]

    data_mat = []

    for i in data_mat_temp:

        data_mat.append([1, i[0], i[1]])

    print(data_mat)

    label_mat = data_list[:, 2:3]

 

 

    #梯度下降求参数

    weight = improve_random_grad_desc(data_mat, label_mat, 500)

    print(weight)

    data_plot(data_list, weight)

 

 

if __name__ == \'__main__\':

    main()
logistic regression

输出:

逻辑回归算法优缺点:

优点:计算代价不高、容易理解和实现

缺点:容易欠拟合,分类精度不高。

适用于数值型和标称型数据。

标称型:标称型目标变量的结果只在有限目标集中取值,如真与假(标称型目标变量主要用于分类)

数值型:数值型目标变量则可以从无限的数值集合中取值,如0.100,42.001等 (数值型目标变量主要用于回归分析)

 

 

下面是我结合一些博主的博客,搬运过来的

from numpy import *
filename=\'...\\testSet.txt\' #文件目录
def loadDataSet():   #读取数据(这里只有两个特征)
    dataMat = []
    labelMat = []
    fr = open(filename)
    for line in fr.readlines():
        lineArr = line.strip().split()
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])   #前面的1,表示方程的常量。比如两个特征X1,X2,共需要三个参数,W1+W2*X1+W3*X2
        labelMat.append(int(lineArr[2]))
    return dataMat,labelMat

def sigmoid(inX):  #sigmoid函数
    return 1.0/(1+exp(-inX))

def gradAscent(dataMat, labelMat): #梯度上升求最优参数
    dataMatrix=mat(dataMat) #将读取的数据转换为矩阵
    classLabels=mat(labelMat).transpose() #将读取的数据转换为矩阵
    m,n = shape(dataMatrix)
    alpha = 0.001  #设置梯度的阀值,该值越大梯度上升幅度越大
    maxCycles = 500 #设置迭代的次数,一般看实际数据进行设定,有些可能200次就够了
    weights = ones((n,1)) #设置初始的参数,并都赋默认值为1。注意这里权重以矩阵形式表示三个参数。
    for k in range(maxCycles):
        h = sigmoid(dataMatrix*weights)
        error = (classLabels - h)     #求导后差值
        weights = weights + alpha * dataMatrix.transpose()* error #迭代更新权重
    return weights

def stocGradAscent0(dataMat, labelMat):  #随机梯度上升,当数据量比较大时,每次迭代都选择全量数据进行计算,计算量会非常大。所以采用每次迭代中一次只选择其中的一行数据进行更新权重。
    dataMatrix=mat(dataMat)
    classLabels=labelMat
    m,n=shape(dataMatrix)
    alpha=0.01
    maxCycles = 500
    weights=ones((n,1))
    for k in range(maxCycles):
        for i in range(m): #遍历计算每一行
            h = sigmoid(sum(dataMatrix[i] * weights))
            error = classLabels[i] - h
            weights = weights + alpha * error * dataMatrix[i].transpose()
    return weights

def stocGradAscent1(dataMat, labelMat): #改进版随机梯度上升,在每次迭代中随机选择样本来更新权重,并且随迭代次数增加,权重变化越小。
    dataMatrix=mat(dataMat)
    classLabels=labelMat
    m,n=shape(dataMatrix)
    weights=ones((n,1))
    maxCycles=500
    for j in range(maxCycles): #迭代
        dataIndex=[i for i in range(m)]
        for i in range(m): #随机遍历每一行
            alpha=4/(1+j+i)+0.0001  #随迭代次数增加,权重变化越小。
            randIndex=int(random.uniform(0,len(dataIndex)))  #随机抽样
            h=sigmoid(sum(dataMatrix[randIndex]*weights))
            error=classLabels[randIndex]-h
            weights=weights+alpha*error*dataMatrix[randIndex].transpose()
            del(dataIndex[randIndex]) #去除已经抽取的样本
    return weights

def plotBestFit(weights):  #画出最终分类的图
    import matplotlib.pyplot as plt
    dataMat,labelMat=loadDataSet()
    dataArr = array(dataMat)
    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)
    y = (-weights[0]-weights[1]*x)/weights[2]
    ax.plot(x, y)
    plt.xlabel(\'X1\')
    plt.ylabel(\'X2\')
    plt.show()

def main():
    dataMat, labelMat = loadDataSet()
    weights=gradAscent(dataMat, labelMat).getA()
    plotBestFit(weights)

if __name__==\'__main__\':
    main()
Logistic回归

输出:

-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
0.850433    6.920334    1
1.347183    13.175500   0
1.176813    3.167020    1
-1.781871   9.097953    0
-0.566606   5.749003    1
0.931635    1.589505    1
-0.024205   6.151823    1
-0.036453   2.690988    1
-0.196949   0.444165    1
1.014459    5.754399    1
1.985298    3.230619    1
-1.693453   -0.557540   1
-0.576525   11.778922   0
-0.346811   -1.678730   1
-2.124484   2.672471    1
1.217916    9.597015    0
-0.733928   9.098687    0
-3.642001   -1.618087   1
0.315985    3.523953    1
1.416614    9.619232    0
-0.386323   3.989286    1
0.556921    8.294984    1
1.224863    11.587360   0
-1.347803   -2.406051   1
1.196604    4.951851    1
0.275221    9.543647    0
0.470575    9.332488    0
-1.889567   9.542662    0
-1.527893   12.150579   0
-1.185247   11.309318   0
-0.445678   3.297303    1
1.042222    6.105155    1
-0.618787   10.320986   0
1.152083    0.548467    1
0.828534    2.676045    1
-1.237728   10.549033   0
-0.683565   -2.166125   1
0.229456    5.921938    1
-0.959885   11.555336   0
0.492911    10.993324   0
0.184992    8.721488    0
-0.355715   10.325976   0
-0.397822   8.058397    0
0.824839    13.730343   0
1.507278    5.027866    1
0.099671    6.835839    1
-0.344008   10.717485   0
1.785928    7.718645    1
-0.918801   11.560217   0
-0.364009   4.747300    1
-0.841722   4.119083    1
0.490426    1.960539    1
-0.007194   9.075792    0
0.356107    12.447863   0
0.342578    12.281162   0
-0.810823   -1.466018   1
2.530777    6.476801    1
1.296683    11.607559   0
0.475487    12.040035   0
-0.783277   11.009725   0
0.074798    11.023650   0
-1.337472   0.468339    1
-0.102781   13.763651   0
-0.147324   2.874846    1
0.518389    9.887035    0
1.015399    7.571882    0
-1.658086   -0.027255   1
1.319944    2.171228    1
2.056216    5.019981    1
-0.851633   4.375691    1
-1.510047   6.061992    0
-1.076637   -3.181888   1
1.821096    10.283990   0
3.010150    8.401766    1
-1.099458   1.688274    1
-0.834872   -1.733869   1
-0.846637   3.849075    1
1.400102    12.628781   0
1.752842    5.468166    1
0.078557    0.059736    1
0.089392    -0.715300   1
1.825662    12.693808   0
0.197445    9.744638    0
0.126117    0.922311    1
-0.679797   1.220530    1
0.677983    2.556666    1
0.761349    10.693862   0
-2.168791   0.143632    1
1.388610    9.341997    0
0.317029    14.739025   0
此代码用到的数据

下面的博客是某博主利用excel和spss搞的,写的不错

https://www.cnblogs.com/nxld/p/6124235.html?utm_source=itdadao&utm_medium=referral

 

下面顺便介绍一下过拟合问题

过拟合问题
过拟合即是过分拟合了训练数据,使得模型的复杂度提高,繁华能力较差(对未知数据的预测能力)
下面左图即为欠拟合,中图为合适的拟合,右图为过拟合。

2)过拟合主要原因
过拟合问题往往源自过多的特征
解决方法
1)减少特征数量(减少特征会失去一些信息,即使特征选的很好)
• 可用人工选择要保留的特征;
• 模型选择算法;
2)正则化(特征较多时比较有效)
• 保留所有特征,但减少θ的大小

(3)正则化方法
正则化是结构风险最小化策略的实现,是在经验风险上加一个正则化项或惩罚项。正则化项一般是模型复杂度的单调递增函数,模型越复杂,正则化项就越大。

正则项可以取不同的形式,在回归问题中取平方损失,就是参数的L2范数,也可以取L1范数。取平方损失时,模型的损失函数变为:

lambda是正则项系数:
• 如果它的值很大,说明对模型的复杂度惩罚大,对拟合数据的损失惩罚小,这样它就不会过分拟合数据,在训练数据上的偏差较大,在未知数据上的方差较小,但是可能出现欠拟合的现象;
• 如果它的值很小,说明比较注重对训练数据的拟合,在训练数据上的偏差会小,但是可能会导致过拟合。
正则化后的梯度下降算法θ的更新变为:

在逻辑回归实战中有详细介绍及代码实现,有人看到这篇文章想要的。请加qq:761256405

 

分类:

技术点:

相关文章: