GPU版本: 注意都是Tensorflow1.0版本,2.0版本不再用Session了,
import tensorflow as tf
import numpy as np
import os
import time
ISOTIMEFORMAT = '%Y-%m-%d-%H-%M-%S'
localtime = time.strftime(ISOTIMEFORMAT, time.localtime())
from tensorflow.examples.tutorials.mnist import input_data
#import input_data
os.environ['CUDA_VISBLE_DEVICES'] = '0'
# 输入数据 mnist数据集,55000张图片;
mnist=input_data.read_data_sets(r'C:\Users\c00525771\Documents\Python Scripts\CNN\MNIST_data',one_hot=True)#参数一:文件目录。参数二:是否为one_hot向量
# interactiveSession 交互会话
config = tf.ConfigProto(log_device_placement = True) #, allow_soft_placement = True
config.gpu_options.allow_growth = True
#config = tf.ConfigProto(log_device_placement = True, allow_soft_placement = True)
with tf.device('/gpu:0'):
sess = tf.InteractiveSession(config = config)
#tf.Session(config = tf.ConfigProto(log_device_placement = True))
#tf.InteractiveSession()
"""计算图
为了在Python中进行高效的数值计算,我们通常会使用像NumPy一类的库,将一些诸如矩阵乘法的耗时操作在Python环境的外部来计算,这些计算通常会通过其它语言并用更为高效的代码来实现。
但遗憾的是,每一个操作切换回Python环境时仍需要不小的开销。如果你想在GPU或者分布式环境中计算时,这一开销更加可怖,这一开销主要可能是用来进行数据迁移。
TensorFlow也是在Python外部完成其主要工作,但是进行了改进以避免这种开销。其并没有采用在Python外部独立运行某个耗时操作的方式,而是先让我们描述一个交互操作图,然后完全将其运行在Python外部。这与Theano或Torch的做法类似。
因此Python代码的目的是用来构建这个可以在外部运行的计算图,以及安排计算图的哪一部分应该被运行。详情请查看基本用法中的计算图表一节。
--- 计算图的含义是:矩阵乘法等耗时的操作应该转换到python外用更高效语言(如C)实现,但是切换本身很耗时。所以排列好,整体外置来运算,这是session层层建立的原因;
不是每一步都到外部,机制上是整个委托外部,内部结算和观察;
"""
# softmax回归模型建立;
'建立输入出'
in_size = 28*28
out_size = 10
x = tf.placeholder("float", shape = [None, in_size]) # 784长张量作为输入 input,
# None易混淆-表示的不是“无”而是不定,相当于 NotSure, Scalable (输入10,1000,10000个784 Tensor都可以接受)
y_ = tf.placeholder("float", shape = [None, out_size]) #10个种类输出(就是keyhole是10bit) #真实的输出
'建立中间量'
W = tf.Variable(tf.zeros([in_size, out_size]))
b = tf.Variable(tf.zeros([out_size]))
'初始化'
sess.run(tf.initialize_all_variables()) #这里all variables为函数,而非一个变量集合,注意;
'类别预测与loss'
y = tf.nn.softmax(tf.matmul(x, W)+b) # 关键的预测函数 y = Wx + b nural network 's softmax functions;
cross_entropy = -tf.reduce_sum(y_*tf.log(y)) # -Sigma{ y_obs*log(y_pred) };
'训练模型'
train_step = tf.train.GradientDescentOptimizer(learning_rate = 0.01).minimize(cross_entropy)
# 最优化梯度下降算法,-s*delta(fx),s learning_rate + fx-object function (cross_entropy, ls, MMSE), 算法:最速下降、牛顿法
# #gradentDescentOptimizer 梯度下降优化法,梯度下降优化 需要迭代次数,会有反复性, 更新权值; x = -s*delta(f(x)); xnew;
# operate train_step to iteratively update train_step
for i in range(1000):
batch = mnist.train.next_batch(50)
train_step.run(feed_dict = {x: batch[0], y_:batch[1]}) #反馈字典: 真实x值batch x: 真实y值y_ batch y_
# 注意,在计算图中,你可以用feed_dict来替代任何张量,并不仅限于替换占位符。
'评估模型'
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) # 判断最大索引值是否相等来看正确,错误;
# 注意y_是一批数据,每行是同一份输出 none行,out_size列; 沿着axis = 1;
accuracy = tf.reduce_mean(tf.cast(correct_prediction,"float")) #转bool类型为 float类型;
print(accuracy.eval(feed_dict = {x:mnist.test.images, y_: mnist.test.labels}) )
""'构建一个多层卷积网络'
'权重初始化'# b +XW; 故 0.01 mean Value + 0.01*normVariable
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev = 0.1) #截断正态分布,norm(0,stddev = 0.01), 但是大于2*stddec 的值被切掉了,保证平稳性;
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape = shape)
return tf.Variable(initial)
'卷积和池化' # 超参数1: 步幅长度,边距是不是1或2, 池化核大小
#卷积函数和池化函数,步幅度stride都设置为1,0边距,池化核2x2最简版;
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides = [1, 1, 1, 1], padding = 'SAME')
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize = [1, 2, 2, 1], strides = [1, 2, 2, 1], padding = 'SAME')
'一层 二层卷积层,密集连接层' # 超参数2:层数,池化要不要,各卷积核5x5?,深度32?,
W_conv1 = weight_variable([5, 5, 1, 32]) # 卷积核mxn x 通道数k x 卷积深度 p;
b_conv1 = bias_variable([32])
x_image = tf.reshape(x, [-1,28,28,1])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
# layer2:
W_conv2 = weight_variable([5, 5, 32, 64]) #64是32的每个输出2个吗?
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
#注意数据流动,流动过程中处理的相应变化;; (这里池化因为2x2,长宽均缩小一半每次)
# x-(reshape 28x28)->x_image -> conv1+pool--(5x5x1x32, 2x2x1pool)-->pool1 -(conv2+pool2 5x5x32x64)->
#whole link 超参数3:全连接的大小
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'
#减少过拟合,加dropout, placeholder代表神经元输出在dropout中保持不变;
# 训练中drouout,测试关闭dropOut的; 附带处理scale,缩小放大值使得正好码?
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) #丢弃功率,丢掉h——fc1后的输出(丢的不是超参数,而是输入 训练值)
'输出层'
w_fc2 = weight_variable([1024, out_size])
b_fc2 = bias_variable([out_size])
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, w_fc2) + b_fc2)
'训练和评估模型'
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(learning_rate = 1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,'float32'))
#启动流程和启动循环,每100个输出一次进展,step多少,准确率多少,训练的测试的准确率
sess.run(tf.initialize_all_variables())
for i in range(2000): #20
batch = mnist.train.next_batch(50) # batch 大小一个超参数4
if i%100 == 0:
train_accuracy = accuracy.eval(feed_dict = {x : batch[0], y_:batch[1], keep_prob : 1.0})
print("step %d, training accuracy %g"%(i, train_accuracy))
train_step.run(feed_dict= {x:batch[0], y_:batch[1], keep_prob: 0.5})
print("test accuracy%g" % accuracy.eval(feed_dict = {x:mnist.test.images, y_:mnist.test.labels, keep_prob:1}))
- A 椭圆形式操作函数:绿色输入、重整函数、标签输入出、交叉熵操作,softmax操作(都是在nn之外)
- B 白色是nn内操作(循环迭代lay1-layer2,更新参数)
- C 橙色方框是永久变量 placeholder那个东西; W和偏差b; 黄色方框是迭代公式,迭代W和b的值的(批更新,取
平均值得更新) - D 白色内的椭圆也是操作, 紫色是最耗时的矩阵乘法操作,蓝色是简单加操作, 粉红色是神经元激活函数,
流图输入出,各个变量W,b,还有乘法MatMul什么的都看得懂,但是怎么一混起来就迷糊呢?因为中央关键Gradients你没抓住,NN迭代的关键是最优化之梯度下降(最速下降、牛顿法等等类似思想)。迭代值x_ = -α*df(x) 即需要步长(所谓学习速率)、目标函数(交叉熵、最小均方等)、还有做梯度运算的方法(简单梯度下降还是Adam之类的),做完就去更新权值W,更新偏差b,好进入下一轮迭代。
所以承上启下的Gradients模块,下面大白框运算是前一轮的预测过程,上面是更新W、b好进入下一轮运算(所以此W非彼W了)。W b独自要placeHolder永久设立储存空间意义就在这里,一直迭代轮询下去。-- 隐藏循环在内的。
小结
(总结了好多字,被限制,都丢了。|T~T|)