logistic回归是个最优化算法
用一条直线对这些直线进行拟合(该线称为:最佳拟合直线)该拟合过程称为回归,即找到最佳拟合参数
主要思想:根据现有数据对分类边界线建立回归公式,一次进行分类
优点:计算代价不高,易于理解和实现
缺点:容易欠拟合,分类精度可能不高
适合数据类型:数据型和标称型数据
Sigmoid函数作为 σ(z) = 1/(1+e^-z) 阶跃函数
为实现logistic回归分类器。每一个特征上都乘以一个回归系数,最后结果相加,将总和带入Sigmoid函数
进而得到一个范围在0-1之间的数值。这样大于0.5的数据分入1类,小于0.5的数据分为0类
from numpy import *
# 载入数据集 返回数据矩阵和便签矩阵
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]))
return dataMat , labelMat
# sigmoid()函数 返回0-1的一个值
def sigmoid(inX):
# math.exp()只能处理标准的数值 需要调用 numpy.exp()
return 1.0/(1+exp(-inX))
# logistic回归梯度上升优化算法
def gradAscent(dataMatIn , classLabels):
dataMatrix = mat(dataMatIn)
labelMat = mat(classLabels).transpose()
m , n = shape(dataMatrix)
alpha = 0.001
maxCycles = 500
weights = ones((n,1))
# 梯度迭代公式
for k in range(maxCycles):
h = sigmoid(dataMatrix*weights)
error = (labelMat - h)
weights = weights + alpha*dataMatrix.transpose()*error
return weights
# 画出数据集和logistic回归最佳拟合直线的函数
def plotBestFit(wei):
import matplotlib.pyplot as plt
if isinstance(wei,matrix):
weights = wei.getA()
else:
weights = wei
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()
# 梯度上升算法在每次更新回归系数时都需要遍历整个数据集
# 该方法在处理100个左右的数据时尚可,如果数据集变大,
# 计算复杂度太高
# 随机梯度上升
# 一种改进算法 一次仅用一个样本来更新回归系数
# 由于可以在新样本到来时对分类器进行增量式更新
# 因此随机梯度上升算法是一个“在线学习算法”
# 与在线学习算法相对应的是一次处理所有数据即“批处理”
# 随机梯度上升算法
def stocGradAscent0(dataMatrix , classLabels):
m ,n = shape(dataMatrix)
alpha = 0.01
# Numpy数组类型
# 随机梯度上升算法 h 和误差 error 都是数值 没有矩阵转换过程
# 梯度上升算法 h 和 error是向量
weights = ones(n)
for i in range(m):
h = sigmoid(sum(dataMatrix[i]*weights))
error = classLabels[i] - h
weights = weights +alpha * error * dataMatrix[i]
return weights
# 随机梯度上升算改进
def stocGradAscent1(dataMatrix , classLabels , numIter = 150):
m , n = shape(dataMatrix)
weights = ones(n)
for j in range(numIter):
# dataIndex = range(m)
# range 不能用删除 转换为list
# python 3.x range返回的是range对象不再是list对象 需要转换为list对象
dataIndex = list(range(m))
for i in range(m):
alpha = 4/(1.0+j+1)+0.01
randIndex = int(random.uniform(0,len(dataIndex)))
h = sigmoid(sum(dataMatrix[randIndex]*weights))
error = classLabels[randIndex] - h
weights = weights + alpha*error*dataMatrix[randIndex]
del dataIndex[randIndex]
return weights
# 1
# dataArr , labelMat = loadDataSet()
# weights = gradAscent(dataArr , labelMat)
# plotBestFit(weights)
# 2
# dataArr1 , labelMat1 = loadDataSet()
# weights1 = stocGradAscent0(array(dataArr1) , labelMat1)
# 3
dataArr2 , labelMat2 = loadDataSet()
weights2 = stocGradAscent1(array(dataArr2),labelMat2,500)
plotBestFit(weights2)
运行截图:
testSet.txt下载地址: