在机器学习领域,分类是机器能够被训练执行的基本任务之一。这包括使用天气数据预测今天是否会下雨、根据面部图像确定表情,或根据文本内容判断评论的情感等。分类被广泛应用于各种应用场景,因此它是监督式机器学习中最基本的任务之一。
根据不同的数据集类型,有多种算法用于执行分类。这从基于树的分类器如随机森林和决策树,到梯度提升算法如XGBoost,再到基于神经网络的分类器。在本文中,将探讨如何使用神经网络为表格数据集构建自定义分类器。使用神经网络的优势在于,可以轻松地检测并学习数据中存在的未知模式。
用于训练模型的数据集是鸢尾花数据集。这个数据集包含150个样本,属于3种鸢尾花,即鸢尾花Setosa、鸢尾花Versicolour和鸢尾花Virginica。这是一个多变量数据集,即每个样本提供了4个特征,分别是萼片长度、萼片宽度、花瓣长度和花瓣宽度。需要使用这4个特征来分类鸢尾花的种类。因此,使用多类分类模型来训练这个数据集。关于这个数据集的更多信息可以在这里找到。
首先,导入所需的库。
import os
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras import layers
from tensorflow.keras import models
from tensorflow.keras import optimizers
from tensorflow.keras import losses
from tensorflow.keras import metrics
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, accuracy_score
from tensorflow import keras
from sklearn.preprocessing import LabelEncoder
检查安装的TensorFlow版本:
print(tf.__version__)
接下来,需要从这里下载并提取数据集。然后将其移动到笔记本/脚本的位置或复制数据集的位置。现在从该位置读取CSV文件:
file_path = 'iris_dataset.csv'
df = pd.read_csv(file_path)
df.head()
可以看到,数据集有4个输入特征和1个目标变量。目标变量包括3个类别,即‘Iris-setosa’、‘Iris-versicolor’和‘Iris-verginica’。现在让进一步准备数据集以进行模型训练。
首先,让检查数据集是否包含任何空值。
print(df.isnull().sum())
没有空值。因此可以继续分离输入和目标。
X = df.drop('target', axis=1)
y = df['target']
现在已经分离了输入特征(X)和目标标签(y),让将数据集分割成训练集和验证集。为此,使用Scikit-Learn的train_test_split方法来分割数据集。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print("The length of training dataset: ", len(X_train))
print("The length of validation dataset: ", len(X_test))
在上面的代码中,已经将数据集分割,使得验证数据包含整个数据集中随机选择的20%样本。现在让在创建模型之前进一步进行一些处理。
由于已经准备好了数据分割,现在让进行一些基本处理,如特征缩放和标签编码。输入特征包含花瓣和萼片的属性,即长度和宽度,以厘米为单位。因此,这些特征是数值型的,需要被标准化,即转换数据使得均值为0,标准差为1。让使用Scikit-learn的StandardScaler模块来实现这一点。
features_encoder = StandardScaler()
features_encoder.fit(X_train)
X_train = features_encoder.transform(X_train)
X_test = features_encoder.transform(X_test)
现在应该对分类目标标签进行编码。这是因为模型无法理解如果类别以字符串形式表示的话。因此让使用Scikit-learn的LabelEncoder模块来编码标签。
label_encoder = LabelEncoder()
label_encoder.fit(y_train)
y_train = label_encoder.transform(y_train).reshape(-1, 1)
y_test = label_encoder.transform(y_test).reshape(-1, 1)
现在让检查数据集的形状。
print(X_train.shape)
print(X_test.shape)
print(y_train.shape)
print(y_test.shape)
太好了!现在已经准备好定义和训练模型了。
让使用Keras的Sequential API来定义分类的模型。可以堆叠所需的层并定义模型架构。对于这个模型,定义Dense层来定义输入、输出和中间层。
model = Sequential([
layers.Dense(8, activation="relu", input_shape=(4,)),
layers.Dense(16, activation="relu"),
layers.Dense(32, activation="relu"),
layers.Dense(3, activation="softmax")
])
在上面的模型中,定义了4个Dense层。输出层由3个神经元组成,即等于存在的输出标签数量。在最后一层使用softmax激活函数,因为它使模型能够为每个标签提供概率。模型确定的输出预测是具有最高概率的输出标签。在其他层中,使用了relu激活函数。
现在让通过定义损失函数、优化器和指标来编译模型。
model.compile(optimizer=optimizers.SGD(),
loss=losses.SparseCategoricalCrossentropy(),
metrics=metrics.SparseCategoricalAccuracy())
根据上述代码,使用SGD或随机梯度下降作为优化器,默认学习率为0.01。使用SparseCategoricalCrossEntropy损失函数。使用SparseCategoricalCrossEntropy而不是CategoricalCrossEntropy损失函数,因为输出类别是以整数格式的。如果类别是独热编码的,CategoricalCrossEntropy将是一个不错的选择。最后,使用SparseCategoricalAccuracy作为跟踪的指标。
现在让训练模型……
现在让使用处理过的训练数据训练模型200个周期,并为验证提供测试数据集。
history = model.fit(x=X_train,
y=y_train,
epochs=200,
validation_data=(X_test, y_test),
verbose=0)
现在已经使用训练数据训练了模型。在评估之前,让检查定义的模型的摘要。
model.summary()
现在让在测试数据集上评估模型。
model.evaluate(X_test, y_test)
太好了……现在让定义一些辅助函数来绘制准确度和损失图。
def plot_loss(history):
plt.plot(history.history['loss'], label='loss')
plt.plot(history.history['val_loss'], label='val_loss')
plt.ylim([0,10])
plt.xlabel('Epoch')
plt.ylabel('Error (Loss)')
plt.legend()
plt.grid(True)
def plot_accuracy(history):
plt.plot(history.history['sparse_categorical_accuracy'], label='accuracy')
plt.plot(history.history['val_sparse_categorical_accuracy'], label='val_accuracy')
plt.ylim([0, 1])
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.grid(True)
现在让传递模型训练历史并检查模型在数据集上的性能。
plot_loss(history)
plot_accuracy(history)
可以看到,从下面的图表中,模型已经学会了随着时间的推移对不同种类进行分类,几乎达到了准确的程度。
由于已经训练了模型,可以将其导出以供进一步使用案例,部署在应用程序中,或从上次中断的地方继续训练。可以使用save方法并以H5格式导出模型。
model.save("trained_classifier_model.h5")
可以使用load_model方法加载保存的模型检查点。
loaded_model = models.load_model('trained_classifier_model.h5')
results = loaded_model.predict(X_test)
preds = np.argmax(results, axis=1)
print(accuracy_score(y_test, preds))
print(classification_report(y_test, preds))