Logistic回归的优缺点:
优点:计算代价不高,易于理解和实现
缺点:容易欠拟合,分类精度可能不高
适用数据类型:数值型和标称型数据
Sigmoid函数:
sigmoid函数性质:当x为0时,Sigmoid函数值为0.5。随着x的增大,对应的Sigmoid值将逼近于1;随着x的减小,sigmoid值将逼近于0。
上述的z,由下面的公式得出:
其中的向量x是分类器的输入数据,向量w也就是我们要找到的最佳系数
# encoding: utf-8
import numpy as np
from numpy import *
import matplotlib
import matplotlib.pyplot as plt
#5-1 Logistic回归梯度上升优化算法
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])])
#除了将lineArr第一列和第二列加进来,还加入一列的1.0
labelMat.append(int(lineArr[2]))
return dataMat,labelMat
def sigmoid(inX):
return 1.0/(1+exp(-inX))
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
#5-2画出数据集和Logistic回归最佳拟合直线的函数
def plotBestFit(weights):
dataMat,labelMat = loadDataSet()
dataArr = array(dataMat)#转为Numpy中的数组
n = shape(dataArr)[0]
#shape函数是返回一个数组,只有shape[0]或者shape[1]才表示长度或者宽度
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)
#arange([start,stop,step)根据start与stop指定的范围以及step设定的步长,生成一个 ndarray。
y = ((-weights[0]-weights[1]*x)/weights[2]).transpose()
#找分割线就是令w0x0+w1x1+w2x2=0,其中x0=1,x1和x2就是x,y坐标,这就是y的由来
ax.plot(x,y)
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()
#5-3随机梯度上升法
def stocGradAscent0(dataMatrix, classLabels):
m,n = shape(dataMatrix)
alpha = 0.01
weights = ones(n)
for i in range(m):
h = sigmoid(sum(dataMatrix[i]*weights))
#和梯度上升算法不同的是,这里h是向量而不是数值
error = classLabels[i] - h
#error也是向量
weights = weights + alpha * error * dataMatrix[i]
return weights
#5-4改进的随机梯度上升算法
#为何改进?在每次迭代时会引发系数的剧烈改变,5-3的随机梯度上升算法并没有避免来回波动
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
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
#这样使得alpha在每次迭代时都改变,缓解5-3代码出现的数据波动或者高频波动
randIndex = int(random.uniform(0,len(dataIndex)))
#这里第二个改动就是通过随机选取样本来更新h
h = sigmoid(sum(dataMatrix[randIndex]*weights))
error = classLabels[randIndex] - h
weights = weights + alpha * error *dataMatrix[randIndex]
del(dataIndex[randIndex])
return weights
#总结一下,此方法的准确率已经与梯度下降法类似,但计算率却大大降低了。
python中numpy模块下函数array()和mat()的区别:
功能基本类似,有一些小差别
https://blog.csdn.net/Build_Tiger/article/details/79848808
#应用:预测兵马的死亡率
#5-5Logistic回归分类函数
def classifyVector(inX, weights):#第一个参数是特征向量,第二个参数是回归系数
prob = sigmoid(sum(inX * weights))
if prob > 0.5:
return 1.0
else:return 0.0
def colicTest():
frTrain = open('horseColicTraining.txt')
frTest = open('horseColicTest.txt')
trainingSet = [];trainingLabels = []
for line in frTrain.readlines():
currLine = line.strip().split('\t')
lineArr = []
for i in range(21):
lineArr.append(float(currLine[i]))#将每行数据加入到lineArr列表中
trainingSet.append(lineArr)#再讲所有数据加入到trainingSet列表中
trainingLabels.append(float(currLine[21]))
trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 200)
#使用随机梯度上升算法来计算回归系数向量
errorCount = 0;numTestVec = 0.0
for line in frTest.readlines():
numTestVec += 1.0 #numTestVec代表的是总样本数
currLine = line.strip().split('\t')
lineArr = []
for i in range(21):
lineArr.append(float(currLine[i]))
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()具有完全独立的功能,多次运行得到的结果可能稍有不同,因为是采用的是随机梯度上升算法
def multiTest():#调用colicTest()十次,来求平均值
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))
multiTest()