多类标签的概率预测指南
分类问题是机器学习中最常见的问题之一。因此,有必要了解有多种方法可以解决这些问题。
解决分类问题最常见的方法是根据有关问题的性质得到离散的或明确的分类。这并不总是如此,因为可以通过使用概率来解决分类问题,而不是使用特定类别中的离散值类。
通过使用这种方法,你可以评估一组给定的特征与其他标签相比,给出所需标签的可能性。
此外,在一个表格上做一个清晰的可视化,将所有这些不同的标签和概率进行比较,以便对我们预测的数据的性质有一个更有力的了解,这也是可取的。
先决条件
- [Python 3及以上版本。]
- [Pandas。]
- [Scikit-learn和它的依赖性。]
- 安装Matplotlib。
- XGBoost
- 一个合适的IDE或环境。
- 有学习的欲望。
简介
这种特殊的问题被称为不平衡分类。为了使用这种方法进行成功的分类,有一些事情是需要的。可能需要一些关于损失函数和超参数调整的预先知识。我们将学习不平衡分类,但这将是一个介绍核心概念的初级课程。
实现这一目标所需的探索性数据分析和数据预处理步骤将与正常工作流程类似。
让我们开始吧!
步骤
- 加载数据集
- 进行简单的探索性数据分析。
- 使用一个可以预测概率的模型。
- 将不同的预测结果排列在一个表中,以便进行适当的比较。
1.加载数据集
我们将使用一个普通的数据集。这将需要一个耗时的预处理方法。最好的人选是著名的Iris数据集,可以在Scikit-learn中找到,或者在Kaggle上下载。
第一步是调用所有我们需要的库。
import pandas as pd
import matplotlib.pyplot as plt
from xgboost import XGBClassifier
from sklearn.preprocessing import
然后我们将加载数据集并查看数据。
df = pd.read_csv("Iris.csv")
df = pd.drop(["Id"], axis=1) #This drops the Id column that is not needed
print(df.head())
上面的代码让我们看到了数据的前五行。
SepalLengthCm | SepalWidthCm | PetalLengthCm | PetalWidthCm | Species
0 |5.1 | 3.5 | 1.4 | 0.2 | Iris-setosa
1 |4.9 | 3.0 | 1.4 | 0.2 | Iris-setosa
2 |4.7 | 3.2 | 1.3 | 0.2 | Iris-setosa
3 |4.6 | 3.1 | 1.5 | 0.2 | Iris-setosa
4| 5.0 | 3.6 | 1.4 | 0.2 | Iris-setosa
2.执行简单的探索性数据分析
下一步是检查数据是否在任何一个方向上严重偏斜。
print(df["SepalLengthCm"].skew())
print(df["SepalWidthCm"].skew())
print(df["PetalLengthCm"].skew())
print(df["PetalWidthCm"].skew())
上面的代码给了我们四个明显的数字,表明数据没有过度倾斜,不需要进行减斜的转换。
The values that the above code presents
0.3149109566369728
0.3340526621720866
-0.27446425247378287
-0.10499656214412734
另一个实用的步骤是看一下可能很重要的数值,如平均值、标准差和数值的计数。所有这些都可以通过运行一行代码来实现。
df.describe()
| SepalLengthCm | 萼片宽度Cm | 花瓣长度Cm | 花瓣宽度Cm | |
|---|---|---|---|---|
| 计数 | 150.000000 | 150.000000 | 150.000000 | 150.000000 |
| 平均数 | 5.843333 | 3.054000 | 3.758667 | 1.198667 |
| 中位数 | 0.828066 | 0.433594 | 1.764420 | 0.763161 |
| 最小值 | 4.300000 | 2.000000 | 1.000000 | 0.100000 |
| 25% | 5.100000 | 2.800000 | 1.600000 | 0.300000 |
| 50% | 5.800000 | 3.000000 | 4.350000 | 1.300000 |
| 75% | 6.400000 | 3.300000 | 5.100000 | 1.800000 |
| 最大 | 7.900000 | 4.400000 | 6.900000 | 2.500000 |
上面的结果使我们能够提取一些关键的见解和趋势,这些见解和趋势在后面会有用处。例如,从所提供的数据中我们可以推断出,平均来说,最高的数值是在萼片长度Cm一栏,而最低的是在花瓣宽度Cm一栏。但这可能没有什么好处,因为我们要看的是所有三类物种。
如果单独描述不同的物种会产生什么结果呢?
让我们看看鸢尾花-维吉尼亚,并将其与鸢尾花-塞托莎进行比较。
Iris-virginica。
#Drops Iris-setosa and Iris-versicolor
df = df[df["Species"].str.contains("Iris-setosa|Iris-versicolor")== False]
df.describe()
| 萼片长度Cm | 萼片宽度Cm | 花瓣长度Cm | 花瓣宽度Cm | |
|---|---|---|---|---|
| 计数 | 50.00000 | 50.000000 | 50.000000 | 50.00000 |
| 平均数 | 6.58800 | 2.974000 | 5.552000 | 2.02600 |
| 中位数 | 0.63588 | 0.322497 | 0.551895 | 0.27465 |
| 最小值 | 4.90000 | 2.200000 | 4.500000 | 1.40000 |
| 25% | 6.22500 | 2.800000 | 5.100000 | 1.80000 |
| 50% | 6.50000 | 3.000000 | 5.550000 | 2.00000 |
| 75% | 6.90000 | 3.175000 | 5.875000 | 2.30000 |
| 最大 | 7.90000 | 3.800000 | 6.900000 | 2.50000 |
Iris-setosa:
#Drops Iris-virginca and Iris-Versicolor
df = df[df["Species"].str.contains("Iris-virginica|Iris-versicolor")== False]
df.describe()
| 萼片长度Cm | 萼片宽度Cm | 花瓣长度Cm | 花瓣宽度Cm | |
|---|---|---|---|---|
| 计数 | 50.00000 | 50.000000 | 50.000000 | 50.00000 |
| 平均数 | 5.00600 | 3.418000 | 1.464000 | 2.02600 |
| 中位数 | 0.35249 | 0.381024 | 0.173511 | 0.10721 |
| 最小值 | 4.30000 | 2.300000 | 1.000000 | 0.10000 |
| 25% | 4.80000 | 3.125000 | 1.400000 | 0.20000 |
| 50% | 5.00000 | 3.400000 | 1.500000 | 0.20000 |
| 75% | 5.20000 | 3.675000 | 1.575000 | 0.30000 |
| 最大 | 5.80000 | 4.400000 | 1.900000 | 0.60000 |
现在的洞察力更清晰了,因为我们正在比较两个不同的类别。平均值有明显的差异,突出表明我们在这里处理的是不同的范围。
3.使用一个可以预测概率的模型
我想要的模型是XGBoost,因为它能迅速让我们得到一个我们可能想要的解决方案。
X = df.drop(["Species"], axis=1)
y = df["Species"]
#performing train test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=5)
#Training XGBoost
model = XGBClassifier(eval_metric = "mlogloss")
model.fit(X_train, y_train)
y_predict = model.predict_proba(X_test)
print(y_predict)
在进行训练-测试-分片以避免数据过度拟合后,我们希望有三个新的列来代表3个不同的物种和它们的概率值。在我们的XGBoost模型中,我们使用logloss来进行这种类型的预测,因为它告诉我们我们的值是否接近真实值,即0(错误)或1(真实)。
前两行将以这种方式出现。
[[2.5100906e-03 9.9584949e-01 1.6403686e-03]
[1.6350182e-02 6.5069902e-01 3.3295083e-01]
[1.0797891e-03 2.8213044e-03 9.9609888e-01]
[9.9380070e-01 4.2259935e-03 1.9732981e-03]
[1.3190582e-03 2.5665318e-03 9.9611437e-01]]
它们将按照 "物种 "栏中唯一标签的出现顺序排列。如果模型尽可能准确,任何大于0.5的值都将被认为是给定身份的最佳候选人。
但这并不是最后一步。我们可能需要在给定的情况下将其呈现在一个数据集中,以便进行展示或提交。下一步将是转移数组中的概率,并将其分配给唯一的列。
4.将不同的预测结果排列在一个表中
y_predict_0 = y_predict[:, 0]
y_predict_1 = y_predict[:, 1]
y_predict_2 = y_predict[:, 2]
#Assigning values to columns and a new file
predicted = pd.DataFrame() #Creates empty dataframe
predicted["Iris-setosa"] = y_predict_0
predicted["Iris-versicolor"] = y_predict_1
predicted["Iris-virginica"] = y_predict_2
predicted.to_csv("predicted.csv", index = False)
predicted.head()
Iris-setosa,Iris-versicolor,Iris-virginica
.0025100, .9958490, .00164010
.0163500, .6506990, .33295120
.0010800, .0028210, .99609930
.9938010, .0042260, .00197340
.0013190, .0025670, .996114
结论
我们现在有了一个文件,如果有需要,可以用来提交。有一个奇特的问题。由于没有识别指数,我们无法知道这些观察结果来自哪个特定的数据。
这特别是因为我们使用了从原始文件中提取的测试数据。在同时提供训练和测试文件的情况下,在测试文件中放弃识别是没有用的。