二、逻辑回归算法
1. 线性回归与分类
分类问题与回归问题有一定的相似性,都是通过对数据集的学习来对未知结果进行预测,区别在于输出值不同。
- 分类问题的输出值是离散值(如垃圾邮件和正常邮件)
- 回复i问题的输出值是连续值(如房子的价格)
尝试使用一元线性函数去进行拟合数据,函数体现在图片中就是这条黑色直线。这样分类问题就可以转化为:对于这个线性拟合的假设函数,给定一个肿瘤的大小,可以将其带入假设函数,并将其输出值和0.5进行比较:
- 如果线性回归值大于0.5,就输出1(恶行肿瘤)
- 如果线性回归值小于0.5,就输出0(良性肿瘤)
但是如果数据集更改一下,如图所示,如果我们还是以0.5为判定阈值,那么就会把肿瘤大小为6的情况进行误判为良好。
所以,单纯地通过将线性拟合的输出值与某一个阈值进行比较,这种方法用于分类非常不稳定。
2. 逻辑回归核心思想
因为线性回归+阈值的方法很难得到鲁棒性好的分类器,我们对其进行拓展得到鲁棒性更好的逻辑回归(Logistic Regression)。逻辑回归将数据拟合到一个logit函数中,从而完成对事件发生概率的预测。
如果线性回归的结果输出是一个连续值,而值的范围是无法限定的,这种情况下我们无法得到稳定的判断阈值。那是否可以把这个结果映射到一个固定大小的区间内(比如0~1),进而判断呢?
这就是逻辑回归做的事情,而其中用于对连续值压缩变化的函数叫做Sigmoid函数(也称Logistic函数,S函数)。
3. Sigmoid函数与决策边界
下面看Sigmoid函数如何和线性拟合结合,如何完成分类问题,并且得到清晰可解释的分类器判断决策边界。
3.1 分类与决策边界
决策边界就是分类器对于样本进行区分的边界,主要有线性决策边界(linear decision boundaries)和非线性决策边界(non-linear decision boundaries),如下图所示.
3.2 线性决策边界生成
逻辑回归是怎么得到决策边界的呢,它与Sigmoid函数有什么关系?
如下例:
如果我们用函数g表示Sigmoid函数,逻辑回归的输入结果由假设函数得到。
对于图中的例子,我们暂时去参数分别为-3、-1和1,那么对于图上的两类样本点,我们代入一些坐标到,会得到什么结果值呢?
- 对于直线上方的点(例如(100,100)),带入
,得到大于0的取值,经过Sigmoid映射后得到的是大于0.5的取值。
- 对于直线下方的值(例如(0,0)),带入
,得到小于0的取值,经过Sigmoid映射后得到的是小于0.5的取值。
如果我们以0.5为判定边界,则线性拟合的直线变幻成了一条决策边界(这里是线性决策边界)。
3.3 非线性决策边界生成
其实,我们不仅仅可以得到线性决策边界,当更复杂的时候,我们甚至可以得到对样本非线性切分的非线性决策边界(这里的非线性指的是无法通过直线或者超平面把不同类别的样本很好的且分开)。
如下图中,另外一个例子:如果我们用函数g表示Sigmoid函数,逻辑回归的输出结果由假设函得到。参数分别取-1、0、0、1和1:
- 对于圆外部的点(例如(100,100)),带入
,得到大于0的取值,经过Sigmoid映射后得到的是大于0.5的取值。
- 对于圆内部的点(例如(0,0)),带入
,得到大于0的取值,经过Sigmoid映射后得到的是大于0.5的取值。
如果我们以0.5为判定边界,则线性拟合的圆曲线变幻成了一条决策边界(这里是非线性决策边界)。
4. 梯度下降与优化
4.1 损失函数
哪一条决策边界是最好的呢?我们需要定义一个能量化衡量模型好坏的函数—损失函数(有时候也叫做目标函数或者代价函数)。我们的目标是使得损失函数最小化。
我们如何衡量预测值和标准答案之间的差异呢?最简单直接的方式是数学中的均方误差。他的计算方式很简单,对于所有的样本点,预测值
与标准答案
作差后平方,求均值即可,这个取值越小代表差异度越小
均方误差对应的损失函数:均方损失误差(MSE)在回归问题损失定义与优化中广泛应用,但是在逻辑回归问题中不大适用。Sigmoid函数的变换使得我们最终得到损失函数曲线如下图所示,是非常不光滑凹凸不平的,这种数学上叫做非凸的损失函数,我们要找到最优参数(使得函数取值最小的参数)是很困难的.
我们更希望我们的损失函数如下图所示,是凸函数,我们在数学上由很好优化方法可以对其进行优化。
5 正则化与缓解过拟合
5.1 过拟合现象
在训练数据不够多,或者模型复杂又过度训练时,模型会陷入过拟合(Overfiting)状态。
拟合曲线中的抖动,表示拟合曲线不规则、不光滑(上图的拟合曲线3),对数据的学习程度深,过拟合了。
5.2 正则化处理
过拟合的一种处理方式时正则化,我们通过对损失函数添加正则化项,我们约束参数的搜索空间,从而保证你和的决策边界并不会抖动非常厉害。
其中表示正则化系数,表示惩罚成都,的值越大,为使得的值越小,则参数的绝对值就得越小,通常对应于越光滑的函数,也就是更加简单的函数,因此不易发生过拟合的问题。
6 特征变换或非线性表达
6.1 多项式特征
对于输入的特征,如果我们直接进行线性拟合再给到Sigmoid函数,得到的是线性决策边界。但添加多项式特征,可以对样本点进行郭象是回归拟合,也能再后续得到更好的非线性决策边界。
多项式回归,回归函数是回归变量多项式。多项式回归模型是线性回归模型的一种,此时回归函数关于回归函数是线性的。
7. 逻辑回归实战——基于鸢尾花数据集的逻辑回归分类预测
逻辑回归以回归之名,行分类之事,实质上是一个分类模型。本实战中我们的学习目标是:
- 了解逻辑回归的理论
- 掌握逻辑回归的sklearn函数调用使用,并将其运用到鸢尾花数据集预测
7.1 代码流程
- part1 Demo实践
- step1:库函数导人
- step2:模型训练
- step3:模型参数查看
- step4:数据和模型可视化
- step5:模型预测
- part2基于鸢尾花(iris)数据集的逻辑回归分类实战
- step1:库函数导入
- step2:数据读取/载入
- step3:数据信息简单查看
- step4:可视化
- step5:利用逻辑回归模型在二分类上进行训练和预测
- step6:利用逻辑回归模型在三分类(多分类)上进行训练和预测
7.2 Demo实践
# 库函数导入
import numpy as np
# 导入画图库
import matplotlib.pyplot as plt
import seaborn as sns
# 导入逻辑回归模型函数
from sklearn.linear_model import LogisticRegression
# 创建数据集
def setdataset():
x_features = np.array([[-1,-2], [-2, -1], [-3, -2], [1, 3], [2, 1], [3,2]])
y_label = np.array([0, 0, 0, 1, 1, 1])
return x_features, y_label
# 调用逻辑回归模型
lr_clf = LogisticRegression()
# 用逻辑回归模型拟合构造的数据集
if __name__ == "__main__":
x_features, y_label = setdataset() # 读取数据集
lr_clf = lr_clf.fit(x_features, y_label) # 拟合方程y=w0+w1*x1+w2*x2
print('the weight of Logistic Reegression:', lr_clf.coef_)
print('the intercept(w0) of Logitstc Regression:', lr_clf.intercept_)
plt.figure()
# 可视化训练样本
plt.scatter(x_features[:,0], x_features[:,1], c=y_label, s=50, cmap='viridis')
plt.title('Dataset')
# 可视化决策边界
nx, ny = 200, 100
x_min, x_max = plt.xlim()
# print(x_min, x_max)
y_min, y_max = plt.ylim()
x_grid, y_grid = np.meshgrid(np.linspace(x_min, x_max, nx), np.linspace(y_min, y_max, ny))
z_proba = lr_clf.predict_proba(np.c_[x_grid.ravel(), y_grid.ravel()])
z_proba = z_proba[:,1].reshape(x_grid.shape)
plt.contour(x_grid, y_grid, z_proba, [0.5], linewidths=2., colors='blue')
# new point 1
x_features_new1 = np.array([[0, -1]])
plt.scatter(x_features_new1[:,0], x_features_new1[:,1], s=50, cmap='viridis')
plt.annotate('New point 1',
xy=(0, -1),
xytext=(-2,0),
color='blue',
arrowprops=dict(arrowstyle='-|>', connectionstyle='arc3', color='red'))
# new point 2
x_features_new2 = np.array([[1, 2]])
plt.scatter(x_features_new2[:,0], x_features_new2[:,1], s=50, cmap='viridis')
plt.annotate('New point 2',
xy=(1,2),
xytext=(-1.5, 2.5),
color='red',
arrowprops=dict(arrowstyle='-|>', connectionstyle='arc3', color='red'))
plt.show()
运行结果:
demo部分简单看一看就好,因为难度不大。
7.3 基于鸢尾花(iris)数据集的逻辑回归分类实践
# 导入函数库
import numpy as np
import pandas as pd
# 导入绘图库
import matplotlib.pyplot as plt
import seaborn as sns
# 加载数据
from sklearn.datasets import load_iris
data = load_iris() # 得到数据特征
iris_target = data.target # 得到数据对应的标签
iris_features = pd.DataFrame(data=data.data, columns=data.feature_names) # 利用Pandas转化为DataFreme格式
# 查看数据整体信息
iris_features.info()
# 简单查看数据,我们可以利用.head(),.tail()
iris_features.head()
pd.Series(iris_target).value_counts()
# 可视化描述
# 合并标签和特征信息
iris_all = iris_features.copy()
iris_all['target'] = iris_target
# 特征和标签组合的散点可视化
sns.pairplot(data=iris_all, diag_kind='hist', hue='target')
plt.show()
for col in iris_features.columns:
sns.boxplot(x='target', y=col, saturation=0.5,palette='pastel', data=iris_all)
plt.title(col)
plt.show()
# 选取其前三个特征绘制三维散点图
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111, projection='3d')
iris_all_class0 = iris_all[iris_all['target']==0].values
iris_all_class1 = iris_all[iris_all['target']==1].values
iris_all_class2 = iris_all[iris_all['target']==2].values
# 'setosa'(0), 'versicolor'(1), 'virginica'(2)
ax.scatter(iris_all_class0[:,0], iris_all_class0[:,1], iris_all_class0[:,2],label='setosa')
ax.scatter(iris_all_class1[:,0], iris_all_class1[:,1], iris_all_class1[:,2],label='versicolor')
ax.scatter(iris_all_class2[:,0], iris_all_class2[:,1], iris_all_class2[:,2],label='virginica')
plt.legend()
plt.show()
## 为了正确评估模型性能,将数据划分为训练集和测试集,并在训练集上训练模型,在测试集上验证模型性能。
from sklearn.model_selection import train_test_split
## 选择其类别为0和1的样本 (不包括类别为2的样本)
iris_features_part = iris_features.iloc[:100]
iris_target_part = iris_target[:100]
## 测试集大小为20%, 80%/20%分
x_train, x_test, y_train, y_test = train_test_split(iris_features_part, iris_target_part, test_size = 0.2, random_state = 2020)
## 从sklearn中导入逻辑回归模型
from sklearn.linear_model import LogisticRegression
## 定义 逻辑回归模型
clf = LogisticRegression(random_state=0, solver='lbfgs')
# 在训练集上训练逻辑回归模型
clf.fit(x_train, y_train)
## 查看其对应的w
print('the weight of Logistic Regression:',clf.coef_)
## 查看其对应的w0
print('the intercept(w0) of Logistic Regression:',clf.intercept_)
## 在训练集和测试集上分布利用训练好的模型进行预测
train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)
from sklearn import metrics
## 利用accuracy(准确度)【预测正确的样本数目占总预测样本数目的比例】评估模型效果
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_train,train_predict))
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_test,test_predict))
## 查看混淆矩阵 (预测值和真实值的各类情况统计矩阵)
confusion_matrix_result = metrics.confusion_matrix(test_predict,y_test)
print('The confusion matrix result:\n',confusion_matrix_result)
# 利用热力图对于结果进行可视化
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix_result, annot=True, cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()