Python Plato区块链数据智能中逻辑回归的权威指南。 垂直搜索。 人工智能。

Python中逻辑回归的权威指南

介绍

有时混淆 线性回归 新手 - 由于共享术语 回归逻辑回归 远不同于 线性回归. 虽然线性回归预测值如 2、2.45、6.77 或 连续值,使其成为 回归 算法, 逻辑回归 预测诸如 0 或 1、1 或 2 或 3 之类的值,它们是 离散值,使其成为 分类 算法。 是的,它叫做 回归 但是是一个 分类 算法。 稍后会详细介绍。

因此,如果您的数据科学问题涉及连续值,您可以应用 回归 算法(线性回归就是其中之一)。 否则,如果它涉及对输入、离散值或类别进行分类,您可以应用 分类 算法(逻辑回归就是其中之一)。

在本指南中,我们将使用 Scikit-Learn 库在 Python 中执行逻辑回归。 我们还将解释为什么这个词 “回归” 出现在名称中以及逻辑回归的工作原理。

为此,我们将首先加载将被分类、可视化和预处理的数据。 然后,我们将构建一个逻辑回归模型来理解该数据。 然后将对该模型进行评估,并用于根据新输入预测值。

动机

您工作的公司与一家土耳其农场建立了合作伙伴关系。 这种合作关系涉及销售南瓜种子。 南瓜子对人体营养非常重要。 它们含有大量的碳水化合物、脂肪、蛋白质、钙、钾、磷、镁、铁和锌。

在数据科学团队中,您的任务是仅通过使用数据来区分南瓜种子的类型——或者 分类 根据种子类型的数据。

土耳其农场使用两种南瓜种子,一种叫做 切尔切韦利克 和另一个 乌尔居普西夫里西.

为了对南瓜种子进行分类,您的团队遵循了 2021 年的论文 “使用机器学习方法对南瓜种子 (Cucurbita pepo L.) 进行分类。 遗传资源和作物进化” 来自 Koklu、Sarigil 和 Ozbek——在这篇论文中,有一种从图像中拍摄和提取种子测量值的方法。

完成论文中描述的过程后,提取了以下测量值:

  • 面积 – 南瓜种子边界内的像素数
  • 周长 – 南瓜种子的周长(以像素为单位)
  • 长轴长度 – 还有南瓜种子的周长(以像素为单位)
  • 短轴长度 – 南瓜种子的小轴距
  • 怪癖 – 南瓜种子的偏心
  • 凸区 – 南瓜种子形成区域中最小凸壳的像素数
  • 程度 – 南瓜种子区域与边界框像素的比率
  • 当量直径 – 南瓜种子面积乘以四除以 pi 的平方根
  • 紧凑 – 南瓜籽面积与同周长圆面积之比
  • 密实度 – 南瓜子的凸凸情况
  • 圆度 – 南瓜种子的椭圆度,不考虑其边缘变形
  • 长宽比 – 南瓜子的纵横比

这些是您必须使用的测量值。 除了测量,还有 增益级 两种南瓜种子的标签。

要开始对种子进行分类,让我们导入数据并开始查看它。

了解数据集

请注意: 您可以下载南瓜数据集 相关信息.

下载数据集后,我们可以使用 pandas 图书馆。 由于它是一个 excel 文件,我们将使用 read_excel() 方法:

import pandas as pd

fpath = 'dataset/pumpkin_seeds_dataset.xlsx' 
df = pd.read_excel(fpath)

加载数据后,我们可以快速查看前 5 行,使用 head() 方法:

df.head() 

结果是:

	Area 	Perimeter 	Major_Axis_Length 	Minor_Axis_Length 	Convex_Area 	Equiv_Diameter 	Eccentricity 	Solidity 	Extent 	Roundness 	Aspect_Ration 	Compactness 	Class
0 	56276 	888.242 	326.1485 			220.2388 			56831 			267.6805 		0.7376 			0.9902 		0.7453 	0.8963 		1.4809 			0.8207 			Çerçevelik
1 	76631 	1068.146 	417.1932 			234.2289 			77280 			312.3614 		0.8275 			0.9916 		0.7151 	0.8440 		1.7811 			0.7487 			Çerçevelik
2 	71623 	1082.987 	435.8328 			211.0457 			72663 			301.9822 		0.8749 			0.9857 		0.7400 	0.7674 		2.0651 			0.6929 			Çerçevelik
3 	66458 	992.051 	381.5638 			222.5322 			67118 			290.8899 		0.8123 			0.9902 		0.7396 	0.8486 		1.7146 			0.7624 			Çerçevelik
4 	66107 	998.146 	383.8883 			220.4545 			67117 			290.1207 		0.8187 			0.9850 		0.6752 	0.8338 		1.7413 			0.7557 			Çerçevelik

在这里,我们在各自的列中有所有测量值,我们的 功能,还有 增益级 专栏,我们的 目标,这是数据框中的最后一个。 我们可以看到我们有多少测量使用 shape 属性:

df.shape 

输出是:

(2500, 13)

形状结果告诉我们数据集中有 2500 个条目(或行)和 13 列。 因为我们知道有一个目标列——这意味着我们有 12 个特征列。

我们现在可以探索目标变量南瓜种子 Class. 由于我们将预测该变量,因此查看每个南瓜种子的样本数量很有趣。 通常,我们的类中实例数量之间的差异越小,我们的样本就越平衡,我们的预测就越好。

这种检查可以通过用 value_counts() 方法:

df['Class'].value_counts() 

上面的代码显示:

Çerçevelik       1300
Ürgüp Sivrisi    1200
Name: Class, dtype: int64

我们可以看到有 1300 个样本 切尔切韦利克 种子和 1200 个样本 乌尔居普西夫里西 种子。 请注意,它们之间的差异是 100 个样本,非常小的差异,这对我们有好处,表明无需重新平衡样本数。

让我们也看看我们的特征的描述性统计数据 describe() 查看数据分布情况的方法。 我们还将转置结果表 T 为了更容易比较统计数据:

df.describe().T

结果表是:

					count 	mean 			std 			min 		25% 			50% 			75% 			max
Area 				2500.0 	80658.220800 	13664.510228 	47939.0000 	70765.000000 	79076.00000 	89757.500000 	136574.0000
Perimeter 			2500.0 	1130.279015 	109.256418 		868.4850 	1048.829750 	1123.67200 		1203.340500 	1559.4500
Major_Axis_Length 	2500.0 	456.601840 		56.235704 		320.8446 	414.957850 		449.49660 		492.737650 		661.9113
Minor_Axis_Length 	2500.0 	225.794921 		23.297245 		152.1718 	211.245925 		224.70310 		240.672875 		305.8180
Convex_Area 		2500.0 	81508.084400 	13764.092788 	48366.0000 	71512.000000 	79872.00000 	90797.750000 	138384.0000
Equiv_Diameter 		2500.0 	319.334230 		26.891920 		247.0584 	300.167975 		317.30535 		338.057375 		417.0029
Eccentricity 		2500.0 	0.860879 		0.045167 		0.4921 		0.831700 		0.86370 		0.897025 		0.9481
Solidity 			2500.0 	0.989492 		0.003494 		0.9186 		0.988300 		0.99030 		0.991500 		0.9944
Extent 				2500.0 	0.693205 		0.060914 		0.4680 		0.658900 		0.71305 		0.740225 		0.8296
Roundness 			2500.0 	0.791533 		0.055924 		0.5546 		0.751900 		0.79775 		0.834325 		0.9396
Aspect_Ration 		2500.0 	2.041702 		0.315997 		1.1487 		1.801050 		1.98420 		2.262075 		3.1444
Compactness 		2500.0 	0.704121 		0.053067 		0.5608 		0.663475 		0.70770 		0.743500 		0.9049

通过查看表格,比较 意味着标准偏差 (std) 列,可以看出大多数特征的均值与标准差相差甚远。 这表明数据值并不集中在平均值周围,而是更分散在平均值周围——换句话说,它们有 高可变性.

另外,当查看 最低限度 (min) 以及 最多 (max) 列,一些特征,例如 AreaConvex_Area, 最小值和最大值之间有很大差异。 这意味着这些列具有非常小的数据和非常大的数据值,或者 更高的振幅 数据值之间。

由于具有高可变性、高振幅和具有不同测量单位的特征,我们的大多数数据将受益于所有特征具有相同的比例或被 缩放. 数据缩放将使数据以均值为中心并减少其方差。

这种情况可能还表明数据中存在异常值和极值。 所以,最好有一些 异常值处理 除了缩放数据。

有一些机器学习算法,例如,基于树的算法,例如 随机森林分类,不受高数据方差、离群值和极值的影响。 逻辑回归 不同的是,它基于对我们的值进行分类的函数,而该函数的参数可能会受到超出一般数据趋势且具有高方差的值的影响。

当我们开始实施它时,我们将对逻辑回归有更多的了解。 现在,我们可以继续探索我们的数据。

请注意: 计算机科学中流行一句话: “垃圾进,垃圾出”(GIGO),这非常适合机器学习。 这意味着当我们有垃圾数据时——没有描述现象本身的测量,没有根据算法或模型的种类理解和准备好的数据,很可能会产生不正确的输出,无法处理一天一天的基础上。
这就是为什么探索、理解数据以及所选模型的工作方式如此重要的原因之一。 通过这样做,我们可以避免在我们的模型中放入垃圾——取而代之的是将价值放入其中,然后从中获取价值。

可视化数据

到目前为止,通过描述性统计,我们对数据的某些质量有了一个抽象的快照。 另一个重要步骤是将其可视化并确认我们关于高方差、振幅和异常值的假设。 要查看我们目前观察到的内容是否显示在数据中,我们可以绘制一些图表。

查看这些特征如何与将要预测的两个类相关也很有趣。 为此,让我们导入 seaborn 打包并使用 pairplot 查看每个特征分布的图表,以及每个特征的每个类分离:

import seaborn as sns


sns.pairplot(data=df, hue='Class')

请注意: 上面的代码可能需要一段时间才能运行,因为 pairplot 结合了所有特征的散点图(它可以),并且还显示了特征分布。

查看 pairplot,我们可以看到在大多数情况下 Çerçevelik 班级明显分开的点 Ürgüp Sivrisi 班级。 要么一类点在右边而其他点在左边,要么一些点在上面而另一些点在下面。 如果我们用某种曲线或直线来分类,这说明分类比较容易,如果混合在一起,分类就比较难了。

Eccentricity, CompactnessAspect_Ration 列,一些“孤立”或偏离一般数据趋势的点——异常值——也很容易被发现。

当查看图表从左上角到右下角的对角线时,请注意数据分布也根据我们的类别进行了颜色编码。 分布形状和两条曲线之间的距离是它们可分离程度的其他指标——彼此距离越远越好。 在大多数情况下,它们不会叠加,这意味着它们更容易分离,也有助于我们的任务。

按顺序,我们还可以绘制所有变量的箱线图 sns.boxplot() 方法。 大多数时候,将箱线图水平放置很有帮助,因此箱线图的形状与分布形状相同,我们可以使用 orient 参数:


sns.boxplot(data=df, orient='h') 

Python Plato区块链数据智能中逻辑回归的权威指南。 垂直搜索。 人工智能。

在上图中,请注意 AreaConvex_Area 与其他列的大小相比具有如此高的大小,以至于它们压扁了其他箱线图。 为了能够查看所有箱线图,我们可以缩放特征并再次绘制它们。

在这样做之前,让我们先了解一下,如果存在与其他值密切相关的特征值,例如 - 如果当其他特征值变大时,某些值也会变大,则具有 正相关; 或者如果有相反的值,则变小而其他值变小,具有 负相关关系.

这一点很重要,因为在数据中具有很强的关系可能意味着某些列派生自其他列或与我们的模型具有相似的含义。 当发生这种情况时,模型结果可能会被高估,我们希望得到更接近现实的结果。 如果有很强的相关性,这也意味着我们可以减少特征的数量,并使用更少的列使模型更 吝啬.

请注意: 计算的默认相关性 corr() 方法是 皮尔逊相关系数. 当数据是定量的、正态分布的、没有异常值并且具有线性关系时,表示该系数。

另一种选择是计算 斯皮尔曼相关系数. 当数据是有序的、非线性的、具有任何分布并且具有离群值时,使用 Spearman 系数。 请注意,我们的数据并不完全符合 Pearson 或 Spearman 的假设(还有更多相关方法,例如 Kendall 的)。 由于我们的数据是定量的,并且衡量其线性关系对我们来说很重要,因此我们将使用 Pearson 系数。

让我们看一下变量之间的相关性,然后我们可以开始预处理数据。 我们将计算与 corr() 方法并用 Seaborn 的可视化它们 heatmap(). 热图标准尺寸往往很小,所以我们将导入 matplotlib (Seaborn 建立在其之上的通用可视化引擎/库)并更改大小 figsize:

import matplotlib.pyplot as plt
plt.figure(figsize=(15, 10))

correlations = df.corr()
sns.heatmap(correlations, annot=True) 

Python Plato区块链数据智能中逻辑回归的权威指南。 垂直搜索。 人工智能。

在这张热图中,接近1或-1的值是我们需要关注的值。 第一种情况表示高度正相关,第二种情况表示高度负相关。 如果不高于 0.8 或 -0.8,这两个值都将有利于我们的逻辑回归模型。

当存在高相关性时,例如 0.99 之间 Aspec_RationCompactness,这意味着我们可以选择只使用 Aspec_Ration 或仅 Compactness,而不是他们两个(因为他们几乎相等 预测变量 彼此的)。 同样适用于 EccentricityCompactness-0.98 相关性,对于 AreaPerimeter0.94 相关性,以及其他一些列。

预处理数据

由于我们已经探索了一段时间的数据,我们可以开始对其进行预处理。 现在,让我们使用所有功能进行类别预测。 在获得第一个模型,即基线后,我们可以删除一些高度相关的列并将其与基线进行比较。

特征列将是我们的 X 数据和类列,我们的 y 目标数据:

y = df['Class']
X = df.drop(columns=['Class'], axis=1)

将分类特征转化为数字特征

关于我们的 Class column – 它的值不是数字,这意味着我们还需要转换它们。 有很多方法可以进行这种转换; 在这里,我们将使用 replace() 方法和替换 Çerçevelik0Ürgüp Sivrisi1.

y = y.replace('Çerçevelik', 0).replace('Ürgüp Sivrisi', 1)

记住映射! 当从你的模型中读取结果时,你会希望至少在你的脑海中将它们转换回来,或者转换回其他用户的类名。

将数据划分为训练集和测试集

在我们的探索中,我们注意到功能需要缩放。 如果我们现在进行缩放,或者以自动方式进行缩放,我们将对整个值进行缩放 Xy. 在这种情况下,我们会介绍 数据泄漏,因为即将成为测试集的值会影响缩放。 数据泄露是导致 ML 模型无法重现结果和虚幻高性能的常见原因。

考虑缩放表明我们需要先拆分 Xy 数据进一步进入训练和测试集,然后 适合 训练集上的缩放器,以及 改造 训练集和测试集(测试集不会影响执行此操作的缩放器)。 为此,我们将使用 Scikit-Learn 的 train_test_split() 方法:

from sklearn.model_selection import train_test_split
SEED = 42 

X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                    test_size=.25, 
                                                    random_state=SEED)

设置 test_size=.25 确保我们使用 25% 的数据进行测试,75% 的数据用于训练。 这可以省略,一旦它是默认拆分,但是 蟒蛇式 编写代码的方式建议“显式优于隐式”。

请注意: “显式优于隐式”这句话是对 Python的禅宗, 或 PEP20。 它列出了编写 Python 代码的一些建议。 如果遵循这些建议,则考虑代码 蟒蛇式. 你可以了解更多 相关信息.

将数据拆分为训练集和测试集后,最好查看每个集中有多少条记录。 这可以通过 shape 属性:

X_train.shape, X_test.shape, y_train.shape, y_test.shape

这显示:

((1875, 12), (625, 12), (1875,), (625,))

我们可以看到拆分后,我们有 1875 条记录用于训练,625 条记录用于测试。

缩放数据

一旦我们准备好训练集和测试集,我们就可以继续使用 Scikit-Learn 扩展数据 StandardScaler 对象(或库提供的其他缩放器)。 为避免泄漏,洁牙器安装在 X_train 然后使用数据和训练值来缩放或转换训练和测试数据:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

因为你通常会打电话给:

scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

前两行可以用单数折叠 fit_transform() 调用,它适合集合上的缩放器,并一次性转换它。 我们现在可以重现箱线图以查看缩放数据后的差异。

考虑到缩放删除了列名,在绘图之前,我们可以再次将训练数据组织到带有列名的数据框中,以方便可视化:

column_names = df.columns[:12] 
X_train = pd.DataFrame(X_train, columns=column_names)

sns.boxplot(data=X_train, orient='h')

Python Plato区块链数据智能中逻辑回归的权威指南。 垂直搜索。 人工智能。

我们终于可以看到我们所有的箱线图了! 请注意,所有这些都有异常值,并且呈现出远离正态分布的特征(曲线向左或向右倾斜),例如 Solidity, Extent, Aspect_RationCompactedness, 与具有更高相关性的相同。

使用 IQR 方法去除异常值

我们已经知道逻辑回归会受到异常值的影响。 治疗它们的方法之一是使用一种称为 四分位距 or 智商. IQR 方法的第一步是将我们的火车数据分成四个部分,称为四分位数。 第一个四分位数, Q1, 占数据的 25%,第二个, Q2, 到 50%, 第三, Q3, 到 75%, 最后一个, Q4, 至 100%。 箱线图中的方框由 IQR 方法定义,是它的可视化表示。

考虑水平箱线图,左侧的垂直线标记 25% 的数据,中间的垂直线标记 50% 的数据(或中值),右侧最后一条垂直线标记 75% 的数据. 垂直线定义的两个正方形的大小越均匀——或者中线垂直线在中间越多——意味着我们的数据更接近正态分布或偏斜程度更低,这有助于我们的分析。

除了 IQR 框外,它的两侧也有水平线。 这些线标记了定义的最小和最大分布值

$$
最小值 = Q1 – 1.5*IQR
$$

$$
最大值 = Q3 + 1.5*IQR
$$

IQR正是Q3与Q1(或Q3-Q1)之差,是数据的最中心点。 这就是为什么在寻找 IQR 时,我们最终会过滤掉数据末端或最小值和最大值点中的异常值。 箱形图让我们先睹为快,了解 IQR 方法的结果。

Python Plato区块链数据智能中逻辑回归的权威指南。 垂直搜索。 人工智能。

我们可以使用熊猫 quantile() 找到我们的分位数的方法,以及 iqr 来自 scipy.stats 包获取每一列的四分位数数据范围:

from scipy.stats import iqr

Q1 = X_train.quantile(q=.25)
Q3 = X_train.quantile(q=.75)

IQR = X_train.apply(iqr)

现在我们有了 Q1、Q3 和 IQR,我们可以过滤掉更接近中位数的值:


minimum = X_train < (Q1-1.5*IQR)
maximum = X_train > (Q3+1.5*IQR)


filter = ~(minimum | maximum).any(axis=1)


X_train = X_train[filter]

过滤我们的训练行后,我们可以看到其中有多少仍在数据中 shape:

X_train.shape

结果是:

(1714, 12)

我们可以看到过滤后行数从 1875 变为 1714。 这意味着 161 行包含离群值或 8.5% 的数据。

请注意: 建议过滤异常值、移除 NaN 值以及其他涉及过滤和清理数据的操作保持在数据的 10% 以下或最高 10%。 如果过滤或删除超过数据的 XNUMX%,请尝试考虑其他解决方案。

移除异常值后,我们几乎准备好将数据包含在模型中。 对于模型拟合,我们将使用训练数据。 X_train 被过滤了,但是怎么样 y_train?

y_train.shape

输出:

(1875,)

注意到 y_train 仍然有 1875 行。 我们需要匹配的数量 y_train 行数 X_train 行而不仅仅是任意的。 我们需要删除我们删除的南瓜种子实例的 y 值,它们很可能散布在 y_train 放。 过滤后的 X_train stil 有它的原始索引,并且索引在我们删除异常值的地方有差距! 然后我们可以使用索引 X_train DataFrame中搜索对应的值 y_train:

y_train = y_train.iloc[X_train.index]

完成后,我们可以查看 y_train 再次塑造:

y_train.shape

哪些输出:

(1714,)

查看我们的 Git 学习实践指南,其中包含最佳实践、行业认可的标准以及随附的备忘单。 停止谷歌搜索 Git 命令,实际上 学习 它!

现在, y_train 也有 1714 行,它们与 X_train 行。 我们终于准备好创建逻辑回归模型了!

实施逻辑回归模型

困难的部分已经完成! 预处理通常比模型开发更难,当涉及到使用像 Scikit-Learn 这样的库时,它已将 ML 模型的应用程序简化为几行代码。

首先,我们导入 LogisticRegression 类并实例化它,创建一个 LogisticRegression 宾语:

from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression(random_state=SEED)

其次,我们将训练数据拟合到 logreg 模型与 fit() 方法,并用 predict() 方法,将结果存储为 y_pred:



logreg.fit(X_train.values, y_train)
y_pred = logreg.predict(X_test)

我们已经用我们的模型做出了预测! 让我们看看前 3 行 X_train 查看我们使用了哪些数据:

X_train[:3]

上面的代码输出:

       Area          Perimeter     Major_Axis_Length    Minor_Axis_Length    Convex_Area   Equiv_Diameter       Eccentricity  Solidity      Extent        Roundness     Aspect_Ration        Compactness
0      -1.098308     -0.936518     -0.607941            -1.132551            -1.082768     -1.122359            0.458911      -1.078259     0.562847      -0.176041     0.236617             -0.360134
1      -0.501526     -0.468936     -0.387303            -0.376176            -0.507652     -0.475015            0.125764      0.258195      0.211703      0.094213      -0.122270            0.019480
2      0.012372      -0.209168     -0.354107            0.465095              0.003871      0.054384            -0.453911     0.432515      0.794735      0.647084      -0.617427            0.571137

在前 3 个预测中 y_pred 查看结果:

y_pred[:3] 

结果是:

array([0, 0, 0])

对于那三行,我们的预测是它们是一流的种子, Çerçevelik.

逻辑回归,而不是预测最终类别,例如 0,我们还可以预测该行与 0 班级。 这就是逻辑回归对数据进行分类时实际发生的情况,而 predict() 方法然后通过阈值传递此预测以返回“硬”类。 为了预测属于某个类别的概率, predict_proba() 用来:

y_pred_proba = logreg.predict_proba(X_test)

我们还看一下 y 概率预测的前 3 个值:

y_pred_proba[:3] 

哪些输出:

        # class 0   class 1   
array([[0.54726628, 0.45273372],
       [0.56324527, 0.43675473],
       [0.86233349, 0.13766651]])

现在,每个类都有一列,而不是三个零。 在左侧的列中,从 0.54726628, 是属于该类别的数据的概率 0; 在右栏中,从 0.45273372, 是属于类别的概率 1.

请注意: 这种分类上的差异也被称为 预言。 硬预测将预测框为一个类,而软预测输出 可能性 属于一个类的实例。

有关如何生成预测输出的更多信息。 其实不是 0, 但有 55% 的机会上课 0, 以及 45% 的机会上课 1. 这表明前三个 X_test 数据点,属于类 0, 仅关于第三个数据点非常清楚,概率为 86%——而对于前两个数据点则不太清楚。

当使用 ML 方法交流发现时——通常最好返回一个软类,并将相关概率作为 “信心” 该分类的。

当我们更深入地研究模型时,我们将更多地讨论它是如何计算的。 这个时候,我们就可以进行下一步了。

使用分类报告评估模型

第三步是查看模型在测试数据上的表现如何。 我们可以导入 Scikit-Learn classification_report() 并通过我们的 y_testy_pred 作为参数。 之后,我们可以打印出它的响应。

分类报告包含最常用的分类指标,例如 精确, 记得, f1-分数 .

  1. 平台精度:了解我们的分类器认为哪些正确的预测值是正确的。 Precision 会将这些真阳性值除以任何被预测为阳性的值:

$$
精度 = frac{text{true positive}}{text{true positive} + text{false positive}}
$$

  1. 记得:了解我们的分类器识别了多少真阳性。 召回率是通过将真阳性除以任何应该被预测为阳性的值来计算的:

$$
回忆 = frac{文本{真阳性}}{文本{真阳性} + 文本{假阴性}}
$$

  1. F1分数: 是平衡的还是 谐波均值 精度和召回率。 最小值为 0,最大值为 1。当 f1-score 等于 1,这意味着所有类别都被正确预测——这是一个很难用真实数据获得的分数:

$$
文本{f1-分数} = 2* 压裂{文本{精度} * 文本{召回}}{文本{精度} + 文本{召回}}
$$

  1. 准确性:描述了我们的分类器有多少预测是正确的。 最低准确度值为 0,最高准确度值为 1。该值通常乘以 100 以获得百分比:

$$
准确度 = frac{text{正确预测数}}{text{预测总数}}
$$

请注意: 任何真实数据都很难获得 100% 的准确度,如果发生这种情况,请注意可能会发生一些泄漏或错误 - 对于理想的准确度值没有达成共识,它也取决于上下文。 70% 的值意味着分类器将在 30% 的数据上出错,或者 70% 以上对于大多数模型来说就足够了。

from sklearn.metrics import classification_report
cr = classification_report(y_test, y_pred)
print(cr)

然后我们可以查看分类报告输出:

				precision    recall  f1-score   support

           0       0.83      0.91      0.87       316
           1       0.90      0.81      0.85       309

    accuracy                           0.86       625
   macro avg       0.86      0.86      0.86       625
weighted avg       0.86      0.86      0.86       625

这是我们的结果。 请注意 precision, recall, f1-scoreaccuracy 指标都非常高,超过 80%,这是理想的——但这些结果可能受到高相关性的影响,从长远来看不会持续。

该模型的准确率为 86%,这意味着它有 14% 的时间分类错误。 我们掌握了总体信息,但很想知道 14% 的错误是否发生在类别分类方面 0 或班级 1. 为了确定哪些类别被错误识别为哪些类别以及以何种频率被错误识别——我们可以计算并绘制一个 混淆矩阵 我们模型的预测。

使用混淆矩阵评估模型

让我们计算然后绘制混淆矩阵。 这样做之后,我们就可以理解它的每个部分了。 为了绘制混淆矩阵,我们将使用 Scikit-Learn confusion_matrix(),我们将从 metrics 模块。

使用 Seaborn 可以更容易地可视化混淆矩阵 heatmap(). 因此,在生成它之后,我们将把我们的混淆矩阵作为热图的参数传递:

from sklearn.metrics import confusion_matrix

cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt='d')

Python Plato区块链数据智能中逻辑回归的权威指南。 垂直搜索。 人工智能。

  1. 混淆矩阵:矩阵显示模型在每个类别中正确或错误的样本数量。 正确且正确预测的值称为 真正的积极,那些被预测为正但不是正的被称为 误报. 相同的命名法 真正的负面假阴性 用于负值;

通过查看混淆矩阵图,我们可以看到我们有 287 曾经的价值观 0 并预测为 0 - 要么 真正的积极 上课 0 (Çerçevelik 种子)。 我们还有 250 班级的真正积极因素 1 (Ürgüp Sivrisi 种子)。 真阳性总是位于从左上角到右下角的矩阵对角线上。

我们还有 29 应该是的值 0, 但预测为 1 (误报) 以及 59 曾经的价值观 1 并预测为 0 (假阴性). 通过这些数字,我们可以了解到该模型最常犯的错误是它预测了假阴性。 因此,它最终可能会将 Ürgüp Sivrisi 种子分类为 Çerçevelik 种子。

这种错误也可以用81%的课堂召回率来解释 1. 请注意,指标是相关联的。 召回的不同之处在于 Ürgüp Sivrisi 类的样本减少了 100 个。 这是仅比其他类别少几个样本的含义之一。 为了进一步提高召回率,您可以尝试使用类别权重或使用更多 Ürgüp Sivrisi 样本。

到目前为止,我们已经执行了大部分数据科学传统步骤,并将逻辑回归模型用作黑盒。

请注意: 如果您想走得更远,请使用 交叉验证 (CV) 和网格搜索 分别寻找最能概括数据的模型,以及训练前选择的最佳模型参数,或者 超参数.

理想情况下,使用 CV 和网格搜索,您还可以实现一种串联的方式来执行数据预处理步骤、数据拆分、建模和评估——使用 Scikit-Learn 可以轻松实现 管道.

现在是时候打开黑匣子,看看它的内部,更深入地了解逻辑回归的工作原理了。

深入了解逻辑回归的真正工作原理

回归 这个词不是偶然出现的,要了解逻辑回归的作用,我们可以记住它的兄弟线性回归对数据的作用。 线性回归公式如下:

$$
y = b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n
$$

其中b0 是回归截距,b1 系数和 x1 数据。

该等式产生了一条直线,用于预测新值。 回顾一下介绍,现在不同的是我们不会预测新的值,而是一个类。 所以这条直线需要改变。 通过逻辑回归,我们引入了非线性,现在使用曲线而不是直线进行预测:

Python Plato区块链数据智能中逻辑回归的权威指南。 垂直搜索。 人工智能。

观察到当线性回归线继续前进并且由连续的无限值组成时,逻辑回归曲线可以在中间分开并且在 0 和 1 值处具有极值。 “S”形是它对数据进行分类的原因——靠近或落在最上端的点属于第 1 类,而位于下象限或靠近 0 的点属于第 0 类。 “S”是 0 和 1 之间的中间值,0.5——它是逻辑回归点的阈值。

Python Plato区块链数据智能中逻辑回归的权威指南。 垂直搜索。 人工智能。

我们已经了解了逻辑回归和线性回归之间的视觉差异,但是公式呢? 逻辑回归的公式如下:

$$
y = b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n
$$

也可以写成:

$$
y_{prob} = frac{1}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}
$$

或者甚至可以写成:

$$
y_{prob} = frac{e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}
$$

在上面的等式中,我们有输入的概率,而不是它的值。 它的分子是 1,所以它可以得到一个介于 0 和 1 之间的值,而 1 加上它的分母中的一个值,所以它的值是 1 等等——这意味着整个分数结果不能大于 1 .

分母的值是多少? 这是 e,自然对数的底(约 2.718282),提高到线性回归的幂:

$$
e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

另一种写法是:

$$
ln left( frac{p}{1-p} right) = {(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

在最后一个等式中, ln 是自然对数(以 e 为底)和 p 是概率,所以结果概率的对数与线性回归结果相同。

换句话说,利用线性回归结果和自然对数,我们可以得出输入属于或不属于设计类别的概率。

整个逻辑回归推导过程如下:

$$
p{X} = frac{e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}
$$

$$
p(1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}) = e^{(b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

$$
p + p*e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)} = e^{(b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

p
=

e

(

b
0

+

b
1

*

x
1

+

b
2

*

x
2

+

b
3

*

x
3

+
...
+

b
n

*

x
n

)

-
p
*

e

(

b
0

+

b
1

*

x
1

+

b
2

*

x
2

+

b
3

*

x
3

+
...
+

b
n

*

x
n

)

$$
分形{p}{1-p} = e^{(b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

$$
ln 左(frac{p}{1-p} 右)= (b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)
$$

这意味着逻辑回归模型也有系数和截距值。 因为它使用线性回归并用自然对数(e).

我们可以看到模型的系数值和截距,就像我们对线性回归所做的一样,使用 coef_intercept_ 特性:

logreg.coef_

其中显示了 12 个特征中每个特征的系数:

array([[ 1.43726172, -1.03136968,  0.24099522, -0.61180768,  1.36538261,
        -1.45321951, -1.22826034,  0.98766966,  0.0438686 , -0.78687889,
         1.9601197 , -1.77226097]])
logreg.intercept_

这导致:

array([0.08735782])

使用系数和截距值,我们可以计算数据的预测概率。 让我们得到第一个 X_test 再次值,例如:

X_test[:1]

这将返回第一行 X_test 作为 NumPy 数组:

array([[-1.09830823, -0.93651823, -0.60794138, -1.13255059, -1.0827684 ,
        -1.12235877,  0.45891056, -1.07825898,  0.56284738, -0.17604099,
         0.23661678, -0.36013424]])

按照初始等式:

$$
p{X} = frac{e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}
$$

在 python 中,我们有:

import math

lin_reg = logreg.intercept_[0] + 
((logreg.coef_[0][0]* X_test[:1][0][0])+ 
(logreg.coef_[0][1]* X_test[:1][0][1])+ 
(logreg.coef_[0][2]* X_test[:1][0][2])+ 
(logreg.coef_[0][3]* X_test[:1][0][3])+ 
(logreg.coef_[0][4]* X_test[:1][0][4])+ 
(logreg.coef_[0][5]* X_test[:1][0][5])+ 
(logreg.coef_[0][6]* X_test[:1][0][6])+ 
(logreg.coef_[0][7]* X_test[:1][0][7])+ 
(logreg.coef_[0][8]* X_test[:1][0][8])+ 
(logreg.coef_[0][9]* X_test[:1][0][9])+ 
(logreg.coef_[0][10]* X_test[:1][0][10])+ 
(logreg.coef_[0][11]* X_test[:1][0][11]))

px = math.exp(lin_reg)/(1 +(math.exp(lin_reg)))
px

结果是:

0.45273372469369133

如果我们再看看 predict_proba 第一的结果 X_test 行,我们有:

logreg.predict_proba(X_test[:1])


这意味着原始逻辑回归方程为我们提供了关于类别的输入概率 1, 找出类别的概率 0,我们可以简单地:

1 - px


请注意,两者 px1-pxpredict_proba 结果。 这就是逻辑回归的计算方式和原因 回归 是其名称的一部分。 但是这个词呢 物流?

期限 物流 来自 Logit,这是一个我们已经见过的函数:

$$
ln 左(frac{p}{1-p} 右)
$$

我们刚刚用 px1-px. 这就是logit,也叫 对数赔率 因为它等于赔率的对数,其中 p 是概率。

结论

在本指南中,我们研究了一种最基本的机器学习分类算法,即 逻辑回归.

最初,我们使用 Scikit-Learn 的机器学习库将逻辑回归实现为一个黑盒,后来我们一步步理解它,清楚了回归和逻辑这两个术语的来由和来源。

我们还探索和研究了数据,了解这是数据科学分析中最关键的部分之一。

从这里,我建议你玩 多类逻辑回归,多于两个类的逻辑回归——您可以对具有多个类的其他数据集应用相同的逻辑回归算法,并解释结果。

请注意: 可以使用大量的数据集 相关信息 供你玩。

我还建议你学习L1和L2 正则化,它们是一种“惩罚”较高数据以使其更接近正常的方法,保持模型的复杂性,因此算法可以获得更好的结果。 我们使用的 Scikit-Learn 实现默认已经具有 L2 正则化。 另一个要看的是不同的 求解器,如 lbgs,优化了逻辑回归算法的性能。

同样重要的是要看看 统计 逻辑回归的方法。 它有 假设 关于数据的行为,以及为了保证满意的结果而必须持有的其他统计数据,例如:

  • 观察是独立的;
  • 解释变量之间不存在多重共线性;
  • 没有极端异常值;
  • 解释变量与响应变量的logit之间存在线性关系;
  • 样本量足够大。

请注意我们对数据的分析和处理中已经涵盖了其中多少假设。

我希望您继续探索逻辑回归在其所有不同方法中必须提供的内容!

时间戳记:

更多来自 堆栈滥用