使用卷积神经网络开发图像分类模型
! L' c0 v1 k$ V1 A2 v9 s# S简介0 U. O' ` ], \7 v9 L$ V5 z" W
4 }- t& e o* B这篇文章是关于卷积网络、它的工作和组件: 在本文中,我们将使用卷积神经网络执行图像分类,并详细了解所有步骤。因此,如果你对此不熟悉,请继续阅读。( k. r1 j" t* p/ N1 X! p# ^+ ]
9 W4 k" Z! g0 o+ a7 I
简而言之,CNN 是一种深度学习算法,也是适用于图像和视频的神经网络类型之一。我们可以从 CNN 中实现各种功能,其中一些是图像分类、图像识别、目标检测、人脸识别等等。
+ S( R# a7 ]* s% }, t) W* V, N, G; k: G8 Y5 A( q
今天,我们将对CIFAR10 数据集执行图像分类,它是 Tensorflow 库的一部分。它由各种物体的图像组成,如船舶、青蛙、飞机、狗、汽车。该数据集共有 60,000 张彩色图像和 10 个标签。现在让我们进入编码部分。1 N$ E$ a. m% K( g+ |# m/ ]4 H
( p# I5 `9 }0 c2 P实施5 A$ c1 ^* M: U# ]
$ ?# f* T% W8 u! w% }; @
# importing necessary libraries
5 ?" V* c0 n+ c, N$ m" @" himport numpy as np# R, Q5 V5 L9 S5 `
import matplotlib.pyplot as plt
. D) b. }; o9 U# P) L+ o%matplotlib inline; |1 T4 v& s' J% b G
# To convert to categorical data6 g8 V) B6 q5 F9 Y$ G6 [* E
from tensorflow.keras.utils import to_categorical
* x# H; K; m( Q+ l7 R#libraries for building model
. Q; S, I/ |8 Y* Lfrom tensorflow.keras.models import Sequential4 R, j7 }$ q' A9 g G
from tensorflow.keras.layers import Dense, Conv2D, MaxPool2D, Dropout,Flatten' b& V, T7 K% I# b* n
from tensorflow.keras.datasets import cifar10
. T* s, g: Q& h/ I# ~5 D3 M p0 c. o) T( k7 e
#loading the data" ]3 Y- a, h: Z9 Q
(X_train, y_train), (X_test, y_test) = cifar10.load_data(): O" a+ H& j3 [7 l% u, ?1 E- ~
# p8 t* k, i D3 W* z+ ?7 _6 h/ r1 ?探索性数据分析
5 h- A3 f' L! }3 s4 c#shape of the dataset
4 M% i+ A1 d& C, gprint(X_train.shape)
: ?9 Q0 i- o3 f9 bprint(y_train.shape)$ N* _4 K$ J1 t/ M. L. [( k
print(X_test.shape): x3 e# f7 Z& n8 K3 i6 b/ P7 v. K
print(y_test.shape)% I- z& u& J8 E$ }: S4 I* K5 ^6 a
; C6 {- \/ d! @8 J* q4 V# V/ | 4 N- R E: ~; \% V' Z: ~
我们的训练数据有 50,000 张图像,测试数据有 10,000 张图像,大小为 32*32 和 3 个通道,即 RGB(红、绿、蓝)
: y( r, l3 G9 ~( B#checking the labels - T; b8 H R4 n G' T. u
np.unique(y_train)
/ |- h0 \9 w$ ?1 K& D3 O# {0 [ H7 d1 V) T* W$ x9 Q
![]()
0 ]/ M. W, I& R: O% R* ]: _ @#first image of training data! a4 e& V. ~) D9 y" b( N4 l1 L
plt.subplot(121)
/ v% R" g* Q" R G* cplt.imshow(X_train[0])
/ P. [2 g0 I9 T4 i( @plt.title("Label : {}".format(y_train[0]))
. g- k4 A: [" w" S* Q#first image of test data
) C, i2 `0 F; l# k+ Uplt.subplot(122)0 v! I2 F3 C+ M! G0 R9 k
plt.imshow(X_test[0])
7 o1 E: O1 u4 U1 _, X6 Gplt.title("Label : {}".format(y_test[0]));
@3 j+ t7 f$ a) a9 v7 j! x) y* |- M5 e" V: G# E1 R3 r
![]()
, m8 [5 B$ ~- g, k& T) M( v K#visualizing the first 20 images in the dataset& h- _8 i3 {3 K& a4 ^0 x
for i in range(20):
, V& l, Q; m# b$ w- ?0 g* W: P: H- `+ x #subplot
0 ]% |$ T7 i& `, [, T3 P plt.subplot(5, 5, i+1)1 Z/ D1 a' x: X" i8 z3 p' Z8 g* C
# plotting pixel data; h: D0 z& Z, ]- F% k
plt.imshow(X_train, cmap=plt.get_cmap('gray'))$ t j* |# F5 u5 h( @" u
# show the figure8 ?' N$ p X: F/ Z6 n8 p6 Z8 O6 q
plt.show()* x/ l( R: [0 l( v" P9 P* h: N2 k
" z0 V- q- n* k& s1 l' N% E7 F![]()
1 G/ B" r: R4 D& V( u预处理数据对于数据预处理,我们只需要在这里执行两个步骤,首先是缩放图像的像素值到0到1之间,然后是将标签从 2D 重塑为 1D
/ q+ i ]* V! Q9 N" x/ m# ]) l# Scale the data to lie between 0 to 10 g& z# W! R3 p: \! e! O# t2 O0 D! v8 E* m
X_train = X_train/255) R* M3 y1 g( ~7 x
X_test = X_test/255- B. z0 w1 R8 A' y3 {
print(X_train) E& p; X, j1 M! q$ M0 j# {7 B
5 ?; e5 H S8 w % C2 A, X& q, p- n, d( Y4 N: |5 W6 D0 }
#reshaping the train and test lables to 1D
" R7 l/ v z- `2 _: Y6 b: m( Zy_train = y_train.reshape(-1,)+ d: N& ^! K5 z4 C+ x
y_test = y_test.reshape(-1,)
; V/ H. W$ w4 c0 N/ i
3 k A- } A5 g! |0 I j5 G4 o* ^我们在上图中可以看到,图像的像素值已经进行了缩放,其数值在 0 到 1 之间,并且标签也进行了重塑。数据已准备好建模,现在让我们构建 CNN 模型。$ @1 O. F. o" v: h$ _9 k8 b
模型搭建正如我们之前讨论的,深度学习模型的构建分为 5 个步骤,即定义模型、编译模型、拟合模型、评估模型和进行预测,这也是我们在这里要做的。
5 D& W6 x! Y% J1 Pmodel=Sequential()
. L' l$ z/ T& w) k7 u. E0 J; Q#adding the first Convolution layer
7 v) X7 |/ O' U* N- v" H/ Y7 Mmodel.add(Conv2D(32,(3,3),activation='relu',input_shape=(32,32,3)))1 E6 g8 ?4 n4 f* \+ R
#adding Max pooling layer
d3 k8 M4 n9 t8 V" x2 r5 ~. Xmodel.add(MaxPool2D(2,2))- f5 c3 w/ o; P! R% V% W. }
#adding another Convolution layer6 e2 b- U& ~6 Z4 L! C9 v! k- P
model.add(Conv2D(64,(3,3),activation='relu'))9 I: S) \. g: ]! H a+ l
model.add(MaxPool2D(2,2))
) G" ?- X9 ]" y3 D s, S1 C) I+ Rmodel.add(Flatten())
4 G& F8 Y) e( \$ \2 ^#adding dense layer
+ ?5 H" |& E: W: L3 m. Omodel.add(Dense(216,activation='relu'))
3 }" X. _3 r; S" b9 N#adding output layer
. h& |! @7 C3 M0 _6 _; q' ^model.add(Dense(10,activation='softmax'))6 O, y7 P; ~* R0 O. i; T
" ?& E% z& M2 }: S' v; L我们添加了第一个带有 32 个大小为 (3*3) 的过滤器的卷积层,使用的激活函数是 Relu,并为模型提供输入形状。
3 e K' N& O4 N6 A$ i4 Q4 ]; T8 t; U
# f) P1 R7 i2 |9 X1 k接下来添加了大小为 (2*2)的Max Pooling 层。最大池化有助于减少维度。CNN 组件的解释请参考:https://www.analyticsvidhya.com/blog/2021/08/beginners-guide-to-convolutional-neural-network-with-implementation-in-python/# n% {1 G3 H4 t3 f& g
' r5 n/ b, d8 ]# @$ O0 I: c0 J* I然后我们又添加了一个卷积层, 其中包含 64 个大小为(3*3) 的过滤器 和一个大小为 (2*2)的 最大池化层" t) V/ t; v* l- V
' o2 S2 f$ q1 ` w
在下一步中,我们将层展平以将它们传递到 Dense 层,并添加了一个包含 216 个神经元的Dense 层。
7 D0 B) s. k/ ?$ i0 O4 W% u& S$ `
" ~. b2 |: J& U% k. N0 S5 X最后,输出层添加了一个 softmax 激活函数,因为我们有 10 个标签。
4 s, m9 v" g% D. J$ \5 ]! H+ K+ d+ G
第 2 步:编译模型" G' U8 g5 H8 |; w# t4 ~' H
model.compile(optimizer='rmsprop',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
! t j1 x2 E& S" j" n& {5 m- _7 ?/ m, y9 X6 O" Y n* E
第 3 步:拟合模型model.fit(X_train,y_train,epochs=10)! R; S+ L8 n. a# |3 z; y/ T; w
. h7 P* E7 P2 M/ l2 E
- }! ?$ i8 l; u d! d" x( G
如上图所示,我们的准确率为 89%,损失为 0.31。让我们看看测试数据的准确性。
4 I0 M- L" i$ ]0 |" l- x第 4 步:评估模型model.evaluate(X_test,y_test)
& I# L5 M4 b+ Y5 r- i & M" o( e$ @3 d. m, i
1 N& R% n" T) T, c
测试数据的准确率为 69%,与训练数据相比非常低,这意味着我们的模型过度拟合。
! T8 j5 X, J# J, Y, W第 5 步:进行预测
- g( e4 R$ ^0 \pred=model.predict(X_test)
' F; ]5 z$ r+ D0 s, X3 c#printing the first element from predicted data
. h5 C" I8 ?% k: b3 I N! [print(pred[0])3 d( n6 r* Y5 M
#printing the index of
; P, N4 d3 X3 e: Y7 O6 S" sprint('Index:',np.argmax(pred[0]))( l0 a' g1 I9 D0 K# o
0 W5 \5 N6 R" p6 Z! b; r6 F$ c7 c![]()
; Z2 S* _6 V: e9 T! M% m6 g% `4 F8 y6 i/ }2 M5 J4 S5 q2 e8 s1 k
因此,预测函数给出的是所有10个标签的概率值,概率最高的标签是最终预测。在我们的例子中,我们得到了第三个索引处的标签作为预测。 将预测值与实际值进行比较以查看模型执行的正确程度。 在下图中,我们可以看到预测值与实际值的差异。 y_classes = [np.argmax(element) for element in pred]% H; c1 V+ k+ r! _6 B
print('Predicted_values:',y_classes[:10])5 P @( f8 C/ h
print('Actual_values:',y_test[:10]): q" S7 s7 s+ o: t. O9 K% O; v# u
% `% G' s. q( L, R0 E1 u0 ]![]()
7 @% [/ Z6 D) F当我们看到我们的模型过度拟合时,我们可以使用一些额外的步骤来提高模型性能并减少过度拟合,例如向模型添加 Dropouts或执行数据增强,因为过度拟合问题也可能是由于可用数据量较少。 在这里,我将展示我们如何使用 Dropout 来减少过拟合。我将为此定义一个新模型。
/ h! e0 `- I( U! Q. a1 Smodel4=Sequential()4 X3 ~+ V6 z: A& B
#adding the first Convolution layer
; B5 j+ Q+ e7 [4 a" Hmodel4.add(Conv2D(32,(3,3),activation='relu',input_shape=(32,32,3)))
) ^( ]; _2 e% S7 L! y$ ~3 p7 T8 h#adding Max pooling layer# o- u4 L1 s% ` f, }" m
model4.add(MaxPool2D(2,2))
0 O# w4 I: o0 k" e v#adding dropout
- d0 x8 x4 {- S2 `# g+ K! umodel4.add(Dropout(0.2))
$ {3 W5 J* O2 o# B4 n. w#adding another Convolution layer
2 T' `, ~) _1 [7 s* U. wmodel4.add(Conv2D(64,(3,3),activation='relu')): G. \! C" ? N, M- O6 }/ u( \0 S; S
model4.add(MaxPool2D(2,2)). i& _5 R( y K& W) w7 {& ~
#adding dropout
2 l& v/ g3 Q: _& ?8 hmodel4.add(Dropout(0.2))8 j0 h! @2 h2 m; K) X2 z# l* ]) {5 n
model4.add(Flatten())+ V1 T% L6 D' c! w2 M/ a( ^6 M+ `2 N
#adding dense layer: _( j7 h& ~2 s/ F; L5 G
model4.add(Dense(216,activation='relu'))7 T, U$ N$ g; |3 ?" M/ ?( D
#adding dropout, ~4 h) I0 u% ~
model4.add(Dropout(0.2))( N9 U& b: E) {% w
#adding output layer$ I: ?3 S* r9 B2 ]; x* S
model4.add(Dense(10,activation='softmax'))
8 Q( Y/ M S" ^. m6 _3 B4 xmodel4.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
+ m4 w) ]( b8 W' X: d1 I/ kmodel4.fit(X_train,y_train,epochs=10)/ i; ]" p6 D$ \, ]2 H8 i9 W) V4 |
! w( b& ?. ]2 i% B - b- u Q/ G! N( l& k6 o# t
model4.evaluate(X_test,y_test)8 N4 r4 v5 @$ x( U
![]()
* f, A5 I- @+ P' s8 i: I通过这个模型,我们得到了76%的训练准确率(低于第一个模型),但我们得到了72%的测试准确率,这意味着过拟合的问题在一定程度上得到了解决。
?! ~$ U# J( N4 F9 [
; w" A& X$ j, P! |, f尾注
0 I& I7 J0 |1 B; A5 Z5 f6 a4 M* m这就是我们在 Python 中实现 CNN 的方式。这里使用的数据集是一个简单的数据集,可用于学习目的,但一定要尝试在更大和更复杂的数据集上实现 CNN。这也将有助于发现更多挑战和解决方案。" M* Z" `' d3 \& g1 G0 t5 G
) c5 O1 r# ^/ A$ d% y& I/ i$ T. O& ]
5 {) b- V, y/ o1 ?8 E
, J4 o6 l3 X' F0 Q, b+ l4 b |