使用卷积神经网络开发图像分类模型
4 w. r1 s6 K: k' a) @3 M简介3 p" u7 m/ h7 R2 ]; N7 j* i, q: p) ?
* q, N" l, A1 N, ?. w& P5 d/ o
这篇文章是关于卷积网络、它的工作和组件: 在本文中,我们将使用卷积神经网络执行图像分类,并详细了解所有步骤。因此,如果你对此不熟悉,请继续阅读。
5 j8 B3 A J* I1 ]3 `1 G/ F. w
) b: ~/ o" q$ U( f& ]) O! [3 O7 o! j简而言之,CNN 是一种深度学习算法,也是适用于图像和视频的神经网络类型之一。我们可以从 CNN 中实现各种功能,其中一些是图像分类、图像识别、目标检测、人脸识别等等。2 [+ R' x+ e; ]. t: J' x0 `- z6 M+ H
% U2 m* V9 |5 W+ W; l6 U
今天,我们将对CIFAR10 数据集执行图像分类,它是 Tensorflow 库的一部分。它由各种物体的图像组成,如船舶、青蛙、飞机、狗、汽车。该数据集共有 60,000 张彩色图像和 10 个标签。现在让我们进入编码部分。
' Y# F1 w: Q; R: [- y1 l) `: D- h' ?2 L7 Z# B. U! e
实施7 T. k% e% d8 l
, y. K' g, j" B2 f* a4 @+ U
# importing necessary libraries% m7 C _" A) `1 a
import numpy as np6 F' V. N& U4 K0 e9 ~$ d
import matplotlib.pyplot as plt" P1 G3 @6 O8 j p W4 r' S
%matplotlib inline7 D$ w/ L1 K$ U0 C$ W) h
# To convert to categorical data
" |, r4 J0 U; F8 O' Rfrom tensorflow.keras.utils import to_categorical/ J# T9 v' }& g4 E
#libraries for building model& K- B- I7 ?! _
from tensorflow.keras.models import Sequential
1 D% D1 x, W& [* b6 U! Pfrom tensorflow.keras.layers import Dense, Conv2D, MaxPool2D, Dropout,Flatten8 d3 S' ]3 Z! z* i! O F/ O1 Z
from tensorflow.keras.datasets import cifar10
' Q0 C! F4 f3 I! I2 c& R( E8 Y! I) G& F4 D1 [" e6 q- d. [) n# ~
#loading the data9 H$ f! P; _$ w
(X_train, y_train), (X_test, y_test) = cifar10.load_data()8 }0 E8 d- q. W x! R0 D
/ g5 k* [% ^4 {$ t7 a: g探索性数据分析" m5 |' |$ j/ e% d
#shape of the dataset9 n( [. b0 Z7 r% M# e: W! _
print(X_train.shape)/ O" ]2 }8 o5 I
print(y_train.shape)
8 B0 p; c7 |( Wprint(X_test.shape)
" y( a: g S$ ~print(y_test.shape)% T. i$ p; ~7 @2 \( N
+ a7 s2 |: X! t$ k' J0 Q/ ]
![]()
$ P/ Y% z4 d' A8 N, w: i5 d+ h我们的训练数据有 50,000 张图像,测试数据有 10,000 张图像,大小为 32*32 和 3 个通道,即 RGB(红、绿、蓝)
: _! Q/ Z7 J$ N& V# m t$ R4 Y#checking the labels ( K5 W6 A& ^! m4 I5 g: m
np.unique(y_train)
8 t. a" A4 C0 L3 ?7 q' c# g- f, T. H8 z6 q8 N* Z8 [3 l% @5 s
6 N, I6 }' D, u8 V1 {0 N: `+ }
#first image of training data
/ V/ o4 l6 l& e `6 @5 Qplt.subplot(121)
, s; N5 R& d% l! ^0 ~plt.imshow(X_train[0])
* I0 e, A+ E+ I0 Lplt.title("Label : {}".format(y_train[0]))
, r( t* u1 E( `* ~# m7 Z& E#first image of test data
* x8 t' w. q5 eplt.subplot(122)
% h& \2 i% c% l' yplt.imshow(X_test[0])
% I6 h2 A' q# X" V- j$ Fplt.title("Label : {}".format(y_test[0]));
! D. i9 l) |9 ~- Z3 h
8 r8 z; Y' Z3 j9 a, `# e2 ^ ! }6 W" X8 [4 ~6 f. L, Z ]2 A
#visualizing the first 20 images in the dataset
% ?4 k* k5 }7 |% R* b, N& ~$ Cfor i in range(20):
( v; P8 Y4 D% _' d c #subplot7 F/ n: u6 O3 j" x' D1 _& d6 X3 }
plt.subplot(5, 5, i+1)
2 D5 P6 A9 U! c. U; @3 m7 C # plotting pixel data; [$ m5 G4 G1 Y Q- r% q
plt.imshow(X_train, cmap=plt.get_cmap('gray'))3 h2 V- `, l b$ l D
# show the figure# v% Y9 v5 k, |
plt.show()
$ l" I8 e5 ^% w2 | L5 V7 T1 ^: |. a) q q- i7 v# Y+ U
![]()
+ v J% ~9 N. x# ^6 E5 r0 r; p预处理数据对于数据预处理,我们只需要在这里执行两个步骤,首先是缩放图像的像素值到0到1之间,然后是将标签从 2D 重塑为 1D 1 S% Y! l% q: B7 o4 `. i
# Scale the data to lie between 0 to 1
+ o" f: i+ w7 i6 a8 EX_train = X_train/2554 i$ g' j9 w% Z Z- v
X_test = X_test/2550 S) i0 X7 O& d( ]" P$ O' Y$ o& M R
print(X_train)
+ `. m8 t2 e6 W0 h8 f2 R: C9 U
; e9 S$ D. [2 i! O) e
#reshaping the train and test lables to 1D- c: v/ m- H/ P. v
y_train = y_train.reshape(-1,)% w9 X1 `4 Q1 w t1 `' {
y_test = y_test.reshape(-1,)
1 z( K9 n% E* S2 C: n; x w+ i( l( |5 c! |4 ~" ^, e
我们在上图中可以看到,图像的像素值已经进行了缩放,其数值在 0 到 1 之间,并且标签也进行了重塑。数据已准备好建模,现在让我们构建 CNN 模型。
' k/ B/ ]' _$ n/ w7 n& i2 ]模型搭建正如我们之前讨论的,深度学习模型的构建分为 5 个步骤,即定义模型、编译模型、拟合模型、评估模型和进行预测,这也是我们在这里要做的。
! a" H- f* X: l0 V5 {model=Sequential()8 G8 Y! Y2 G& _7 B* D8 k
#adding the first Convolution layer
1 A( ?# s/ K. ?+ n+ dmodel.add(Conv2D(32,(3,3),activation='relu',input_shape=(32,32,3))). X( m: s- S$ U: ?3 P0 g5 M% d
#adding Max pooling layer& }+ i5 o, \/ ~7 D. B: X9 R1 J
model.add(MaxPool2D(2,2))
: ~) _0 {5 F* _6 q#adding another Convolution layer5 p! o) i( N$ p9 f* p5 J; h
model.add(Conv2D(64,(3,3),activation='relu'))' Q2 o; e6 \* s$ ~ w1 @
model.add(MaxPool2D(2,2))2 j( W4 U( C( V! |" S# M- A
model.add(Flatten())
; y/ O+ J' Q a/ f' I) F#adding dense layer5 ^2 L4 s, I0 h* A
model.add(Dense(216,activation='relu'))+ e M) p6 N! p4 U, N
#adding output layer( l, H/ j8 O5 ~% `
model.add(Dense(10,activation='softmax'))
* D# _& a$ J/ s( g
2 ]7 y' k# A+ G我们添加了第一个带有 32 个大小为 (3*3) 的过滤器的卷积层,使用的激活函数是 Relu,并为模型提供输入形状。0 y8 ?0 H/ r; }# q {( v
+ Z0 I8 y$ I# n接下来添加了大小为 (2*2)的Max Pooling 层。最大池化有助于减少维度。CNN 组件的解释请参考:https://www.analyticsvidhya.com/blog/2021/08/beginners-guide-to-convolutional-neural-network-with-implementation-in-python/
; ]8 G/ [/ n7 Y d5 X! E! v
- o+ L+ U8 k9 N0 _: a然后我们又添加了一个卷积层, 其中包含 64 个大小为(3*3) 的过滤器 和一个大小为 (2*2)的 最大池化层# V( X) C2 f& @: |0 Y+ o
% J. ?8 A& `) f% V6 l* H
在下一步中,我们将层展平以将它们传递到 Dense 层,并添加了一个包含 216 个神经元的Dense 层。
: ]3 G& w/ d2 B2 W8 i5 D& s% D `1 i# K; ]4 P4 s
最后,输出层添加了一个 softmax 激活函数,因为我们有 10 个标签。
$ B- ?- ]$ X" i) s1 E' k$ ~6 B) K8 k* I; F7 F; C
第 2 步:编译模型/ i+ T' p3 M H* d; n& F
model.compile(optimizer='rmsprop',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
; F# w! | H3 U. b- P# X* N7 o' n+ f: ^: y! G! J2 [, p7 z
第 3 步:拟合模型model.fit(X_train,y_train,epochs=10)
. k6 M! \: c; B* h, V- Y! X+ a * A+ T% i% r# i; E/ U
! B9 g# ~8 v. k) t6 K# O3 Y' b
如上图所示,我们的准确率为 89%,损失为 0.31。让我们看看测试数据的准确性。
' U& E% S0 Q0 _2 B2 x& g第 4 步:评估模型model.evaluate(X_test,y_test)
0 ^! ~4 I3 j4 o" Q" U. b3 Z 7 N* B3 l& X# d: J! p) s0 {
) m2 K% x8 R, j/ M5 P
测试数据的准确率为 69%,与训练数据相比非常低,这意味着我们的模型过度拟合。
# d; d0 u% J0 \- K& g第 5 步:进行预测
6 q- t' e8 _$ [; i# Y- epred=model.predict(X_test)
; g9 e7 y+ l* k2 n9 V. h7 D#printing the first element from predicted data
- V* ]7 G: J- r8 }print(pred[0])
) G8 L. l' h/ @7 N+ j#printing the index of
9 S' b! l) v7 j# @. `print('Index:',np.argmax(pred[0]))$ H" Q2 r/ B- \. m
+ }$ k3 Q$ j' E! E9 g( S 9 j) c+ H4 |. B6 ^
b9 P, ~: t* u" v因此,预测函数给出的是所有10个标签的概率值,概率最高的标签是最终预测。在我们的例子中,我们得到了第三个索引处的标签作为预测。 将预测值与实际值进行比较以查看模型执行的正确程度。 在下图中,我们可以看到预测值与实际值的差异。 y_classes = [np.argmax(element) for element in pred]
$ u! L c: F8 f+ Z( Q e0 ?) d% M/ Y: @print('Predicted_values:',y_classes[:10])* i! R/ c; q+ l9 _; ^
print('Actual_values:',y_test[:10])
/ y7 K+ Z4 { U) _3 ]
& W: n$ u, R2 V![]()
% G, q$ u3 C1 u' {当我们看到我们的模型过度拟合时,我们可以使用一些额外的步骤来提高模型性能并减少过度拟合,例如向模型添加 Dropouts或执行数据增强,因为过度拟合问题也可能是由于可用数据量较少。 在这里,我将展示我们如何使用 Dropout 来减少过拟合。我将为此定义一个新模型。
6 Z' \4 i) z. X# Z; ^0 `model4=Sequential()
5 ?$ V+ o2 R# P2 c' q6 s#adding the first Convolution layer
( P( O8 V1 d8 s' emodel4.add(Conv2D(32,(3,3),activation='relu',input_shape=(32,32,3)))
' z$ F+ O- l4 W4 g#adding Max pooling layer
/ f* ^! h! k4 Gmodel4.add(MaxPool2D(2,2))" v, i! p4 r/ z) l
#adding dropout
" Q, M# }9 \) r" ?% }" E, ]model4.add(Dropout(0.2))
, r3 f- Z* _6 ?/ n/ E#adding another Convolution layer! Y' X* r( m2 x1 {! x" F+ \" [
model4.add(Conv2D(64,(3,3),activation='relu'))3 p* i! T. n6 }$ B9 e! e
model4.add(MaxPool2D(2,2))
% w- j6 H4 ~) a8 T9 b5 x, i#adding dropout% ^! b" r& u. Z$ E" W# F
model4.add(Dropout(0.2))
) Z" }' c! ^9 [1 ]model4.add(Flatten())
5 ]' e! g& ^: i: y#adding dense layer1 U, p# Z5 L& m
model4.add(Dense(216,activation='relu'))
% n/ J' I; q/ d6 Z0 j$ v$ c#adding dropout+ W+ \2 T1 x+ ~! \9 v! A4 V' x. k
model4.add(Dropout(0.2))" g* I6 c; P1 I5 m
#adding output layer- S# e: t; j: P$ b# E7 b
model4.add(Dense(10,activation='softmax'))
9 F9 A& ^' i6 b' x% z$ P. Omodel4.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
5 D' c7 m {: |- J9 J$ v0 Xmodel4.fit(X_train,y_train,epochs=10)* K2 D: K- h8 S8 M# c6 r( ~
0 g; K: b$ ]9 |7 I8 t
+ v) o: v8 `" c! N9 n/ ^
model4.evaluate(X_test,y_test)
# ?- {* N: o/ R7 f0 R# N; y 8 w; @4 u2 s4 S" [) T
通过这个模型,我们得到了76%的训练准确率(低于第一个模型),但我们得到了72%的测试准确率,这意味着过拟合的问题在一定程度上得到了解决。
p# j4 o0 i5 N( X z8 W- G( A+ d, Z" n4 Z b5 g, l% U; e
尾注
/ H2 n7 ]( G3 s* D2 X$ n+ P- @2 ?这就是我们在 Python 中实现 CNN 的方式。这里使用的数据集是一个简单的数据集,可用于学习目的,但一定要尝试在更大和更复杂的数据集上实现 CNN。这也将有助于发现更多挑战和解决方案。
6 ~1 h+ I0 ~; A* H8 A5 g, w" E
0 m2 M) |, \, w8 m! |6 J6 F5 j* G5 f6 i1 e4 c7 m3 p3 u: y/ ?
) i* q. d# R$ {$ ^! N$ a
|