使用卷积神经网络开发图像分类模型
5 O) P( v" Z+ z! K简介$ q; G$ } P$ x
; ~5 y( a8 U: v/ q5 ?; I这篇文章是关于卷积网络、它的工作和组件: 在本文中,我们将使用卷积神经网络执行图像分类,并详细了解所有步骤。因此,如果你对此不熟悉,请继续阅读。
$ E. z6 ]& G- c2 J: g/ y% Q8 e( b4 b+ c7 M2 K
简而言之,CNN 是一种深度学习算法,也是适用于图像和视频的神经网络类型之一。我们可以从 CNN 中实现各种功能,其中一些是图像分类、图像识别、目标检测、人脸识别等等。
% j# H$ D* ]4 M9 l5 z4 a- w E5 C- S
0 X( R; U; Y h: `, z3 Z$ D今天,我们将对CIFAR10 数据集执行图像分类,它是 Tensorflow 库的一部分。它由各种物体的图像组成,如船舶、青蛙、飞机、狗、汽车。该数据集共有 60,000 张彩色图像和 10 个标签。现在让我们进入编码部分。
5 O) A9 C, k8 n3 q p/ u. s( t2 b9 D5 L: V8 [: M+ ?8 \1 b
实施
( u" x. P) a! Q) P; y6 L2 V! Z2 z2 V1 b$ s# B9 _
# importing necessary libraries; _4 t, {- y+ i
import numpy as np' w: B8 {4 A7 m1 O( R
import matplotlib.pyplot as plt6 x1 T' T# U: W8 I
%matplotlib inline
. ^: ?) k" i2 A0 v( V( t j# j# To convert to categorical data
$ f. Q" T0 ?1 d. {from tensorflow.keras.utils import to_categorical
: ~" K0 g& x4 `0 B9 i( s#libraries for building model
; b( L/ _1 ?( i9 {from tensorflow.keras.models import Sequential+ x9 Z. T2 m F/ F* w. n
from tensorflow.keras.layers import Dense, Conv2D, MaxPool2D, Dropout,Flatten* g3 @: [0 n: K& v# e5 s+ f
from tensorflow.keras.datasets import cifar10! n! Y7 N# w0 ?' M& s( o5 M
9 s8 j& p. ?# M% C
#loading the data
4 D- [$ u8 {# @5 z(X_train, y_train), (X_test, y_test) = cifar10.load_data()
0 H( k) e M/ s# d* m, {" }; r
& r! b' L" T- B探索性数据分析- s9 {1 r9 H( V' }/ {& e* _# ?1 e
#shape of the dataset% ^: I. S6 q3 [0 z, l) L
print(X_train.shape)
7 W" m* ]/ g: R. m5 fprint(y_train.shape)
# v" h1 Z1 E* F9 S2 }5 K$ H0 Y# hprint(X_test.shape)
5 ]7 q$ [, G4 x1 m- y" v8 vprint(y_test.shape)2 k$ a; H- I% z3 y5 k$ s
9 w3 Y/ e' _- ] 5 R, [0 l2 j' \5 ]1 A
我们的训练数据有 50,000 张图像,测试数据有 10,000 张图像,大小为 32*32 和 3 个通道,即 RGB(红、绿、蓝)
1 c7 Q0 w/ g O5 v j#checking the labels
6 [) w% Q/ B, H X K- ~0 `np.unique(y_train)
7 m2 F: t8 u& {3 {; H* |! n! |/ A+ @6 B& z3 p _
![]()
) X: D; n* |' g: N3 H) i#first image of training data
1 e% w8 _: u3 x, I; S2 nplt.subplot(121)
5 d* Z- s1 b0 ]5 P" C$ hplt.imshow(X_train[0])
9 o E% w# Y& _) ~plt.title("Label : {}".format(y_train[0]))
* ~( h, G- P% n) [" K1 q$ Q( D#first image of test data; Y$ `6 s! f9 V0 N
plt.subplot(122); q8 T& a: e8 l A ?5 P# V6 a( V7 Z
plt.imshow(X_test[0])4 E+ J8 n) E1 t, D7 L
plt.title("Label : {}".format(y_test[0]));; Y' t% m/ N% M: z/ @* `/ d- f2 h
# q w- p5 P, B2 d8 i# e8 p$ ]- l/ T
![]()
+ y2 |( |. k* }2 v#visualizing the first 20 images in the dataset
* z0 G; M3 Q4 Q% B5 _) L, jfor i in range(20):4 `+ F& ]! `, \
#subplot
$ r8 u" {) i( m( U$ v plt.subplot(5, 5, i+1)
* l% f6 b3 `* h( q # plotting pixel data3 `1 K& V2 h; H' q
plt.imshow(X_train, cmap=plt.get_cmap('gray'))
0 P- q1 c$ E2 H" q# show the figure2 c7 z% a5 K/ ]' R8 j2 m
plt.show()
! s; T$ Y- ^5 r) [
; C0 Y: L: c0 n) j+ f4 P# X![]()
5 i4 ~/ g* O8 U y, Q" ]# X5 R预处理数据对于数据预处理,我们只需要在这里执行两个步骤,首先是缩放图像的像素值到0到1之间,然后是将标签从 2D 重塑为 1D " S( Q! V6 g, }: D: B9 k% g
# Scale the data to lie between 0 to 1
- N: P9 i6 t" K) e+ ^4 }/ FX_train = X_train/255
, g; R+ {9 a; T9 }8 j* Y% UX_test = X_test/255
7 O) R0 I7 }& {# d8 e4 A3 iprint(X_train)
, M$ @& W8 C; g) a) c8 Z R+ e% _7 V2 `4 n8 V* o6 {$ @3 A
" o7 N' X0 y+ Q% I0 O5 o4 G
#reshaping the train and test lables to 1D
" }; t( {+ u$ W! b( a. B" Qy_train = y_train.reshape(-1,)$ d7 v* C8 a/ h1 @
y_test = y_test.reshape(-1,)
: K$ s% ^$ u/ Y& K d' ~
1 J- W4 u [9 b我们在上图中可以看到,图像的像素值已经进行了缩放,其数值在 0 到 1 之间,并且标签也进行了重塑。数据已准备好建模,现在让我们构建 CNN 模型。
- M# K, f! q2 B3 S9 t5 h0 K模型搭建正如我们之前讨论的,深度学习模型的构建分为 5 个步骤,即定义模型、编译模型、拟合模型、评估模型和进行预测,这也是我们在这里要做的。 0 n4 g; x* x/ W. K+ h
model=Sequential()* `# _4 X* {" |' Q
#adding the first Convolution layer) f! Q) b1 l: S$ X3 w; n
model.add(Conv2D(32,(3,3),activation='relu',input_shape=(32,32,3)))
' Y' x5 T6 K8 d: f; k% W# U1 V#adding Max pooling layer5 K& u1 D4 A4 D3 t5 e- m
model.add(MaxPool2D(2,2))1 X3 R* \4 a; T+ n3 P) s9 D
#adding another Convolution layer
& h) y6 N7 q9 k5 x' v* O6 |; hmodel.add(Conv2D(64,(3,3),activation='relu'))
& T( Y/ T4 }8 N' Jmodel.add(MaxPool2D(2,2))% ]# e- t6 @7 y/ ?
model.add(Flatten())6 ~5 B6 |4 C# p1 e; b( g y; ^
#adding dense layer
# W" z+ r4 R# v2 Xmodel.add(Dense(216,activation='relu'))9 \6 N* e/ j- K; A; |) D" r, a
#adding output layer
3 ?4 M: D% d5 b f5 H' ~model.add(Dense(10,activation='softmax'))! K1 \9 d* h# B; K2 x! v
! G7 ~- {+ |0 i+ I6 V
我们添加了第一个带有 32 个大小为 (3*3) 的过滤器的卷积层,使用的激活函数是 Relu,并为模型提供输入形状。# J9 \( e( l/ ]4 J
! q/ T' B: r5 j2 U
接下来添加了大小为 (2*2)的Max Pooling 层。最大池化有助于减少维度。CNN 组件的解释请参考:https://www.analyticsvidhya.com/blog/2021/08/beginners-guide-to-convolutional-neural-network-with-implementation-in-python/1 ~5 ~ J7 z. u' m
* ` K4 o* I. }
然后我们又添加了一个卷积层, 其中包含 64 个大小为(3*3) 的过滤器 和一个大小为 (2*2)的 最大池化层
! V$ S0 w) Z' a! } g5 h* z# F
9 a1 l( `% g; x在下一步中,我们将层展平以将它们传递到 Dense 层,并添加了一个包含 216 个神经元的Dense 层。
/ f4 v2 E8 ~2 Z1 C6 Q# H( e0 _) ?0 a
最后,输出层添加了一个 softmax 激活函数,因为我们有 10 个标签。
' X6 S2 `* ^2 K3 P0 a* J
( w/ |% g! _5 {0 M第 2 步:编译模型
" _+ x1 b0 U8 r6 }( B5 `+ Vmodel.compile(optimizer='rmsprop',loss='sparse_categorical_crossentropy',metrics=['accuracy'])% X+ i, i7 k6 @( t
/ q0 ]* @) k$ m _% _- q( ^
第 3 步:拟合模型model.fit(X_train,y_train,epochs=10)* f5 K- P4 J; N2 e' Y
![]()
7 P9 k m4 D$ Y% i4 | & E! ]6 a' E2 D- [" m6 V f
如上图所示,我们的准确率为 89%,损失为 0.31。让我们看看测试数据的准确性。$ e5 m) q7 \8 [' Z4 Q- ?# T
第 4 步:评估模型model.evaluate(X_test,y_test)6 K( O8 \0 e) f5 j
, q: P, i3 A! q1 Y. `8 F
* X0 ^1 H7 x( K' p
测试数据的准确率为 69%,与训练数据相比非常低,这意味着我们的模型过度拟合。
+ M2 \: C8 n2 P第 5 步:进行预测$ Z! }/ ?: x1 T3 F" B
pred=model.predict(X_test)
6 _- J0 \2 d# Q- ~4 t: q#printing the first element from predicted data/ j( ?- S; a/ @$ X1 M
print(pred[0])
. k0 t+ ~/ v5 ?# G: y#printing the index of
( N& v1 I4 c8 V/ q' s' ^print('Index:',np.argmax(pred[0]))4 _' l0 ^7 B: Q7 t* ^1 ^
- o$ e- k1 |& n, n# M- }' A6 x/ F![]()
7 s7 D8 K0 B# E8 d
$ ?4 d3 W$ o( d$ x$ i2 l4 @- d因此,预测函数给出的是所有10个标签的概率值,概率最高的标签是最终预测。在我们的例子中,我们得到了第三个索引处的标签作为预测。 将预测值与实际值进行比较以查看模型执行的正确程度。 在下图中,我们可以看到预测值与实际值的差异。 y_classes = [np.argmax(element) for element in pred]
% ]9 ?" z. z! F5 u( Iprint('Predicted_values:',y_classes[:10])# g) @5 L; h9 o8 e
print('Actual_values:',y_test[:10])
$ X9 {& n) k6 J1 r2 e# T
* X6 L( n0 J& b. I8 N 2 _+ y5 |* t3 {' g
当我们看到我们的模型过度拟合时,我们可以使用一些额外的步骤来提高模型性能并减少过度拟合,例如向模型添加 Dropouts或执行数据增强,因为过度拟合问题也可能是由于可用数据量较少。 在这里,我将展示我们如何使用 Dropout 来减少过拟合。我将为此定义一个新模型。
4 H( R( o, g8 o! B; Z' k/ x' Fmodel4=Sequential()
% o1 s# l* l9 o& j3 F2 h#adding the first Convolution layer$ x& w4 j1 }8 e: F
model4.add(Conv2D(32,(3,3),activation='relu',input_shape=(32,32,3)))( A- H5 k7 Z( F" W2 U0 n
#adding Max pooling layer
3 J( N, s$ d$ ^" y6 D: Pmodel4.add(MaxPool2D(2,2)). A( ]; z y0 }; S
#adding dropout$ q! x: @& E' J5 Y" X7 g& J: g
model4.add(Dropout(0.2))
# R {& p4 X6 H" A: v: _#adding another Convolution layer
6 ]" B8 b$ u |model4.add(Conv2D(64,(3,3),activation='relu')): G0 L) c- Z* y) L
model4.add(MaxPool2D(2,2))
! P9 F1 q. Z* i( J8 Y, C" t#adding dropout$ y& E3 P. W' X0 {, w! A
model4.add(Dropout(0.2)). z9 H% z. O7 H8 m* G; I
model4.add(Flatten())3 A& P* Y( e. L# ^: H! L( S) b3 j
#adding dense layer x0 {4 z& R5 ?, C# |* H. I
model4.add(Dense(216,activation='relu'))4 u9 E* \( H" ^) e& u2 ^
#adding dropout
4 R z5 y6 X) Q$ H0 _1 }1 pmodel4.add(Dropout(0.2)). w# `6 S ^+ k
#adding output layer
. B3 h8 x( R2 J7 ^: O6 [model4.add(Dense(10,activation='softmax'))
9 j5 M6 J4 \0 Q. { }model4.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
. I0 d- U$ N1 Z9 c& Smodel4.fit(X_train,y_train,epochs=10)
5 M! \) F- U4 h' z# j0 b2 b0 i9 k. _. K! _ }3 H3 T( `' [' F5 p. j
5 g* ]1 G4 r* M
model4.evaluate(X_test,y_test)2 n ]2 u0 W- Y! K/ L- M: m
![]()
. G1 D0 {" e8 _4 U: h5 s. w通过这个模型,我们得到了76%的训练准确率(低于第一个模型),但我们得到了72%的测试准确率,这意味着过拟合的问题在一定程度上得到了解决。/ c6 R( P3 e7 G0 L5 ?$ B: i
. l r1 t$ T) S. Q/ o! ]7 \尾注& n3 f) P2 ^3 \: s
这就是我们在 Python 中实现 CNN 的方式。这里使用的数据集是一个简单的数据集,可用于学习目的,但一定要尝试在更大和更复杂的数据集上实现 CNN。这也将有助于发现更多挑战和解决方案。
* f9 j, j2 v k' D. P) ]. x2 k P+ ~# ] N m8 r3 {( O
& I% ]: ~" i6 n
: g: j, t( G0 p( a- M |