赞
踩
本文关注如何使用TensorFlow中的函数来构建AlexNet,详细介绍每一个TF函数的应用方法,适合基础入门。
首先给出AlexNet的代码,但是此处不会对AlexNet的原理做详细解析,而是将重点关注TensorFlow的函数使用
# 加载模块 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data # 导入数据 mnist = input_data.read_data_sets("MNIST_data",one_hot=True) # 相关子函数定义 ################################################### def compute_accuracy(v_xs,v_ys): global prediction y_pre = sess.run(prediction, feed_dict={xs:v_xs, keep_prob:1}) correct_prediction = tf.equal(tf.argmax(y_pre, 1),tf.argmax(v_ys,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) result = sess.run(accuracy, feed_dict={xs:v_xs,ys:v_ys,keep_prob:1}) return result def weight_variable(shape): initial = tf.truncated_normal(shape, stddev=0.1) return tf.Variable(initial) def bias_variable(shape): initial = tf.constant(0.1, shape=shape) return tf.Variable(initial) def conv2d(x, W): return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding="SAME") # 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") #处理图片 ################################################### xs = tf.placeholder(tf.float32, [None,784]) # 训练x ys = tf.placeholder(tf.float32, [None,10]) # 训练y keep_prob = tf.placeholder(tf.float32) # dropout的保留率 x_image = tf.reshape(xs, [-1, 28, 28, 1]) # 向量转矩阵:将1*784的向量reshape为28*28,-1表示不关注这一维度 #构建网络 ################################################### ## convl layer ## W_conv1 = weight_variable([5,5,1,32]) # kernel 5*5, channel is 1, out size 32 b_conv1 = bias_variable([32]) h_conv1 = tf.nn.relu(conv2d(x_image,W_conv1) + b_conv1) # output size 28*28*32 h_pool1 = max_pool_2x2(h_conv1) # output size 14*14*32 ## conv2 layer ## W_conv2 = weight_variable([5,5,32,64]) # kernel 5*5, in size 32, out size 64 b_conv2 = bias_variable([64]) h_conv2 = tf.nn.relu(conv2d(h_pool1,W_conv2) + b_conv2) # output size 14*14*64 h_pool2 = max_pool_2x2(h_conv2) # output size 7*7*64 ## funcl layer ## W_fc1 = weight_variable([7*7*64, 1024]) b_fc1 = bias_variable([1024]) # [n_samples,7,7,64]->>[n_samples, 7*7*64] 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) h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) ## func2 layer ## W_fc2 = weight_variable([1024, 10]) b_fc2 = bias_variable([10]) prediction = tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2)+b_fc2) #优化神经网络################################################### cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys*tf.log(prediction),reduction_indices=[1])) #定义损失函数 train_step = tf.train.GradientDescentOptimizer(1e-4).minimize(cross_entropy) # 定义求解器 sess =tf.Session() # 创建会话前台Python与后台C++之间的会话 sess.run(tf.initialize_all_variables()) # 计算图的初始化 # 主函数开始################################################## if __name__ == '__main__': for i in range(1000): batch_xs,batch_ys = mnist.train.next_batch(100) sess.run(train_step, feed_dict={xs:batch_xs,ys:batch_ys, keep_prob:0.5}) if i % 1 ==0: # print(sess.run(prediction,feed_dict={xs:batch_xs})) print(compute_accuracy(mnist.test.images,mnist.test.labels))
此处将从头到尾,依次解析以上代码中用到的TF函数。
三者都是TF中定义的函数模块,但是使用有所不同。
PS:为什么已经通过函数左值给定变量名了,还需要通过函数的name属性再次定义变量名。 例如x_train = tf.placeholder(tf.float32,shape=(None,28,28,1),name=“x_train1”)。
原因是:
● 函数左值x_train是Python语言中的变量名空间,这个变量名只是在tensorflow图的Python脚本运行过程中指向tensorflow图中的变量的临时指针,这个命名空间在脚本运行完毕之后就会自动删除。
● 而函数中定义的name="x_train1"是tensorflow命名空间中属于这个图变量的真实属性,这个属性不会随着Python代码运行结束而消除,并且在tensorboard中显示的是name="x_train1"这个属性。
作用:tf.truncated_normal作用是利用截断式(truncated截断式的)正态分布输出随机数
PS:截断式:如果生成的某个随机数大于了2倍标准差,就会重新生成,也就是保证生成的随机数处于【-2σ,2σ】区间内。
PS:正态分布中处于【-3σ,3σ】的概率为99.7%;正态分布中处于【-2σ,2σ】的概率为95.6%;正态分布中处于【-2σ,2σ】的概率为68.2%
格式:tf.random.truncated_normal(shape,mean=0.0, stddev=1.0, dtype=tf.dtypes.float32, seed=None, name=None)
举例:w1_conv = tf.random.truncated_normal([5,5,1,32],mean=0.2,stddev=0.5,dtype=tf.flaot32,seed=1,name=‘w1_conv’)
说明:
(1)mean和stddev分别定义正态分布的均值和标准差,
(2)seed用于定义随机数的种子,对于正态分布而言,只要定义了相同的随机数种子,则每次输出的结果都是一样的。如下面的代码实验:只要两者有相同的随机数种子,则生成的随机数的前半部分都是相同的。
PS:这个shape对应着卷积核的shape,分别是【width,height,in_chinnels,out_chinnels】
补充:tf.random_normal()函数是生成普通正态分布的函数,tf.random_normal与tf.truncated_normal的参数格式相同,区别是前者不截断,后者阶段
实验代码:
# 加载模块 a = tf.Variable(tf.random_normal([2,2],seed=1)) # 普通的正态分布 b = tf.Variable(tf.truncated_normal([2,3],seed=1)) # 截断式正态分布 init = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init) print(sess.run(a)) print(sess.run(b)) # 分别输出: a: [[-0.8113182 1.4845988 ] [ 0.06532937 -2.4427042 ]] b: [[-0.8113182 1.4845988 0.06532937] [ 0.0992484 0.6396971 1.6108712 ]] # 可见只要随机数种子相同,就会生成相同的随机数。
作用:tf.constant()基于给定的常数创建张量
格式:tb1 = tf.constant(value, dtype=None, shape=None, name=‘Const’,verify_shape=False )
其中value是给定的常量值或者常量的list。
举例:tensor = tf.constant([1, 2, 3, 4, 5, 6, 7]) 得到[1 2 3 4 5 6 7]
tensor = tf.constant(-1.0, shape=[2, 3])得到 [[-1. -1. -1.],[-1. -1. -1.]]
实验代码:
# 加载模块
a = tf.Variable(tf.constant(1.2,shape=[3,3])) # 生成一个3*3的常量矩阵,所有值都是1.2
b = tf.Variable(tf.constant([1.2,1.3,1.4],shape=[7])) # 生成一个1*7的常量矩阵,前三个值是1.2,1.3,1.4,后续的值用1.4 填补
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
print(sess.run(a))
print(sess.run(b))
# 分别输出:
a:
[[1.2 1.2 1.2]
[1.2 1.2 1.2]
[1.2 1.2 1.2]]
b:
[1.2 1.3 1.4 1.4 1.4 1.4 1.4]
作用:tf.reduce_sum()用于压缩求和
格式:tf.reduce_sum(input_tensor,axis=None,keepdims=None,name=None,reduction_indices=None,keep_dims=None)
● axis 用于指明压缩方向,如果没有指明,就会直接压缩为1个常数
● keepdims表示按照某一维数就行压缩契合
实验代码:
import tensorflow as tf
import numpy as np
x = tf.constant([[1,1,1],[2,2,2]])
with tf.Session() as sess:
print(sess.run(tf.reduce_sum(x))) #所有求和 #输出 9
print(sess.run(tf.reduce_sum(x,0))) #按 列 求和 # 输出 [3 3 3]
print(sess.run(tf.reduce_sum(x,1))) #按 行 求和 # 输出 [3 6]
print(sess.run(tf.reduce_sum(x,1,keepdims=True))) #按维度 行 求和 #输出[[3],[6]]
print(sess.run(tf.reduce_sum(x,[0,1]))) #行列求和 # 输出9
print(sess.run(tf.reduce_sum(x,reduction_indices=[1]))) # 输出[3,6]
作用:
● tensorflow的内核使用更加高效的C++作为后台,以支撑它的密集计算。
● tensorflow把前台(即python程序)与后台程序之间的连接称为"会话(Session)"
● tensorflow的世界里,变量的定义与计算时分开的,比如之前的tf.constant,tf.nn.relu的函数都只是定义了一个变量,而真正要开始幅值和计算还需要对其进行初始化
● sess=tf.session表示创建python与c++之间的会话,也就是启动之前定义好的图,并将这个会话命名为sess
格式:tf.Session作为会话,主要功能是指定操作对象的执行环境,Session类构造函数有3个可选参数。
● target(可选):指定连接的执行引擎,多用于分布式场景。
● graph(可选):指定要在Session对象中参与计算的图(graph)。
● config(可选):辅助配置Session对象所需的参数(限制CPU或GPU使用数目,设置优化参数以及设置日志选项等)。
以上参数都是可选,一般一句sess=tf.session()就可以启动了
PS:
除了tf.session外,还可以使用tf.InteractiveSession()来创建会话,后者将当前会话设置为默认会话,这样在进行eval和run等操作的时候就不用指定名称了
● 对于tf.Session()
sess=tf.Session()
sess.run(op1,feed_dict(x:x1,y:y1))
● 对于tf.InteractiveSession()
sess=tf.InteractiveSession()
op1.eval(feed_dict(x:x1,y:y1))
● 也就是说:tf.InteractiveSession()相当于
sess=tf.Session()
with sess.as_default():
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。