在这里,我们将为theMushroom Classification Dataset建立分类模型。该模型将分类是否可食用(E)或有毒(P)。其他属性是:
您可以在Kaggle link之后找到所有属性的描述。
首先,让我们导入大熊猫并使用它来读取下载的数据集。然后,我们将显示下载的数据集
m_df = pd.read_csv("/content/mushrooms.csv")
m_df
检查未填充的列值:
m_df.isnull().sum()
输出:
class 0
cap-shape 0
cap-surface 0
cap-color 0
bruises 0
odor 0
gill-attachment 0
gill-spacing 0
gill-size 0
gill-color 0
stalk-shape 0
stalk-root 0
stalk-surface-above-ring 0
stalk-surface-below-ring 0
stalk-color-above-ring 0
stalk-color-below-ring 0
veil-type 0
veil-color 0
ring-number 0
ring-type 0
spore-print-color 0
population 0
habitat 0
dtype: int64
没有列缺少值。
现在检查数据集的数据类型:
m_df.dtypes
输出:
class object
cap-shape object
cap-surface object
cap-color object
bruises object
odor object
gill-attachment object
gill-spacing object
gill-size object
gill-color object
stalk-shape object
stalk-root object
stalk-surface-above-ring object
stalk-surface-below-ring object
stalk-color-above-ring object
stalk-color-below-ring object
veil-type object
veil-color object
ring-number object
ring-type object
spore-print-color object
population object
habitat object
dtype: object
我们可以看到没有数值列。
分析数据集后,我们应该将其分为两个:标签数据集和功能数据集。
X = m_df.drop("class", axis=1)
y = m_df["class"]
我们不能训练模型并在同一数据集上测试预测结果,就像学生不应该写他的考试,因此我们必须将数据集分配给测试和培训:< br>
from sklearn.model_selection import train_test_split
# The labels should be numerical so we replace all of the labels
# with ones and zeros
y.replace("p", 0, inplace=True)
y.replace("e", 1, inplace=True)
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=(0.2))
数据集中的所有值均以分类形式。该模型无法以这种形式从数据中学到任何东西,因此我们应该对其进行编码 - 通过将每个分类值转换为新的分类列,并将二进制值分配为1或0的过程。我们也可能想绘制所有蘑菇样品,以便我们可以更好地看到属性与标签的相关性。在此示例中,我们可以通过缩小尺寸来做到这一点 - 使用PCA。
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
cat_features = [*X.columns]
cat_transformer = Pipeline(steps=[("onehot", OneHotEncoder(sparse=False)), ("pca", PCA(n_components=2))])
ct = ColumnTransformer(transformers=[("categories", cat_transformer, cat_features)])
ct.fit(X)
X_train_t = ct.transform(X_train)
X_test_t = ct.transform(X_test)
绘制PCA图:
plt.scatter(X_train_t[:, 0], X_train_t[:, 1], alpha=0.4, color="lightblue");
sns.heatmap(pd.get_dummies(m_df).corr())
现在我们最终可以开始训练我们的模型。我们只需要不同的标签,因此我们应该使用sigmoid
激活函数,因为它将返回我们的值0到1的范围以及使用binary_crossentropy
。我们还将使用LearningRateScheduler
Callback来尝试通过分析从(1e-4 * (10**(1/15)))
(0.000116591440118)到(1e-4 * (10**(100/15)))
(464.1588883361)的不同学习率的损失和准确性来找到理想的学习率。
model = tf.keras.Sequential([
tf.keras.layers.Dense(10, activation="relu"),
tf.keras.layers.Dense(30, activation="relu"),
tf.keras.layers.Dense(1, activation="sigmoid")
])
model.compile(loss="binary_crossentropy", optimizer=tf.keras.optimizers.Adam(), metrics=[tf.keras.metrics.binary_crossentropy, "accuracy"])
lr_cb = tf.keras.callbacks.LearningRateScheduler(lambda epoch: 1e-4 * (10**(epoch/15)))
history = model.fit(X_train_t, y_train, epochs=70, verbose=1, callbacks=[lr_cb])
我们可以可视化模型的训练过程的history
:
hist = pd.DataFrame(history.history).drop("binary_crossentropy", axis=1)
hist.plot()
正如我们在图表上看到的那样,当学习率增加了一定点时,模型的准确性开始下降。
让我们看一下学习率和损失曲线的相关性:
lrs = 1e-4 * (10**(np.arange(0,70)/15)) # generate an array of
# learning rates with the same number of epochs
plt.semilogx(lrs, hist.loss)
损失从10E-4急剧降低到10E-3。我们应该将TE值更接近曲线的最低点(10E-3),该值将等于0.0097左右(这几乎与Adam的默认学习率完全相同)。
现在,让我们以理想的学习率拟合模型:
model = tf.keras.Sequential([
tf.keras.layers.Dense(10, activation="relu"),
tf.keras.layers.Dense(30, activation="relu"),
tf.keras.layers.Dense(1, activation="sigmoid")
])
model.compile(loss="binary_crossentropy", optimizer=tf.keras.optimizers.Adam(learning_rate=0.0097), metrics=[tf.keras.metrics.binary_crossentropy, "accuracy"])
history = model.fit(X_train_t, y_train, epochs=15, verbose=1)
现在,我们可以使用测试数据集用我们的模型进行预测,并绘制混乱矩阵以更好地可视化结果:
y_pred = np.round(model.predict(X_test_t)[:, 0])
ConfusionMatrixDisplay.from_predictions(y_true=y_test, y_pred=y_pred);
现在,让我们编写一个函数,该函数将根据模型的预言和实际值返回不同的指标,并使用它来评估我们的模型:
def metrics(y_test, y_pred):
f1 = f1_score(y_test, y_pred)
rec = recall_score(y_test, y_pred)
acc = accuracy_score(y_test,y_pred)
prec = precision_score(y_test,y_pred)
return f"Accuracy: {round(acc, 2)}, Precision: {round(prec, 2)}, Recall: {round(rec, 2)}, F1: {round(f1, 2)}"
metrics(y_test, y_pred)
输出:
Accuracy: 0.94, Precision: 0.96, Recall: 0.93, F1: 0.94
现在我们的模型完成了!希望这篇文章很有帮助,谢谢您的阅读!