使用卷积神经网络开发图像分类模型
& E. I+ @# R0 X( g: t) S$ K简介0 Z# O0 I3 P, v4 U% J) v+ W
& u/ T& M# s* f' K这篇文章是关于卷积网络、它的工作和组件: 在本文中,我们将使用卷积神经网络执行图像分类,并详细了解所有步骤。因此,如果你对此不熟悉,请继续阅读。
+ ~0 `2 I/ K. X
8 d3 u( c% }. ]) ^简而言之,CNN 是一种深度学习算法,也是适用于图像和视频的神经网络类型之一。我们可以从 CNN 中实现各种功能,其中一些是图像分类、图像识别、目标检测、人脸识别等等。; t; I, e9 ?- H3 O0 S; M/ a% e4 g
& ]7 V* f0 x. q6 Z5 c$ [' R
今天,我们将对CIFAR10 数据集执行图像分类,它是 Tensorflow 库的一部分。它由各种物体的图像组成,如船舶、青蛙、飞机、狗、汽车。该数据集共有 60,000 张彩色图像和 10 个标签。现在让我们进入编码部分。
! b3 E& K- f& ~: G# K6 ?& j3 Y9 u. k. Y( J- R' [& A) R
实施* ]" Z" R) F5 K7 r) y. n4 K2 v U, q& H
1 {* }, W9 l7 p( x6 k. c K& v# importing necessary libraries
6 [% Y% t. T3 g- J( V) H( ], Fimport numpy as np
* y0 z4 s. l+ C) u9 Ximport matplotlib.pyplot as plt
% j8 W+ }# g" J9 i; I$ M0 v%matplotlib inline
9 @5 V+ S k @; A# To convert to categorical data
7 r6 l& I, T# Wfrom tensorflow.keras.utils import to_categorical
1 f' e' w5 k0 h1 ?. Q" F#libraries for building model
& E3 u1 u9 \. O5 V) r- ^: H6 z' tfrom tensorflow.keras.models import Sequential
# d5 ]& c1 C, f2 C1 b0 Q; }9 J* J% u/ Efrom tensorflow.keras.layers import Dense, Conv2D, MaxPool2D, Dropout,Flatten: z/ }0 L/ H" R, d" L9 T
from tensorflow.keras.datasets import cifar10
$ N- l' B) ~, Q0 ^& ^
- }/ g0 K% q. Q4 e3 b- E$ }#loading the data
+ S9 ]0 G: y( S0 B! D. T(X_train, y_train), (X_test, y_test) = cifar10.load_data()
0 O" Y+ P" o$ h" }0 u% r0 k7 P
9 l" |; O4 m) Q8 l8 X探索性数据分析
. q: l T8 Z; _( _/ ? _$ m& B#shape of the dataset z# _, m" A7 m0 k7 l% H8 p
print(X_train.shape)
$ c% i' r) ? D, V; j$ P; |% M% B4 {& Rprint(y_train.shape) W* B- Z4 Q/ @
print(X_test.shape)9 \ i% Q1 k: E. z
print(y_test.shape)
. p! J; G2 ^0 Y# D# f# p" q2 `# a3 T: N# V* a6 K
9 r' o# l& o$ k% O
我们的训练数据有 50,000 张图像,测试数据有 10,000 张图像,大小为 32*32 和 3 个通道,即 RGB(红、绿、蓝)
2 {) `+ K, C: h6 [#checking the labels
' U6 G! o- ?3 H# C$ [" y8 unp.unique(y_train): [1 r2 |4 h$ K+ V5 }4 [
3 t5 K- v r5 j2 w8 R* c![]()
9 n0 I* w3 K2 W1 M, V#first image of training data
9 {( K& z# m( K: i3 b( ^plt.subplot(121)) K8 k9 h4 B* S6 Y
plt.imshow(X_train[0])
* M; T, P5 D( ~$ ~plt.title("Label : {}".format(y_train[0]))
' u7 J0 i; K( g* s6 M) v. Z8 R% s#first image of test data
# \' o& ^! z3 O8 k6 T* y* e/ ^plt.subplot(122), X+ J$ \2 ]$ W/ M2 U# N, f; H
plt.imshow(X_test[0])
/ V! U% S/ s5 H+ K' Bplt.title("Label : {}".format(y_test[0]));
* R) A' y8 X$ e1 f7 D0 Z2 N/ b5 v0 E$ H( K" R- F: w
) X9 w H1 S1 \1 o' d! T9 f
#visualizing the first 20 images in the dataset
) v( d" U$ u8 c0 L/ f; Dfor i in range(20):
. w+ x5 @1 j9 w* S$ g #subplot
F$ \2 `6 P: X3 X( N6 W- Q& q plt.subplot(5, 5, i+1)
0 V- e1 b( |* q V% v" _$ R0 H7 J: c6 G # plotting pixel data" U% D. `5 ]& c1 N& f6 J7 h
plt.imshow(X_train, cmap=plt.get_cmap('gray'))
6 t) L5 |- c* N" _# show the figure4 Y( w n: H0 D% Y/ M1 u6 C
plt.show() t% `$ c% Q# s3 g. B
3 f6 M* b3 m/ z: i, b, j * h- G7 Q; J. k4 e R H1 A/ Y
预处理数据对于数据预处理,我们只需要在这里执行两个步骤,首先是缩放图像的像素值到0到1之间,然后是将标签从 2D 重塑为 1D
6 v" f/ q: ^1 o: f: G+ O# Scale the data to lie between 0 to 1
, v$ I% [# f: z- z# Z* ]X_train = X_train/2557 M) G0 [3 i! r2 I! O( k
X_test = X_test/255
; ` S# @/ O. A5 _0 kprint(X_train)& z7 [! h. S1 d. K# @% D4 T. D
8 Z- n. f! A5 m7 [" W$ s- k# K
![]()
& s& f1 p0 C; e, `0 N6 ?1 H; A5 R#reshaping the train and test lables to 1D. @% A7 z% W8 b" h* c' R
y_train = y_train.reshape(-1,)
3 p! i0 X8 b7 \8 J; l! J8 J: ]y_test = y_test.reshape(-1,)
6 k( R$ }5 P" X: _1 i) C4 J1 y& E3 n; h! s6 h4 L. P+ n% m7 g4 P
我们在上图中可以看到,图像的像素值已经进行了缩放,其数值在 0 到 1 之间,并且标签也进行了重塑。数据已准备好建模,现在让我们构建 CNN 模型。# o0 B1 r; F! O3 K
模型搭建正如我们之前讨论的,深度学习模型的构建分为 5 个步骤,即定义模型、编译模型、拟合模型、评估模型和进行预测,这也是我们在这里要做的。 : e/ r% @/ s- h( g# S
model=Sequential(), X7 I& V: A4 v/ G4 J% L
#adding the first Convolution layer1 q) u; V7 J1 Q$ t2 [
model.add(Conv2D(32,(3,3),activation='relu',input_shape=(32,32,3)))
/ n0 f- e: p/ h2 a2 J4 v#adding Max pooling layer1 n N2 v/ _; K: o5 T. X
model.add(MaxPool2D(2,2))* x6 ^7 F0 M2 m! k* r# A
#adding another Convolution layer7 s/ r8 N& C1 \& J6 @, x8 U
model.add(Conv2D(64,(3,3),activation='relu')): h& ^3 ^6 C: N! @; i* ]
model.add(MaxPool2D(2,2))
% l# W% ` F1 Q- r/ X' Umodel.add(Flatten())! p4 f* b5 e g* q) C+ w8 w7 b9 L
#adding dense layer
3 V: i( N, v; ^5 R) W- e: [model.add(Dense(216,activation='relu'))5 t- ~9 x- v! Z) [8 Y
#adding output layer
5 Z; P/ h8 V8 ?7 [, Q2 u( jmodel.add(Dense(10,activation='softmax'))
3 O8 Q, |! u) b( Q5 J+ |
5 V0 G* Z9 O6 [( L8 z" Q我们添加了第一个带有 32 个大小为 (3*3) 的过滤器的卷积层,使用的激活函数是 Relu,并为模型提供输入形状。
& l4 F0 m% H8 E7 d) w4 P$ y% B
; `2 y$ {2 ?, i8 e# }. s8 Z9 V接下来添加了大小为 (2*2)的Max Pooling 层。最大池化有助于减少维度。CNN 组件的解释请参考:https://www.analyticsvidhya.com/blog/2021/08/beginners-guide-to-convolutional-neural-network-with-implementation-in-python/% {$ E& G }5 i5 U: N4 X! A
9 H6 F' A) y, p& O% W" t1 |然后我们又添加了一个卷积层, 其中包含 64 个大小为(3*3) 的过滤器 和一个大小为 (2*2)的 最大池化层
8 M4 }; L$ Y. I( O* k7 A
; p" K, |% I+ g) X- c在下一步中,我们将层展平以将它们传递到 Dense 层,并添加了一个包含 216 个神经元的Dense 层。
' H6 C! A' A9 O. n7 J. ^, I# V2 ]9 E* y; X, O
最后,输出层添加了一个 softmax 激活函数,因为我们有 10 个标签。- G: x$ Q7 l& Z
+ ^% ?4 g1 s4 E: x! x" s6 w# B l
第 2 步:编译模型 q& T% u9 u$ I
model.compile(optimizer='rmsprop',loss='sparse_categorical_crossentropy',metrics=['accuracy'])* B+ W0 \" R% ~# y0 U4 S
& e: f* Q- h; ]0 B# W
第 3 步:拟合模型model.fit(X_train,y_train,epochs=10)
& c" }; E. k2 Y. a( O" R$ o+ Z4 y 9 s2 m/ G$ I% J. J; F2 u; Q# h
" ^: u: J& y! a u5 Y( N+ v- t
如上图所示,我们的准确率为 89%,损失为 0.31。让我们看看测试数据的准确性。
0 I) K8 b$ B, j# z+ M第 4 步:评估模型model.evaluate(X_test,y_test), b/ U: H/ h& N# K$ U. Z
! K) m, B& |, ~. z( a1 K
5 ~ M/ V. ?% F' Z: G& [7 S. F测试数据的准确率为 69%,与训练数据相比非常低,这意味着我们的模型过度拟合。
: V ^% z- J0 z, G) c% P" g( `第 5 步:进行预测! G( C5 a" ^* g' Q8 v
pred=model.predict(X_test)
6 ~+ m9 B" x+ G" a' H% M#printing the first element from predicted data; M" v' y4 v% X3 k* Z
print(pred[0])
* D" J# O1 M1 ]- S/ z( C0 k' {9 L#printing the index of
- N5 k, b0 n1 Cprint('Index:',np.argmax(pred[0])); g# I3 E) i: j' z( d+ o4 r
% y5 ~) P7 H! o1 I8 ]![]()
7 }/ ]' T- T" {1 j7 L* `, c/ h2 B+ `7 K& y+ ]
因此,预测函数给出的是所有10个标签的概率值,概率最高的标签是最终预测。在我们的例子中,我们得到了第三个索引处的标签作为预测。 将预测值与实际值进行比较以查看模型执行的正确程度。 在下图中,我们可以看到预测值与实际值的差异。 y_classes = [np.argmax(element) for element in pred]; l! G3 X k y8 u& M
print('Predicted_values:',y_classes[:10])& J+ g9 n( x* ~( n
print('Actual_values:',y_test[:10])
6 R/ ?& l: y0 ? d
; E4 N" i6 p9 F* a& ^8 j![]()
8 T, R @2 l' N+ z当我们看到我们的模型过度拟合时,我们可以使用一些额外的步骤来提高模型性能并减少过度拟合,例如向模型添加 Dropouts或执行数据增强,因为过度拟合问题也可能是由于可用数据量较少。 在这里,我将展示我们如何使用 Dropout 来减少过拟合。我将为此定义一个新模型。 * J Y# y+ Y3 O8 ]3 p: T" q+ x
model4=Sequential()
4 g: }; @6 R+ }+ ?+ ~7 J* n#adding the first Convolution layer
& x+ k4 J1 l C jmodel4.add(Conv2D(32,(3,3),activation='relu',input_shape=(32,32,3)))
0 x& t) n9 \) ]' N1 p3 C#adding Max pooling layer
/ `8 Y' g2 @5 E# G# Hmodel4.add(MaxPool2D(2,2))" d5 z; h; Z, O" N- j" G% l
#adding dropout! X, s+ S; L1 }8 F
model4.add(Dropout(0.2))# W3 ?! K- ? y6 d( ]/ Q: w/ u
#adding another Convolution layer
* ^9 h$ Y# _/ i2 f+ g( T3 V) [model4.add(Conv2D(64,(3,3),activation='relu'))
7 ~5 S8 f8 p$ b8 U: {6 p: jmodel4.add(MaxPool2D(2,2))/ R- H2 h- r7 M; ]7 k, m
#adding dropout
; b. B3 a6 H$ p; F" Hmodel4.add(Dropout(0.2))& k; w# {/ n7 g+ w
model4.add(Flatten())
. h- J6 m1 C' i9 p& m#adding dense layer
: W1 }) M8 K, b/ U% v8 ~model4.add(Dense(216,activation='relu'))
3 H2 n2 N' T0 t, N. y. O#adding dropout# r& Q$ [" c8 V" q% Y
model4.add(Dropout(0.2))1 Z& `9 j2 G- ?+ k+ x; x' j
#adding output layer5 X9 C3 b4 U9 p- o
model4.add(Dense(10,activation='softmax'))7 L9 x2 |+ D4 y; a$ P
model4.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
" P: G4 Z6 x5 [$ [model4.fit(X_train,y_train,epochs=10)/ O! _; o! |6 o* t3 h
: \$ _8 d5 e2 v0 ~8 r2 |
9 x w# C2 l5 ?. V: j+ W( Y
model4.evaluate(X_test,y_test)" z5 T5 R5 G- l; i1 z
![]()
& i" `2 o0 L2 c1 O/ R& A, q通过这个模型,我们得到了76%的训练准确率(低于第一个模型),但我们得到了72%的测试准确率,这意味着过拟合的问题在一定程度上得到了解决。# A, ~8 N8 G ]6 ]5 h# d5 J2 [
* @: P n8 T3 M! D$ S8 W尾注7 x* p9 \$ o+ M. I4 H. C$ x
这就是我们在 Python 中实现 CNN 的方式。这里使用的数据集是一个简单的数据集,可用于学习目的,但一定要尝试在更大和更复杂的数据集上实现 CNN。这也将有助于发现更多挑战和解决方案。
% n% g0 F2 o) v& C* D4 ~2 e2 `6 ^7 R6 e& m0 |( S
8 y) C/ s; C7 t$ D6 B6 A! Z
' l7 w( j Z( Y; \" W I
|