logistic回归
一、介绍
逻辑回归算法属于监督学习的分类算法,用于解决二分类(0或1)问题
一篇很好的概念介绍https://zhuanlan.zhihu.com/p/28408516
1、sigmoid函数
逻辑回归引入sigmoid函数进行分类
\(g(x)=\frac{1}{1+e^{-x}}\)
当x为0时,值为0.5
当x减小时,值趋近0
当x增大时,值趋近1
def sigmoid(x):
return 1 / (1 + exp(-x))
图如下
2、分类器
逻辑回归分类器即对每一个特征乘以一个回归系数,然后把所有的值相加,将和带入sigmoid函数中,通过阀值0.5分为两类
3、回归系数
通过最优化算法找出最佳回归系数——梯度上升法
梯度
\(\nabla f(x, y)={(\frac{\partial f}{\partial x}, \frac{\partial f}{\partial y})}\)
即总是指向函数值增长最快的方向,可以用来求函数最大值
设移动为a,那么梯度上升算法的迭代公式为
\(w=w+a\nabla f(w)\)
一直迭代,直至在某个条件下停止(如设定的误差范围)
二、训练算法
1、梯度上升找最佳系数
该处代码有数学推导结论,我当时看也是有点懵,找到两篇推导过程,但没看太懂
https://www.cnblogs.com/weiququ/p/9414746.html
https://zhuanlan.zhihu.com/p/28415991
# data为一个二维列表,每一行代表一条数据,每一列代表一个特征值,初始时第一个特征值初始为1
# label为每条数据对应的类别列表,用0,1区别
def gradAscent(data, label):
dataMat = mat(data)
label = mat(label).T # 转为矩阵后转置便于矩阵乘
m, n = shape(dataMat)
a = 0.001 # a为步长参数
w = ones((n, 1)) # 初始为一个有n行1列的值为1 的列向量,即回归系数初始化为1
# 这里500为迭代次数的参数
for i in range(500):
error = label - sigmoid(dataMat * w) # 计算与实际的相差的值
w = w + a * dataMat.T * error # 然后对该系数w用error不断调整
return w
结果如下
数据集来自《机器学习实战第五章》
用到的画图函数如下
# w为最后得出的参数
def draw(data, label, w):
import matplotlib.pyplot as plt
dataArr = array(data)
m, n = shape(dataArr)
x1 = []
y1 = []
x2 = []
y2 = []
for i in range(m):
if label[i] == 0:
x1.append(dataArr[i, 1])
y1.append(dataArr[i, 2])
else:
x2.append(dataArr[i, 1])
y2.append(dataArr[i, 2])
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(x1, y1, s=30, c='red')
ax.scatter(x2, y2, s=30, c='blue')
# 画出最优的拟合直线
x = arange(-3, 3, 0.1)
y = (-w[0] - w[1] * x) / w[2]
ax.plot(x, y)
plt.show()
2、随机梯度上升找最佳系数
用于改进计算复杂度高的问题,每一次仅用一个样本来更新回归系数
def randGrad(data, label):
dataArr = array(data)
m, n = shape(dataArr)
a = 0.01
w = ones(n)
for i in range(m):
h = sigmoid(sum(dataArr[i] * w))
error = label[i] - h
w = w + a * dataArr[i] * error
return w
结果如下
3、改进随机梯度上升找最佳系数
为了使系数能减少周期波动,快速收敛,每一次随机用一个样本来更新回归系数,且每次都调整步长参数a
def enRandGrad(data, label):
dataArr = array(data)
m, n = shape(dataArr)
w = ones(n)
# 150为迭代的次数参数
for i in range(150):
dataIndex = list(range(m))
for j in range(m):
a = 4 / (1 + i + j) + 0.01 # 调整步长参数a
# 随机选取一个样本更新参数
randIndex = int(random.uniform(0, len(dataIndex)))
h = sigmoid(sum(dataArr[randIndex] * w))
error = label[randIndex] - h
w = w + a * dataArr[randIndex] * error
del (dataIndex[randIndex])
return w
结果如下
数据集里三个系数的变化如下