每当想要学习神经网络的时候,每当想要自己搭建一个神经网络的时候,每当看到别人的神经网络错综复杂就劝退的时候,不如尝试一下搭建一个最简单的CNN试试。或许会有那种搭积木的感觉。
mnist数据集
mnist手写数字数据集是一系列的28x28x1的灰度图片,如图所示:
环境搭建
我的环境如下:
Python 3.10.1
TensorFlow 2.9.1
具体的安装办法可以百度一下。
网络结构
我们经常把神经网络比作黑盒模型,那么黑盒就要有一个输入与输出,我们知道MNIST手写数字是一张张28*28像素的图片,那么输出就是对应的0-9的标签数字。
输出层
如果直接输出0-9,那么就会出现数字之间的相关性,比如1后面是2,在生成的神经网络的权重就会带有数字的顺序特征,所以一般的输出采用的是one-hot模式,就是用一个1维的矩阵来表示输出。
例如:
3:[0 0 0 1 0 0 0 0 0 0]
5:[0 0 0 0 0 1 0 0 0 0]
各个输出矩阵之间相互正交,乘积为0。
最后会用一个全连接层来将卷积运算之后的矩阵映射到one-hot上,并使用softmax将输出转换为概率。
输入层
输入层就是一个28x28x1的矩阵,其中矩阵的值是0-1之间的浮点数,表示手写数字的灰度特征。
中间层
中间部分就是卷积层以及池化层,这两个层不断的叠加以及传递数据,卷积层就是用带加权值的卷积核提取图片特征,而池化层的作用则是减小处理后矩阵的输出大小和降低过拟合。
大致的结构就是
卷积->池化->卷积->池化->卷积->全连接
注:网上抄的图,不完全准确。
具体代码
使用的是Keras深度学习框架,后端是TensorFlow后端。Keras使得神经网络的搭建变得异常简单。
导入数据并处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 from tensorflow.keras.datasets import mnistfrom tensorflow.keras.layers import Dense, Conv2D, MaxPooling2D, Flattenfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.utils import to_categorical(x_train, y_train), (x_test, y_test) = mnist.load_data() x_train = x_train.reshape((-1 , 28 , 28 , 1 )) x_train = x_train.astype('float32' )/255 y_train = to_categorical(y_train) x_test = x_test.reshape((-1 , 28 , 28 , 1 )) x_test = x_test.astype('float32' )/255 y_test = to_categorical(y_test) x_val = x_train[:10000 ] y_val = y_train[:10000 ] partial_x_train = x_train[10000 :] partial_y_train = y_train[10000 :]
注:有可能会报网络错误,导致数据集无法下载,可以自己下载minst数据集 ,然后跟py文件放在一起就可以了。
通过导入mnist数据集,并且经过一个简单的处理,得到一系列的28x28x1的归一化矩阵。并将数据集分为训练集、验证集和测试集。
使用Keras搭建网络
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 model = Sequential() model.add(Conv2D(32 , (3 , 3 ), padding='same' , activation='relu' , input_shape=(28 , 28 , 1 ))) model.add(MaxPooling2D((2 , 2 ))) model.add(Conv2D(64 , (3 , 3 ),padding='same' , activation='relu' )) model.add(MaxPooling2D((2 , 2 ))) model.add(Conv2D(64 , (3 , 3 ), padding='same' , activation='relu' )) model.add(Flatten()) model.add(Dense(64 , activation='relu' )) model.add(Dense(10 , activation='softmax' )) model.summary() model.compile (optimizer='adam' ,loss='categorical_crossentropy' ,metrics=['accuracy' ])
通过简单的添加已经建立连接,一个最简单的CNN神经网络就构建好了。
是准确率的判别,具体怎么选择可以参考知乎
开始训练
1 2 model.fit(partial_x_train, partial_y_train, validation_data=(x_val, y_val), epochs=5 , batch_size=64 )
通过如上方式可以训练出来的一个带加权值的神经网络,将手写数字输入进网络就可以得到结果。
当然,也可以通过model.save(file_path)
方式来保存以及通过model = load_model(file_path)
加载h5模型。
测试模型
最后,通过测试集来测试评估一下模型的准确性。
1 2 test_loss, test_acc = model.evaluate(x_test, y_test) print (str (test_acc*100 )+"%" )
当然,你也可以自己手写一个数字,然后通过将图片处理成28x28的灰度图,通过y_pred = model.predict(X_test,batch_size = 1)
来预测你手写的数字是什么。
结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 WARNING:tensorflow:From c:\users\debin\appdata\local\programs\python\python37\lib\site-packages\tensorflow\python\framework\op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version. Instructions for updating: Colocations handled automatically by placer. _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_1 (Conv2D) (None, 28, 28, 32) 320 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 14, 14, 32) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 14, 14, 64) 18496 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 7, 7, 64) 0 _________________________________________________________________ conv2d_3 (Conv2D) (None, 7, 7, 64) 36928 _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (None, 3, 3, 64) 0 _________________________________________________________________ conv2d_4 (Conv2D) (None, 3, 3, 64) 36928 _________________________________________________________________ flatten_1 (Flatten) (None, 576) 0 _________________________________________________________________ dense_1 (Dense) (None, 64) 36928 _________________________________________________________________ dense_2 (Dense) (None, 10) 650 ================================================================= Total params: 130,250 Trainable params: 130,250 Non-trainable params: 0 _________________________________________________________________ WARNING:tensorflow:From c:\users\debin\appdata\local\programs\python\python37\lib\site-packages\tensorflow\python\ops\math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version. Instructions for updating: Use tf.cast instead. Train on 50000 samples, validate on 10000 samples Epoch 1/5 2021-06-15 19:49:26.050750: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 50000/50000 [==============================] - 113s 2ms/step - loss: 0.1919 - acc: 0.9380 - val_loss: 0.0904 - val_acc: 0.9739 Epoch 2/5 50000/50000 [==============================] - 110s 2ms/step - loss: 0.0540 - acc: 0.9825 - val_loss: 0.0524 - val_acc: 0.9841 Epoch 3/5 50000/50000 [==============================] - 110s 2ms/step - loss: 0.0372 - acc: 0.9880 - val_loss: 0.0491 - val_acc: 0.9851 Epoch 4/5 50000/50000 [==============================] - 108s 2ms/step - loss: 0.0280 - acc: 0.9913 - val_loss: 0.0453 - val_acc: 0.9869 Epoch 5/5 50000/50000 [==============================] - 108s 2ms/step - loss: 0.0211 - acc: 0.9928 - val_loss: 0.0533 - val_acc: 0.9838 10000/10000 [==============================] - 7s 722us/step accuracy in test data is 98.72999999999999%
额,98.73%,对不起,打扰了。。。。
总结
使用Keras搭建神经网络相对于直接使用TensorFlow来搭建会简单很多,只需要将数据预处理,然后搭建起网络并选择合适的激活函数以及优化器,输出结果就可以了。总的来说还是很轻松的。
太久没更新了,趁端午假期赶紧更新一下,更新完假期刚好结束了。