logistic回归:
回归的基本思想:根据训练数据和分类边界线方程(方程参数未知),得到最佳拟合参数集,从而实现数据的分类。
Logistic回归又称logistic回归分析,是一种广义的线性回归分析模型,常用于数据挖掘、疾病自动诊断和经济预测等领域。
通常,Logistic回归适用于二值型输出分类,即二分类,也就是分类结果只有两种情况:是与否,发生与不发生等。
logistic回归的一般过程:
Sigmod函数:
既然,Logistic回归的输出只有两种情况,那么我们有必要引入一种函数,该函数只有两种输出,0或者1。有人可能会想到单位阶跃函数,没错,确实可以,但是考虑到单位阶跃函数是分段函数,其在x=0处的跳变不方便用代码处理。故此,我们介绍另外一种函数——Sigmod函数。其实,从数学的角度上讲,这也是一种阶跃函数。
Sigmoid函数也叫Logistic函数,取值范围为(0,1),它可以将一个实数映射到(0,1)的区间,可以用来做二分类。
梯度下降算法:
梯度下降(Gradient descent )是利用一阶的梯度信息找到函数局部最优解的一种方法,也是机器学习里面常用的一种优化方法。
其基本思想:由于梯度方向是某一个函数值域变化最快的方向,所以要找函数的最值,最好的办法就是沿该函数的梯度方向寻找。
使用python实现logistic
数据集:
TestSet.txt
解析数据:
def loadDataSet(file_name):
'''
Desc:
加载并解析数据
Args:
file_name -- 要解析的文件路径
Returns:
dataMat -- 原始数据的特征
labelMat -- 原始数据的标签,也就是每条样本对应的类别。即目标向量
'''
# dataMat为原始数据, labelMat为原始数据的标签
dataMat = []
labelMat = []
fr = open(file_name)
for line in fr.readlines():
lineArr = line.strip().split()
# 为了方便计算,我们将 X0 的值设为 1.0 ,也就是在每一行的开头添加一个 1.0 作为 X0
dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
labelMat.append(int(lineArr[2]))
return dataMat, labelMat
sigmoid函数:
# sigmoid阶跃函数
def sigmoid(inX):
# return 1.0 / (1 + exp(-inX))
return 1.0/(1+np.exp(-inX))
定义Logistic 回归梯度上升优化算法
def gradAscent(dataMatIn, classLabels):
#用mat函数将列表转换成numpy矩阵
dataMatrix = np.mat(dataMatIn)
#用mat函数将列表转换成numpy矩阵,并进行转置
labelMat = np.mat(classLabels).transpose()
#返回dataMatrix的大小。m为行数,n为列数。
m,n = np.shape(dataMatrix)
#移动步长,也就是学习速率,控制更新的幅度。
alpha = 0.001
#最大迭代次数
maxCycles = 500
# weights 代表回归系数, 此处的 ones((n,1)) 创建一个长度和特征数相同的矩阵,其中的数全部都是 1
weights = np.ones((n,1))
for k in range(maxCycles):
# m*3 的矩阵 * 3*1 的矩阵 = m*1的矩阵
h = sigmoid(dataMatrix*weights)
# labelMat是实际值,labelMat - 是两个向量相减
error = (labelMat - h)
# 0.001* (3*m)*(m*1) 表示在每一个列上的一个误差情况,最后得出 x1,x2,xn的系数的偏移量
# 矩阵乘法,最后得到回归系数
weights = weights + alpha * dataMatrix.transpose() * error
return np.array(weights)
画出数据集和 Logistic 回归最佳拟合直线的函数
# 画出数据集和 Logistic 回归最佳拟合直线的函数
def plotBestFit(dataArr, labelMat, weights):
n = np.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 = np.arange(-3.0, 3.0, 0.1)
y = (-weights[0]-weights[1]*x)/weights[2]
ax.plot(x, y)
plt.xlabel('X'); plt.ylabel('Y')
plt.show()
得出结果:
使用 Logistic 回归进行分类
def testLR():
dataMat, labelMat = loadDataSet("TestSet.txt")
dataArr = np.array(dataMat)
weights = gradAscent(dataArr, labelMat)
plotBestFit(dataArr, labelMat, weights)
得出结果:
完整代码如下:
import matplotlib.pyplot as plt
import numpy as np
#解析数据
def loadDataSet(file_name):
'''
Desc:
加载并解析数据
Args:
file_name -- 要解析的文件路径
Returns:
dataMat -- 原始数据的特征
labelMat -- 原始数据的标签,也就是每条样本对应的类别。即目标向量
'''
# dataMat为原始数据, labelMat为原始数据的标签
dataMat = []
labelMat = []
fr = open(file_name)
for line in fr.readlines():
lineArr = line.strip().split()
# 为了方便计算,我们将 X0 的值设为 1.0 ,也就是在每一行的开头添加一个 1.0 作为 X0
dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
labelMat.append(int(lineArr[2]))
return dataMat, labelMat
# sigmoid阶跃函数
def sigmoid(inX):
# return 1.0 / (1 + exp(-inX))
return 1.0/(1+np.exp(-inX))
# Logistic 回归梯度上升优化算法
def gradAscent(dataMatIn, classLabels):
#用mat函数将列表转换成numpy矩阵
dataMatrix = np.mat(dataMatIn)
#用mat函数将列表转换成numpy矩阵,并进行转置
labelMat = np.mat(classLabels).transpose()
#返回dataMatrix的大小。m为行数,n为列数。
m,n = np.shape(dataMatrix)
#移动步长,也就是学习速率,控制更新的幅度。
alpha = 0.001
#最大迭代次数
maxCycles = 500
# weights 代表回归系数, 此处的 ones((n,1)) 创建一个长度和特征数相同的矩阵,其中的数全部都是 1
weights = np.ones((n,1))
for k in range(maxCycles):
# m*3 的矩阵 * 3*1 的矩阵 = m*1的矩阵
h = sigmoid(dataMatrix*weights)
# labelMat是实际值,labelMat - 是两个向量相减
error = (labelMat - h)
# 0.001* (3*m)*(m*1) 表示在每一个列上的一个误差情况,最后得出 x1,x2,xn的系数的偏移量
# 矩阵乘法,最后得到回归系数
weights = weights + alpha * dataMatrix.transpose() * error
return np.array(weights)
# 画出数据集和 Logistic 回归最佳拟合直线的函数
def plotBestFit(dataArr, labelMat, weights):
n = np.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 = np.arange(-3.0, 3.0, 0.1)
y = (-weights[0]-weights[1]*x)/weights[2]
ax.plot(x, y)
plt.xlabel('X'); plt.ylabel('Y')
plt.show()
#测试算法: 使用 Logistic 回归进行分类
def testLR():
dataMat, labelMat = loadDataSet("TestSet.txt")
dataArr = np.array(dataMat)
weights = gradAscent(dataArr, labelMat)
plotBestFit(dataArr, labelMat, weights)
testLR()