Logistic回归
作者:互联网
文章目录
一、Logistic概述
我们用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称作回归。利用logistic回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。这里的“回归” 一词源于最佳拟合,表示要找到最佳拟合参数集。
logistic回归的一般过程
(1)收集数据:采用任意方法收集数据。
(2)准备数据:由于需要进行距离计算,因此要求数据类型为数值型。另外,结构化数据格式则最佳。
(3)分析数据:采用任意方法对数据进行分析。
(4)训练算法:大部分时间将用于训练,训练的目的是为了找到最佳的分类回归系数。
(5)测试算法:一旦训练步驟完成,分类将会很快。
(6)使用算法:首先,我们需要输入一些数据,并将其转换成对应的结构化数值;接着,基于训练好的回归系数就可以对这些数值进行简单的回归计算,判定它们属于哪个类别.,在这之后,我们就可以夺输出的类别上做一些其他分析工作。
二、Logistic回归算法
1、Logistic回归和sigmoid函数的分类
假设现在有一些数据点,我们利用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称作为回归。
Logistic回归一种二分类算法,它利用的是Sigmoid函数阈值在[0,1]这个特性。Logistic回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。其实,Logistic本质上是一个基于条件概率的判别模型。
下面我们看一下sigmoid函数,
sigmoid值域为[0,1],为了实现logistic回归分类,在每个特征上都乘以一个回归系数,然后把所有值相加,将这个总和带入到sigmoid函数中,进而得到一个范围在0-1之间的数值。任何大于0.5的数据被分入到1类,小于0.5的数据即被分入到0类。
2、最优回归系数确定:梯度上升算法
sigmoid的输入记为z,由下面的公式得出:
采用向量写法z = w(T) * x,表示将这两个数值向量对应元素相乘然后全部加起来得到z值。其中x是分类器的输入数据,向量w就是我们要找的最佳参数,接下来运用梯度上升算法求得数据集的最佳参数。
梯度上升法
基本思想:要找到某函数的最大值,最好的方法是沿着该函数的梯度方向探寻。
下面利用梯度上升算法找到最佳回归系数。数据包含两个数值型特征:X1和X2。
数据:
代码:
from numpy import *
def loaddataset():
dataMat = [] ; classlabel = [] # 建立数据和分类列表
fr = open('testSet.txt').readlines() #打开数据集,按行读取
# 遍历数据,存放到dataMat和classlabel
for line in fr:
lineArr = line.strip().split()
dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])]) # 方便计算,将X0的值设为1.0
classlabel.append(float(lineArr[2]))
return dataMat,classlabel
# sigmid函数
def sigmoid(x):
y = 1.0/(1+exp(-x))
return y
def gradAscent(dataMat,classlabel):
dataMatrix = mat(dataMat) # 转化为矩阵,方便后面计算
labelMatrix = mat(classlabel).transpose()
m,n = shape(dataMatrix) #dataMatrix行列数
alpha = 0.001 #设置步长
maxCycles = 500 # 迭代次数
weights = ones((n,1))
for k in range(maxCycles): # 不断更新系数weights
h = sigmoid(dataMatrix * weights)
error = labelMatrix - h #计算类别数值与预测的误差
weights = weights + alpha * dataMatrix.transpose() *error #更新参数
return weights
dataMat,classlabel = loaddataset()
weights = gradAscent(dataMat,classlabel)
print(weights)
系数weights结果如下:
上面已经解出了一组回归系数,它确立了不同类别数据之间的分割线,画出决策边界使其更加形象。
代码:
from numpy import *
import matplotlib.pyplot as plt
def loaddataset():
dataMat = [] ; classlabel = [] # 建立数据和分类列表
fr = open('testSet.txt').readlines() #打开数据集,按行读取
# 遍历数据,存放到dataMat和classlabel
for line in fr:
lineArr = line.strip().split()
dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])]) # 方便计算,将X0的值设为1.0
classlabel.append(float(lineArr[2]))
return dataMat,classlabel
# sigmid函数
def sigmoid(x):
y = 1.0/(1+exp(-x))
return y
def gradAscent(dataMat,classlabel):
dataMatrix = mat(dataMat) # 转化为矩阵,方便后面计算
labelMatrix = mat(classlabel).transpose()
m,n = shape(dataMatrix) #dataMatrix行列数
alpha = 0.001 #设置步长
maxCycles = 500 # 迭代次数
weights = ones((n,1))
for k in range(maxCycles): # 不断更新系数weights
h = sigmoid(dataMatrix * weights)
error = labelMatrix - h #计算类别数值与预测的误差
weights = weights + alpha * dataMatrix.transpose() *error #更新参数
return weights
# 决策边界绘画
def show(dataMat,classlabel,weights):
label = array(classlabel) #转化为数组
data = array(dataMat)
weights = array(weights)
# 创建两个类别的列表1、2
x1 = []; y1 = []
x2 = []; y2 = []
for i in range(len(label)):
if(label[i] == 1):
x1.append(data[i,1]); y1.append(data[i,2]) # x1为第一个特种类别为1的数据,y1为第二个特种类别为1的数据
else:
x2.append(data[i, 1]); y2.append(data[i, 2]) # x2为第一个特种类别为0的数据,y2为第二个特种类别为0的数据
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.scatter(x1,y1,s=30,c='red',marker='s',label='数据分析')
plt.scatter(x2,y2,s=30,c='green')
# 随机决策边界数据
x = arange(-3.0, 3.0, 0.01)
print(x)
y = (-weights[0] - weights[1] * x) / weights[2] #设置sigmoid函数为0,推出x和y的关系式
print(y)
plt.plot(x, y)
plt.title('BestFit')
plt.xlabel('x1')
plt.ylabel('x2')
plt.legend(loc="best")
plt.show()
dataMat,classlabel = loaddataset()
weights = gradAscent(dataMat,classlabel)
show(dataMat,classlabel,weights)
分类决策边界如下:
改进的随机梯度上升算法
随机梯度上升算法和梯度上升算法代码相似,但有些区别1、后者的变量h和误差error都是向量;2、前者没有矩阵的转换过程,所有都是numpy数组;3、alpha在每次迭代的时候都会调整;4、随机选取样本来更新回归系数。
改进的随机梯度上升算法有效地减少了计算量,收敛速度快,并保证了回归效果。
from numpy import *
def loaddataset():
dataMat = [] ; classlabel = [] # 建立数据和分类列表
fr = open('testSet.txt').readlines() #打开数据集,按行读取
# 遍历数据,存放到dataMat和classlabel
for line in fr:
lineArr = line.strip().split()
dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])]) # 方便计算,将X0的值设为1.0
classlabel.append(float(lineArr[2]))
return dataMat,classlabel
# sigmid函数
def sigmoid(x):
y = 1.0/(1+exp(-x))
return y
#改进的随机梯度算法
def gradAscent(dataMat,classlabel,numIter):
dataMat = array(dataMat) # 数组
m,n = shape(dataMat)
weights = ones(n)
for j in range(numIter):
dataIndex = range(m)
for i in range(m):
alpha = 4/(j+i+1.0) +0.01
randIndex = int(random.uniform(0,len(dataIndex))) # 选取随机数
h = sigmoid(sum(dataMat[randIndex]*weights))
error = classlabel[randIndex] - h #计算误差
weights = weights + alpha * error * dataMat[randIndex]
del(list(dataIndex)[randIndex]) # 删除迭代后的数据
return weights
dataMat,classlabel = loaddataset()
weights = gradAscent(dataMat,classlabel,150)
print(weights)
weights系数如下:
3、实战:疝气病症预测病马的死亡率
使用logstic回归来预测患有疝气病的马的存活问题,编程思想:把测试集上每个特征向量乘以最优化方法得来的回归系数,再将乘积结果求和,最后输入到sigmoid函数中即可。如果对应的sigmoid值大于0.5就预测类别标签为1,否则为0。
函数classifyVector作为判别函数,函数colicTest()打开测试集合训练集,并对数据进行处理。
代码:
数据:
from numpy import *
def sigmoid(x):
y = 1.0/(1+exp(-x))
return y
#改进的随机梯度算法
def gradAscent(dataMat,classlabel,numIter):
dataMat = array(dataMat) # 数组
m,n = shape(dataMat)
weights = ones(n)
for j in range(numIter):
dataIndex = range(m)
for i in range(m):
alpha = 4/(j+i+1.0) +0.01
randIndex = int(random.uniform(0,len(dataIndex))) # 选取随机数
h = sigmoid(sum(dataMat[randIndex]*weights))
error = classlabel[randIndex] - h #计算误差
weights = weights + alpha * error * dataMat[randIndex]
del(list(dataIndex)[randIndex]) # 删除迭代后的数据
return weights
# 判断函数
def classifyVector(x,weights):
prob = sigmoid(sum(x*weights))
if prob >0.5: # >0.5类别为1
return 1.0
else: # <0.5类别为0
return 0.0
def colicTest():
frTrain = open('horseColicTraining.txt').readlines() #打开训练集,按行读取
frTest = open('horseColicTest.txt').readlines()
trainingSet = []; trainingLabels = []
for line in frTrain:
currline = line.strip().split('\t')
lineArr = []
for i in range(len(currline)-1):
lineArr.append(float(currline[i]))
trainingSet.append(lineArr) # 存储训练数据
trainingLabels.append(float(currline[-1])) #存储训练数据类别
trainweights = gradAscent(array(trainingSet),trainingLabels,500) # 求最佳系数
errorcount = 0; numTestVec = 0.0
# 遍历测试数据
for line in frTest:
numTestVec += 1.0
currline = line.strip().split('\t')
lineArr = []
for i in range(len(currline) - 1):
lineArr.append(float(currline[i]))
# 判断当前数据的类别,如果预测类别不等于真实类别,错误errorcount加1
if int(classifyVector(array(lineArr),trainweights))!=int(currline[21]):
errorcount += 1
errorRate = (float(errorcount)/numTestVec) # 计算错误率
print("the error rate of this test is:%f"%errorRate)
return errorRate
# 调用colicTest()10次,取平均误差
def mutiTest():
numTests =10; errorSum =0.0
for k in range(numTests):
errorSum += colicTest()
print('after %d iterations the average error rate is:%f'%(numTests,errorSum/float(numTests)))
colicTest()
mutiTest()
结果如下所示:
标签:sigmoid,回归,weights,Logistic,classlabel,dataMat,数据,def 来源: https://blog.csdn.net/weixin_45422335/article/details/104914654