Logistic回归

                            Logistic回归

1.什么是回归
  将离散的数据用一条线来拟合,这个过程叫做回归
在这里插入图片描述
2.那什么是Logistic回归
  简单来说就是根据现有数据对分类边界线建立回归公式,以此进行分类。因此Logistic regression虽然被称为回归,但实际上是分类模型。它是一种用于解决二分类问题的机器学习方法,用于估计某种事物的可能性 ,比如你能不能追到女朋友,会不会中彩票之类,这种结果是1 or 0的问题。


3.Logisitc回归的一般过程
  (1)收集数据:任意方法收集数据
  (2)准备数据:由于需要进行距离的计算,因此要求数据类型 为数值型。当然结构化数据最好啦
  (3)分析数据:不择一切手段对数据进行分析
  (4)训练算法:训练目的就是为了找到最佳的分类回归系数
  (5)测试算法:看看能不能用
  (6)使用算法:输入数据并转化成结构化数据;利用训练好的回归系数对这些数值进行简单的回归计算,判断它们属于哪个类别

4. 绘制数据集
既然Logistic回归要收集准备数据,那我们不妨将数据绘制出来,更直观一点

代码如下

import matplotlib.pyplot as plt
import numpy as np

"""
函数说明:加载数据函数
Parameters:
   dataMat   数据列表
   labelMat  标签列表
Returns:
   dataMat   数据列表
   labelMat  标签列表
"""
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]))  #添加标签
   fr.close()  #关闭文件
   return dataMat, labelMat



"""
函数说明:绘制函数
"""
def plotDataSet():
    dataMat, labelMat = loadDataSet()   #加载数据集
    dataArr = np.array(dataMat)   #转换成numpy的array数组
    n = np.shape(dataMat)[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])  #1为正样本
        else:
            xcord2.append(dataArr[i, 1]);ycord2.append(dataArr[i, 2])  #0为负样本
    fig = plt.figure()
    ax = fig.add_subplot(111)  # 添加subplot
    ax.scatter(xcord1, ycord1, s=20, c='red', marker='s', alpha=.5)  # 绘制正样本
    ax.scatter(xcord2, ycord2, s=20, c='green', alpha=.5)  #绘制负样本
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.title('数据集')  #绘制title
    plt.xlabel('x')
    plt.ylabel('y')  #绘制label
    plt.show()   #显示

"""
函数说明:主函数
"""
if __name__ == '__main__':
    plotDataSet()

在这里插入图片描述

数据集 testSet.txt

-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

我对代码详细解释

  • ax.scatter(xcord1, ycord1, s=20, c='red', marker='s', alpha=.5) s 大小 c 颜色 marker 形状 alpha透明度
    对于scatter函数各类参数详见
  • plt.title('数据集') #绘制titleMatplotlib默认是不支持显示中文字符的,因此在最前边设置这两条属性即可
    plt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus'] = False

5.基于Logistic回归和Sigmoid函数的分类

- Logisic回归
优点:计算代价不高,易于理解和实现
缺点:容易欠拟合,分类精度可能不高
- Sigmoid函数
 通过上面我们对Logistic回归的解释,我们在选择分类器函数时,由两个条件必须满足
(1)取值在0-1之间
(2)对一个事件发生的概率,50%是其结果的分水岭,选择函数应该关于0.5中心对称
对于好多好多的预测问题我们只想要得到0和1的答案,but好多输出结果不尽人意,也许是0.6.因此我们用这个函数曲线进行预测,当输入的数据待入Sigmoid函数,得到一个在光滑曲线上的某个点,如果该点大于0.5,认为事件的概率为1,若该点小于0.5,认为概率为0.


6. 寻找最佳参数

线性回归模型
在这里插入图片描述
Sigmoid函数
在这里插入图片描述
Logistic回归是处理二分类问题,所以输出的标记y={0,1},并且线性回归模型产生的预测值z是一个实值,所以我们将实值z转化成0/1值便可,即带入Sigmoid函数中。即将线性函数的结果映射到Sigmoid函数中将结果约束到0-1范围内。

而对于线性回归方程来说:
x 分类器输入的数据
w 最佳参数
而为了寻找该最佳参数,需要用到最优化理论的一些知识
介绍的第一个最优化算法叫做梯度上升法

  • 我们由梯度下降法进行引入

在这里插入图片描述
 梯度下降法(gradient descent)是一种常用的一阶(first-order)优化方法,是求解无约束优化问题最简单、最经典的方法之一。我们来考虑一个无约束优化问题min f(x) , 其中f(x)为连续可微函数,如果我们能够构造一个序列
在这里插入图片描述
并满足:

在这里插入图片描述

那么我们就能够不断执行该过程即可收敛到局部极小点,如下。

在这里插入图片描述

那么问题就是如何找到下一个点并满足
[公式]
在这里插入图片描述

- 而对于梯度上升法来说,只不过是将减号改为加号罢了。


梯度上升法的伪代码:

  • 每个回归系数初始化为1
  • 重复R次
    -计算整个数据集的梯度
    -使用alpha*gradient更新回归系数的向量
    -返回回归系数

代码实现如下

import numpy as np

"""
函数说明:加载数据函数
Parameters:
  dataMat   数据列表
  labelMat  标签列表
Returns:
  dataMat   数据列表
  labelMat  标签列表
"""
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]))  #添加标签
  fr.close()  #关闭文件
  return dataMat, labelMat


"""
函数说明:sigmoid函数
Parameters:
   inX - 数据
Returns:
   sigmoid函数
"""
def sigmoid(inX):
   return 1.0 / (1 + np.exp(-inX))


"""
函数说明:梯度上升算法
Parameters:
  dataMatIn - 数据集
  classLabels - 数据标签
Returns:
  weights.getA() - 求得的权重数组(最优参数)
"""
def gradAscent(dataMatIn, classLabels):
  dataMatrix = np.mat(dataMatIn)   #dataMatIn数据集   转换成numpy的mat
  labelMat = np.mat(classLabels).transpose()   #classLabels数据标签  转换成numpy的mat,并进行转置(便于计算)
  m, n = np.shape(dataMatrix)    #返回dataMatrix的大小。m为行数(数据量),n为列数(特征数)
  alpha = 0.001      #移动步长,也就是学习速率,控制更新的幅度。
  maxCycles = 500     #最大迭代次数
  weights = np.ones((n, 1))   #生成一个长度和特征数相同的矩阵,此处n为3
  for k in range(maxCycles):
      h = sigmoid(dataMatrix * weights)  #梯度上升矢量化公式
      error = labelMat - h
      weights = weights + alpha * dataMatrix.transpose() * error           #就是那个梯度算法的公式嘛
  return weights.getA()       #将矩阵转换为数组,返回权重数组


"""
函数说明:主函数
"""
if __name__ == '__main__':
  dataMat, labelMat = loadDataSet()
  print(gradAscent(dataMat, labelMat))

根据计算结果,我们很容易得到回归系数[W0,W1,W2]
在这里插入图片描述

8.分析数据:使用matplotlib画出决策边界
  上面已经解出了便于一组回归系数,确定了不同类别数据之间的分割线。为了我们开展之后的各类分析工作,我们将使用matplotlib画出决策边界,从而使得优化的过程易于理解

代码实现如下

import matplotlib.pyplot as plt
import numpy as np

"""
函数说明:加载数据
Parameters:
    dataMat   数据列表
    labelMat  标签列表
Returns:
    dataMat   数据列表
    labelMat  标签列表
"""


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]))  # 添加标签
    fr.close()  # 关闭文件
    return dataMat, labelMat


"""
函数说明:sigmoid函数
Parameters:
    inX - 数据
Returns:
    sigmoid函数
"""
def sigmoid(inX):
    return 1.0 / (1 + np.exp(-inX))


"""
函数说明:梯度上升算法
Parameters:
    dataMatIn - 数据集
    classLabels - 数据标签
Returns:
    weights.getA() - 求得的权重数组(最优参数)
"""
def gradAscent(dataMatIn, classLabels):
    dataMatrix = np.mat(dataMatIn)  # 转换成numpy的mat
    labelMat = np.mat(classLabels).transpose()  # 转换成numpy的mat,并进行转置
    m, n = np.shape(dataMatrix)  # 返回dataMatrix的大小。m为行数,n为列数。
    alpha = 0.001  # 移动步长,也就是学习速率,控制更新的幅度。
    maxCycles = 500  # 最大迭代次数
    weights = np.ones((n, 1))
    for k in range(maxCycles):
        h = sigmoid(dataMatrix * weights)  # 梯度上升矢量化公式
        error = labelMat - h
        weights = weights + alpha * dataMatrix.transpose() * error
    return weights.getA()  # 将矩阵转换为数组,返回权重数组


"""
函数说明:绘制数据集
Parameters:
    weights - 权重参数数组
Returns:
    无
"""
def plotBestFit(weights):
    dataMat, labelMat = loadDataSet()  # 加载数据集
    dataArr = np.array(dataMat)  # 转换成numpy的array数组
    n = np.shape(dataMat)[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])  # 1为正样本
        else:
            xcord2.append(dataArr[i, 1]);
            ycord2.append(dataArr[i, 2])  # 0为负样本
    fig = plt.figure()
    ax = fig.add_subplot(111)  # 添加subplot
    ax.scatter(xcord1, ycord1, s=20, c='red', marker='s', alpha=.5)  # 绘制正样本
    ax.scatter(xcord2, ycord2, s=20, c='green', alpha=.5)  # 绘制负样本
    x = np.arange(-3.0, 3.0, 0.1)
    y = (-weights[0] - weights[1] * x) / weights[2]
    ax.plot(x, y)
    plt.title('BestFit')  # 绘制title
    plt.xlabel('X1')
    plt.ylabel('X2')  # 绘制label
    plt.show()

"""
函数说明:主函数
"""
if __name__ == '__main__':
    dataMat, labelMat = loadDataSet()
    weights = gradAscent(dataMat, labelMat)
    plotBestFit(weights)

在这里插入图片描述
 这个分类器分类效果不错,从图上看只分错了几个点而已,但是回顾对算法的原理的解析,我们却发现这个这个方法需要相当大量的计算(迭代300次的乘法与加法),因此下一步我们将对其进行改进,从而使它可以运用在我们现实生活中,处理例子复杂数量大的数据集
结构解析

  • loadDataSet()函数功能:
    打开文本文件testSet.txt并逐行读取。每行前两个值为X1和X2,第三个值是数据对应的标签
  • gradAscent()函数
    1.两个参数dataMathIn.labelMat
    First是dataMathIn,它是一个二维Numpy数组,每 列代表不同的特征,每行代表每个训练样本。我们现在使用的是一个存有100个样本的简单数据集,它包含了两个特征X1和X2,再加上一个0维的特征,因此dataMathln里存放的是一个1003的数组。因此我们使用numpy中的mat函数将数组转化为矩阵便于计算。
    Second是类别标签,它是一个1
    100的行向量。不过为了便于计算,我们的做法是将原向量转置再将其赋值给labelMat
    2.梯度上升算法中的参数
    alpha是向目标移动的步长
    maxCycles是迭代次数
    在for循环迭代完成后,将返回一个训练好的回归系数

新手对于代码的详细解释

  • lineArr = line.strip().split() 去回车,放入列表
    strip()函数用于移除字符串头尾指定的字符(默认为空格或者换行符)或字符序列
    split()函数用于拆分字符串,split()不带参数时以空格进行分割

  • dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
    1.描述
    append()函数用于在列表末尾添加新的对象
    2.语法
    list.append(obj)
    list 列表对象
    obj 添加到列表末尾的对象
    注意:append()函数无返回值,但是会修改原本的列表
    3.例子

list = ['hello', 'python', 'world']
list.append(2020)
print('list(updated):',list)

在这里插入图片描述

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值