1. 什么是逻辑回归
逻辑回归是一种有监督的统计学习方法,主要用于对样本进行分类。
y=f(x)=ax+b
通过函数S的作用,我们可以将输出的值限制在区间[0, 1]上,p(x)则可以用来表示概率p(y=1|x),即当一个x发生时,y被分到1那一组的概率。可是,等等,我们上面说y只有两种取值,但是这里却出现了一个区间[0, 1],这是什么鬼??其实在真实情况下,我们最终得到的y的值是在[0, 1]这个区间上的一个数,然后我们可以选择一个阈值,通常是0.5,当y>0.5时,就将这个x归到1这一类,如果y<0.5就将x归到0这一类。但是阈值是可以调整的,比如说一个比较保守的人,可能将阈值设为0.9,也就是说有超过90%的把握,才相信这个x属于1这一类。
逻辑回归模型的代价函数
逻辑回归一般使用交叉熵作为代价函数。关于代价函数的具体细节,请参考代价函数,这里只给出交叉熵公式:
2. 数据准备
两个特征x1, x2 结果
-0.017612 14.053064 0
-1.395634 4.662541 1
-0.752157 6.538620 0
-1.322371 7.152853 0
0.423363 11.054677 0
0.406704 7.067335 1
0.667394 12.741452 0
-2.460150 6.866805 1
0.569411 9.548755 0
-0.026632 10.427743 0
数据是二维的,也就是说这组观察样本中有两个自变量,即两个特征(feature)。两个特征x1, x2,因此整个模型就增加了一项:ax1 + cx2 + b。为了形式上的统一,我们使用带下标的a表示不同的参数(a0表示常数项b并作x0的参数<x0=1>,a1、a2分别表示x1和x2的参数),就可以得到:
python代码:
from numpy import *
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])]) # X0的值初始化设置为1.0 ,三个特征x0, x1, x2 ,,,,
labelMat.append(int(lineArr[2]))
return dataMat, labelMat
def sigmoid(inX):
return 1.0 / (1 + exp(-inX))
'''
Logistic 回归梯度上升优化算法
@param dataMatIn:特征矩阵,行代表样本数,列代表特征数
@param classLabels:每个样本对应的类标签组成的向量
'''
def gradAscent(dataMatIn, classLabels):
dataMatrix = mat(dataMatIn) # 转化为 NumPy 矩阵
labelMat = mat(classLabels).transpose() # 转化为 NumPy 矩阵
m, n = shape(dataMatrix) # m=100,n=3,代表100个样本,3个特征(包括X0)
alpha = 0.001 # 步长,学习速率
maxCycles = 500 # 最大迭代次数
weights = ones((n, 1))
for k in range(maxCycles): # 最大迭代次数
test_h = dataMatrix * weights
# 如果两参数都是矩阵,那么*和dot()都为矩阵相乘,而如果两个都是数组,则*为对应位置相乘,dot()为矩阵相乘
h = sigmoid(dataMatrix * weights) # # 模型预测值 1.0 / (1 + exp(-inX))
error = (labelMat - h) # 每一行的:误差 = 标签 - 预测计算值
test_weights = dataMatrix.transpose() * error # 交叉熵代价函数对所有参数的偏导数, 3 x 1
weights = weights + alpha * dataMatrix.transpose() * error # 更新权值
return weights
def plotBestFit(weights):
import matplotlib.pyplot as plt
dataMat, labelMat = loadDataSet()
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) # 步长0.1
y = (-weights[0] - weights[1] * x) / weights[2] # 0=w0x0+w1x1+w2x2,其中x0=1,y即x2
ax.plot(x, y)
plt.xlabel('X1');
plt.ylabel('X2');
plt.show()
def classifyVector(inX, weights):
dataB = [];
dataB.append([1.0, float(inX[0]), float(inX[1])])
prob = sigmoid(sum(dataB * weights)) # 对应位置相乘,即 σ(z) = σ(x0w0 + x1w1 + x2w2 + ...)
if prob > 0.5:
return 1.0
else:
return 0.0
def predict_test_sample(A, weights):
dataB = [];
dataB.append([1.0, float(A[0]), float(A[1])])
h_test = sigmoid(mat(dataB) * weights) # 将读入的数据和A转化成numpy中的矩阵
print(A,' 的预测结果线性:',mat(dataB) * weights,'最终计算值 ',h_test) # 预测的结果
# 测试画图
# 测试求得的最优回归系数
dataArr, labelMat = loadDataSet()
weights = gradAscent(dataArr, labelMat)
print(weights)
plotBestFit(weights.getA()) # 注意:getA() 方法将自身返回成一个n维数组对象,否则 weights[1] 将为[[0.48007329]],而不是0.48007329,故会报错
A = [ 0.00847797, 2.05168429] # 上面计算出来的回归系数a
predict_test_sample(A, weights)
print(classifyVector(A, weights))
本次预测出来的回归系数a,包括a0, a1, a2
[[ 4.12414349]
[ 0.48007329]
[-0.6168482 ]]
[0.00847797, 2.05168429] 的预测结果线性: [[2.86263578]] 最终计算值 [[0.94596818]]
1.0