1、使用softmax回归对mnist数据集进行分类,准确率大概为0.92左右
2、使用多层感知机(3层)对mnist数据集分类,准确率大概为0,98
2、使用多层感知机(3层)对mnist数据集分类,准确率大概为0,98
3、使用CNN对mnist进行分类,准确率为0.99
#coding=utf-8 import pickle import numpy as np import matplotlib.pyplot as plt import tensorflow as tf import time # 定义一个mnist数据集的类 class mnistReader(): def __init__(self,mnistPath,onehot=True): self.mnistPath=mnistPath self.onehot=onehot self.batch_index=0 print ('read:',self.mnistPath) fo = open(self.mnistPath, 'rb') self.train_set,self.valid_set,self.test_set = pickle.load(fo,encoding='bytes') fo.close() self.data_label_train=list(zip(self.train_set[0],self.train_set[1])) np.random.shuffle(self.data_label_train) # 打印一些数据集的信息 def data_info(self): # train_set是一个元组,元组第一个元素是图片像素,元组第二个元素是图片对应的数字 print ("type:",type(self.train_set)) rdata = self.train_set[0] rlabel=self.train_set[1] print ("train_set:",type(rdata)) #可以看到训练集大小为(50000,28*28)的二维矩阵 print ("train_label:",type(rlabel)) # 可以看到训练集标签大小为(50000,)的数组 # 打印数据集的图片 def show_image(self): rdata,rlabel = self.train_set pic=np.reshape(rdata[0],(28,28)) print (pic) print (rlabel[0]) plt.imshow(pic) plt.show() # 获取下一个训练集的batch def next_train_batch(self,batch_size=100): if self.batch_index < len(self.data_label_train)/batch_size: print ("batch_index:",self.batch_index ) datum=self.data_label_train[self.batch_index*batch_size:(self.batch_index+1)*batch_size] self.batch_index+=1 return self._decode(datum,self.onehot) else: self.batch_index=0 np.random.shuffle(self.data_label_train) datum=self.data_label_train[self.batch_index*batch_size:(self.batch_index+1)*batch_size] self.batch_index+=1 return self._decode(datum,self.onehot) # 获取测试集的数据 def test_data(self): tdata,tlabel=self.test_set data_label_test=list(zip(tdata,tlabel)) return self._decode(data_label_test,self.onehot) # 把一个batch的训练数据转换为可以放入模型训练的数据 def _decode(self,datum,onehot): rdata=list() # batch训练数据 rlabel=list() if onehot: for d,l in datum: rdata.append(np.reshape(d,[784])) # 转变形状为:一维向量 hot=np.zeros(10) hot[int(l)]=1 # label设为100维的one-hot向量 rlabel.append(hot) else: for d,l in datum: rdata.append(np.reshape(d,[784])) rlabel.append(int(l)) return rdata,rlabel # ------------softmax回归的模型------------------ def softmax_model(): sess=tf.InteractiveSession() """ placeholder是输入数据的地方,第一个参数是数据类型,第二个参数代表tensor的shape,也就是数据的尺寸 ,这里None代表不限条数的输入,784代表每条输入是一个784维的向量 """ x=tf.placeholder(tf.float32,[None,784],name='x') # 训练集的输入数据 w=tf.Variable(tf.zeros([784,10])) # softmax回归的权重值 b=tf.Variable(tf.zeros([10])) # softmax回归的参数值 y=tf.nn.softmax(tf.matmul(x,w)+b,name='y') # softmax回归的公式定义 y_=tf.placeholder(tf.float32,[None,10],name='y_') # 真实的label输入 cross_entropy=tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y),reduction_indices=[1])) #交叉熵的定义,类似损失函数, train_step=tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) # 梯度下降法,学习率为0.5 tf.global_variables_initializer().run() # 初始化全局变量 mnist=mnistReader(mnistPath="E:/testdata/mnist.pkl") # 开始训练数据 for i in range(1000): batch_x,batch_y=mnist.next_train_batch() train_step.run({x:batch_x,y_:batch_y}) # 训练完成后计算准确率 correction_prediction=tf.equal(tf.argmax(y,1),tf.argmax(y_,1)) # 预测结果类别和真实类别是否相同 accuracy=tf.reduce_mean(tf.cast(correction_prediction,tf.float32)) # 转换为float值,并求平均 test_data,test_label=mnist.test_data() # 获得测试数据和训练数据 print (accuracy.eval({x:test_data,y_:test_label})) # 将测试数据输入评测流程accuracy,计算准确率 # 保存模型 saver = tf.train.Saver() save_path = saver.save(sess,"./Softmax/model.ckpt") print("save model:{0} Finished".format(save_path)) # 加载训练好的 softmax 回归模型用于预测 def load_softmax(): # 加载了TensorFlow计算图上定义的全部变量 ,直接加载持久化的图 saver = tf.train.import_meta_graph("./Softmax/model.ckpt.meta") sess=tf.InteractiveSession() # 即将固化到硬盘中的Session从保存路径再读取出来 saver.restore(sess,'./Softmax/model.ckpt') mnist=mnistReader(mnistPath="E:/testdata/mnist.pkl") data,label=mnist.test_data() graph = tf.get_default_graph() # 通过张量的名称来获取张量 x = graph.get_tensor_by_name("x:0") logits = graph.get_tensor_by_name("y:0") # 填充需要预测的样本点 feed=np.reshape(data[0],[1,784]) feed_dict = {x:feed} # 进行预测 result=sess.run(logits,feed_dict) #输出结果,返回最大的数的下标,1代表1维,返回一个tensor,用eval()来去取出tensor的值 print ("predict result:",tf.argmax(result,1).eval()) print ("real result:",tf.argmax(label[0],0).eval()) #--------多层感知机模型(只有一个隐藏层)-------------- def multi_perceptron(): sess=tf.InteractiveSession() # 网络的参数设置 in_units=784 # 输入节点数 h1_units=300 # 隐藏层的输出节点数 w1=tf.Variable(tf.truncated_normal([in_units,h1_units],stddev=0.1))# 隐藏层权重,正太分布,标准差为0.1 b1=tf.Variable(tf.zeros([h1_units])) # 隐藏层的偏置 w2=tf.Variable(tf.zeros([h1_units,10])) # 输出层的权重 b2=tf.Variable(tf.zeros([10])) # 输出层的偏置 # 网络的输入值 x=tf.placeholder(tf.float32,shape=[None,in_units],name='x') # 网络的输入,注意要命名 keep_prob=tf.placeholder(tf.float32,name='keep_prob') # Dropout比率,注意命名 y_=tf.placeholder(tf.float32,[None,10],name='y_') # 真实的label,注意命名 # 网络各层的计算 hidden1=tf.nn.relu(tf.matmul(x,w1)+b1) # 隐藏层的模型 hidden1_drop=tf.nn.dropout(hidden1,keep_prob) # Dropout:随机将一部分节点置0 y=tf.nn.softmax(tf.matmul(hidden1_drop,w2)+b2,name='y') # 输出层的模型,注意命名 # 定义损失函数和优化器 cross_entropy=tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y),reduction_indices=[1])) #定义交叉熵为损失函数 train_step=tf.train.AdagradOptimizer(0.3).minimize(cross_entropy) # 定义优化方法,学习率为0.3 # 开始训练 tf.global_variables_initializer().run() mnist=mnistReader(mnistPath="E:/testdata/mnist.pkl") for i in range(1000): batch_x,batch_y = mnist.next_train_batch() train_step.run({x:batch_x,y_:batch_y,keep_prob:0.75}) # 计算测试集上的准确率 correction_prediction=tf.equal(tf.argmax(y,1),tf.argmax(y_,1)) accuracy=tf.reduce_mean(tf.cast(correction_prediction,tf.float32)) test_data,test_label=mnist.test_data() print (accuracy.eval({x:test_data,y_:test_label,keep_prob:1.0})) # 保存模型的参数 saver = tf.train.Saver() save_path = saver.save(sess,"./MLP/model.ckpt") #保存模型,生成了4个文件:.data、.index、.meta、checkpoint print("save model:{0} Finished".format(save_path)) # 加载训练好的MLP模型用于预测 def load_mlp(): # 加载了TensorFlow计算图上定义的全部变量 ,直接加载持久化的图 saver = tf.train.import_meta_graph("./MLP/model.ckpt.meta") sess=tf.InteractiveSession() # 即将固化到硬盘中的Session从保存路径再读取出来 saver.restore(sess,'./MLP/model.ckpt') mnist=mnistReader(mnistPath="E:/testdata/mnist.pkl") data,label=mnist.test_data() graph = tf.get_default_graph() # 通过张量的名称来获取张量 x = graph.get_tensor_by_name("x:0") logits = graph.get_tensor_by_name("y:0") keep_prob=graph.get_tensor_by_name("keep_prob:0") # 填充需要预测的样本点 feed=np.reshape(data[0],[1,784]) feed_dict = {x:feed,keep_prob:1.0} # 进行预测 result=sess.run(logits,feed_dict) #输出结果,返回最大的数的下标,1代表1维,返回一个tensor,用eval()来去取出tensor的值 print ("predict result:",tf.argmax(result,1).eval()) print ("real result:",tf.argmax(label[0],0).eval()) # -----------卷积神经网络--------------------------- def CNN(): sess=tf.InteractiveSession() x=tf.placeholder(tf.float32,[None,784],name='x') y_=tf.placeholder(tf.float32,[None,10],name='y_') x_image=tf.reshape(x,[-1,28,28,1]) #转为28*28的原始结构,第一个-1代表数量不确定,最后一个-1代表通道 # 第一个卷积层的定义 w_conv1=weight_variable([5,5,1,32]) # 初始化第一个卷积层卷积核参数 b_conv1=bias_variable([32]) # 初始化第一个卷积层的偏置 h_conv1=tf.nn.relu(conv2d(x_image,w_conv1)+b_conv1) # 第一个卷积层的卷积运算 h_pool1=max_pool_2x2(h_conv1) # 第一个卷积层的池化运算 # 第二个卷积层的定义 w_conv2=weight_variable([5,5,32,64]) # 初始化第二个卷积层卷积核参数 b_conv2=bias_variable([64]) # 初始化第二个卷积层的偏置 h_conv2=tf.nn.relu(conv2d(h_pool1,w_conv2)+b_conv2) # 第二个卷积层的卷积运算 h_pool2=max_pool_2x2(h_conv2) # 第二个卷积层的池化运算 # 全连接层 w_fc1=weight_variable([7*7*64,1024]) b_fc1=bias_variable([1024]) h_pool2_flat=tf.reshape(h_pool2,[-1,7*7*64]) # 转换为一维向量 h_fc1=tf.nn.relu(tf.matmul(h_pool2_flat,w_fc1)+b_fc1) # 全连接 # Dropout层 keep_prob=tf.placeholder(tf.float32,name='keep_prob') h_fc1_drop=tf.nn.dropout(h_fc1,keep_prob) # Softmax层 w_fc2=weight_variable([1024,10]) b_fc2=bias_variable([10]) y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop,w_fc2)+b_fc2,name='y') # 定义交叉熵和优化器 cross_entropy=tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y_conv),reduction_indices=[1])) train_step=tf.train.AdagradOptimizer(1e-4).minimize(cross_entropy) # 用于保存模型的Saver类 saver = tf.train.Saver(max_to_keep=10) # 保存最新的10个文件,默认为 5个 # 开始训练 tf.global_variables_initializer().run() mnist=mnistReader(mnistPath="E:/testdata/mnist.pkl") start=time.time() print ("begin training...") for i in range(20000): batch_x,batch_y = mnist.next_train_batch() train_step.run(feed_dict={x:batch_x,y_:batch_y,keep_prob:0.5}) # 每1000轮保存一次中间结果 if i%1000 ==0: save_path=saver.save(sess,"./testCNN/model.ckpt",global_step=i) print("save model:{0} Finished".format(save_path)) # 计算准确率 correction_prediction=tf.equal(tf.argmax(y_conv,1),tf.argmax(y_,1)) accuracy=tf.reduce_mean(tf.cast(correction_prediction,tf.float32)) test_data,test_label=mnist.test_data() print (accuracy.eval(feed_dict={x:test_data,y_:test_label,keep_prob:1.0})) print ("cast time:",time.time() - start) # 加载训练好的CNN模型用于预测 def load_cnn(): # 加载了TensorFlow计算图上定义的全部变量 ,直接加载持久化的图 saver = tf.train.import_meta_graph("./CNN/model.ckpt-19000.meta") sess=tf.InteractiveSession() # 即将固化到硬盘中的Session从保存路径再读取出来,需要指定保存的文件名 # saver.restore(sess,'./CNN/model.ckpt-19000') # 获取最新的模型,只需要指定保存模型的目录即可 ckpt=tf.train.get_checkpoint_state('./CNN/') saver.restore(sess, ckpt.model_checkpoint_path) mnist=mnistReader(mnistPath="E:/testdata/mnist.pkl") data,label=mnist.test_data() graph = tf.get_default_graph() # 通过张量的名称来获取张量 x = graph.get_tensor_by_name("x:0") logits = graph.get_tensor_by_name("y:0") keep_prob=graph.get_tensor_by_name("keep_prob:0") # 填充需要预测的样本点 feed=np.reshape(data[0],[1,784]) feed_dict = {x:feed,keep_prob:1.0} # 进行预测 result=sess.run(logits,feed_dict) #输出结果,返回最大的数的下标,1代表1维,返回一个tensor,用eval()来去取出tensor的值 print ("predict result:",tf.argmax(result,1).eval()) print ("real result:",tf.argmax(label[0],0).eval()) # 权重初始化函数,正太分布,方差为0.1 def weight_variable(shape): initial =tf.truncated_normal(shape,stddev=0.1) return tf.Variable(initial) # 偏置初始化函数,常数0.1 def bias_variable(shape): initial=tf.constant(0.1,shape=shape) return tf.Variable(initial) # 2维卷积层 ''' x为输入 w为卷积核参数,如[5,5,1,32],前面两个代表核尺寸,第三个代表通道,最后一个是核数量 strides为卷积核移动步长,都是1代表不遗漏的划过每个点 padding为边界处理填充方式 ''' def conv2d(x,w): return tf.nn.conv2d(x,w,strides=[1,1,1,1],padding='SAME') # 2维池化层 ''' ksize为池化核大小,这里为2*2 strides步长这里设为横竖两个方向以2为步长 ''' def max_pool_2x2(x): return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME') #----------------------------------------------------------------------------- if __name__ == '__main__': # softmax_model() # softmax回归得到的准确率大概为0.92左右 # load_softmax() # 加载softmax回归保存的模型 # multi_perceptron() # 多层感知机得到的准确率大概为0.98左右 # load_mlp() # 加载多层感知机保存的模型用于预测 CNN() # 卷积神经网络据说可以达到0.99的准确率,没跑过 # load_cnn() # 加载CNN保存的模型用于预测