学了这么久机器学习和深度学习,应该来个小项目练练手。
于是选择了最经典的数据集MNIST来锻炼下自己卷积神经网络的熟练度。
我采用了比较简单的结构,没有用强大的GooLeNet(…实则是电脑带不动),两个卷积层加一个最大池化层,然后加一个大小为64的全连接层,最后是softmax输出。其实这个结构也是看了n遍了,这次来手写一下代码,顺便熟悉熟悉tensorflow的函数。
话不多说,上代码(python 3.7)
import tensorflow as tf import numpy as np def reset_graph(seed=42):#设置一下随机数种子 tf.reset_default_graph() tf.set_random_seed(seed) np.random.seed(seed) height = 28 #长 width = 28 #宽 channels = 1 #通道数为1 n_inputs = height * width #图片大小为784像素 conv1_fmaps = 32 #卷积核的数量 conv1_ksize = 3 #卷积核的大小 conv1_stride = 1 #第一卷积层步长为1 conv1_pad = "SAME" #padding采用same conv2_fmaps = 64 #64个卷积核 conv2_ksize = 3 #卷积核大小为3 conv2_stride = 2 #第二卷积层步长为2 conv2_pad = "SAME" #padding也采用same pool3_fmaps = conv2_fmaps #64 n_fc1 = 64 #全连接层有64个单元 n_outputs = 10 #输出10个类型 reset_graph() with tf.name_scope("inputs"): X = tf.placeholder(tf.float32, shape=[None, n_inputs], name="X")# X为 m*784型 X_reshaped = tf.reshape(X, shape=[-1, height, width, channels]) #reshape成 m*28*28*1 y = tf.placeholder(tf.int32, shape=[None], name="y") conv1 = tf.layers.conv2d(X_reshaped, filters=conv1_fmaps, kernel_size=conv1_ksize, strides=conv1_stride, padding=conv1_pad, activation=tf.nn.relu, name="conv1") conv2 = tf.layers.conv2d(conv1, filters=conv2_fmaps, kernel_size=conv2_ksize, strides=conv2_stride, padding=conv2_pad, activation=tf.nn.relu, name="conv2") with tf.name_scope("pool3"):#池化层 pool3 = tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="VALID") pool3_flat = tf.reshape(pool3, shape=[-1, pool3_fmaps * 7 * 7]) with tf.name_scope("fc1"):#全连接层 fc1 = tf.layers.dense(pool3_flat, n_fc1, activation=tf.nn.relu, name="fc1") with tf.name_scope("output"):#输出层 logits = tf.layers.dense(fc1, n_outputs, name="output") Y_proba = tf.nn.softmax(logits, name="Y_proba") with tf.name_scope("train"):#训练部分 xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=y)#用交叉熵作为代价函数 loss = tf.reduce_mean(xentropy)#定义损失为交叉熵的均值 optimizer = tf.train.AdamOptimizer()#采用目前最强最快的adam梯度下降法 training_op = optimizer.minimize(loss)#定义训练的一个步骤(最小化损失) with tf.name_scope("eval"):#判断准确率 correct = tf.nn.in_top_k(logits, y, 1)#判断是否准确预测y值(判断预测的y值可能性是不是排第一) accuracy = tf.reduce_mean(tf.cast(correct, tf.float32)) with tf.name_scope("init_and_save"): init = tf.global_variables_initializer() saver = tf.train.Saver() (X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()#获取mnist数据 X_train = X_train.astype(np.float32).reshape(-1, 28*28) / 255.0#改变一下数据的格式,并除以255(灰度的最大值)便于训练 X_test = X_test.astype(np.float32).reshape(-1, 28*28) / 255.0#对测试数据进行同样处理 y_train = y_train.astype(np.int32)#标签只需要改一下数据类型 y_test = y_test.astype(np.int32) X_valid, X_train = X_train[:5000], X_train[5000:]#将训练集拆训练集和验证集,验证集大小为5000 y_valid, y_train = y_train[:5000], y_train[5000:] def shuffle_batch(X, y, batch_size): rnd_idx = np.random.permutation(len(X))#打乱序号 n_batches = len(X) // batch_size#计算出batch for batch_idx in np.array_split(rnd_idx, n_batches): X_batch, y_batch = X[batch_idx], y[batch_idx] yield X_batch, y_batch#这里使用yield而不是return,因为要保证下一次训练能继续运行这个循环 n_epochs = 10#训练十代 batch_size = 100#梯度下降的batch大小为100 with tf.Session() as sess: init.run()#首先初始化数据 for epoch in range(n_epochs): for X_batch, y_batch in shuffle_batch(X_train, y_train, batch_size): sess.run(training_op, feed_dict={X: X_batch, y: y_batch}) acc_batch = accuracy.eval(feed_dict={X: X_batch, y: y_batch}) acc_test = accuracy.eval(feed_dict={X: X_test, y: y_test}) print(epoch, "Last batch accuracy:", acc_batch, "Test accuracy:", acc_test) save_path = saver.save(sess, "./my_mnist_model")
放一下最后的训练正确率,98.9%,还可以的样子,改天尝试多加几层卷积层和全连接层看一下正确率是否有提升
文章来源: https://blog.csdn.net/qq_43088815/article/details/90522376