tensorflow 笔记附注(全)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32023541/article/details/83054678

附注一:常用的 TensorFlow 数据处理函数 & TensorBoard 可视化

# 主要是写一些 TensorFlow 经常用到的东西
import tensorflow as tf
tf.multiply(a,b)    a * b
tf.add(a,b)         a + b
tf.cast(x,dtype,name = None)   类型转换
tf.ones(shape,dtype)  tf.zeros(shape,dtype)  指定类型与性质的 1/0 值
tf.ones_like(input_tensor)  tf.zeros_like(input_tensor) 指定 input_tensor 形状和类型的 1/0 
tf.fill(shape,value)  将 value 填进 shape
tf.constant(value,shape) 生成常量
tf.random_normal(shape,mean = 0.0,stddev = 1.0) 
tf.truncated_normal(shape,nean = 0.0,stddev = 1.0)
tf.set_random_seed(seed)  设置随机种子
tf.linspace(start,stop,num,name = None) 生成从 start 至 stop 的 num 个等差数列
tf.range(start,limit,delta = 1) 生成从 start 到 limit 的增量为 delta 的等差数列

tf.shape(x)  返回 x 的shape
tf.size(x)   返回 x 的元素个数
tf.rank(x)   返回 x 的阶
tf.reshape(input,shape,name = None) 将 input reshape
tf.expand_dims(input,dim,name = None)  在 dim 维度将 input 扩展一维
tf.squeeze(input,dim,name = None)  将 dim 指定的维度去掉

tf.slice(input,begin,size,name = None)  切片操作,begin 指定维度偏移位置,size 指定对应维度切片数目
tf.split(value,num_or_size_splits,axis = 0) 沿着 axis 轴分割input (axis = 0 表示列,1 表示行)
tf.concat([t1,t2],values,name = 'concat')   将 t1,t2 按照指定的维度拼接,不改变维度数量
tf.stack([t1,t2],axis = 0)  按 axis 轴将 t1,t2 两个 N 维张量组合成 N+1 维张量
tf.gather(params,indices)   合并索引 indices 所指示 params 中的切片
tf.count_nonzero(input_tensor,axis = None) 统计非零个数

tf.assign(x,y,name = None)   赋值 x = y
tf.subtract(x,y,name = None) x - y
tf.divide(x,y,name = None)   除法
tf.mod(x,y,name = None)      求模
tf.abs(x,name = None)        绝对值
tf.negative(x,name = None)   取反
tf.sign(x,name = None)       符号函数
tf.square(x,name = None)     求平方
tf.round(x,name = None)      最近整数
tf.sqrt(x,name = None)       开根号
tf.pow(x,y,name = None)      求幂函数
tf.exp(x,name = None)        e 指数
tf.log(x,name = None)        ln 函数,两输入以第二个输入为底
tf.maximum(x,y,name = None)  返回最大值 x>y?x:y
tf.minimum(x,y,name = None)  返回最小值

tf.diag(diagonal,name = None)  生成对角矩阵
tf.diag_part(input,name = None) 与上面相反
tf.trace(x,name = None)     求对角值 diagonal 之和
tf.transpose(a)             转置矩阵
tf.reverse(tensor,dims,name = None)   沿着 dims 指定的维度列表进行反转
tf.matmul(x,y)              矩阵乘法
tf.matrix_determinant(input,name = None)   求给定方阵的行列式
tf.matrix_inverse(input,name = None)       求方阵的逆矩阵

tf.reduce_sum(input_tensor,axis = None) 按照 axis 轴计算输入 tensor 的元素之和
tf.reduce_prod(...)                     求积
tf.reduce_min  tf.reduce_max tf.reduce_mean
tf.reduce_all(input_tensor,axis = None) 按照 axis 轴计算输入的逻辑 与
tf.recude_any(input_tensor,axis = None) 按照 axis 轴计算输入的逻辑 或

tf.argmin(input,axis,name = None)     按axis 轴返回最小值索引
tf.argmax(input,axis,name = None)     按axis 轴返回最大值索引
tf.setdiffld(x,y,name = None)         返回 x,y 中不同值的索引
tf.where(condition,x,y)               condition 对应为True,返回对应 x 中的元素,否则返回对应 y 中的元素
tf.unique(x,name = None)              y,idx = tf.unique([0,0,1,3]) y = [0,1,3] idx = [0,0,1,2]
tf.invert_permutation(x,name = None)  将 x 中的值作为索引返回对应值
tf.random_shuffle(input)              沿着 input 的第一维进行随机重新排列

# 指定GPU 、CPU 因为TensorFlow 只会使用第一个,其他的默认不参与运算
with tf.device('/gpu:1'):
	add = tf.add(a,b)
	sess.run(...)

-----------------------------------------------------------------------	
'''通过 tf.ConfigProto 分配 GPU计算资源'''
config = tf.ConfigProto(log_device_placement = True,allow_soft_placement = True)
'''gpu 按需分配资源'''
config.gpu_options.allow_growth = True or gpu_options = tf.GPUOptions(allow_growth = True)
'''固定资源比例'''
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction =  0.7)
config = tf.ConfigProto(gpu_options = gpu_options)
with tf.Session(config = config):
	xxx
-----------------------------------------------------------------------

-----------------------------------------------------------------------
# 保存和加载模型
saver = tf.train.Saver()
with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	xxx
	saver.save(sess,"save_path.cpkt")
with tf.Session() as sess:
	# 可以初始化也可以不初始化变量,初始化后也会被 restore 覆盖
	saver.restore(sess,"save_path.cpkt")

# 打印保存的内容
from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
print_tensors_in_checkpoint_file("save_path.cpkt",None,True)

# 检查点 加入 max_to_keep 设置保存最大个数,同时传入训练轮数
saver = tf.train.Saver(max_to_keep = 2)
with tf.Session() as sess:
	...
	saver.save(sess,"save_path.cpkt",global_step = epoch)
# 加载的时候指定加载轮次
with tf.Session() as sess2:
	saver.restore(sess2,"save_path.ckpt-" + str(load_epoch))
	
''' 如果觉得指定迭代轮数比较麻烦,还可以这样快速加载模型'''
kpt = tf.train.latest_checkpoint(save_dir):
	if kpt != None:saver.restore(sess,kpt)
-----------------------------------------------------------------------

# TensorBoard 可视化
tf.summary.scalar(tags,value)   # 标量数据汇总
tf.summary.histogram(tag,value) # 直方图汇总
tf.summary.image(tag,tensor)    # 图像数据汇总
tf.summary.merge(inputs)        # 合并所有的汇总日志
tf.summary.FileWriter           # 创建一个 FileWriter

代码片段 ...
...
z = tf.multiply(X,W) + b
tf.summary.histogram('z',z)     # 预测值以直方图展示
cost = tf.reduce_mean(tf.square(Y-z))
tf.summary.scalar("loss",cost)  # 将损失以标量形式表示
with tf.Session() as sess:
	sess.run(init)
	# 合并所有 summary
	merged_summary_op = tf.summary.merge_all()
	# 创建 FileWriter
	summary_writer = tf.summary.FileWriter('log/mnist_with_summaries',sess.graph)
	# 向模型中输入数据
	for epoch in range(20):
		for (x,y) in zip(X_train,Y_train):
			sess.run(train_op,feed_dict = {X:x,Y:y})
		# 每一轮生成一个 summary
		summary_str = sess.run(merged_summary_op,feed_dict = {X:x,Y:y})
		summary_writer.add_summary(summary_str,epoch)
		...
# 此时会在 log/mnist_with_summaries 生成一个文件
cd log 执行
tensorboard --logdir mnist_with_summaries  
即可在浏览器输入 http://ip:6006 查看可视化

附注二:变量共享 & 图的操作

# 共享变量 tf.get_variable 方法,使用 get_variable 生成的变量以指定的 name 为唯一标识符,而不是变量名
# tf.variable_scope 变量作用域

var1 = tf.Variable(1.0,name = 'var1')
print var1.name   var1:0
var1 = tf.Variable(2.0,name = 'var1')
print var1.name   var1_1:0

# 但是如果是 tf.get_variable 就会报错,因为不允许同样的名字
var1 = tf.get_variable('var1',[1],initializer = tf.constant_initializer(1.0))
print var1.name  var1:0
var1 = tf.get_variable('var1',[1],initializer = tf.constant_initializer(2.0))
报错,除非改个 name 或者在不同的变量作用域

with tf.variable_scope("test1") as t1:
    var1 = tf.get_variable("var1",[1],dtype = tf.float32)   test1/var1:0
with tf.variable_scope("test2"):
    var2 = tf.get_variable("var1",[1],dtype = tf.float32)   test2/var1:0
with tf.variable_scope("test1",reuse = tf.AUTO_REUSE): 等同 with tf.variable_scope(t1,reuse = tf.AUTO_REUSE) 且不受外层束缚
    var3 = tf.get_variable("var1",[1],dtype = tf.float32)   test1/var1:0
    
tf.variable_scope 还支持嵌套,上面 var1 和 var3 的 name 是一样的,这表明 var1 和 var3 共享一个变量
tf.reset_default_graph()  # 将图(一个计算任务) 里面的变量清空删除
-----------------------------------------------------------------------------------------------------------

# 初始化共享变量的作用域
with tf.variable_scope("test1",initializer = tf.constant_initializer(0.4)):
    var1 = tf.get_variable("var1",shape = [2],dtype = tf.float32)
    with tf.variable_scope("test2"):
        var2 = tf.get_variable("var2",shape = [2],dtype = tf.float32)
        var3 = tf.get_variable("var3",shape = [2],dtype = tf.float32,initializer = tf.constant_initializer(0.3))
        
print var1.eval()  [0.4 0.4]
print var2.eval()  [0.4 0.4]
print var3.eval()  [0.3 0.3]

# tf.name_scope 只能限制 op,不能限制变量的命名
with tf.variable_scope("test2"):
    with tf.name_scope("bar"):
        v = tf.get_variable("v",[1])
        x = tf.add(1.0,v)
print v.name   test2/v:0  # v 变量明不限制
print x.op.name  test2/bar/add # 影响 op 名

--------------------------------------------------------------------------------------------------------------

# 图的操作
c = tf.constant(0.0)
g = tf.Graph()  建立图
with g.as_default():
    c1 = tf.constant(0.0)
    print c1.graph

g2 = tf.get_default_graph()
print g2
tf.reset_default_graph()
g3 = tf.get_default_graph()
print g3

# 获取张量
t = g.get_tensor_by_name(name = 'Const:0') 获取子图 g 中建立的 c1

a = tf.constant([[1.0,2.0]])
b = tf.constant([[1.0],[3.0]])
tensor1 = tf.matmul(a,b,name = 'exampleop')
test = g3.get_tensor_by_name('exampleop:0') 获取张量
print test  Tensor("exampleop:0",shape = (1,1),dtype = float32)
print tensor1.op.name = exampleop

testop = g3.get_operation_by_name("exampleop")
with tf.Session() as sess:
    test = sess.run(test)
    print "test = ",test  [[7.0]]
    test = tf.get_default_graph().get_tensor_by_name("exampleop:0")
    print "test = ",test  Tensor("exampleop:0", shape=(1, 1), dtype=float32)

'''也可以直接根据变量命名获取'''
tt2 = g.as_graph_element(c1)  # 这里是 c1 而不是 Const:0
print tt2  Tensor("Const:0",shape = (),dtype = float32)

附注三:分布式 TensorFlow

# 分布式 TensorFlow
ps : 作为分布式训练的服务端,等待各个终端 supervisors 来连接
worker : 在 TensorFlow 的代码注释中被称为 supervisors ,作为分布式训练的运算终端
chief supervisors: 在众多运算终端中必须选择一个作为主要的运算终端,该终端是最先启动的。

# 定义 IP 和端口
strps_hosts = "localhost:1681"
strworker_hosts = "localhost:1682,localhost:1683"

# 定义角色名称
strjob_name = "ps"
task_index = 0
# 将字符转成数组
ps_hosts = strps_hosts.split(",")
worker_hosts = strworker_hosts.split(",")

# 创建 server
cluster_spec = tf.train.ClusterSpec({'ps':ps_hosts,'worker':worker_hosts})
server = tf.train.Server(
                    {'ps':ps_hosts,'worker':worker_hosts},
                    job_name = strjob_name,
                    task_index = task_index)

# 为ps 角色使用 join 等待
if strjob_name == 'ps':
    print "Wait"
    server.join()
    
在 tf.train.replica_device_setter 中使用 worker_device 来定义具体任务名称,使用 cluster 指定角色和对应的 IP 地址
with tf.device(tf.train.replica_device_setter(
        worker_device = "/job:worker/task:%d" % task_index,
        cluster = cluster_spec)):
    X = tf.placeholder("float")
    Y = tf.placeholder("float")
    W = tf.Variable(tf.random_normal([1]),name = "weight")
    b = tf.Variable(tf.zeros([1]),name = "bias")
    
    # 获得迭代次数
    global_step = tf.train.get_or_create_global_step()
    z = tf.multiply(X,W) + b
    cost = tf.reduce_mean(tf.square(Y - z))
    train_op = tf.train.GradientDescentOptimizer(0.01).minimize(cost,global_step = global_step)
    saver = tf.train.Saver(max_to_keep = 1)
    init = tf.global_variables_initializer()
    
    trainning_epochs = 2200
    display_step = 2
    # 设置主运算终端
    sv = tf.train.Supervisor(is_chief = (task_index == 0), # 0 号 worker 为 chief
                                logdir = "log/super/",
                                init_op = init,
                                saver = saver,
                                global_step = global_step,
                                save_model_secs = 5)
    # 连接目标角色 session
    with sv.managed_session(server.target) as sess:
        print global_step.eval(session = sess)
        for epoch in range(global_step.eval(session = sess),trainning_epochs * len(train_X)):
            for (x,y) in zip (train_X,train_Y):
                _,epoch = sess.run([train_op,global_step],feed_dict = {X:x,Y:y})
                ... 训练代码
        
        print "Finished"
        sv.saver.save(sess,"xxx" + "sv.cpk",global_step = epoch)
    
    sv.stop()

附注四:激活函数,损失函数,优化方法 & Maxout 神经网络

tf.nn.softmax()                 softmax 层
tf.equal(x,y)                   对应相等为 True
tf.nn.sigmoid(x,name = None)    sigmoid 函数,适用于特征差异比较小的数据
tf.nn.tanh(x,name = None)       tanh 函数,适用于特征相差比较大的数据
tf.nn.relu(x,name = None)       relu 函数,其处理后的数据具有更好的稀疏性,用以替代 sigmoid 函数

由于 relu 函数对负值直接过滤了,所以导致很容易使模型输出全零导致无法训练。
因此 relu 函数存在一些变种,对负值不再直接虑除,而是加以处理
tf.nn.elu(x,name = None)       e^x - 1 (x<0)

tf.nn.relu6(x,name = None)      以6 为阈值的relu ,防止梯度爆炸

swith 函数是谷歌公司发现的一个效果更优于 relu 的函数,经过测试,模型准确率更高
def Swith(x,beta = 1):
    return x * tf.nn.sigmoid(x * beta)

----------------------------------------------------------------------------------------
交叉熵: -[plnq + (1-p)ln(1-q)]

tf.nn.sigmoid_cross_entropy_with_logits(logits,targets)   计算 logits 和 targets 之间的交叉熵
tf.nn.softmax_cross_entropy_with_logits(logits,labels)    计算 softmax 交叉熵,传入的 logits 不需要进行 softmax
                                                          否则就相当于计算了两次 softmax 转换
tf.nn.sparse_softmax_cross_entropy_with_logits(logits,labels) 同上,只是不需要 one_hot 编码,[2,1] 相当于 [[0,0,1],[0,1,0]]

梯度下降分类:
批量梯度下降:遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度和更新梯度。很慢
随机梯度下降:每看一个数据就计算一次损失函数,然后求梯度更新参数,很快,但是收敛性不好
小批量梯度下降:也就是最常用的计算一个batch 的损失函数,再梯度下降
tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
tf.train.AdamOptimizer(learn_rate).minimize(loss) 反向传播算法

----------------------------------------------------------------------------------------
初始化函数:
tf.constant_initializer(value,dtype)    初始化常量
tf.random_normal_initializer(mean = 0.0,stddev = 1.0) 正太随机分布
tf.truncated_normal_initializer(mean = 0.0,stddev = 1.0) 截断的正太分布
tf.random_uniform_initializer(minval = 0,maxval = None)  均匀分布
tf.zeros_initializer(shape)  tf.ones_initializer(shape)
一般常用的初始化函数为 tf.truncated_normal_initializer 函数,因为有截断的功能,生成相对温和的初始值

另外,还有个 tf.contrib.layers.xavier_initializer 初始化函数,用来在所有层中保持梯度大体相同

Maxout 神经网络:
取一层神经网络中最敏感的节点传导下一层,Maxout 神经网络具有很强的拟合性
z = tf.matmul(x,W) + b
maxout = tf.reduce_max(z,axis = 1,keep_dims = True)
W2 = tf.Variable(tf.truncated_normal([1,10],stddev = 0.1))
b2 = tf.Variable(tf.zeros([10]))
pred = tf.nn.softmax(tf.matmul(maxout,W2) + b2)
...

附注五:激活函数 & 隐藏层

tf.nn.softmax()                 softmax 层
tf.equal(x,y)                   对应相等为 True
tf.nn.sigmoid(x,name = None)    sigmoid 函数,适用于特征差异比较小的数据
tf.nn.tanh(x,name = None)       tanh 函数,适用于特征相差比较大的数据
tf.nn.relu(x,name = None)       relu 函数,其处理后的数据具有更好的稀疏性,用以替代 sigmoid 函数

由于 relu 函数对负值直接过滤了,所以导致很容易使模型输出全零导致无法训练。
因此 relu 函数存在一些变种,对负值不再直接虑除,而是加以处理
tf.nn.elu(x,name = None)       e^x - 1 (x<0)

tf.nn.relu6(x,name = None)      以6 为阈值的relu ,防止梯度爆炸

swith 函数是谷歌公司发现的一个效果更优于 relu 的函数,经过测试,模型准确率更高
def Swith(x,beta = 1):
    return x * tf.nn.sigmoid(x * beta)

隐藏层可以看做逻辑门,也可以看做将低维可分转化成高一维的可分
模型正则化有两种
tf.contrib.layers.l2_regularizer(lambda)(w)
tf.nn.l2_loss(w) * lambda

dropout 随机失活
layer = tf.nn.dropout(layer,keep_prob)

附注六:卷积神经网络 & 多线程读取机制

退化学习率
tf.train.exponential_decay(learning_rate,global_step,train_step,0.9)

在搭建网络结构时,一般倾向于使用更深的模型,来减少网络中需要神经元的数量,使得网络具有更好的泛化能力。
但注意使用 sigmoid 或 tanH 激活函数时,其反向传播的有效层数大概 4 ~6 层,层数再多可能导致梯度消失无法训练的问题。

卷积神经网络 CNN -> 解决参数过多的问题
一般对一幅图片(或者输入矩阵)会使用多个卷积核,将它们统一放到卷积层操作,得到更深的矩阵。
一般CNN 结构如下:
输入层:将每个像素代表一个特征节点输入进来
卷积操作部分:由多个滤波器组合的卷积层
池化层:减少参数
全剧平均池化层:对生成的结果取全局平均值
输出层:softmax

卷积操作:
1.窄卷积:就是不使用 PADDING 填充,步长不固定
2.同卷积:使用 PADDING 填充,得到的尺寸不变,步长固定为 1
3.全卷积:也叫反卷积,把图片中的每个像素都用卷积操作展开,得到的结果比原始图片大,步长固定为 1

tf.nn.conv2d(input,filter,strides,padding,name = None) padding = 'SAME' 则填充到滤波器可达到图像边缘,先在右下补零

池化层:tf.nn.max_pool (avg_pool)
tf.nn.max_pool(input,ksize,strides,padding,name = None)
ksize: 池化窗口的大小,一般是 [1,height,width,1] 因为我们不想在 batch 和 channels 上池化
strides: 和卷积参数含义一样,一般也是 [1,stride,stride,1]
padding: 和卷积层含义一样
注意平均池化层计算的是非零值的平均值

-------------------------------------------------------------------------------------
在 TensorFlow 中使用 queue 多线程数据读取机制
TensorFlow 提供了一个队列机制,通过多线程将读取数据和计算数据分开,因为在处理海量数据时,无法将数据集一次性载入内存
images_test,labels_test = cifar10_input.inputs(eval_data = False,data_dir = data_dir,batch_size = 128)
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
tf.train.start_queue_runners()
image_batch,label_batch = sess.run([images_test,labels_test]) # 从队列里拿出指定批次的数据
...
如果注释掉 tf.global_variables_initializer().run() ,
则程序会在 image_batch,label_batch = sess.run([images_test,labels_test]) 挂起不动
缺点是不能 with tf.Session() 语法,因为session 一旦关闭,等待队列出错

协调器: tf.train.Coordinator,通常搭配 tf.train.start_queue_runners() 一起使用
coord.request_stop() 会通知数据输入线程退出
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    # 定义协调器
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess,coord)
    image_batch,label_batch = sess.run([images_test,labels_test])
    ...
    coord.request_stop()

附注七:反卷积神经网络 & 梯度求解

反卷积神经网络: 卷积神经网络的可视化
反卷积过程并不具有学习的能力,仅仅是用于可视化一个已经训练好的卷积神经网络模型。

反卷积步骤:
1.卷积核反转(上下左右颠倒)
2.将卷积结果作为输入,做步长补零的操作。
3.在补充后的输入基础上整体补零,以使得与反卷积核卷积后的结果为原始的 shape
4.将得到的补零的结果与反卷积核进行步长为 1 的卷积,得到最终的反卷积结果。

tf.conv2d_transpose(value,  # 卷积后的张量
                    filter, # 卷积核 - 不用自己转置
                    output_shape, #输出的张量形状 4 维
                    strides, # 卷积时的 strides
                    padding, # 卷积时的 padding
                    name = None)
                    
注意反卷积只能恢复部分特征,并不能完全还原。

反池化步骤:
反平均池化:直接还原成原来的大小,然后将池化结果中每个值填入对应区域。
反最大池化:要求在池化过程中记录最大激活位置,然后把池化结果填入对应位置,其他补零。
所以在反最大池化时,必须记录最大池化激活位置
_,mask = tf.nn.max_pool_with_argmax(net,ksize = ksize,strides = strides,padding = 'SAME')
mask = tf.stop_gradient(mask) # mask 就会记录最大激活位置
net = tf.nn.max_pool(net,ksize = ksize,strides = strides,padding = 'SAME') # 最大池化层

-------------------------------------------------------------------------------------------
求梯度函数 tf.gradients
W1 = tf.Variable([[1,2]])
y = tf.matmul(W1,[[9],[10]])
grads = tf.gradients(y,W1)
# 求 W1 的梯度,由于 y 是由 W1 和 [[9],[10]] 相乘而来,所以其导数也就是 [[9,10]]
with tf.Session() as sess:
    tf.all_variables_initializer().run()
    gradval = sess.run(grads)
    print gradval # 输出 [array([[9,10]])]

使用 gradients 对多个式子求多变量偏导
W1 = tf.get_variable("W1",shape = [2])
W2 = tf.get_variable("W2",shape = [2])
W3 = tf.get_variable("W3",shape = [2])
W4 = tf.get_variable("W4",shape = [2])
y1 = W1 + W2 +W3
y2 = W3 + W4
# grad_ys 求梯度的输入值
gradients = tf.gradients([y1,y2],[W1,W2,W3,W4],grad_ys = [
                                   tf.convert_to_tensor([1.,2.]),
                                   tf.convert_to_tensor([3.,4.])])
grads_ys 给定公式结果的值,相当于 y1 = [1.,2.] y2 = [3.,4.] 时,W1,W2,W3,W4 的导数
对 W1 求导时,W2,W3 为常数,所以 W1 的导数为[1.,2.], W2,W3 也如此
同理,W3 W4 的导数为 [3.,4.]

梯度停止的用法,被 tf.stop_gradients 定义过的节点将没有梯度运算功能
a = W1 + W2
a_stop = tf.stop_gradients(a) # 令 a 梯度停止
y3 = a_stop + W3
gradients2 = tf.gradients(y3,[W1,W2,W3],grad_ys = tf.convert_to_tensor([1.,2.]))
运行 sess.run(gradients2) 则会报错,因为 W1 和 W2 的梯度不可求,除非去掉 W1,W2

附注八:卷积层测高层封装 & 批量归一化

卷积层和全连接层的高层封装
tf.contrib.layers.conv2d(x_image,过滤器深度,过滤器尺寸,strides,padding,activation_fn = tf.nn.relu)
tf.contrib.layers.max_pool2d(h_pool2,过滤器尺寸,stride,padding)
tf.contrib.layers.full_connected(input,下一节点个数,activation_fn = tf.nn.softmax)

批量归一化
from tensorflow.contrib.layers.python.layers import batch_norm
def batch_norm_layer(value,train = None,name = 'batch_norm'):
    if train is not None:
        return batch_norm(value,decay = 0.9,updates_collections = None,
                is_training = True)
    else:
        return batch_norm(value,decay = 0.9,updates_collections = None,
                is_training = False)

猜你喜欢

转载自blog.csdn.net/qq_32023541/article/details/83054678