本文是基于Tensorflow的手写数字识别的项目最终篇,最终准确率为99.2%
这样截止到3/8,终于算是入门了一个深度学习项目-《基于Tensorflow的手写数字识别》
网络模型3层卷积,区别在于每次卷积后面加上了规范层:
该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1
(1)加速收敛 (2)控制过拟合,可以少用或不用Dropout和正则 (3)降低网络对初始化权重不敏感 (4)允许使用较大的学习率
首先记录一下我写代码遇到的坑:
按照教程写代码报错:
ValueError: Dimension (-1) must be in the range [0, 2), where 2 is the number of dimensions in the input. for 'metrics/categorical_accuracy/ArgMax' (op: 'ArgMax') with input shapes: [?,?], [].
后来才知道是这里的问题:
cnn_net.compile(loss='categorical_crossentropy',optimizer='adam',metrics=[metrics.categorical_accuracy])
把后面的metrics参数去掉就可以了(至于原因目前我也不太清楚):
cnn_net.compile(loss='categorical_crossentropy',optimizer='adam')
运行如下:
64/33600 [..............................] - ETA: 48:49 - loss: 2.6620
128/33600 [..............................] - ETA: 30:09 - loss: 3.2769
192/33600 [..............................] - ETA: 22:57 - loss: 3.5317
256/33600 [..............................] - ETA: 18:53 - loss: 3.2478
320/33600 [..............................] - ETA: 16:16 - loss: 2.9932
384/33600 [..............................] - ETA: 14:24 - loss: 2.7520
448/33600 [..............................] - ETA: 12:57 - loss: 2.5195
512/33600 [..............................] - ETA: 11:55 - loss: 2.4143
576/33600 [..............................] - ETA: 11:02 - loss: 2.2881
完整代码如下:
import numpy as np
import tensorflow as tf
import pandas as pd
from keras.models import Sequential
from keras.layers import Dense,Activation,Conv2D
from keras.layers import MaxPool2D,Flatten,Dropout,ZeroPadding2D,BatchNormalization
from keras.utils import np_utils
from keras import metrics
import keras
from keras.models import save_model,load_model
from keras.models import Model
df=pd.read_csv("train.csv")
#data由dataframe类型转换为矩阵类型
data=df.as_matrix()
df=None
# shuffle() 方法将序列的所有元素随机排序
np.random.shuffle(data)
x_train=data[:,1:]
x_train=x_train.reshape(data.shape[0],28,28,1).astype("float32")
x_train=x_train/255.0
#把训练的图片类型进行onehot编码
#将类别向量(从0到nb_classes的整数向量)映射为二值类别矩阵, 用于应用到以categorical_crossentropy为目标函数的模型中.
y_train=np_utils.to_categorical(data[:,0],10).astype("float32")
x_train_test=np.random.random((10,28,28,1))
y_train_test=keras.utils.to_categorical(np.random.randint(10,size=(10,1)),num_classes=10)
print(x_train.shape)
print(y_train.shape)
#设置相关参数
batch_size=64
n_filters=32
pool_size=(2,2)
#d定义网络
cnn_net=Sequential()
cnn_net.add(Conv2D(32,kernel_size=(3,3),strides=(1,1),input_shape=(28,28,1)))
cnn_net.add(Activation('relu'))
#第0轴沿着行的垂直往下,第1轴沿着列的方向水平延伸。
#该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1
cnn_net.add(BatchNormalization(epsilon=1e-6,axis=1))
cnn_net.add(MaxPool2D(pool_size=pool_size))
#对2D输入(如图片)的边界填充0,以控制卷积以后特征图的大小
cnn_net.add(ZeroPadding2D((1,1)))
cnn_net.add(Conv2D(48,kernel_size=(3,3)))
cnn_net.add(Activation('relu'))
#第0轴沿着行的垂直往下,第1轴沿着列的方向水平延伸。
#该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1
cnn_net.add(BatchNormalization(epsilon=1e-6,axis=1))
cnn_net.add(MaxPool2D(pool_size=pool_size))
#对2D输入(如图片)的边界填充0,以控制卷积以后特征图的大小
cnn_net.add(ZeroPadding2D((1,1)))
cnn_net.add(Conv2D(64,kernel_size=(2,2)))
cnn_net.add(Activation('relu'))
#第0轴沿着行的垂直往下,第1轴沿着列的方向水平延伸。
#该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1
cnn_net.add(BatchNormalization(epsilon=1e-6,axis=1))
cnn_net.add(MaxPool2D(pool_size=pool_size))
cnn_net.add(Dropout(0.25))
#Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。
cnn_net.add(Flatten())
cnn_net.add(Dense(3168))
cnn_net.add(Activation('relu'))
cnn_net.add(Dense(10))
cnn_net.add(Activation('softmax'))
#summary查看网络结构
cnn_net.summary()
cnn_net.compile(loss='categorical_crossentropy',optimizer='adam')
#训练模型
#validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等
cnn_net.fit(x_train,y_train,batch_size=batch_size,epochs=50,verbose=1,validation_split=0.2)
总之,通过keras框架,确实使得深度学习变得非常简单,比tensorflow要简单不少。