# Check the versions of libraries
# Python version
import sys
print('Python: {}'.format(sys.version))
# scipy
import scipy
print('scipy: {}'.format(scipy.__version__))
# numpy
import numpy
print('numpy: {}'.format(numpy.__version__))
# matplotlib
import matplotlib
print('matplotlib: {}'.format(matplotlib.__version__))
# pandas
import pandas
print('pandas: {}'.format(pandas.__version__))
# scikit-learn
import sklearn
print('sklearn: {}'.format(sklearn.__version__))
Python: 3.12.2 | packaged by Anaconda, Inc. | (main, Feb 27 2024, 17:28:07) [MSC v.1916 64 bit (AMD64)]
scipy: 1.13.0
numpy: 1.26.4
matplotlib: 3.8.4
pandas: 2.2.2
sklearn: 1.4.2
我们将使用鸢尾花数据集。该数据集之所以著名,是因为它几乎被每个人用作机器学习和统计中的“hello world”数据集。
该数据集包含 150 个鸢尾花的观察结果。有四列以厘米为单位的花朵测量值。第五列是观察到的花的种类。所有观察到的花都属于三个物种之一。
# Load libraries
from pandas import read_csv
from pandas.plotting import scatter_matrix
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
我们可以直接从 UCI 机器学习存储库加载数据。
我们使用 pandas 来加载数据。接下来我们还将使用 pandas 通过描述性统计和数据可视化来探索数据。
请注意,我们在加载数据时指定每列的名称。这将有助于我们稍后探索数据。
...
# Load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv"
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class']
dataset = read_csv(url, names=names)
print(dataset)
sepal-length sepal-width petal-length petal-width class
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
.. ... ... ... ... ...
145 6.7 3.0 5.2 2.3 Iris-virginica
146 6.3 2.5 5.0 1.9 Iris-virginica
147 6.5 3.0 5.2 2.0 Iris-virginica
148 6.2 3.4 5.4 2.3 Iris-virginica
149 5.9 3.0 5.1 1.8 Iris-virginica
[150 rows x 5 columns]
在此步骤中,我们将通过几种不同的方式查看数据:
1 数据集的维度。
2 查看数据本身。
3 所有属性的统计摘要。
4 按类变量对数据进行细分。
...
# shape
print(dataset.shape)
(150, 5)
3.2 查看数据
#head
print(dataset.head(20))
sepal-length sepal-width petal-length petal-width class
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
5 5.4 3.9 1.7 0.4 Iris-setosa
6 4.6 3.4 1.4 0.3 Iris-setosa
7 5.0 3.4 1.5 0.2 Iris-setosa
8 4.4 2.9 1.4 0.2 Iris-setosa
9 4.9 3.1 1.5 0.1 Iris-setosa
10 5.4 3.7 1.5 0.2 Iris-setosa
11 4.8 3.4 1.6 0.2 Iris-setosa
12 4.8 3.0 1.4 0.1 Iris-setosa
13 4.3 3.0 1.1 0.1 Iris-setosa
14 5.8 4.0 1.2 0.2 Iris-setosa
15 5.7 4.4 1.5 0.4 Iris-setosa
16 5.4 3.9 1.3 0.4 Iris-setosa
17 5.1 3.5 1.4 0.3 Iris-setosa
18 5.7 3.8 1.7 0.3 Iris-setosa
19 5.1 3.8 1.5 0.3 Iris-setosa
#description:
print(dataset.describe())
sepal-length sepal-width petal-length petal-width
count 150.000000 150.000000 150.000000 150.000000
mean 5.843333 3.054000 3.758667 1.198667
std 0.828066 0.433594 1.764420 0.763161
min 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
max 7.900000 4.400000 6.900000 2.500000
看一下属于每个类的实例(行)数。我们可以将其视为绝对计数。
...
# class distribution
# print(dataset.groupby('class'))
print(dataset.groupby('class').size())
class
Iris-setosa 50
Iris-versicolor 50
Iris-virginica 50
dtype: int64
# summarize the data
from pandas import read_csv
# Load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv"
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class']
dataset = read_csv(url, names=names)
# shape
print(dataset.shape)
# head
print(dataset.head(20))
# descriptions
print(dataset.describe())
# class distribution
print(dataset.groupby('class').size())
(150, 5)
sepal-length sepal-width petal-length petal-width class
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
5 5.4 3.9 1.7 0.4 Iris-setosa
6 4.6 3.4 1.4 0.3 Iris-setosa
7 5.0 3.4 1.5 0.2 Iris-setosa
8 4.4 2.9 1.4 0.2 Iris-setosa
9 4.9 3.1 1.5 0.1 Iris-setosa
10 5.4 3.7 1.5 0.2 Iris-setosa
11 4.8 3.4 1.6 0.2 Iris-setosa
12 4.8 3.0 1.4 0.1 Iris-setosa
13 4.3 3.0 1.1 0.1 Iris-setosa
14 5.8 4.0 1.2 0.2 Iris-setosa
15 5.7 4.4 1.5 0.4 Iris-setosa
16 5.4 3.9 1.3 0.4 Iris-setosa
17 5.1 3.5 1.4 0.3 Iris-setosa
18 5.7 3.8 1.7 0.3 Iris-setosa
19 5.1 3.8 1.5 0.3 Iris-setosa
sepal-length sepal-width petal-length petal-width
count 150.000000 150.000000 150.000000 150.000000
mean 5.843333 3.054000 3.758667 1.198667
std 0.828066 0.433594 1.764420 0.763161
min 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
max 7.900000 4.400000 6.900000 2.500000
class
Iris-setosa 50
Iris-versicolor 50
Iris-virginica 50
dtype: int64
我们将看两种类型的图:
1 单变量图可以更好地理解每个属性。
2 多元图可以更好地理解属性之间的关系。
鉴于输入变量是数字,我们可以为每个变量创建箱线图和须线图。
# box and whisker plots
dataset.plot(kind='box', subplots=True, layout=(2,2), sharex=False, sharey=False)
plt.show
我们还可以创建每个输入变量的直方图以了解分布。
#histograms
dataset.hist()
plt.show()
现在,我们可以查看变量之间的相互作用。
首先,让我们看一下所有属性的散点图。这可能有助于发现输入变量之间的结构化关系
# scatter plot matrix
scatter_matrix(dataset)
plt.show()
# visualize the data
from pandas import read_csv
from pandas.plotting import scatter_matrix
from matplotlib import pyplot as plt
# Load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv"
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class']
dataset = read_csv(url, names=names)
# box and whisker plots
dataset.plot(kind='box', subplots=True, layout=(2,2), sharex=False, sharey=False)
plt.show()
# histograms
dataset.hist()
plt.show()
# scatter plot matrix
scatter_matrix(dataset)
plt.show()
现在是时候创建一些数据模型并估计其在看不见的数据上的准确性了。
这是我们将在此步骤中涵盖的内容:
1 分开验证数据集。
2 设置测试线束以使用10倍的交叉验证。
3 构建多个不同的模型以预测花朵测量的物种
4 选择最佳模型。
我们需要知道我们创建的模型很好。
稍后,我们将使用统计方法来估计我们在看不见的数据上创建的模型的准确性。我们还希望通过对实际看不见的数据进行评估,对最佳模型的准确性进行更具体的估计。
也就是说,我们将删除算法无法看到的一些数据,我们将使用这些数据来获得第二个独立的想法,即最佳模型的实际性如何。
我们将将加载的数据集分为两个,其中80%将用于训练,评估和选择我们的模型,而20%我们将作为验证数据集退缩。
#split-out validation dataset
array = dataset.values
X = array[:, 0:4]
y = array[:, 4]
X_train, X_validation, Y_train, Y_validation = train_test_split(X, y, test_size=0.20, random_state=1)
现在,可以在X_Train和Y_Train中使用训练数据,用于准备模型以及X_validation和Y__Validation集,我们可以在以后使用。
我们将使用分层 10 倍交叉验证来估计模型准确性。
这会将我们的数据集分为 10 个部分,对 9 个部分进行训练,对 1 个部分进行测试,然后对训练-测试分割的所有组合重复此操作。
分层意味着数据集的每次折叠或分割都旨在具有与整个训练数据集中存在的相同的类示例分布。
我们通过 random_state 参数将随机种子设置为固定数字,以确保每个算法在训练数据集的相同分割上进行评估。
我们使用“准确性”指标来评估模型。
这是正确预测的实例数除以数据集中的实例总数再乘以 100 得出的百分比(例如,准确率 95%)。当我们接下来运行构建和评估每个模型时,我们将使用评分变量。
我们不知道哪种算法适合解决这个问题或使用什么配置。
我们从图中了解到,某些类在某些维度上是部分线性可分的,因此我们预计总体上会得到良好的结果。
让我们测试 6 种不同的算法:
这是简单线性(LR 和 LDA)、非线性(KNN、CART、NB 和 SVM)算法的良好组合。
让我们构建并评估我们的模型:
# from sklearn.linear_model import LogisticRegression
# from sklearn.tree import DecisionTreeClassifier
# from sklearn.neighbors import KNeighborsClassifier
# from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
# from sklearn.naive_bayes import GaussianNB
# from sklearn.svm import SVC
# spot check algorithms
models = []
models.append(('LR', LogisticRegression(solver = 'liblinear', multi_class = 'ovr' )))
models.append(('LDA', LinearDiscriminantAnalysis()))
models.append(('KNN', KNeighborsClassifier()))
models.append(('CART', DecisionTreeClassifier()))
models.append(('NB', GaussianNB()))
models.append(('SVM', SVC(gamma = 'auto')))
# evaluate each model in turn
results = []
names = []
for name, model in models:
kfold = StratifiedKFold(n_splits=10, random_state=1, shuffle=True)
cv_results = cross_val_score(model, X_train, Y_train, cv=kfold, scoring='accuracy')
results.append(cv_results)
names.append(name)
print('%s: %f (%f)' % (name, cv_results.mean(), cv_results.std()))
LR: 0.941667 (0.065085)
LDA: 0.975000 (0.038188)
KNN: 0.958333 (0.041667)
CART: 0.950000 (0.040825)
NB: 0.950000 (0.055277)
SVM: 0.983333 (0.033333)
我们现在有 6 个模型以及每个模型的准确度估计。我们需要对模型进行相互比较并选择最准确的模型。
注意:由于算法或评估过程的随机性或数值精度的差异,您的结果可能会有所不同。考虑运行该示例几次并比较平均结果。
在这种情况下,我们可以看到支持向量机 (SVM) 的估计准确度分数最大,约为 0.98 或 98%。
我们还可以创建模型评估结果图,并比较每个模型的分布和平均准确度。每个算法都有一组准确度度量,因为每个算法都被评估了 10 次(通过 10 次交叉验证)。
比较每种算法的结果样本的一个有用方法是为每个分布创建箱须图并比较分布。
#compare algorithms
plt.boxplot(results, labels= names)
plt.title('Algorithm Comparison')
plt.show()
我们可以看到箱线图和须线图在范围的顶部被压扁,许多评估达到了 100% 的准确度,有些则降低到了 80% 的准确度。
作为参考,我们可以将前面的所有元素组合到一个脚本中。
下面列出了完整的示例。
# compare algorithms
from pandas import read_csv
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import StratifiedKFold
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
# Load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv"
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class']
dataset = read_csv(url, names=names)
# Split-out validation dataset
array = dataset.values
X = array[:, 0:4]
y = array[:, 4]
X_train, X_validation, Y_train, Y_validation = train_test_split(
X, y, test_size=0.20, random_state=1)
# Spot Check Algorithms
models = []
models.append(('LR', LogisticRegression(
solver='liblinear', multi_class='ovr')))
models.append(('LDA', LinearDiscriminantAnalysis()))
models.append(('KNN', KNeighborsClassifier()))
models.append(('CART', DecisionTreeClassifier()))
models.append(('NB', GaussianNB()))
models.append(('SVM', SVC(gamma='auto')))
# evaluate each model in turn
results = []
names = []
for name, model in models:
kfold = StratifiedKFold(n_splits=10, random_state=1, shuffle=True)
cv_results = cross_val_score(
model, X_train, Y_train, cv=kfold, scoring='accuracy')
results.append(cv_results)
names.append(name)
print('%s: %f (%f)' % (name, cv_results.mean(), cv_results.std()))
# Compare Algorithms
plt.boxplot(results, labels=names)
plt.title('Algorithm Comparison')
plt.show()
LR: 0.941667 (0.065085)
LDA: 0.975000 (0.038188)
KNN: 0.958333 (0.041667)
CART: 0.958333 (0.041667)
NB: 0.950000 (0.055277)
SVM: 0.983333 (0.033333)
我们必须选择一种算法来进行预测。
上一节的结果表明 SVM 可能是最准确的模型。我们将使用这个模型作为我们的最终模型。
现在我们想要了解模型在验证集上的准确性。
这将使我们能够对最佳模型的准确性进行独立的最终检查。保留验证集很有价值,以防万一您在训练过程中出现失误,例如训练集过度拟合或数据泄漏。这两个问题都会导致过于乐观的结果。
我们可以将模型拟合到整个训练数据集上,并对验证数据集进行预测。
#make predictions on validaton dataset
model = SVC(gamma='auto')
model.fit(X_train, Y_train)
predictions = model.predict(X_validation)
您可能还想对单行数据进行预测。有关如何执行此操作的示例,请参阅教程:https://machinelearningmastery.com/make-predictions-scikit-learn/
您可能还想将模型保存到文件并稍后加载以对新数据进行预测。有关如何执行此操作的示例,请参阅教程:https://machinelearningmastery.com/save-load-machine-learning-models-python-scikit-learn/
我们可以通过将预测与验证集中的预期结果进行比较来评估预测,然后计算分类准确性以及混淆矩阵和分类报告。
# Evaluate predictions
print(accuracy_score(Y_validation, predictions))
print(confusion_matrix(Y_validation, predictions))
print(classification_report(Y_validation, predictions))
0.9666666666666667
[[11 0 0]
[ 0 12 1]
[ 0 0 6]]
precision recall f1-score support
Iris-setosa 1.00 1.00 1.00 11
Iris-versicolor 1.00 0.92 0.96 13
Iris-virginica 0.86 1.00 0.92 6
accuracy 0.97 30
macro avg 0.95 0.97 0.96 30
weighted avg 0.97 0.97 0.97 30
我们可以看到,在保留数据集上,准确率为 0.966,即 96% 左右。
混淆矩阵提供了所犯错误的指示。
最后,分类报告按精度、召回率、f1 分数和支持度对每个类别进行了细分,显示出出色的结果(假设验证数据集很小)。
# make predictions
from pandas import read_csv
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.svm import SVC
# load dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv"
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class']
dataset = read_csv(url, names=names)
# split-out validation dataset
array = dataset.values
X = array[:, 0:4]
y = array[:, 4]
X_train, X_validation, Y_train, Y_validation = train_test_split(
X, y, test_size=0.20, random_state=1)
# make predictions on validation dataset
model = SVC(gamma='auto')
model.fit(X_train, Y_train)
predictions = model.predict(X_validation)
# evaluate predictions
print(accuracy_score(Y_validation, predictions))
print(confusion_matrix(Y_validation, predictions))
print(classification_report(Y_validation, predictions))
0.9666666666666667
[[11 0 0]
[ 0 12 1]
[ 0 0 6]]
precision recall f1-score support
Iris-setosa 1.00 1.00 1.00 11
Iris-versicolor 1.00 0.92 0.96 13
Iris-virginica 0.86 1.00 0.92 6
accuracy 0.97 30
macro avg 0.95 0.97 0.96 30
weighted avg 0.97 0.97 0.97 30