前面我们用sklearn简单的实现了逻辑回归,数据集是我们自己所创造的,并不能很好的代表我们用逻辑回归对真实数据进行分类的效果。
所以下面我们就基于一份真实的数据来进行逻辑回归吧。先来介绍一下本节需要用到的数据集。
1. 鸢(yuan)尾花数据集
1.1 数据集介绍
鸢尾花数据集也叫iris数据集,是一个学习机器学习用于分类的常用的入门级的数据集。该数据集总共有150条数据,分为3类(Iris Setosa(山鸢尾)、Iris Versicolour(杂色鸢尾),以及Iris Virginica(维吉尼亚鸢尾)),每类有50个样本,每个样本包含四个特征(花萼长度,花萼宽度,花瓣长度,花瓣宽度),由Fisher, 1936年收集整理。
下面我们将数据集导入,先大致的来看一下:
# 基础函数库
import numpy as np
import pandas as pd
# 绘图函数库
import matplotlib.pyplot as plt
import seaborn as sns
# 我们利用 sklearn 中自带的 iris 数据作为数据载入
from sklearn.datasets import load_iris
data = load_iris() #得到数据特征
data # 将数据集信息展示出来
iris数据集是以字典
形式存储的,我们来看看数据集里面的键值有哪些
print(data.keys()) # 打印字典的键值
len(data) # 查看字典的长度
# dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename'])
# 7
可以看到该数据又7个键值对,其中:
data
: 特征值 (数组)
target
: 标签值 (数组)
target_names
: 真实标签名(列表)
DESCR
:数据集描述
feature_names
:特征名称 (列表)
filename
:iris.csv 文件路径
frame
: 只有当load_iris中的参数as_frame=True
时存在。 返回整合了data
和target
的DataFrame。
参考:sklearn.datasets.load_iris¶
sklearn.datasets.load_iris(*, return_X_y=False, as_frame=False)
让我们来看看里面都有些什么东西吧:
data.data # 展示数据集里面data键所对应的信息
因为有150行,4列,所以这里只截取了一部分。
# 展示数据集里面target键所对应的信息
# 其中0,1,2分别代表'setosa', 'versicolor', 'virginica'三种不同花的类别。
data.target
data.target_names # 展示数据集里面target_names键所对应的信息
data.feature_names # 展示数据集里面feature_names键所对应的信息
data.filename # 展示数据集里面filename键所对应的信息
上面的格式可能不太易于观看,所以下面将数据集中的关键信息转换为DataFrame格式:
iris_target = data.target #得到数据对应的标签
iris_features = pd.DataFrame(data=data.data, columns=data.feature_names) #利用Pandas转化为DataFrame格式,以feature_names作为列名
# 利用.info()查看数据的整体信息
iris_features.info()
下面简单查看一下格式转换后的数据(前5行,后5行)
iris_features.head() # 默认参数为5,所以是查看数据的前五行,可以改变参数查看更多行的数据
iris_features.tail() # 默认参数为5,所以是查看数据的后五行,可以改变参数查看更多行的数据
我们在来查看一些统计量
# 利用value_counts函数查看每个类别数量
pd.Series(iris_target).value_counts()
# 对于特征进行一些统计描述
iris_features.describe()
从统计描述中我们可以看到不同数值特征的变化范围。
1.2 数据可视化
接下来我们对数据做一下基本的可视化工作
# 合并标签和特征信息
iris_all = iris_features.copy() # 进行浅拷贝,防止对于原始数据的修改
iris_all['target'] = iris_target
# 特征与标签组合的散点可视化
sns.pairplot(data=iris_all,diag_kind='hist', hue= 'target')
plt.show()
从上图可以发现,在2D情况下不同的特征组合对于不同类别的花的散点分布,以及大概的区分能力。
利用箱型图,查看不同类别花的各个特征参数的分布情况
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()
2. 利用逻辑回归进行二分类
前面对数据做了简单的分析和可视化,下面我们就来利用该数据集学习逻辑回归。
2.1 数据预处理,分割好训练集,测试集
# 为了正确评估模型性能,将数据划分为训练集和测试集,并在训练集上训练模型,在测试集上验证模型性能。
# train_test_split函数用于将数据集分割为训练集和测试集
from sklearn.model_selection import train_test_split
# 选择用于训练和测试的数据
# 选择其类别为0和1的样本 (不包括类别为2的样本)
iris_features_part = iris_features.iloc[:100]
iris_target_part = iris_target[:100]
# 将数据和标签按照test_size = 0.2进行划分
# 训练集大小为80%,测试集大小为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)
2.2 导入,定义逻辑回归模型
# 从sklearn中导入逻辑回归模型
from sklearn.linear_model import LogisticRegression
# 定义逻辑回归模型,设置求解器为'lbfgs'
clf =Logistic Regression(random_state=0, solver='lbfgs')
2.3 利用训练集训练逻辑回归模型
# 在训练集上训练逻辑回归模型
clf.fit(x_train, y_train)
2.4 查看模型在训练集到底学习到了什么(即:学习到的参数)
## 查看其对应的w(系数)
print('the weight of Logistic Regression:',clf.coef_)
# 查看其对应的w0(截距)
print('the intercept(w0) of Logistic Regression:',clf.intercept_)
# the weight of Logistic Regression: [[ 0.45181973 -0.81743611 2.14470304 0.89838607]]
# the intercept(w0) of Logistic Regression: [-6.53367714]
打印出的参数就是模型在训练集上所学习到的东西。
2.5 利用训练好的模型重新对训练集进行预测,并在测试集上也进行预测;并查看其预测的准确率。
# 利用训练好的模型在训练集和测试集上进行预测
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)
# The accuracy of the Logistic Regression is: 1.0
# The accuracy of the Logistic Regression is: 1.0
# [[ 9 0]
# [ 0 11]]
2.6 预测结果可视化
# 利用热力图对于结果进行可视化
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix_result, annot=True, cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()
我们可以发现其准确度为1,代表所有的样本都预测正确了。
混淆矩阵的可视化效果说明:在20个测试样本中,有9个标签为0的样本被正确预测(将标签为0的样本预测为1的个数为0),11个标签为1的样本被正确预测(将标签为1的样本预测为0的个数为0)。
3. 利用逻辑回归进行多(三)分类
前面我们讲了逻辑回归除了用于二分类,还可用于多分类,下面我们就用逻辑回归来实现多分类(三分类)。
3.1 同样的,首先划分好训练集和测试集;
# 将数据和标签按照test_size = 0.2进行划分
# 训练集大小为80%,测试集大小为20%, 80%/20%分
x_train, x_test, y_train, y_test = train_test_split(iris_features, iris_target, test_size = 0.2, random_state = 2020)
3.2 定义逻辑回归模型;
# 定义逻辑回归模型,设置求解器为'lbfgs'
clf = LogisticRegression(random_state=0, solver='lbfgs')
3.3 然后在训练集上训练模型;
# 在训练集上训练逻辑回归模型
clf.fit(x_train, y_train)
3.4 我们来查看一下模型在训练集上学习到了什么;
# 查看其对应的w(系数)
print('the weight of Logistic Regression:\n',clf.coef_)
# 查看其对应的w0(截距)
print('the intercept(w0) of Logistic Regression:\n',clf.intercept_)
# 由于这个是3分类,所有我们这里得到了三个逻辑回归模型的参数,其三个逻辑回归组合起来即可实现三分类。
# the weight of Logistic Regression:
# [[-0.45928925 0.83069886 -2.26606531 -0.9974398 ]
# [ 0.33117319 -0.72863423 -0.06841147 -0.9871103 ]
# [ 0.12811606 -0.10206463 2.33447679 1.9845501 ]]
# the intercept(w0) of Logistic Regression:
# [ 9.43880677 3.93047364 -13.36928041]
可以看到此处打印出了三组参数,这是因为这里我们是三分类。下面来解释一下原因:
我们用逻辑回归实现多分类的时候,通常使用one-vs-rest的思想。假如现在我们有一个训练集,好比下图表示的有3个类别,我们用三角形表示 ,方框表示,叉叉表示 。我们下面要做的就是使用一个训练集,将其分成3个二元分类问题。
我们先从用三角形代表的类别1开始,实际上我们可以创建一个,新的"伪"训练集,类型2和类型3定为负类,类型1设定为正类,我们创建一个新的训练集,如下图所示的那样,我们要拟合出一个合适的分类器。
这里的三角形是正样本,而圆形代表负样本。可以这样想,设置三角形的值为1,圆形的值为0,下面我们来训练一个标准的逻辑回归分类器,这样我们就得到一个正边界。
为了能实现这样的转变,我们将多个类中的一个类标记为正向类(
y
=
1
y=1
y=1),然后将其他所有类都标记为负向类,这个模型记作
h
θ
(
1
)
(
x
)
h^{(1)}_\theta(x)
hθ(1)(x)。接着,类似地第我们选择另一个类标记为正向类(
y
=
2
y=2
y=2),再将其它类都标记为负向类,将这个模型记作
h
θ
(
2
)
(
x
)
h^{(2)}_\theta(x)
hθ(2)(x) ,依此类推。 最后我们得到一系列的模型简记为:
h
θ
(
i
)
(
x
)
=
p
(
y
=
i
∣
x
;
θ
)
h^{(i)}_\theta(x)=p(y=i|x;\theta)
hθ(i)(x)=p(y=i∣x;θ),其中:
i
=
(
1
,
2
,
3
,
.
.
.
k
)
i=(1,2,3,...k)
i=(1,2,3,...k)
最后,在我们需要做预测时,我们将所有的分类机都运行一遍,然后对每一个输入变量,都选择最高可能性的输出变量。
总之,我们已经把要做的做完了,现在要做的就是训练这个逻辑回归分类器:
h
θ
(
i
)
(
x
)
h^{(i)}_\theta(x)
hθ(i)(x), 其中
i
i
i 对应每一个可能的
y
=
i
y=i
y=i ,最后,为了做出预测,我们给出输入一个新的
x
x
x值,用这个做预测。我们要做的就是在我们三个分类器里面输入
x
x
x ,然后我们选择一个让
h
θ
(
i
)
(
x
)
h^{(i)}_\theta(x)
hθ(i)(x)最大的,即
m
a
x
h
θ
(
i
)
(
x
)
maxh^{(i)}_\theta(x)
maxhθ(i)(x),其中
i
=
(
1
,
2
,
3
,
.
.
.
k
)
i=(1,2,3,...k)
i=(1,2,3,...k),对于此处的三分类,
i
=
(
1
,
2
,
3
)
i=(1,2,3)
i=(1,2,3)。
3.5 然后同样的,我们训练好的模型在训练集和测试集上做预测;
# 利用训练好的模型在训练集和测试集上进行预测
train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)
# 由于逻辑回归模型是概率预测模型,所有我们可以利用 predict_proba 函数预测其概率
train_predict_proba = clf.predict_proba(x_train)
test_predict_proba = clf.predict_proba(x_test)
print('The test predict Probability of each class:\n',test_predict_proba)
# 其中第一列代表预测为0类的概率,第二列代表预测为1类的概率,第三列代表预测为2类的概率。
# 利用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))
3.6 最后我们对预测结果进行可视化
# 查看混淆矩阵
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()
# The confusion matrix result:
# [[10 0 0]
# [ 0 8 2]
# [ 0 2 8]]
通过结果我们可以发现,其在三分类的结果的预测准确度上有所下降,其在测试集上的准确度为: 86.67% ,这是由于’versicolor’(1)和 ‘virginica’(2)这两个类别的特征,我们从可视化的时候也可以发现,其特征的边界具有一定的模糊性(边界类别混杂,没有明显区分边界),所有在这两类的预测上出现了一定的错误。
从混淆矩阵中可以看出:标签值y=0的10个样本都被正确分类;标签值y=1的10个样本中,有8个被正确分类,其中有两个被误分类为y=2;标签值y=2的10个样本中,有8个被正确分类,其中有两个被误分类为y=1。