机器学习-- 逻辑回归
一、逻辑回归
1、逻辑回归:逻辑回归与多重线性回归实际上有很多相似之处,最大的区别就在于它们的因变量不同,其他的基本都差不多。正是因为如此,这两种回归可以归于同一个家族,即广义线性模型(generalizedlinear model)。
2、逻辑回归算法本质还是回归,只是其引入了逻辑函数来帮助其分类。逻辑回归实际上是一种分类方法,主要用于两分类问题,即输出只有两种,比如0和1.
3、假设数据有n个独立的特征,到为样本的n个特征。常规的回归算法的目标是拟合出一个多项式函数,使得预测值和真实值的误差最小:
而我们希望这样的g(x)能够具有很好的逻辑判断性质,最好是能够直接表达具有特征x的样本被分到某类的概率。比如g(x)>0.5的时候表示x被分为正类,g(x)<0.5表示被分为反类,g(x)在0~1之间,所以引入Logistic函数(或称为Sigmoid函数)。
函数形式为:
Sigmoid函数:
当x=0时,g(x)=0.5;
当x>0时,g(x)>0.5;
当x<0时,g(x)<0.5.
当Sigmoid函数值大于0.5时,归为1类别;
当Sigmoid函数值小于0.5时,归为0类别。
二、梯度上升法
1、梯度上升法基于的思想是:要找到某函数的最大值,最好的方法是沿着该函数的梯度方向探寻。
这里为了求解最优回归参数,需求解损失函数
的最小值。
2、特点:结果理想,但运算过程需进行大量运算,不利于大数据进行运算。
3、线性边界为:
构造预测函数:
对于输入x的分类结果为类别1和类别0的概率分别为:
对于任意y,有:
m个样本的概率分布为(似然函数):
等式两边同事去对数,得(对数似然函数):
构造损失函数:
4、函数f(x,y)的梯度:
梯度算子总是指向函数增长最快的方向。移动方向为梯度方向,移动量大小需要乘以一个参数,称之为步长。参数迭代公式为:
该公式将一直被迭代执行,直到达到某个停止条件为止,比如迭代次数达到某个指定值或者算法达到某个可以允许的误差范围。
梯度上升法求回归系数:
其中:
为第j个特征值的系数;
a为步长(实数);
m为样本数;
为第i个数据。
三、Python代码实现
1、条件:给出100个样本点,每个样本点包含两个特征x1和x2,再加上一个标签:1或0。
目标:利用梯度上升法求得回归系数,化为线性函数,并在图中表示出来。
2、伪代码:
- 调用numpy函数和matplotlib函数
- 定义函数loadDataSet处理数据
- 定义sigmoid函数
- 定义函数求回归参数w
- 定义函数plotBestFit绘图
- 将个定义的函数串起来
import matplotlib.pyplot as plt
from numpy import *
def loadDataSet():
dataMat = []; labelMat = []
fr = open('testSet.txt') #打开文件,100行3列的数据
for line in fr.readlines(): #读取整行,如第一行为:-0.017612 14.053064 0
lineArr = line.strip().split() #以列表的形式读取,如第一行为:['-0.017612', '14.053064', '0']
dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) #取每行数据的前两个数组成100个元素如[1.0,-0.017612, 14.053064]的列表
labelMat.append(int(lineArr[2])) #取每行数据的最后一个数组成100个元素如[1],[0]的列表
return dataMat,labelMat #返回上面两个列表
def sigmoid(inX):
return 1.0/(1+exp(-inX)) #构建sigmoid函数
def gradAscent(dataMat, labelMat):
dataMatrix = mat(dataMat) #转化为100行3列的矩阵
labelMat = mat( labelMat).transpose() #转化为100行1列的矩阵
m,n = shape(dataMatrix) #获取行数m=100,列数n=3
alpha = 0.001
maxCycles = 500
weights = ones((n,1)) #创建n行1列元素均为1.的矩阵
for k in range(maxCycles): #进行500次循环运算
h = sigmoid(dataMatrix*weights)
error = labelMat - h
weights = weights + alpha * dataMatrix.transpose()* error #迭代w=w0+a*x*(y-h(x))
return weights #返回w的值
def stocGradAscent0(dataMat, labelMat):
m,n = shape(dataMat) #获取行数m=100,列数n=3
alpha = 0.01
weights = ones(n) #创建1行n列元素均为1.的矩阵
for i in range(m):
#h = sigmoid(sum(dataMat[i]*weights)) #dataMat[i]指第i个列表,dataMat[i]*weights为1行3列的矩阵,sum使这3个数加起来
h = sigmoid(sum(dataMat[i]*weights))
error = labelMat[i] - h
weights = weights + alpha * error * dataMat[i] #迭代w=w0+a*x*(y-h(x))
return weights
def stocGradAscent1(dataMat, labelMat):
m,n = shape(dataMat) #获取行数m=100,列数n=3
numIter=150
weights = ones(n) #创建1行n列元素均为1.的矩阵
for j in range(numIter):
dataIndex = range(m)
for i in range(m):
alpha = 4/(1.0+j+i)+0.01 #调整alpha值
randIndex = int(random.uniform(0,len(dataIndex))) #在(0,100)内取随机数randIndex
h = sigmoid(sum(dataMat[randIndex]*weights))
error = labelMat[randIndex] - h
weights = weights + alpha * error * dataMat[randIndex] #迭代w=w0+a*x*(y-h(x))
del(dataIndex[randIndex])
return weights
def plotBestFit(weights):
dataMat,labelMat=loadDataSet() #从loadDataSet()函数读取数据
dataArr = array(dataMat) #将dataMat中的100组数据转化为100行3列的矩阵
n = shape(dataArr)[0] #得到行数100
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时,将矩阵的第二三个的元素赋值给x y
else:
xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2]) #当标签为0时,将矩阵的第二三个的元素赋值给x y
x = arange(-4.0, 4.0, 0.1) #从-4.0~4.0每隔0.1取一个数组成的列表
y = (-float(weights[0])-float(weights[1])*x)/float(weights[2]) #令 y=(-w0-w1*x)/w2
plt.plot(xcord1, ycord1,'r*') #创建标签为1的散点图,用红色的*号表示
plt.plot(xcord2, ycord2,'g+') #创建标签为0的散点图,用绿色的+号表示
plt.plot(x, y,'b') #创建目标函数曲线
plt.legend(['sort 1','sort 0']) #添加图例
plt.xlabel('X1'); plt.ylabel('X2') #横轴设为X1,纵轴设为X2
#定义函数后下面开始调用
dataMat,labelMat=loadDataSet() #从loadDataSet()函数读取数据
weights0=gradAscent(dataMat,labelMat)
weights1=stocGradAscent0(array(dataMat), labelMat)
weights2=stocGradAscent1(array(dataMat), labelMat)
print 'w0=',weights0, '\nw1=',weights1,'\nw2=',weights2 #输出w
plt.figure(1);plotBestFit(weights0)
plt.figure(2);plotBestFit(weights1)
plt.figure(3);plotBestFit(weights2) #引用函数plotBestFit
plt.show() #使图像显示在表格中
输出:
w0= [[ 4.12414349]
[ 0.48007329]
[-0.6168482 ]]
w1= [ 1.01702007 0.85914348 -0.36579921]
w2= [ 14.39064495 0.68717787 -2.00324495]
四、小结
优点:计算代价不高,易于理解和实现。
缺点:容易欠拟合,分类轻度可能不高。
使用数据类型:数值型和标称型数据。