0 簡(jiǎn)介
?? 優(yōu)質(zhì)競(jìng)賽項(xiàng)目系列,今天要分享的是
基于人工智能的圖像分類技術(shù)
該項(xiàng)目較為新穎,適合作為競(jìng)賽課題方向,學(xué)長(zhǎng)非常推薦!
?? 更多資料, 項(xiàng)目分享:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-787219.html
https://gitee.com/dancheng-senior/postgraduate文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-787219.html
1 常用的分類網(wǎng)絡(luò)介紹
1.1 CNN
傳統(tǒng)CNN包含卷積層、全連接層等組件,并采用softmax多類別分類器和多類交叉熵?fù)p失函數(shù)。如下圖:
-
卷積層(convolution layer): 執(zhí)行卷積操作提取底層到高層的特征,發(fā)掘出圖片局部關(guān)聯(lián)性質(zhì)和空間不變性質(zhì)。
-
池化層(pooling layer): 執(zhí)行降采樣操作。通過(guò)取卷積輸出特征圖中局部區(qū)塊的最大值(max-pooling)或者均值(avg-pooling)。降采樣也是圖像處理中常見(jiàn)的一種操作,可以過(guò)濾掉一些不重要的高頻信息。
-
全連接層(fully-connected layer,或者fc layer): 輸入層到隱藏層的神經(jīng)元是全部連接的。
-
非線性變化: 卷積層、全連接層后面一般都會(huì)接非線性變化層,例如Sigmoid、Tanh、ReLu等來(lái)增強(qiáng)網(wǎng)絡(luò)的表達(dá)能力,在CNN里最常使用的為ReLu激活函數(shù)。
-
Dropout : 在模型訓(xùn)練階段隨機(jī)讓一些隱層節(jié)點(diǎn)權(quán)重不工作,提高網(wǎng)絡(luò)的泛化能力,一定程度上防止過(guò)擬合
在CNN的訓(xùn)練過(guò)程總,由于每一層的參數(shù)都是不斷更新的,會(huì)導(dǎo)致下一次輸入分布發(fā)生變化,這樣就需要在訓(xùn)練過(guò)程中花費(fèi)時(shí)間去設(shè)計(jì)參數(shù)。在后續(xù)提出的BN算法中,由于每一層都做了歸一化處理,使得每一層的分布相對(duì)穩(wěn)定,而且實(shí)驗(yàn)證明該算法加速了模型的收斂過(guò)程,所以被廣泛應(yīng)用到較深的模型中。
1.2 VGG
VGG 模型是由牛津大學(xué)提出的(19層網(wǎng)絡(luò)),該模型的特點(diǎn)是加寬加深了網(wǎng)絡(luò)結(jié)構(gòu),核心是五組卷積操作,每?jī)山M之間做Max-
Pooling空間降維。同一組內(nèi)采用多次連續(xù)的3X3卷積,卷積核的數(shù)目由較淺組的64增多到最深組的512,同一組內(nèi)的卷積核數(shù)目是一樣的。卷積之后接兩層全連接層,之后是分類層。該模型由于每組內(nèi)卷積層的不同主要分為
11、13、16、19 這幾種模型
增加網(wǎng)絡(luò)深度和寬度,也就意味著巨量的參數(shù),而巨量參數(shù)容易產(chǎn)生過(guò)擬合,也會(huì)大大增加計(jì)算量。
1.3 GoogleNet
GoogleNet模型由多組Inception模塊組成,模型設(shè)計(jì)借鑒了NIN的一些思想.
NIN模型特點(diǎn):
-
1. 引入了多層感知卷積網(wǎng)絡(luò)(Multi-Layer Perceptron Convolution, MLPconv)代替一層線性卷積網(wǎng)絡(luò)。MLPconv是一個(gè)微小的多層卷積網(wǎng)絡(luò),即在線性卷積后面增加若干層1x1的卷積,這樣可以提取出高度非線性特征。
- 2)設(shè)計(jì)最后一層卷積層包含類別維度大小的特征圖,然后采用全局均值池化(Avg-Pooling)替代全連接層,得到類別維度大小的向量,再進(jìn)行分類。這種替代全連接層的方式有利于減少參數(shù)。
Inception 結(jié)構(gòu)的主要思路是怎樣用密集成分來(lái)近似最優(yōu)的局部稀疏結(jié)構(gòu)。
2 圖像分類部分代碼實(shí)現(xiàn)
2.1 環(huán)境依賴
?
python 3.7
jupyter-notebook : 6.0.3
cudatoolkit 10.0.130
cudnn 7.6.5
tensorflow-gpu 2.0.0
scikit-learn 0.22.1
numpy
cv2
matplotlib
2.2 需要導(dǎo)入的包
?
import os
import cv2
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers,models
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import Callback
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.applications import VGG19
from tensorflow.keras.models import load_model
import matplotlib.pyplot as plt
from sklearn.preprocessing import label_binarize
tf.compat.v1.disable_eager_execution()
os.environ['CUDA_VISIBLE_DEVICES'] = '0' #使用GPU
2.3 參數(shù)設(shè)置(路徑,圖像尺寸,數(shù)據(jù)集分割比例)
?
preprocessedFolder = '.\\ClassificationData\\' #預(yù)處理文件夾
outModelFileName=".\\outModelFileName\\"
ImageWidth = 512
ImageHeight = 320
ImageNumChannels = 3
TrainingPercent = 70 #訓(xùn)練集比例
ValidationPercent = 15 #驗(yàn)證集比例
2.4 從preprocessedFolder讀取圖片并返回numpy格式(便于在神經(jīng)網(wǎng)絡(luò)中訓(xùn)練)
?
def read_dl_classifier_data_set(preprocessedFolder):
num = 0 # 圖片的總數(shù)量
cnt_class = 0 #圖片所屬的類別
label_list = [] # 存放每個(gè)圖像的label,圖像的類別
img_list = [] #存放圖片數(shù)據(jù)
for directory in os.listdir(preprocessedFolder):
tmp_dir = preprocessedFolder + directory
cnt_class += 1
for image in os.listdir(tmp_dir):
num += 1
tmp_img_filepath = tmp_dir + '\\' + image
im = cv2.imread(tmp_img_filepath) # numpy.ndarray
im = cv2.resize(im, (ImageWidth, ImageHeight)) # 重新設(shè)置圖片的大小
img_list.append(im)
label_list.append(cnt_class) # 在標(biāo)簽中添加類別
print("Picture " + str(num) + "Load "+tmp_img_filepath+"successfully")
print("共有" + str(num) + "張圖片")
print("all"+str(num)+"picturs belong to "+str(cnt_class)+"classes")
return np.array(img_list),np.array(label_list)
all_data,all_label=read_dl_classifier_data_set(preprocessedFolder)
2.5 數(shù)據(jù)預(yù)處理
圖像數(shù)據(jù)壓縮, 標(biāo)簽數(shù)據(jù)進(jìn)行獨(dú)立熱編碼one-hot
?
def preprocess_dl_Image(all_data,all_label):
all_data = all_data.astype("float32")/255 #把圖像灰度值壓縮到0--1.0便于神經(jīng)網(wǎng)絡(luò)訓(xùn)練
all_label = to_categorical(all_label) #對(duì)標(biāo)簽數(shù)據(jù)進(jìn)行獨(dú)立熱編碼
return all_data,all_label
all_data,all_label = preprocess_dl_Image(all_data,all_label) #處理后的數(shù)據(jù)
對(duì)數(shù)據(jù)及進(jìn)行劃分(訓(xùn)練集:驗(yàn)證集:測(cè)試集 = 0.7:0.15:0.15)
?
def split_dl_classifier_data_set(all_data,all_label,TrainingPercent,ValidationPercent):
s = np.arange(all_data.shape[0])
np.random.shuffle(s) #隨機(jī)打亂順序
all_data = all_data[s] #打亂后的圖像數(shù)據(jù)
all_label = all_label[s] #打亂后的標(biāo)簽數(shù)據(jù)
all_len = all_data.shape[0]
train_len = int(all_len*TrainingPercent/100) #訓(xùn)練集長(zhǎng)度
valadation_len = int(all_len*ValidationPercent/100)#驗(yàn)證集長(zhǎng)度
temp_len=train_len+valadation_len
train_data,train_label = all_data[0:train_len,:,:,:],all_label[0:train_len,:] #訓(xùn)練集
valadation_data,valadation_label = all_data[train_len:temp_len, : , : , : ],all_label[train_len:temp_len, : ] #驗(yàn)證集
test_data,test_label = all_data[temp_len:, : , : , : ],all_label[temp_len:, : ] #測(cè)試集
return train_data,train_label,valadation_data,valadation_label,test_data,test_label
train_data,train_label,valadation_data,valadation_label,test_data,test_label=split_dl_classifier_data_set(all_data,all_label,TrainingPercent,ValidationPercent)
2.6 訓(xùn)練分類模型
-
使用遷移學(xué)習(xí)(基于VGG19)
-
epochs = 30
-
batch_size = 16
-
使用 keras.callbacks.EarlyStopping 提前結(jié)束訓(xùn)練
def train_classifier(train_data,train_label,valadation_data,valadation_label,lr=1e-4): conv_base = VGG19(weights='imagenet', include_top=False, input_shape=(ImageHeight, ImageWidth, 3) ) model = models.Sequential() model.add(conv_base) model.add(layers.Flatten()) model.add(layers.Dense(30, activation='relu')) model.add(layers.Dense(6, activation='softmax')) #Dense: 全連接層。activation: 激勵(lì)函數(shù),‘linear’一般用在回歸任務(wù)的輸出層,而‘softmax’一般用在分類任務(wù)的輸出層 conv_base.trainable=False model.compile( loss='categorical_crossentropy',#loss: 擬合損失方法,這里用到了多分類損失函數(shù)交叉熵 optimizer=Adam(lr=lr),#optimizer: 優(yōu)化器,梯度下降的優(yōu)化方法 #rmsprop metrics=['accuracy']) model.summary() #每個(gè)層中的輸出形狀和參數(shù)。 early_stoping =tf.keras.callbacks.EarlyStopping(monitor="val_loss",min_delta=0,patience=5,verbose=0,baseline=None,restore_best_weights=True) history = model.fit( train_data, train_label, batch_size=16, #更新梯度的批數(shù)據(jù)的大小 iteration = epochs / batch_size, epochs=30, # 迭代次數(shù) validation_data=(valadation_data, valadation_label), # 驗(yàn)證集 callbacks=[early_stoping]) return model,history model,history = train_classifier(train_data,train_label,valadation_data,valadation_label,)
2.7 模型訓(xùn)練效果
?
def plot_history(history):
history_df = pd.DataFrame(history.history)
history_df[['loss', 'val_loss']].plot()
plt.title('Train and valadation loss')
history_df = pd.DataFrame(history.history)
history_df[['accuracy', 'val_accuracy']].plot()
plt.title('Train and valadation accuracy')
plot_history(history)
2.8 模型性能評(píng)估
-
使用測(cè)試集進(jìn)行評(píng)估
-
輸出分類報(bào)告和混淆矩陣
-
繪制ROC和AUC曲線
from sklearn.metrics import classification_report from sklearn.metrics import confusion_matrix from sklearn.metrics import accuracy_score import seaborn as sns Y_pred_tta=model.predict_classes(test_data) #模型對(duì)測(cè)試集數(shù)據(jù)進(jìn)行預(yù)測(cè) Y_test = [np.argmax(one_hot)for one_hot in test_label]# 由one-hot轉(zhuǎn)換為普通np數(shù)組 Y_pred_tta=model.predict_classes(test_data) #模型對(duì)測(cè)試集進(jìn)行預(yù)測(cè) Y_test = [np.argmax(one_hot)for one_hot in test_label]# 由one-hot轉(zhuǎn)換為普通np數(shù)組 print('驗(yàn)證集分類報(bào)告:\n',classification_report(Y_test,Y_pred_tta)) confusion_mc = confusion_matrix(Y_test,Y_pred_tta)#混淆矩陣 df_cm = pd.DataFrame(confusion_mc) plt.figure(figsize = (10,7)) sns.heatmap(df_cm, annot=True, cmap="BuPu",linewidths=1.0,fmt="d") plt.title('PipeLine accuracy:{0:.3f}'.format(accuracy_score(Y_test,Y_pred_tta)),fontsize=20) plt.ylabel('True label',fontsize=20) plt.xlabel('Predicted label',fontsize=20)
?
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import average_precision_score
from sklearn.metrics import roc_curve
from sklearn import metrics
import matplotlib as mpl
# 計(jì)算屬于各個(gè)類別的概率,返回值的shape = [n_samples, n_classes]
y_score = model.predict_proba(test_data)
# 1、調(diào)用函數(shù)計(jì)算驗(yàn)證集的AUC
print ('調(diào)用函數(shù)auc:', metrics.roc_auc_score(test_label, y_score, average='micro'))
# 2、手動(dòng)計(jì)算驗(yàn)證集的AUC
#首先將矩陣test_label和y_score展開(kāi),然后計(jì)算假正例率FPR和真正例率TPR
fpr, tpr, thresholds = metrics.roc_curve(test_label.ravel(),y_score.ravel())
auc = metrics.auc(fpr, tpr)
print('手動(dòng)計(jì)算auc:', auc)
mpl.rcParams['font.sans-serif'] = u'SimHei'
mpl.rcParams['axes.unicode_minus'] = False
#FPR就是橫坐標(biāo),TPR就是縱坐標(biāo)
plt.figure(figsize = (10,7))
plt.plot(fpr, tpr, c = 'r', lw = 2, alpha = 0.7, label = u'AUC=%.3f' % auc)
plt.plot((0, 1), (0, 1), c = '#808080', lw = 1, ls = '--', alpha = 0.7)
plt.xlim((-0.01, 1.02))
plt.ylim((-0.01, 1.02))
plt.xticks(np.arange(0, 1.1, 0.1))
plt.yticks(np.arange(0, 1.1, 0.1))
plt.xlabel('False Positive Rate', fontsize=16)
plt.ylabel('True Positive Rate', fontsize=16)
plt.grid(b=True, ls=':')
plt.legend(loc='lower right', fancybox=True, framealpha=0.8, fontsize=12)
plt.title('37個(gè)驗(yàn)證集分類后的ROC和AUC', fontsize=18)
plt.show()
3 1000種圖像分類
這是學(xué)長(zhǎng)訓(xùn)練的能識(shí)別1000種類目標(biāo)的圖像分類模型,演示效果如下
4 最后
?? 更多資料, 項(xiàng)目分享:
https://gitee.com/dancheng-senior/postgraduate
到了這里,關(guān)于互聯(lián)網(wǎng)加競(jìng)賽 基于人工智能的圖像分類算法研究與實(shí)現(xiàn) - 深度學(xué)習(xí)卷積神經(jīng)網(wǎng)絡(luò)圖像分類的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!