利用Logistic回归进行分类的主要思想是,根据现有数据对分类边界建立回归公式,以此进行分类。
这里的回归表示要找到最佳拟合参数集。训练分类器就是要寻找最佳拟合参数。
优点:计算代价不高、易于理解实现
缺点:容易欠拟合、分类精度可能不高
使用数据类型:数值型和标称型
Sigmoid函数:能够接受所有的输入然后预测出类别,在两个类的情况下,输出0或1。
计算公式f(x)=1/(1+e^-x)。
当x为0时,Sigmoid函数值为0.5。随着x的增大,对应的值逼近于1;随着x的减小,值逼近于0。
要实现Logistic回归分类器,在每个特征上乘以一个回归系数,然后把结果相加代入Sigmoid函数即可。
任何大于0.5的数据分为1类,小于0.5分为0类。
如何确定最佳回归系数:
若将Sigmoid函数的输入记为向量z,则z=w0x0+w1x1+...+wnxn,它表示系数向量与特征向量对应元素相乘后再相加的值。
寻找最佳系数要用到最优化理论。
梯度上升算法:
要找到某函数最大值,最好沿着该函数的梯度方向探寻。
如果梯度记为▽,则函数f(x,y)的梯度表示为:▽f(x,y)={∂f(x,y)/∂x, ∂f(x,y)/∂y},意味着沿x方向移动∂f(x,y)/∂x,沿y方向移动∂f(x,y)/∂y。
其中函数f(x,y)必须要在待计算的点上有定义且可微。
梯度算子总是指向函数值增长最快的方向。移动量称为步长,记做α。
用向量来表示梯度上升算法的迭代公式:w:=w+α▽_w{f(w)}
该公式将一直被迭代执行,直到迭代次数达到某个值或达到算法允许的误差范围。
梯度上升算法在每次更新回归系数时都要重新遍历整个数据集,复杂度太高。
一次仅用一个样本点来更新回归系数,称为随机梯度上升算法。
它可以在新样本到来时对分类器进行增量式更新,因此是一个在线学习算法。
# coding=gbk
from numpy import *
def loadDataSet(filename):
"""
从文件中读取数据
Returns:
dataMat: 数据集
labelMat: 标签集
"""
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
labelMat.append(int(lineArr[2])) # 第三个值属于标签集
return dataMat, labelMat # 返回数据集与标签集
def sigmoid(inX):
"""
Sigmoid 函数
"""
return 1.0 / (1 + exp(-inX))
def gradAscent(dataMatIn, classLabels):
"""
梯度上升算法
Args:
dataMatIn: 数据集,二维矩阵,每列代表不同的特征,每行代表训练样本
classLabels: 标签集,类别标签,是一个一维向量
Returns:
weights: 回归系数
"""
dataMatrix = mat(dataMatIn) # 数据样本矩阵
labelMat = mat(classLabels).transpose() # 标签矩阵的转置
m, n = shape(dataMatrix) # 读取矩阵的大小 m * n,m 是行数,n是列数
alpha = 0.001 # 向目标移动的步长
maxCycles = 500 # 迭代次数
weights = ones((n, 1)) # 创建 n*1 的数组
for k in range(maxCycles):
h = sigmoid(dataMatrix * weights) # 矩阵相乘,得到一个 m * 1 的矩阵
error = (labelMat - h)
weights = weights + alpha * dataMatrix.transpose() * error # 梯度上升算法的迭代公式
return weights
def stocGradAscent0(dataMatIn, classLabels):
"""
随机梯度上升算法 beta
"""
dataMatrix = array(dataMatIn)
m, n = shape(dataMatrix)
alpha = 0.01
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 weigths
def stocGradAscent1(dataMatIn, classLabels, numIter = 150):
"""
随机梯度上升算法
"""
dataMatrix = array(dataMatIn)
m, n = shape(dataMatrix)
weights = ones(n)
for j in range(numIter):
dataIndex = range(m)
for i in range(m):
alpha = 4 / (1.0 + j + i) + 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
def plotBestFit(dataMatIn, classLabels, wei):
"""
画出数据集和Logistic回归最佳拟合直线的函数
"""
import matplotlib.pyplot as plt
#weights = wei.getA()
weights = wei
dataMat, labelMat = dataMatIn, classLabels
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()