搜索
您的当前位置:首页正文

Core ML框架详细解析(十五) —— 机器学习:分类(一)

来源:二三娱乐

版本记录

版本号 时间
V1.0 2018.10.16 星期二

前言

开始

在机器学习中,分类是在给定一些输入标记数据集的情况下从有限数量的类中预测对象类的任务。 在本教程中,您将学习如何预处理训练数据,评估分类器并对其进行优化。

在机器学习中,分类是在给定一些输入标记数据集的情况下从有限数量的类中预测对象类的任务。 例如,您可能有一个包含10,000封电子邮件的列表,并且需要确定它们是否是垃圾邮件。 您可以在此输入数据上训练分类器,并且能够预测新电子邮件是否是垃圾邮件。 另一个经典的例子是一个分类器,它可以从已知类的列表中预测图像中描绘的对象,例如房屋,汽车,猫等。

在本教程中,您将学习如何:

  • 预处理和准备数据以提供给机器学习分类算法。
  • 根据最常用的分类指标评估分类器。
  • 优化机器学习分类器的参数。

注意:本教程要求使用Jupyter Notebook和几个用于机器学习训练的Python科学库。具体如何配置不多说了,前面几篇都有所涉及。

打开已有工程,将两个ipynb文件复制到Jupyter Notebooks文件夹。 然后,用Jupyter打开Starter.ipynb

Jupyter的顶部菜单中,选择Kernel,然后选择Restart&Run All

如果提示Restart kernel and re-run the whole notebook,请选择Restart and Run All Cells

底部单元格包含用于下载名为credit的数据集的代码。 此数据集包含400行,其中每行包含一些与人相关的信用相关信息以及一些个人详细信息,如年龄和学生状态。 您可以在笔记本中看到前5行。

您在此项目中的目标是使用此数据集创建分类器,以使用尽可能少的个人信息来预测用户是否具有信誉。 您将信誉良好的人定义为信用评分(评分)超过600的人。


Preprocessing and Selecting Features - 预处理和选择功能

任何机器学习项目的第一步是清理数据或将数据转换为机器学习算法可以使用的格式。 在大多数情况下,您需要数字数据而没有任何缺失值或异常值,否则可能会使训练模型更加困难。

对于信用数据集,值已经非常清理,但您仍需要将数据转换为数值。

1. Encoding Labels - 编码标签

最简单的预处理步骤之一称为标签编码(label encoding)。 它允许您将非数字值转换为数值。 您将使用它来转换StudentMarriedGender列。

将以下代码添加到下面的新单元格中,您的代码在此处:

# 1
credit_ = credit.copy()

# 2
credit_["Student"] = credit["Student"].map(lambda student: 1 if student == "Yes" else 0)

credit_["Married"] = credit["Married"].map(lambda married: 1 if married == "Yes" else 0)

# 3
credit_["Female"] = credit["Gender"].map(lambda gender: 1 if gender == "Female" else 0)
credit_.drop("Gender", axis=1, inplace=True)

# 4
credit_.head()

下面进行细分:

  • 1) 您可以复制信用数据集,以便能够干净地转换数据集。 credit_将在处理完成后保留即用数据。
  • 2) 对于StudentMarried,您标记编码YES是1,NO为0。
  • 3) 在这里,您还可以对Gender字段执行相同操作,同时将列重命名为Female。 您也可以在之后删除Gender列。
  • 4) 在单元格的末尾,显示数据的顶行以验证处理步骤是否成功。

Control + Enter运行您的代码。 它应该类似于以下内容:

到现在为止还挺好! 您可能正在考虑对Eye Color列执行相同操作。 此列包含三个值:绿色,蓝色和淡褐色。 您可以分别用0,1和2替换这些值。

大多数机器学习算法会误解这些信息。 像逻辑回归这样的算法会得知值为2的Eye Color将具有比1更强的效果。更好的方法是使用单热编码。

2. One-Hot Encoding - 单热编码

使用单热编码(one-hot encoding)(也称为Dummy Variables)时,可以创建与不同值一样多的列。 然后每列变为0或1,具体取决于该行的原始值是否等于新列。 例如,如果行的值为蓝色,则在单热编码数据中,蓝色列将为1,则绿色和黑色列都将为0。

为了更好地显示此内容,请通过从顶部菜单中选择Insert ▸ Insert Cell Below来创建新单元格,并将以下代码添加到新单元格:

pd.get_dummies(credit_["Eye Color"])

get_dummies将根据Eye Color中观察到的值创建虚拟变量。 运行单元格检查出来:

因为数据集中的第一个条目有淡褐色(hazel)眼睛,所以此处的第一个结果在Hazel中包含1,在蓝色和绿色中包含0。 其余399个条目的工作方式相同!

转到Edit ▸ Delete Cells以删除最后一个单元格。 接下来,在最新单元格中的credit_.head()之前添加以下行:

eye_color = pd.get_dummies(credit["Eye Color"], drop_first=True)
credit_ = pd.concat([credit_.drop("Eye Color", axis=1), eye_color], axis=1)

在第一行中,您使用drop_first = True来丢弃第一个虚拟列,为Eye Color创建虚拟列。 这样做是为了节省空间,因为可以从其他两个值推断出最后一个值。

然后,使用concat将虚拟列连接到最后的数据。 再次运行单元格并查看结果!

3. Target Label - 目标标签

对于预处理的最后一步,您将创建目标标签。 这将是您的分类器将预测的列 - 在这种情况下,该人是否具有信誉。

对于大于600的Rating,标签将为1(信誉良好)。 否则,将其设置为0。将以下代码再次添加到credit_.head()之前的当前单元格中:

credit_["Creditworthy"] = credit["Rating"].map(lambda val: 0 if val < 600 else 1)
credit_.drop("Rating", axis=1, inplace=True)

最后一列将是您的分类器将使用其他列的组合预测的列。

最后一次运行此单元格。 预处理现已完成,您的数据帧已准备好进行训练!


Training and Cross Validation - 训练和交叉验证

现在数据准备就绪,您可以创建分类器并对其进行训练。 将以下代码添加到新单元格:

X = credit_[["Age", "Education", "Student", "Married"]]
y = credit_["Creditworthy"]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=RANDOM_STATE)

您正在选择要训练模型的四个要素,并将它们存储在X中,Credworthy列是您的目标,名为y

在最后一行中,您将数据集拆分为两个随机的一半,一个用于训练分类器的训练集,以及一个用于验证分类器以查看其执行情况的测试集。

接下来,将以下代码添加到新单元格:

estimator = LogisticRegression(random_state=RANDOM_STATE)  # 1
estimator.fit(X_train, y_train)  # 2

y_true = y_test  # 3
y_pred = estimator.predict(X_test)  # 4
y_score = estimator.predict_proba(X_test)[:, 0]  # 5

这里有很多事情要做:

  • 1) 您使用逻辑回归作为分类器。其背后的细节超出了本教程的范围。您可以在中了解更多相关信息。
  • 2) 您训练 - 或“fit” - 数据集训练部分的分类器。
  • 3) y_true将保存y列的真实值,即信誉值。在这种情况下,它只是测试值本身。
  • 4) y_pred保持预测的信誉新值。您将使用此值以及真值来评估分类器的性能。请注意,此评估是使用测试集完成的,因为分类器还没有“看到”这些,并且目标是预测未知值。否则,你可能只是记住了训练值并且每次都正确地预测了一切。
  • 5) 逻辑回归是一种实际预测概率的分类算法。该模型的输出类似于:“具有给定值的人具有信誉的概率为75%。”您可以使用这些概率分数来评估分类器的更高级度量。

您已经成功训练了分类器并用它来预测概率!接下来,你会发现你的表现如何。

1. Accuracy - 准确性

检查模型准确性的最简单指标之一是模型的准确性。分类器可以正确预测的值的百分比是多少?

将此行添加到新单元格:

accuracy_score(y_true=y_true, y_pred=y_pred)

accuracy_score将您的y列设为true和预测值,并返回准确度。 运行单元格并检查结果:

差不多95%! 你是否真的只用一个人的年龄,教育,学生和婚姻状况来做得那么好?

事实证明,在测试数据集中的200行中,只有11行是有信誉的。 这意味着始终预测该行不具有信誉的分类器也具有约95%的准确度!

因此,你的分类器预测的95%不是那么好 - 或实际上有任何好处。 准确性虽然在不同类别平衡时通常很有用,但如果没有上下文可能会非常误导。 一个更好的度量标准或一系列度量标准,以及您应该始终关注的标准,是混淆矩阵(confusion matrix)

2. Understanding Confusion Matrix, Precision and Recall - 了解混淆矩阵,精度和回调

混淆矩阵将真实值与预测值进行对比。 精确度和回调是从混淆矩阵派生的两个非常有用的度量。 在数据集的上下文中,指标回答以下问题:

  • Precision - 精确度:在所有信誉良好的人中,有多少百分比被正确预测为信誉良好?
  • Recall - 回调:在预计信誉良好的所有人中,有多少人实际上是有信誉的?

当您看到数据时,这将变得更加清晰,因此是时候添加一些代码了。 为以下每个代码块创建新单元格并运行它们(不要担心警告):

confusion_matrix(y_true=y_true, y_pred=y_pred)
precision_score(y_true=y_true, y_pred=y_pred)
recall_score(y_true=y_true, y_pred=y_pred)
plot_confusion_matrix(cm=confusion_matrix(y_true=y_true, y_pred=y_pred),
                      class_names=["not creditworthy", "creditworthy"])

在第一个单元格中,confusion_matrix将真实值与预测值进行对比。输出多维数组中的每个象限表示true valuepredicted value的组合。例如,右上角是不具有信誉且行分类器正确预测不具有信誉的行数。

最后一个单元包括对此的可视化,其中每个象限也除以总行数。您可以看到您当前的分类器实际上正在执行您所担心的操作:它只是预测所有行都不值得信任。

在中间,您将看到precision_scorerecall_score的计算结果。这两个指标的范围从0(0%)1(100%)。你离1越近越好。这两个指标之间总是存在权衡。

例如,如果您对信用检查没有那么严格,并且让一些有问题的人通过,您会提高您的精确度,但您的recall会受到影响。另一方面,如果你非常严格,你的recall可能是无可挑剔的,但你不会向许多有信誉的人发放信用,你的精确度会受到影响。您需要准确权衡取决于您的使用情况。

您的精度和recall都是0,表明分类器目前非常糟糕。返回到设置Xy的单元格,并将X更改为以下内容:

X = credit_[["Income", "Education", "Student", "Married"]]

您现在使用Income值作为训练的一部分。 转至Kernel ▸ Restart & Run All运行以重新运行所有单元格。

精度提高到0.64,recall到0.81! 这表明您的分类器实际上具有一定的预测能力。 现在你到了某个地方。

3. Parameter tuning and pipelines - 参数调整和管道

但是你应该设置哪些值? 实际上,为什么不尝试所有这些并看看哪些有效?

在估算单元格中,替换:

estimator = LogisticRegression(random_state=RANDOM_STATE)
estimator.fit(X_train, y_train)

使用下面的

param_grid = dict(C=np.logspace(-5, 5, 11), penalty=['l1', 'l2'])
regr = LogisticRegression(random_state=RANDOM_STATE)
cv = GridSearchCV(estimator=regr, param_grid=param_grid, scoring='average_precision')
cv.fit(X_train, y_train)
estimator = cv.best_estimator_

在这里,您可以在0.00001100000之间进行详尽的搜索,而不是使用C为1.0和penaltyl2的默认逻辑回归,以查看哪个在分类器中产生更好的精度。

此网格搜索还完成另一项非常重要的任务:它在您的测试集上执行交叉验证。 在这样做时,它将测试集分成较小的子集,并且连续地从训练/评估中留下一个子集。 然后它评估分类器的精度,它选择的最终参数是在所有这些子集中产生最佳平均精度的参数。 通过这种方式,您可以更加确信您的分类器非常强大,并且在用于评估没使用过的新数据时会产生类似的结果。

转到Kernel ▸ Restart & Run All,再次运行所有单元格。

你会发现精度实际下降到56%。 它失败的原因是它并不是真正的apples-to-apples比较,你上次可能会幸运。 您看到的新精度将更接近您在“in the wild”所期望的精度。

4. Scaling - 缩放

你的分类器现在已经相当不错了,但你仍然可以提高56%左右的精度。 您总是希望做的一件事是将数据集扩展到0到1的范围内。当数据集具有不同比例值的列时,大多数分类算法都会表现不佳。 在这种情况下,教育范围从0到50,收入可以是从0到几乎无限制的任何地方。

用以下内容替换整个估算器单元:

scaler = StandardScaler()  # 1
param_grid = dict(C=np.logspace(-5, 5, 11), penalty=['l1', 'l2'])
regr = LogisticRegression(random_state=RANDOM_STATE)
cv = GridSearchCV(estimator=regr, param_grid=param_grid, scoring='average_precision')
pipeline = make_pipeline(scaler, cv)  # 2

pipeline.fit(X_train, y_train)

# 3
y_true = y_test
y_pred = pipeline.predict(X_test)
y_score = pipeline.predict_proba(X_test)[:, 1]

下面进行细分:

  • 1) 您可以创建标准缩放器。
  • 2) 您创建一个管道对象,首先缩放数据,然后将其提供给网格搜索。
  • 3) 您可以像使用估算器一样使用管道。 您可以对其调用fitpredict,默认情况下它甚至会使用网格搜索的最佳估算器。

再次运行所有指标单元格。 精度提高到72%!

5. ROC

在结束分类器之前,您应该总是看一个指标:ROC AUC。它与混淆矩阵密切相关,但也包含预测的概率 - 或分类器的分数。它的范围从01,其中越高越好。

直观地说,它衡量的是得分预测比随机好多少。

它通过在各种阈值处切断概率分数并将其向下舍入以进行预测来实现此目的。然后绘制真实的正面率 - 实际信誉良好的预测信誉人群的比率,或者仅仅是从上面recall - 与错误的比率,即实际上没有信誉的预测为有信誉度人的比率。该图称为ROC(接收器工作特性),ROC AUC(曲线下面积)就是该曲线下的面积!

将以下代码块添加到笔记本的底部,分成两个新单元格,然后再次运行单元格:

roc_auc_score(y_true=y_true, y_score=y_score)
plot_roc_curve(y_true=y_true, y_score=y_score)

ROC0.98表示您的预测非常好!

本教程为您提供了一些在处理自己的分类问题时会遇到的最常用的策略。

后记

本篇主要讲述了机器学习:分类,感兴趣的给个赞或者关注~~~

Top