AI技術發展迅猛,利用各種先進的AI模型,可以打造聊天機器人、仿人機器人、自動駕駛汽車等。 AI已成為發展最快的技術,而物件偵測和物件分類是最近的趨勢。
本文將介紹使用卷積神經網路從頭開始建立和訓練一個影像分類模型的完整步驟。本文將使用公開的Cifar-10資料集來訓練這個模型。這個資料集是獨一無二的,因為它包含了像汽車、飛機、狗、貓等日常所見物體的圖像。透過對這些物體進行神經網路訓練,本文將發展出智慧系統來對現實世界中的這些東西進行分類。它包含了6萬多張32x32大小的10種不同類型的物件影像。在本教程結束時,你將擁有一個可以根據物體的視覺特徵來判斷物件的模型。
圖1 資料集樣本圖片|圖片來自datasets.activeloop
本文將從頭開始講述所有內容,所以如果你還沒有學習過神經網絡的實際實現,也完全沒問題。
以下是本教學的完整工作流程:
#圖2 完整的流程
首先必須安裝一些模組才能開始這個專案。本文將使用Google Colab,因為它提供免費的GPU訓練。
以下是安裝所需庫的命令:
<code>$ pip install tensorflow, numpy, keras, sklearn, matplotlib</code>
將庫匯入到Python檔案中。
<code>from numpy import *from pandas import *import matplotlib.pyplot as plotter# 将数据分成训练集和测试集。from sklearn.model_selection import train_test_split# 用来评估我们的训练模型的库。from sklearn.metrics import classification_report, confusion_matriximport keras# 加载我们的数据集。from keras.datasets import cifar10# 用于数据增量。from keras.preprocessing.image import ImageDataGenerator# 下面是一些用于训练卷积Nueral网络的层。from keras.models import Sequentialfrom keras.layers import Dense, Dropout, Activationfrom keras.layers import Conv2D, MaxPooling2D, GlobalMaxPooling2D, Flatten</code>
現在,進入資料載入的步驟。
本節將載入資料集並執行訓練-測試資料的拆分。
載入和分割資料:
<code># 类的数量nc = 10(training_data, training_label), (testing_data, testing_label) = cifar10.load_data()((training_data),(validation_data),(training_label),(validation_label),) = train_test_split(training_data, training_label, test_size=0.2, random_state=42)training_data = training_data.astype("float32")testing_data = testing_data.astype("float32")validation_data = validation_data.astype("float32")</code>
cifar10資料集是直接從Keras資料集庫中載入的。而這些數據也分為訓練資料和測試資料。訓練資料用於訓練模型,以便它可以識別其中的模式。而測試資料對模型來說是不可見的,它被用來檢查其效能,即相對於總的資料點,有多少資料點被正確預測。
training_label包含了與training_data中的圖像對應的標籤。
接著使用內建sklearn的train_test_split函數將訓練資料再次拆分成驗證資料。驗證資料用於選擇和調整最終的模型。最後,所有的訓練、測試和驗證資料都轉換為32位數的浮點數。
現在,資料集的載入已經完成。在下一節中,本文將對其執行一些預處理步驟。
資料預處理是開發機器學習模型時的第一步,也是最關鍵的一步。跟隨本文一起看看如何做到這一點。
<code># 归一化training_data /= 255testing_data /= 255validation_data /= 255# 热编码training_label = keras.utils.to_categorical(training_label, nc)testing_label = keras.utils.to_categorical(testing_label, nc)validation_label = keras.utils.to_categorical(validation_label, nc)# 输出数据集print("Training: ", training_data.shape, len(training_label))print("Validation: ", validation_data.shape, len(validation_label))print("Testing: ", testing_data.shape, len(testing_label))</code>
輸出:
<code>Training:(40000, 32, 32, 3) 40000Validation:(10000, 32, 32, 3) 10000Testing:(10000, 32, 32, 3) 10000</code>
此資料集包含10個類別的影像,每個影像的大小為32x32像素。每個像素都有一個0-255的值,我們需要在0-1之間進行歸一化以簡化計算過程。之後,我們將把分類標籤轉換為單一熱編碼標籤。這樣做是為了將分類數據轉換為數值數據,這樣我們就可以毫無問題地應用機器學習演算法。
現在,進入CNN模型的建構。
CNN模型分三個階段工作。第一階段由卷積層組成,從影像中擷取相關特徵。第二階段由池化層組成,用於降低影像的尺寸。它也有助於減少模型的過度擬合。第三階段由密集層組成,將二維影像轉換為一維數組。最後,這個陣列被送入全連接層,進行最後的預測。
以下是程式碼:
<code>model = Sequential()model.add(Conv2D(32, (3, 3), padding="same", activatinotallow="relu", input_shape=(32, 32, 3)))model.add(Conv2D(32, (3, 3), padding="same", activatinotallow="relu"))model.add(MaxPooling2D((2, 2)))model.add(Dropout(0.25))model.add(Conv2D(64, (3, 3), padding="same", activatinotallow="relu"))model.add(Conv2D(64, (3, 3), padding="same", activatinotallow="relu"))model.add(MaxPooling2D((2, 2)))model.add(Dropout(0.25))model.add(Conv2D(96, (3, 3), padding="same", activatinotallow="relu"))model.add(Conv2D(96, (3, 3), padding="same", activatinotallow="relu"))model.add(MaxPooling2D((2, 2)))model.add(Flatten())model.add(Dropout(0.4))model.add(Dense(256, activatinotallow="relu"))model.add(Dropout(0.4))model.add(Dense(128, activatinotallow="relu"))model.add(Dropout(0.4))model.add(Dense(nc, activatinotallow="softmax"))</code>
本文應用了三組圖層,每組包含兩個卷積層、一個最大池化層和一個丟棄層。 Conv2D層接收input_shape為(32,32,3),必須與影像的尺寸相同。
每個Conv2D層也需要一個激活函數,即relu。激活函數是用於增加系統中的非線性。更簡單地說,它決定神經元是否需要根據某個閾值被激活。有許多類型的活化函數,如ReLu、Tanh、Sigmoid、Softmax等,它們使用不同的演算法來決定神經元的激發。
之后,添加了平坦层和全连接层,在它们之间还有几个Dropout层。Dropout层随机地拒绝一些神经元对网层的贡献。它里面的参数定义了拒绝的程度。它主要用于避免过度拟合。
下面是一个CNN模型架构的示例图像。
图3 Sampe CNN架构|图片来源:Researchgate
现在,本文将编译和准备训练的模型。
<code># 启动Adam优化器opt = keras.optimizers.Adam(lr=0.0001)model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"])# 获得模型的摘要model.summary()</code>
输出:
图4 模型摘要
本文使用了学习率为0.0001的Adam优化器。优化器决定了模型的行为如何响应损失函数的输出而变化。学习率是训练期间更新权重的数量或步长。它是一个可配置的超参数,不能太小或太大。
现在,本文将把模型拟合到我们的训练数据,并开始训练过程。但在此之前,本文将使用图像增强技术来增加样本图像的数量。
卷积神经网络中使用的图像增强技术将增加训练图像,而不需要新的图像。它将通过在图像中产生一定量的变化来复制图像。它可以通过将图像旋转到一定程度、添加噪声、水平或垂直翻转等方式来实现。
<code>augmentor = ImageDataGenerator(width_shift_range=0.4,height_shift_range=0.4,horizontal_flip=False,vertical_flip=True,)# 在augmentor中进行拟合augmentor.fit(training_data)# 获得历史数据history = model.fit(augmentor.flow(training_data, training_label, batch_size=32),epochs=100,validation_data=(validation_data, validation_label),)</code>
输出:
图5 每个时期的准确度和损失
ImageDataGenerator()函数用于创建增强的图像。fit()用于拟合模型。它以训练和验证数据、Batch Size和Epochs的数量作为输入。
Batch Size是在模型更新之前处理的样本数量。一个关键的超参数必须大于等于1且小于等于样本数。通常情况下,32或64被认为是最好的Batch Size。
Epochs的数量代表了所有样本在网络的前向和后向都被单独处理了多少次。100个epochs意味着整个数据集通过模型100次,模型本身运行100次。
我们的模型已经训练完毕,现在我们将评估它在测试集上的表现。
本节将在测试集上检查模型的准确性和损失。此外,本文还将绘制训练和验证数据的准确率与时间之间和损失与时间之间的关系图。
<code>model.evaluate(testing_data, testing_label)</code>
输出:
<code>313/313 [==============================] - 2s 5ms/step - loss: 0.8554 - accuracy: 0.7545[0.8554493188858032, 0.7545000195503235]</code>
本文的模型达到了75.34%的准确率,损失为0.8554。这个准确率还可以提高,因为这不是一个最先进的模型。本文用这个模型来解释建立模型的过程和流程。CNN模型的准确性取决于许多因素,如层的选择、超参数的选择、使用的数据集的类型等。
现在我们将绘制曲线来检查模型中的过度拟合情况。
<code>def acc_loss_curves(result, epochs):acc = result.history["accuracy"]# 获得损失和准确性loss = result.history["loss"]# 声明损失和准确度的值val_acc = result.history["val_accuracy"]val_loss = result.history["val_loss"]# 绘制图表plotter.figure(figsize=(15, 5))plotter.subplot(121)plotter.plot(range(1, epochs), acc[1:], label="Train_acc")plotter.plot(range(1, epochs), val_acc[1:], label="Val_acc")# 给予绘图的标题plotter.title("Accuracy over " + str(epochs) + " Epochs", size=15)plotter.legend()plotter.grid(True)# 传递值122plotter.subplot(122)# 使用训练损失plotter.plot(range(1, epochs), loss[1:], label="Train_loss")plotter.plot(range(1, epochs), val_loss[1:], label="Val_loss")# 使用 ephocsplotter.title("Loss over " + str(epochs) + " Epochs", size=15)plotter.legend()# 传递真值plotter.grid(True)# 打印图表plotter.show()acc_loss_curves(history, 100)</code>
输出:
图6 准确度和损失与历时的关系
在本文的模型中,可以看到模型过度拟合测试数据集。(蓝色)线表示训练精度,(橙色)线表示验证精度。训练精度持续提高,但验证误差在20个历时后恶化。
本文展示了构建和训练卷积神经网络的整个过程。最终得到了大约75%的准确率。你可以使用超参数并使用不同的卷积层和池化层来提高准确性。你也可以尝试迁移学习,它使用预先训练好的模型,如ResNet或VGGNet,并在某些情况下可以提供非常好的准确性。
以上是用TensorFlow和Keras來建立和訓練你的第一個神經網路非常容易的詳細內容。更多資訊請關注PHP中文網其他相關文章!