利用Logistic回归进行分类的主要思想是:根据现有数据对分类边界建立回归公式,以此进行分类。
最优化算法:梯度上升法和一个改进的随机梯度上升法
训练算法:使用梯度上升找到最佳参数
.read() 每次读取整个文件,.readlines()自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for… in … 结构进行处理,.readline()每次只读取一行,通常比 .readlines()慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用.readline()。
Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。
str.strip([chars]);chars – 移除字符串头尾指定的字符序列。
返回移除字符串头尾指定的字符生成的新字符串。
str = "00000003210Runoob01230000000";
print str.strip( '0' ); # 去除首尾字符 0
str2 = " Runoob "; # 去除首尾空格
print str2.strip();
以上实例输出结果如下:
3210Runoob0123
Runoob
Python split() 通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则仅分隔 num 个子字符串
str.split(str=”“, num=string.count(str)).
str – 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
num – 分割次数。
返回分割后的字符串列表。
str = "Line1-abcdef \nLine2-abc \nLine4-abcd";
print str.split( );
print str.split(' ', 1 );
以上实例输出结果如下:
['Line1-abcdef', 'Line2-abc', 'Line4-abcd']
['Line1-abcdef', '\nLine2-abc \nLine4-abcd']
zeros():可以用来构造全零矩阵
>>> zeros(3)
array([ 0., 0., 0.])
>>> zeros((3,3))
array([[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]])
ones(): 可以用来构造全一矩阵
>>> ones((3,3))
array([[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]])
eyes(): 可以用来构造单位矩阵
>>> eye(3)
array([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
.shape()
输入参数:类似数组(比如列表,元组)等,或是数组
返回:一个整型数字的元组,元组中的每个元素表示相应的数组每一维的长度
>>> e = eye(3)
>>> e
array([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
>>> e.shape
(3, 3)
Logistic回归梯度上升优化算法:
from numpy import *
def loadDataSet():#打开文本文件testSet.txt并逐行读取
#每行前两个值分别是X1和X2,第三个值是数据对应的类别标签
dataMat = []; labelMat = []
fr = open('testSet.txt')#打开文本文件testSet.txt
for line in fr.readlines():#逐行读取
lineArr = line.strip().split()
dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])#存放数据X1和X2
labelMat.append(int(lineArr[2]))#存放第三个值标签
return dataMat,labelMat
def sigmoid(inX):
return 1.0/(1+exp(-inX))
def gradAscent(dataMatIn,classLabels):#dataMatIn是一个2维Numpy数组,每列分别代表每个不同的特征,每行则代表每个训练样本
dataMatrix = mat(dataMatIn)#mat创建矩阵
labelMat = mat(classLabels).transpose()#为了方便矩阵进行计算,将原向量进行转置
m,n = shape(dataMatrix)
alpha = 0.001
maxCycles = 500
weights = ones((n,1))#构建n行1列的全1矩阵
for k in range(maxCycles):
h = sigmoid(dataMatrix * weights)
error = (labelMat - h)#计算真实类别与预测类别的差值,按照差值的方向调整回归系数
weights = weights + alpha * dataMatrix.transpose() * error
return weights
求得最优回归系数
>>> import logRegres
>>> from imp import reload
>>> reload(logRegres)
<module 'logRegres' from 'E:\\Python\\logRegres.py'>
>>> dataArr,labelMat=logRegres.loadDataSet()
>>> logRegres.gradAscent(dataArr,labelMat)
matrix([[ 4.12414349],
[ 0.48007329],
[-0.6168482 ]])
中间把readlines 写成了readLine
报错ValueError: could not convert string to float: ‘-‘
分析数据:画出决策边界
arange:
>>> np.arange(3)
array([0, 1, 2])
>>> np.arange(3.0)
array([ 0., 1., 2.])
>>> np.arange(3,7)
array([3, 4, 5, 6])
>>> np.arange(3,7,2)
array([3, 5])
y = (-weights[0]-weights[1]*x)/weights[2]#最佳拟合直线
在这里设置了sigmoid函数为0,0是两个分类(类别1和类别0)的分解处,因此,设定0 = w0x0 + w1x1 + w2x2,然后解出X2和X1的关系式。
getA()函数与mat()函数的功能相反,是将一个numpy矩阵转换为数组
画出数据集和Logistic回归最佳拟合直线的函数
def plotBestFit(weights):
import matplotlib.pyplot as plt
dataMat,labelMat = loadDataSet()
dataArr = array(dataMat)
n = shape(dataArr)[0]#dataArr有几行
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)
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()
尽管例子简单且数据集很小,这个方法需要大量的计(300次乘法),下一节对算法做改进。