TensorFlow 中的 DenseNet 简介
介绍
为什么要使用 DenseNet?
DenseNet 架构
DenseNet 结构
DenseNet 属于经典网络类别。
该图展示了增长率为 k = 4 的5 层密集块和标准 ResNet 结构。
前一层的输出通过复合函数运算作为第二层的输入,该复合运算由卷积层、池化层、批量归一化层和非线性激活层组成。
这些连接意味着网络具有 L(L+1)/2 个直接连接。L 是架构中的层数。
DenseNet 有不同的版本,如 DenseNet-121、DenseNet-160、DenseNet-201 等。数字表示神经网络中的层数。数字 121 的计算方式如下:
DenseBlocks 和层
无论是添加还是连接,只有当特征图尺寸相同时,才有可能通过上述公式对层进行分组。如果尺寸不同怎么办?DenseNet 分为 DenseBlocks,其中过滤器数量不同,但块内的维度相同。过渡层使用下采样应用批量归一化;这是 CNN 中必不可少的一步。
让我们看看 DenseBlock 和过渡层里面有什么:
这是抽象形式的完整架构:
资料来源:Pablo R
过滤器的数量在 DenseBlocks 之间发生变化,从而增加了通道的维度。增长率 (k) 有助于概括第 l 层。它控制要添加到每层的信息量。
实施守则
开始之前,必须导入所有相关库。这里的主要驱动程序是tensorflow.keras.applications(用于导入 DenseNet121)和tensorflow.keras.layers(用于导入构建网络所涉及的层)。
import tensorflow
import pandas as pd
import numpy as np
import os
import keras
import random
import cv2
import math
import seaborn as sns
from sklearn.metrics import confusion_matrix
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from tensorflow.keras.layers import Dense,GlobalAveragePooling2D,Convolution2D,BatchNormalization
from tensorflow.keras.layers import Flatten,MaxPooling2D,Dropout
from tensorflow.keras.applications import DenseNet121
from tensorflow.keras.applications.densenet import preprocess_input
from tensorflow.keras.preprocessing import image
from tensorflow.keras.preprocessing.image import ImageDataGenerator,img_to_array
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau
import warnings
warnings.filterwarnings("ignore")
print("Tensorflow-version:", tensorflow.__version__)
输出:Tensorflow-version:2.0.0
model_d=DenseNet121(weights='imagenet',include_top=False, input_shape=(128, 128, 3))
x=model_d.output
x= GlobalAveragePooling2D()(x)
x= BatchNormalization()(x)
x= Dropout(0.5)(x)
x= Dense(1024,activation='relu')(x)
x= Dense(512,activation='relu')(x)
x= BatchNormalization()(x)
x= Dropout(0.5)(x)
preds=Dense(8,activation='softmax')(x) #FC-layer
model=Model(inputs=base_model.input,outputs=preds)
model.summary()
为了避免过度拟合的问题,请避免训练整个网络。layer.trainable=False将冻结所有层,仅保留最后八层(FC)来检测图像中的边缘和斑点。一旦模型拟合良好,就可以使用layer.trainable=True进行微调。
for layer in model.layers[:-8]:
layer.trainable=False
for layer in model.layers[-8:]:
layer.trainable=True
model.compile(optimizer='Adam',loss='categorical_crossentropy',metrics=['accuracy'])
model.summary()
注意参数的下降。
data=[]
labels=[]
random.seed(42)
imagePaths = sorted(list(os.listdir("../input/natural-images/")))
random.shuffle(imagePaths)
print(imagePaths)
for img in imagePaths:
path=sorted(list(os.listdir("../input/natural-images/"+img)))
for i in path:
image = cv2.imread("../input/natural-images/"+img+'/'+i)
image = cv2.resize(image, (128,128))
image = img_to_array(image)
data.append(image)
l = label = img
labels.append(l)
data = np.array(data, dtype="float32") / 255.0
labels = np.array(labels)
mlb = LabelBinarizer()
labels = mlb.fit_transform(labels)
print(labels[0])
(xtrain,xtest,ytrain,ytest)=train_test_split(data,labels,test_size=0.4,random_state=42)
print(xtrain.shape, xtest.shape)
如果模型的验证损失没有变化,则ReduceLROnPlateau函数将降低学习率,这通常对模型有利。ImageDataGenerator函数在循环中对生成的张量图像数据批次执行实时数据增强。
anne = ReduceLROnPlateau(monitor='val_accuracy', factor=0.5, patience=5, verbose=1, min_lr=1e-3)
checkpoint = ModelCheckpoint('model.h5', verbose=1, save_best_only=True)
datagen = ImageDataGenerator(zoom_range = 0.2, horizontal_flip=True, shear_range=0.2)
datagen.fit(xtrain)
# Fits-the-model
history = model.fit_generator(datagen.flow(xtrain, ytrain, batch_size=128),
steps_per_epoch=xtrain.shape[0] //128,
epochs=50,
verbose=2,
callbacks=[anne, checkpoint],
validation_data=(xtrain, ytrain))
ypred = model.predict(xtest)
total = 0
accurate = 0
accurateindex = []
wrongindex = []
for i in range(len(ypred)):
if np.argmax(ypred[i]) == np.argmax(ytest[i]):
accurate += 1
accurateindex.append(i)
else:
wrongindex.append(i)
total += 1
print('Total-test-data;', total, '\taccurately-predicted-data:', accurate, '\t wrongly-predicted-data: ', total - accurate)
print('Accuracy:', round(accurate/total*100, 3), '%')
label=['dog', 'flower', 'motorbike', 'person', 'cat', 'fruit', 'airplane', 'car']
imidx = random.sample(accurateindex, k=9)# replace with 'wrongindex'
nrows = 3
ncols = 3
fig, ax = plt.subplots(nrows,ncols,sharex=True,sharey=True,figsize=(15, 12))
n = 0
for row in range(nrows):
for col in range(ncols):
ax[row,col].imshow(xtest[imidx[n]])
ax[row,col].set_title("Predicted label :{}\nTrue label :{}".format(label[np.argmax(ypred[imidx[n]])], label[np.argmax(ytest[imidx[n]])]))
n += 1
plt.show()
Ypred = model.predict(xtest)
Ypred = np.argmax(Ypred, axis=1)
Ytrue = np.argmax(ytest, axis=1)
cm = confusion_matrix(Ytrue, Ypred)
plt.figure(figsize=(12, 12))
ax = sns.heatmap(cm, cmap="rocket_r", fmt=".01f",annot_kws={'size':16}, annot=True, square=True, xticklabels=label, yticklabels=label)
ax.set_ylabel('Actual', fontsize=20)
ax.set_xlabel('Predicted', fontsize=20)
结论
您已构建一个准确率约为 98% 的 DenseNet 模型。DenseNet 减少了梯度消失问题,并且训练模型所需的参数更少。动态特征传播负责实现信息的无缝流动。
本指南介绍了构建 DenseNet-121 的基本知识、其架构、优势以及它与 ResNet 的区别。从热图中,我们可以看到 44 只狗被错误分类为猫,可能是因为错误分类的狗图片具有与猫相似的特征。可以通过微调模型来改善结果。尝试添加或删除更多密集块和层,查找每个类别中数据的频率,并增强图像。
深度神经网络是一个广阔的领域。不断进行的研究使学习和解决复杂的现实问题变得更加简单。如果您在深度学习项目中需要任何帮助,请通过CodeAlphabet与我联系。
参考
G. Huang、Z. Liu 和 L. van der Maaten,“密集连接卷积网络”,2018 年。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~