python tf学习(四) 实现神经网络手写数字识别
import tensorflow as tf
from tensorflow.examples.tutorials.mnist.input_data import read_data_sets
# 规定神经网络的规格(神经网络手写数字识别)输入的shape(None, 784)
# 规定2层, 每层256个神经元(神经元的个数一般为2的幂次方)
# 第一层 X(None, 784) * W1 (784, 256) + b1(256) --> (None, 256)
# 第二层 (None, 256) * W2 (256, 256) + b2(256) --> (None, 256)
# 输出层 (None, 256) * W_out (256, 10) + b_out(10) --> (None, 10)
digits = read_data_sets('./', one_hot=True)
X = tf.placeholder(dtype=tf.float64, shape=(None, 784))
Y = tf.placeholder(dtype=tf.float64, shape=(None, 10))
# 定义第一层的W1 b1
W1 = tf.Variable(initial_value=tf.random_normal(shape=(784, 256), stddev=0.1, dtype=tf.float64))
b1 = tf.Variable(initial_value=tf.zeros(shape=256, dtype=tf.float64))
# 定义第一层的W2 b2
W2 = tf.Variable(initial_value=tf.random_normal(shape=(256, 256), stddev=0.1, dtype=tf.float64))
b2 = tf.Variable(initial_value=tf.zeros(shape=256, dtype=tf.float64))
# 定义输出层
W_out = tf.Variable(initial_value=tf.random_normal(shape=(256, 10), stddev=0.1, dtype=tf.float64))
b_out = tf.Variable(initial_value=tf.zeros(shape=10, dtype=tf.float64))
# 第一层网络
layer1 = tf.add(tf.matmul(X, W1), b1)
# 加relu激活函数
layer1_relu = tf.nn.relu(layer1)
# 加dropout防止过拟合
kb = tf.placeholder(dtype=tf.float64)
dropout1 = tf.nn.dropout(layer1_relu, keep_prob=kb)
# 第二层网络
layer2 = tf.add(tf.matmul(dropout1, W2), b2)
# 加激活函数
layer2_relu = tf.nn.relu(layer2)
# 加dropout
dropout2 = tf.nn.dropout(layer2_relu, keep_prob=kb)
# 输出层
out = tf.add(tf.matmul(dropout2, W_out), b_out)
# 把输出通过softmax变成概率
Y_prob = tf.nn.softmax(out)
# 定义损失函数 (None, 10)
cost = tf.reduce_mean(Y * tf.log(1 / Y_prob)) # Y和Y_proba的shape是一样 的,所以可以直接相乘, 这个时候是对应的元素 相乘
# 定义优化器, AdamOptimizer 是对普通梯度下降法的改进.
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
# 初始化
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for i in range(20):
# 一遍所有数据epoch
for j in range(550):
X_train, y_train = digits.train.next_batch(batch_size=100)
sess.run(optimizer, feed_dict={X: X_train, Y: y_train, kb: 0.8})
X_test, y_test = digits.test.next_batch(5000) # 总共有10000个测试
loss = sess.run(cost, feed_dict={X: X_test, Y: y_test, kb: 1})
prob = sess.run(Y_prob, feed_dict={X: X_test, kb: 1})
# 从10个概率找到最大的概率的下标,axis=1 (5000,10) 和测试的标记比较, tf.cast转化为0和1 计算
acc = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(prob, axis=1), tf.argmax(y_test, axis=1)), dtype=tf.float64))
acc_ = sess.run(acc)
print(f'损失:{loss},准确率:{acc_}')
X_test, y_test = digits.test.next_batch(5000)
prob = sess.run(Y_prob, feed_dict={X: X_test, kb: 1})
acc = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(prob, axis=1), tf.argmax(y_test, axis=1)), dtype=tf.float64))
acc_ = sess.run(acc)
print(f'准确率:{acc_}')
看到定义后面的代码发现和上一期的代码一样,也就是说神经网络和手写逻辑斯蒂算法的是代码一样的,运行如下
未加激活函数训练20次和上一期的逻辑回归得分一样
加入激活函数relu后发现达到大约98%,最后加入dropout发现也差不多,因为神经层太少了,dropout效果不明显