1. 问题
上次我们聊了线性回归模型。线性回归模型得出的结果是连续的,但有时候我们并不需要连续解,而是需要是非解。比如来看病的人是否真的生病,照片里的人是否是本人,信用卡本笔消费是否诈骗等。
这类问题统一称为分类(Classification)。逻辑回归模型(Logistic Regression)是分类问题中一种基础且应用广泛的模型。
2. 分析
线性回归模型为
现在我们想要把输出结果限制在
来实现。我们定义 ,便可得到
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gRAbzxie-1587689973775)(assets/sigmoid.png)]
可见,函数单调递增,而且输出结果恰好限制在了[0, 1]之间。我们可以设定一个阈值,当输出大于时结果取1,否则取0,即
从而实现分类。
的作用,是对于给定的输入变量,根据选择的参数计算输出变量=1 的可能性,即。背后的数学原理,是最大似然法(maximum likelihood)。
线性回归求解模型参数时,用的是最小二乘法(least square method)。逻辑回归由于不连续,没有办法使用这个方法。但利用逻辑回归的结果只有0和1的特点,我们定义其代价函数为
为什么是这么奇怪一个函数?主要是利用了函数的特性,以及结果只有[0, 1]的特点。背后的原理内容比较多,这里就不展开了,有兴趣深挖其数学原理的朋友可以参考文献[1]或其他相关文献。
有了代价函数,我们就可以利用类似线性回归的梯度下降法来求解出合适的。也即
其中
3. 实现
与线性回归类似,逻辑回归作为一种经典算法,已经在众多软件包里面集成。实际应用中,我们只需要了解以上大致原理即可,无需自己手动实现。比如我们可以调用 scikit learn 包实现[2]。
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
data = np.loadtxt('assets\ex2data1.txt', delimiter=',')
X = data[:, 0:2]; y = data[:, 2]
X_train, X_test, y_train, y_test = train_test_split(X, y)
lr = LogisticRegression().fit(X_train, y_train)
print("lr.coef_: {}".format(lr.coef_))
print("lr.intercept_: {}".format(lr.intercept_))
print("Training set score: {:.2f}".format(lr.score(X_train, y_train)))
print("Test set score: {:.2f}".format(lr.score(X_test, y_test)))
输出结果为
lr.coef_: [[0.271231 0.24299562]]
lr.intercept_: [-32.44502147]
Training set score: 0.92
Test set score: 0.80
,效果颇赞。
4. 总结及扩展
今天我们大致聊了逻辑回归的基本原理及其实现。以上都是二分类,即分类结果只有两个。但现实中我们也时常需要多分类预测,即分类结果有多个。
比如预测明天天气是晴天、阴天还是雨天,或者根据一个人聊天推测他毕业于清华、浸会大学还是斯坦福大学。
类似之前二分类的方法,我们现在要求解的概率成了
然而,我们无需为每一个分类都创造一种新的分类方法,而是把它们在二分类上面进行扩展。以天气预测为例,我们可以
- 把晴天的数据标记为1,其他为0,得出晴天时的概率模型;
- 把阴天的数据标记为2,其他为0,得出阴天时的概率模型;
- 把雨天的数据标记为3,其他为0,得出雨天时的概率模型
对于新数据 x,带入以上三个模型,便可得到三个概率,取其中最大值,便是 x 的最佳预测结果。
这种算法叫做一对余 (one-vs-rest, OvR)。这样,我们就可以用一招吃遍天下。
对应于 scikit learn,代码无需更改。当数据为多分类时,scikit learn 会自行调用多分类算法。而且在 scikit learn 里面还可以指定其他算法。