您的位置:首页 > 理论基础 > 计算机网络

使用逻辑回归方法(softmax regression)识别MNIST手写体数字、使用CNN神经网络识别MNIST手写体数字、使用tensorboard可视化训练过程数据

2018-10-26 18:00 931 查看
版权声明:站在巨人的肩膀上学习。 https://blog.csdn.net/zgcr654321/article/details/83418438

使用逻辑回归方法(softmax regression)识别MNIST手写体数字:

首先下载和读取mnist数据集;

定义每批训练的图片数量batch_size=100;

定义输入数据x和对应图片标签值y;

定义逻辑回归的w和b,由于图片每张是28X28个像素点,共有10个类的图片(数字0-9),因此我们定义w为784X10的矩阵,b为10个,对应10个类的图片。初始时w和b均为0;

定义预测值为输入图像x为不定行(行数和batch_size相同)784列(即一张图片的像素点信息都在矩阵的一列中)与W(784X10矩阵)做矩阵乘法,再加上b,经过激活函数softplus处理后,再经过softmax函数处理成一个有10个元素的一维数组,且10个元素的和为1;

定义cost函数为交叉熵函数,对输出的一维数组的10个元素分别求ln值再乘以y对应元素值,然后按列压缩求和,最后得到10个元素的和在第一行的第一个元素,后面元素都没有了,再除以10求平均值;

定义优化器使用梯度下降方法;

创建Session会话,初始化所有变量;

设置50轮循环,每轮循环初始将avg_cost置0,然后计算整个数据集可以划分成多少个batch_size,即total_batch;

设置一个total_batch轮的内层for循环,即每次给模型使用batch_size大小的样本训练,然后更新一次w、b、wgrad、bgrad、cost值,进行total_batch轮训练,正好将全部样本使用完了一次。外层的50轮循环即重复这个训练方式进行50次循环;

每当使用全体样本训练5次后,打印一次avg_cost的值;

训练结束后,将预测者与真实值比较,计算预测的准确率。

代码如下:

[code]import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

# 数据集规模100
batch_size = 100

# 定义可以改变传入数据的x和y
x = tf.placeholder(tf.float32, [None, 784])
# x实际上是一个浮点数矩阵,元素的值是我们传入的
# 列有784列,行不定,由于图片是28X28=784个像素,即一张图片的所有像素点是矩阵中的1行的所有元素
# 而输入的图片数量(行数)不定,因为后面可能会修改batch_size
y = tf.placeholder(tf.float32, [None, 10])
# y实际上是一个浮点数矩阵,元素的值是我们传入的
# 列是10,因为y是我们接收的训练集中的数据真实值,该数据集使用one_hot编码来表示一张图片属于数字0-9中的哪一个
# 即矩阵的一行元素代表一个图片的数字是几,假如是5,则这一行的第5个元素置1,其他都为0,任何时候只有一个元素为1,其他都为0

# 图片每张是28X28,共784个像素,10表示数字有10类(0-9),所以一共要设置784X10个变量w
W = tf.Variable(tf.zeros([784, 10]))
# 每种数字(0-9)设置一个bias,共10个b
b = tf.Variable(tf.zeros([10]))

# 预测值为pred,使用softmax来处理由模型tf.matmul(x, W) + b计算得到的输出值
# matmul为做矩阵乘法函数,即矩阵x和W相乘(x矩阵为输入图片数量x784,W矩阵为784X10,这样就可以进行矩阵相乘)
# 矩阵相乘的结果再加b,然后经过softmax函数处理
pred = tf.nn.softmax(tf.nn.softplus(tf.matmul(x, W) + b))
# loss函数,使用交叉熵
cost = tf.reduce_mean(- tf.reduce_sum(y * tf.log(pred), 1))
# 定义优化器,使用梯度下降方法
optimizer = tf.train.GradientDescentOptimizer(0.01).minimize(cost)

# 创建Session会话,开始运行
with tf.Session() as sess:
# 初始化所有变量
sess.run(tf.global_variables_initializer())
# 进行50轮训练
for epoch in range(50):
# 每轮训练先重置cost为0
avg_cost = 0.
# 计算我们的数据集中安batch_size大小总共可以划分成多少个小批量样本
total_batch = int(mnist.train.num_examples / batch_size)
# 设置total_batch轮循环,每轮训练使用一个batch_size大小的样本来进行训练
for i in range(total_batch):
# 每次使用batch_size个样本来进行训练
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
# 运行优化器
sess.run(optimizer, feed_dict={x: batch_xs, y: batch_ys})
# 计算损失函数平均值,因为每轮都使用一个batch_size来进行训练,然后产生一个cost
# 最终的avg_cost就是所有的cost加起来除以循环轮数total_batch
avg_cost += sess.run(cost, feed_dict={x: batch_xs, y: batch_ys}) / total_batch
# 每使用全体样本训练5次后,打印一次avg_cost值
if (epoch + 1) % 5 == 0:
print(" Epoch: ", '%d' % (epoch + 1), "cost=", "{:.9f}".format(avg_cost))

# 计算正确率并打印
correct = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
print("正确率: ", accuracy.eval({x: mnist.test.images, y: mnist.test.labels}))

运行结果如下:

[code]WARNING:tensorflow:From F:/0 system backup/desktop/data/testpython/test2.py:7: read_data_sets (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.
Instructions for updating:
Please use alternatives such as official/mnist/dataset.py from tensorflow/models.
WARNING:tensorflow:From C:\ProgramData\Anaconda3\envs\tensorflow-gpu\lib\site-packages\tensorflow\contrib\learn\python\learn\datasets\mnist.py:260: maybe_download (from tensorflow.contrib.learn.python.learn.datasets.base) is deprecated and will be removed in a future version.
Instructions for updating:
Please write your own downloading logic.
WARNING:tensorflow:From C:\ProgramData\Anaconda3\envs\tensorflow-gpu\lib\site-packages\tensorflow\contrib\learn\python\learn\datasets\mnist.py:262: extract_images (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.
Instructions for updating:
Please use tf.data to implement this functionality.
Extracting MNIST_data\train-images-idx3-ubyte.gz
Extracting MNIST_data\train-labels-idx1-ubyte.gz
WARNING:tensorflow:From C:\ProgramData\Anaconda3\envs\tensorflow-gpu\lib\site-packages\tensorflow\contrib\learn\python\learn\datasets\mnist.py:267: extract_labels (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.
Instructions for updating:
Please use tf.data to implement this functionality.
WARNING:tensorflow:From C:\ProgramData\Anaconda3\envs\tensorflow-gpu\lib\site-packages\tensorflow\contrib\learn\python\learn\datasets\mnist.py:110: dense_to_one_hot (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.
Instructions for updating:
Please use tf.one_hot on tensors.
Extracting MNIST_data\t10k-images-idx3-ubyte.gz
Extracting MNIST_data\t10k-labels-idx1-ubyte.gz
WARNING:tensorflow:From C:\ProgramData\Anaconda3\envs\tensorflow-gpu\lib\site-packages\tensorflow\contrib\learn\python\learn\datasets\mnist.py:290: DataSet.__init__ (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.
Instructions for updating:
Please use alternatives such as official/mnist/dataset.py from tensorflow/models.
Epoch:  5 cost= 0.470797282
Epoch:  10 cost= 0.393224098
Epoch:  15 cost= 0.362505492
Epoch:  20 cost= 0.344750969
Epoch:  25 cost= 0.332776082
Epoch:  30 cost= 0.323931764
Epoch:  35 cost= 0.317050944
Epoch:  40 cost= 0.311557643
Epoch:  45 cost= 0.306929545
Epoch:  50 cost= 0.302941875
正确率:  0.9183

Process finished with exit code 0

使用CNN神经网络识别MNIST手写体数字:

首先定义batch_size和test_size大小;

定义一个model函数,包含三层隐藏层(卷积、池化并dropout)、一个全连接层、一个输出层;

定义输入数据trX,trY,测试数据teX,teY;

定义占位符X和Y;

定义三层隐藏层的卷积核大小,定义全连接层的神经元数量,定义输出层的神经元数量;

定义dropout的关键参数keep_prob;

定义模型的输出值py_x为model函数运行的结果;

定义cost函数,这里使用交叉熵作为cost函数,因为我们要使用softmax分类器;

定义优化器,使用RMSProp优化方法;

处理输出值,得到我们预测的值predict_op;

创建Session会话,控制我们的训练过程;

run初始化所有变量;

设置10次for循环,每次先训练模型,然后随机取一些测试数据来测试模型,并计算准确率。

代码如下:

[code]import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
os.environ["CUDA_VISIBLE_DEVICES"] = "0"

# 定义训练样本的batch_size为128
batch_size = 128
# 定义测试样本的test_size为256
test_size = 256

# 定义生成随机值的函数,shape由我们自己指定
def init_weights(shape):
return tf.Variable(tf.random_normal(shape, stddev=0.01))

# 定义隐藏层l1,l2,l3,定义全连接层l4,定义输出层pyx
def model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden):
# 隐藏层l1的卷积层l1a,步长是1,padding是SAME模式;池化层是l1,窗口大小2X2,步长是2,padding是SAME模式
# dropout函数对池化后的输出数据进行处理,保留一部分非0元素并且值乘以1/keep_prob倍,不保留的元素值全部置0
l1a = tf.nn.relu(tf.nn.conv2d(X, w, strides=[1, 1, 1, 1], padding='SAME'))  # 输入的X为28x28x1
l1 = tf.nn.max_pool(l1a, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')  # 输出的l1为14x14x32
l1 = tf.nn.dropout(l1, p_keep_conv)

# 隐藏层l2的卷积层l2a,步长是1,padding是SAME模式;池化层是l2,窗口大小2X2,步长是2,padding是SAME模式
# dropout函数对池化后的输出数据进行处理,保留一部分非0元素并且值乘以1/keep_prob倍,不保留的元素值全部置0
l2a = tf.nn.relu(tf.nn.conv2d(l1, w2, strides=[1, 1, 1, 1], padding='SAME'))  # 输入的l1为14x14x32
l2 = tf.nn.max_pool(l2a, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')  # 输出的l2为7x7x64
l2 = tf.nn.dropout(l2, p_keep_conv)

# 隐藏层l3的卷积层l3a,步长是1,padding是SAME模式;池化层是l3,窗口大小2X2,步长是2,padding是SAME模式
# dropout函数对池化后的输出数据进行处理,保留一部分非0元素并且值乘以1/keep_prob倍,不保留的元素值全部置0
l3a = tf.nn.relu(tf.nn.conv2d(l2, w3, strides=[1, 1, 1, 1], padding='SAME'))  # 输入的l2为7x7x64
l3 = tf.nn.max_pool(l3a, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')  # 输出的l3为4x4x128
l3 = tf.reshape(l3, [-1, w4.get_shape().as_list()[0]])  # 将数据重整为一个一维数组,有4*4*128个元素值
l3 = tf.nn.dropout(l3, p_keep_conv)

# 全连接层l4,进行矩阵乘法,得到的结果是一个1*625的矩阵
l4 = tf.nn.relu(tf.matmul(l3, w4))
l4 = tf.nn.dropout(l4, p_keep_hidden)
# p_keep_hidden其实就是keep_prob

# 输出层,进行矩阵乘法,得到一个1行10列的矩阵
pyx = tf.matmul(l4, w_o)
return pyx

# 定义输入数据,trX为输入的训练图像,teX为输入的测试图像,trY为输入的训练图像的标签,teY为输入的测试图像的标签
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels
trX = trX.reshape(-1, 28, 28, 1)  # 28x28x1 input img
teX = teX.reshape(-1, 28, 28, 1)  # 28x28x1 input img

# 定义直接将数据传入神经网络的变量X和Y
X = tf.placeholder("float", [None, 28, 28, 1])
Y = tf.placeholder("float", [None, 10])

#  3层神经网络过滤器大小都是3x3,层数由1到32到64到128递增,全连接层为1024个神经元,输出层定义10个神经元,因为输出结果有10个类
w = init_weights([3, 3, 1, 32])  # 3x3x1 conv, 32 outputs
w2 = init_weights([3, 3, 32, 64])  # 3x3x32 conv, 64 outputs
w3 = init_weights([3, 3, 64, 128])  # 3x3x32 conv, 128 outputs
w4 = init_weights([128 * 4 * 4, 1024])  # FC 128 * 4 * 4 inputs, 625 outputs
w_o = init_weights([1024, 10])  # FC 625 inputs, 10 outputs (labels)

p_keep_conv = tf.placeholder("float")
p_keep_hidden = tf.placeholder("float")
py_x = model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden)

# 定义loss函数为交叉熵函数,softmax_cross_entropy_with_logits函数是将softmax和cross_entropy函数的操作合并到一起
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=py_x, labels=Y))
# 定义优化器,使用RMSProp优化方法
train_op = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)
# 取出预测值的一维数组中最大值元素的下标,准备与真实值比对
predict_op = tf.argmax(py_x, 1)

# 建立Session()对话,并初始化所有变量
with tf.Session() as sess:
# you need to initialize all variables
tf.global_variables_initializer().run()
for i in range(10):
# 设置训练样本的大小
training_batch = zip(range(0, len(trX), batch_size), range(batch_size, len(trX) + 1, batch_size))
# range函数即取从0开始到len(trX)结束,以batch_size为间隔取元素的值,一共取了len(trX)/batch_size个下标
# zip()函数用来把这些元素组成元组,并返回一个指向这个元组的对象
# 用在下面的循环中的作用就是每隔batch_size从total_batch中取一个图片作为输入,直到到total_batch末尾
for start, end in training_batch:
sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end], p_keep_conv: 0.8, p_keep_hidden: 0.5})

# 创建一个一维数组,从0开始到len(teX)-1结束,间隔为1
test_indices = np.arange(len(teX))
# 打乱上面的数组,让元素随机排列
np.random.shuffle(test_indices)
# 取test_indices中的一部分元素,数量为test_size,由于之前元素已经被打乱,所以我们取到的元素也是随机的
test_indices = test_indices[0:test_size]
# 以我们取到的打乱后的元素作为下标,把这些下标对应的测试图像作为输入,然后计算准确率
print(i, np.mean(np.argmax(teY[test_indices], axis=1) == sess.run(predict_op, feed_dict={X: teX[test_indices],
p_keep_conv: 1.0,
p_keep_hidden: 1.0})))

运行结果如下:

[code]0 0.96484375
1 0.9921875
2 0.9765625
3 0.9921875
4 1.0
5 0.97265625
6 0.99609375
7 0.99609375
8 0.98828125
9 0.99609375

Process finished with exit code 0

使用tensorboard可视化训练过程数据:

我们还是使用上面的模型。这次把训练过程中的一些数据显示在tensorboard上。

代码如下:

[code]import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
os.environ["CUDA_VISIBLE_DEVICES"] = "0"

# 定义训练样本的batch_size为128
batch_size = 128
# 定义测试样本的test_size为256
test_size = 128

# 定义生成随机值的函数,shape由我们自己指定
def init_weights(shape):
return tf.Variable(tf.random_normal(shape, stddev=0.01))

# 定义隐藏层l1,l2,l3,定义全连接层l4,定义输出层pyx
def model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden):
# 隐藏层l1的卷积层l1a,步长是1,padding是SAME模式;池化层是l1,窗口大小2X2,步长是2,padding是SAME模式
# dropout函数对池化后的输出数据进行处理,保留一部分非0元素并且值乘以1/keep_prob倍,不保留的元素值全部置0
l1a = tf.nn.relu(tf.nn.conv2d(X, w, strides=[1, 1, 1, 1], padding='SAME'))  # 输入的X为28x28x1
l1 = tf.nn.max_pool(l1a, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')  # 输出的l1为14x14x32
l1 = tf.nn.dropout(l1, p_keep_conv)

# 隐藏层l2的卷积层l2a,步长是1,padding是SAME模式;池化层是l2,窗口大小2X2,步长是2,padding是SAME模式
# dropout函数对池化后的输出数据进行处理,保留一部分非0元素并且值乘以1/keep_prob倍,不保留的元素值全部置0
l2a = tf.nn.relu(tf.nn.conv2d(l1, w2, strides=[1, 1, 1, 1], padding='SAME'))  # 输入的l1为14x14x32
l2 = tf.nn.max_pool(l2a, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')  # 输出的l2为7x7x64
l2 = tf.nn.dropout(l2, p_keep_conv)

# 隐藏层l3的卷积层l3a,步长是1,padding是SAME模式;池化层是l3,窗口大小2X2,步长是2,padding是SAME模式
# dropout函数对池化后的输出数据进行处理,保留一部分非0元素并且值乘以1/keep_prob倍,不保留的元素值全部置0
l3a = tf.nn.relu(tf.nn.conv2d(l2, w3, strides=[1, 1, 1, 1], padding='SAME'))  # 输入的l2为7x7x64
l3 = tf.nn.max_pool(l3a, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')  # 输出的l3为4x4x128
l3 = tf.reshape(l3, [-1, w4.get_shape().as_list()[0]])  # 将数据重整为一个一维数组,有4*4*128个元素值
l3 = tf.nn.dropout(l3, p_keep_conv)

# 全连接层l4,进行矩阵乘法,得到的结果是一个1*625的矩阵
l4 = tf.nn.relu(tf.matmul(l3, w4))
l4 = tf.nn.dropout(l4, p_keep_hidden)
# p_keep_hidden其实就是keep_prob

# 输出层,进行矩阵乘法,得到一个1行10列的矩阵
pyx = tf.matmul(l4, w_o)
return pyx

# 定义输入数据,trX为输入的训练图像,teX为输入的测试图像,trY为输入的训练图像的标签,teY为输入的测试图像的标签
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels
trX = trX.reshape(-1, 28, 28, 1)  # 28x28x1 input img
teX = teX.reshape(-1, 28, 28, 1)  # 28x28x1 input img

# 定义直接将数据传入神经网络的变量X和Y
X = tf.placeholder("float", [None, 28, 28, 1])
Y = tf.placeholder("float", [None, 10])

#  3层神经网络过滤器大小都是3x3,层数由1到32到64到128递增,全连接层为1024个神经元,输出层定义10个神经元,因为输出结果有10个类
w = init_weights([3, 3, 1, 32])  # 3x3x1 conv, 32 outputs
w2 = init_weights([3, 3, 32, 64])  # 3x3x32 conv, 64 outputs
w3 = init_weights([3, 3, 64, 128])  # 3x3x32 conv, 128 outputs
w4 = init_weights([128 * 4 * 4, 1024])  # FC 128 * 4 * 4 inputs, 625 outputs
w_o = init_weights([1024, 10])  # FC 625 inputs, 10 outputs (labels)

p_keep_conv = tf.placeholder("float", name="p_keep_conv")
p_keep_hidden = tf.placeholder("float", name="p_keep_hidden")
py_x = model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden)

# 输出一个直方图,并把一个张量的值变化情况在直方图上显示
tf.summary.histogram("w_h_summ", w)
tf.summary.histogram("w_h2_summ", w2)
tf.summary.histogram("w_h3_summ", w3)
tf.summary.histogram("w_h4_summ", w4)
tf.summary.histogram("w_o_summ", w_o)
# 定义一个命名空间cost,把cost变量放在这个命名空间里
with tf.name_scope("cost"):
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=py_x, labels=Y))
train_op = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)
tf.summary.scalar("cost ", cost)
# 定义一个命名空间accuracy,把准确率这个变量放在这个命名空间里
with tf.name_scope("accuracy"):
correct_pred = tf.equal(tf.argmax(Y, 1), tf.argmax(py_x, 1))
acc_op = tf.reduce_mean(tf.cast(correct_pred, "float"))
tf.summary.scalar("accuracy", acc_op)

# 建立一个会话
with tf.Session() as sess:
# 创建一个新文件,指定文件所在的路径,把一个要记录的图的信息保存在这个文件里
writer = tf.summary.FileWriter("./logs/nn_logs", sess.graph)
# 将所有summary全部保存到磁盘,以便tensorboard显示。使用这个命令后就可以显示我们要显示在tensorboard上的信息了。
merged = tf.summary.merge_all()
# 初始化所有变量
tf.global_variables_initializer().run()

for i in range(2):
for start, end in zip(range(0, len(trX), 128), range(128, len(trX) + 1, 128)):
sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end], p_keep_conv: 0.8, p_keep_hidden: 0.5})
# 用测试数据运行时返回我们需要表示在图上的信息
test_indices = np.arange(len(teX))
# 打乱上面的数组,让元素随机排列
np.random.shuffle(test_indices)
# 取test_indices中的一部分元素,数量为test_size,由于之前元素已经被打乱,所以我们取到的元素也是随机的
test_indices = test_indices[0:test_size]
# 以我们取到的打乱后的元素作为下标,把这些下标对应的测试图像作为输入,然后计算准确率
summary, acc = sess.run([merged, acc_op],
feed_dict={X: teX[test_indices], Y: teY[test_indices], p_keep_conv: 1.0,
p_keep_hidden: 1.0})
# 把summary中的信息写入文件
writer.add_summary(summary, i)

为了节省运行时间,循环只有2次,但运行起来也要十来分钟。运行结束后,查看项目所在文件中的log/nn_logs文件夹,可以看到多了一个日志记录。

我们打开Anaconda prompt窗口,激活我们的tensorflow环境,如activate tesnsorflow-gpu,然后输入:

tensorboard --logdir=F:\0 system backup\desktop\data\testpython\logs\nn_logs

=后面是日志的路径。

出现下面的窗口:

即成功启动tensorboard并在端口6006监听。

这时我们打开浏览器,输入

http://1234-pc:6006

即可进入tensorboard界面。

如图:

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐