一、逻辑斯蒂回归介绍
前面介绍的最小二乘法能够较好地对线性模型进行回归学习,但是不能有效地解决离散的分类问题。
逻辑斯蒂回归是一种将预测值限定到区间(0, 1)上的回归模型,回归曲线如下图。
逻辑斯蒂回归函数在x=0附近对输入值十分敏感,而在x>>0或x<<0时对输入值不敏感。
总结下来就是,逻辑斯蒂回归通过将线性模型的输出通过逻辑斯蒂函数映射到概率空间,从而实现对二分类问题的预测。
也就是,逻辑斯蒂回归通常是用来解决而分类问题的。
二、逻辑斯蒂回归的数学模型
上面的逻辑斯蒂函数的数学表达式为:
该函数也成为Sigmoid函数。
将线性回归的模型的表达式(y = ax+b)矩阵形似为(y =
)带入到g(z)函数中,得到如下的公式:
这样就把之前的线性回归的值域映射到(0, 1)范围内了。
那么,此时,y的值h0(x)就有特殊的意义了,它表示结果取1的概率,因此就有了对于输入x,分类结果为1和0的概率分别为:
合并上面的两个表达式后结果为:
得到逻辑回归的表达式后,下一步跟线性回归类似,构建似然函数,然后最大似然估计,最终推导出参数theta。
只不过这里用的不是梯度下降,而是梯度上升,因为这里是最大似然函数。
似然函数表达式为:
对似然函数取log,转换为:
然后似然函数对theta求偏导数,在这里以一有一个训练样本的情况为例:
由此,我们就得到了梯度上升每次迭代的更新方向,那么theta的迭代表达式为:
可以看到,它与前面介绍的最小二乘的剃度下降法的更新公式非常相似。
三、逻辑斯蒂回归的代码实现
有了上面的参数的更新公式,就可以用代码来实现逻辑斯蒂回归算法了。
import numpy as np
import sklearn.datasets
import matplotlib.pyplot as plt
np.random.seed(0)
# 生成模拟数据
data, label = sklearn.datasets.make_moons(200, noise=0.30)
print('data = ', data[:10, :])
print('label = ', label[:10])
plt.scatter(data[:,0], data[:,1], c=label)
plt.title('train, test data')
plt.show()
def sigmoid(x):
return 1.0 / (1 + np.exp(-x))
class Logistic(object):
'''逻辑斯蒂回归模型'''
def __init__(self, data, label):
self.data = data
self.label = label
self.data_num, n = np.shape(data)
self.weights = np.ones(n)
self.b = 1
def train(self, num_iteration=150):
'''
随机梯度下降算法,参数:
data(numpy.ndarray):训练数据集
labels (numpy.ndarray):训练标签
num_iteration (int):迭代次数
'''
# 学习率
alpha = 0.01
# 对每次迭代
for j in range(num_iteration):
data_index = list(range(self.data_num))
for i in range(self.data_num):
# 随机选择一个样本
rand_index = int(np.random.uniform(0, len(data_index)))
# 计算误差
error = self.label[rand_index] - sigmoid(sum(self.data[rand_index] * self.weights + self.b))
# 更新模型参数
self.weights += alpha * error * self.data[rand_index]
self.b += alpha * error
del(data_index[rand_index])
def predict(self, predict_data):
'''预测函数'''
result = list(map(lambda x : 1 if sum(self.weights * x + self.b) > 0 else 0, predict_data))
return np.array(result)
# 逻辑斯蒂结果可视化
logistic = Logistic(data, label)
logistic.train(200)
def plot_decision_boundary(predict_func, data, label):
x_min, x_max = data[:, 0].min() - .5, data[:, 0].max() + .5
y_min, y_max = data[:, 1].min() - .5, data[:, 1].max() + .5
h = 0.01
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
Z = predict_func(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap = plt.cm.Spectral) # 画出等高线并填充
plt.scatter(data[:, 0], data[:, 1], c=label, cmap=plt.cm.Spectral)
plt.show()
plot_decision_boundary(lambda x:logistic.predict(x), data, label)
运行后,会显示训练数据分布图和逻辑斯蒂回归分类的结果:
训练数据分布:
预测结果:
四、总结
逻辑斯蒂回归本质上是一个线性模型,因此无法有效地区分交叉的数据。
想要区分上图中的交叉的数据需要引入一些非线性方法。
|