在学习手写体识别的时候,看到一些B站的教学视频发现,很多用TensorFlow完成的手写体识别,在下载数据集的时候会报错,无法使用,这是因为TensorFlow在维护的时候,处理的不是很好,无法使用input_data,有解决办法,但是太麻烦了,Keras是在TensorFlow之上 运行的,采用Keras能省去很多麻烦。
手写体的具体实现直接上代码;具体操作看注释。
from numpy import mean
from numpy import std
from matplotlib import pyplot
from sklearn.model_selection import KFold
import tensorflow as tf
from tensorflow.keras import utils
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import MaxPooling2D
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Flatten
from tensorflow.keras.optimizers import SGD
#load train & test data
def load_dataset():
#加载minister手写体数据 训练集和测试集都有两个数据一个是图像一个是标签表示这个是什么数字
(trainX,trainY),(testX,testY)=tf.keras.datasets.mnist.load_data()
print("trainX shape",trainX.shape) #(60000, 28, 28)
print("trainY shape",trainY.shape)
#reshape dataset to have a signal channel
trainX=trainX.reshape((trainX.shape[0],28,28,1))
testX=testX.reshape((testX.shape[0],28,28,1))
#one hot编码
trainY=to_categorical(trainY)
testY=to_categorical(testY)
#打印前5行one hot represent是什么样的
for i in range(5):
print("trainY",trainY[i])
return trainX,trainY,testX,testY
#线性处理 scale pixels
def prep_pixels(train,test):
#把样本中的值转化为浮点数
train_norm=train.astype('float32')
test_norm=test.astype('float32')
#可以像我们第一段程序那样把0转为0.01 1转为0.99,也可以不转
#normallize to range 0-1
train_norm=train_norm/255.0
test_norm=test_norm/255.0
return train_norm,test_norm
#配置学习模型
def define_model():
model=Sequential()
#8个(3,3)的卷积核 激活函数relu,kernel_initializer初始化卷积核的方法
model.add(Conv2D(8,(3,3),activation='relu',kernel_initializer='he_uniform',input_shape=(28,28,1)))
#convolution output number of parameter = 26 x 26 x 8
model.add(MaxPooling2D((2,2))) #这里的stride相当于2,就像卷积一样在这里会以2的步长进行移动
#(26-2)/2+1=13 13x13x8 没有padding,所以不用加padding
#formula for calucate the number of output for each layer
#output = (input - kernel+2*padding)/Stride + 1 输出矩阵大小的求解公式
model.add(Flatten())
#flatten作用:Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。
#隐含层
model.add(Dense(120,activation='relu',kernel_initializer='he_uniform'))
model.add(Dense(10,activation='softmax')) #输出节点10个
#compile the model
#定义优化器为SGD
#出SGD外常用的优化器还有RMSprop,Adam,adadelte,adagrad,adamax,Nadam,Ftrl
#monentum项能够在相关方向加速SGD
#对于monentum参数可以看看这篇博客;https://blog.csdn.net/fengbingchun/article/details/124648766?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166576412016800182168388%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166576412016800182168388&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-124648766-null-null.142^v56^opensearch_v2,201^v3^add_ask&utm_term=sgd%E4%B8%ADmomentum%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE&spm=1018.2226.3001.4187
#metircs是对模型有效性,performance的测量classification 问题与regression 问题的测量方法不同
#Keras对classification问题支持的测量包括:Binary Accoracy,Categorical Accuracy,Saprese Categorical Accuracy,Top K,Sparese Top K
opt=SGD(lr=0.01,momentum=0.9) #lr指学习率
model.compile(optimizer=opt,loss='categorical_crossentropy',metrics=['accuracy'])
print(model.summary())
return model
def evaluate_model(dataX,dataY,n_folds=5):
scores,histories=list(),list()
#prepare cross validation 准备交叉验证
kfold=KFold(n_folds,shuffle=True,random_state=1) #random_state相当于随机数种子,保证每次随机运行的结果一样
#enumerate splite
for train_ix,test_ix in kfold.split(dataX):
model=define_model()
#select rows for train or test
trainX,trainY,testX,testY=dataX[train_ix],dataY[train_ix],dataX[test_ix],dataY[test_ix]
#fit model
history=model.fit(trainX,trainY,epochs=10,batch_size=60,validation_data=(testX,testY),verbose=0)
#增加几个打印语句方便调试和程序理解
print(history.history.keys())
#evalute model
loss,acc=model.evaluate(testX,testY,verbose=0)
print('>%.3f'%(acc*100))
#stores scores
scores.append(acc)
histories.append(history)
print("scores",scores)
print("histories.len",len(histories))
return scores,histories
#plot diagnostic learning curves
def summarize_diagnostics(histories):
for i in range(len(histories)):
#plot loss
pyplot.subplot(2,1,1)
pyplot.title('Cross Entropy loss')
pyplot.plot(histories[i].histories['loss'],color='blue',label='train')
pyplot.plot(histories[i].histories['val_loss'],color='orange',lable='test')
pyplot.ylabel('loss')
pyplot.xlabel('epoch')
pyplot.legend(['train','test'],loc='upper right')
#plot accuracy
pyplot.subplot(2,1,2)
pyplot.title("classification accuracy")
pyplot.plot(histories[i].histories['accuracy'],color='blue',lable='train')
pyplot.plot(histories[i].histories['val_accuracy'],color='orange',lable='test')
pyplot.ylabel('accuracy')
pyplot.xlabel('epoch')
pyplot.legend(['train', 'test'], loc='upper right')
pyplot.show()
def summarize_performance(scores):
#print summary
print('Accuracy: mean= %.3f, n=%d '% (mean(scores)*100,std(scores)*100),len(scores))
# box and whisker plots of results
pyplot.boxplot(scores)
pyplot.show()
#run the test harness for evaluating a model
def run_mymodel_test():
#加载数据集
trainX,trainY,testX,testY = load_dataset()
#数据集,像素预处理,转化为浮点数,并压缩到0-1之前
trainX,testX=prep_pixels(trainX,testX)
#模型评估,其中先构造模型再调用学习
scores,histories=evaluate_model(trainX,trainY)
#打印学习曲线,看学习的过程趋势
summarize_diagnostics(histories)
#总结模型的performance
summarize_performance(scores)
#主程序入口
run_mymodel_test()
参考:ANN第三课 -卷积神经网络实现手写体识别的python程序 - 使用keras+tensorflow_哔哩哔哩_bilibili