TensorFlow中cnn-cifar10样例代码详解

来源:互联网 发布:知乎 正装西服品牌 编辑:程序博客网 时间:2024/06/09 18:46

       TensorFlow是一个支持分布式的深度学习框架,在Google的推动下,它正在变得越来越普及。我最近学了TensorFlow教程上的一个例子,即采用CNNcifar10数据集进行分类。在看源代码的时候,看完后有一种似懂非懂的感觉,又考虑到这个样例涵盖了tensorflow的大部分语法知识,包括QueueRunners机制、Tensorboard可视化和多GPU数据并行编程等。“纸上得来终觉浅,绝知此事要躬行”,于是我便照着自己的理解和记忆来重新编程实现一遍,实现过程中也遇到了一些问题,在这里把我对程序的详细的理解和遇到的问题记录下来,本着“知其然,知其所以然”的标准,程序中的注释更加侧重于对‘为什么这一行代码要这样写’的解读,以供以后参考(关于卷积神经网络相关的理论部分,网上有很多了,这里就不做太多介绍)

一个标准的机器学习程序,应该包括数据输入、定义模型本身、模型训练和模型性能测试四大部分,可以分成四个.py文件。

(一)数据输入部分(input_dataset.py

       从概念上来说,这部分主要是关于数据管道(data pipe)的构建,数据流向为“二进制文件->文件名队列->数据队列->读取出的data-batch”。数据块用于输入到深度学习网络中,进行信息的forward propagation,这部分在定义模型本身部分讨论。在定义整个数据管道的时候,会使用到TensorFlow的队列机制,这部分在之前的博文“TensorFlow读取二进制文件数据到队列”中进行了详细讲述。另外,读原数据文件的时候,要结合文件本身的格式,相信编写过c语言读取二进制文件的程序的朋友,对这应该再熟悉不过了,具体的代码如下,

# -*- coding: utf-8 -*-import osimport tensorflow as tf# 原图像的尺度为32*32,但根据常识,信息部分通常位于图像的中央,这里定义了以中心裁剪后图像的尺寸fixed_height = 24fixed_width = 24# cifar10数据集的格式,训练样例集和测试样例集分别为50k和10ktrain_samples_per_epoch = 50000test_samples_per_epoch = 10000data_dir='./cifar-10-batches-bin' # 定义数据集所在文件夹路径batch_size=128 #定义每次参数更新时,所使用的batch的大小 def read_cifar10(filename_queue):    # 定义一个空的类对象,类似于c语言里面的结构体定义    class Image(object):        pass    image = Image()    image.height=32    image.width=32    image.depth=3    label_bytes = 1    image_bytes = image.height*image.width*image.depth    Bytes_to_read = label_bytes+image_bytes    # 定义一个Reader,它每次能从文件中读取固定字节数    reader = tf.FixedLengthRecordReader(record_bytes=Bytes_to_read)     # 返回从filename_queue中读取的(key, value)对,key和value都是字符串类型的tensor,并且当队列中的某一个文件读完成时,该文件名会dequeue    image.key, value_str = reader.read(filename_queue)     # 解码操作可以看作读二进制文件,把字符串中的字节转换为数值向量,每一个数值占用一个字节,在[0, 255]区间内,因此out_type要取uint8类型    value = tf.decode_raw(bytes=value_str, out_type=tf.uint8)     # 从一维tensor对象中截取一个slice,类似于从一维向量中筛选子向量,因为value中包含了label和feature,故要对向量类型tensor进行'parse'操作        image.label = tf.slice(input_=value, begin=[0], size=[label_bytes])# begin和size分别表示待截取片段的起点和长度    data_mat = tf.slice(input_=value, begin=[label_bytes], size=[image_bytes])    data_mat = tf.reshape(data_mat, (image.depth, image.height, image.width)) #这里的维度顺序,是依据cifar二进制文件的格式而定的    transposed_value = tf.transpose(data_mat, perm=[1, 2, 0]) #对data_mat的维度进行重新排列,返回值的第i个维度对应着data_mat的第perm[i]维    image.mat = transposed_value        return image        def get_batch_samples(img_obj, min_samples_in_queue, batch_size, shuffle_flag):'''tf.train.shuffle_batch()函数用于随机地shuffling 队列中的tensors来创建batches(也即每次可以读取多个data文件中的样例构成一个batch)。这个函数向当前Graph中添加了下列对象:*创建了一个shuffling queue,用于把‘tensors’中的tensors压入该队列;*一个dequeue_many操作,用于根据队列中的数据创建一个batch;*创建了一个QueueRunner对象,用于启动一个进程压数据到队列capacity参数用于控制shuffling queue的最大长度;min_after_dequeue参数表示进行一次dequeue操作后队列中元素的最小数量,可以用于确保batch中元素的随机性;num_threads参数用于指定多少个threads负责压tensors到队列;enqueue_many参数用于表征是否tensors中的每一个tensor都代表一个样例tf.train.batch()与之类似,只不过顺序地出队列(也即每次只能从一个data文件中读取batch),少了随机性。'''    if shuffle_flag == False:        image_batch, label_batch = tf.train.batch(tensors=img_obj,                                                   batch_size=batch_size,                                                   num_threads=4,                                                   capacity=min_samples_in_queue+3*batch_size)    else:        image_batch, label_batch = tf.train.shuffle_batch(tensors=img_obj,                                                           batch_size=batch_size,                                                           num_threads=4,                                                           min_after_dequeue=min_samples_in_queue,                                                          capacity=min_samples_in_queue+3*batch_size)                                                        tf.image_summary('input_image', image_batch, max_images=6) #输出预处理后图像的summary缓存对象,用于在session中写入到事件文件中                                                        return image_batch, tf.reshape(label_batch, shape=[batch_size])                                            def preprocess_input_data():'''这部分程序用于对训练数据集进行‘数据增强’操作,通过增加训练集的大小来防止过拟合'''    filenames = [os.path.join(data_dir, 'data_batch_%d.bin' % i) for i in range(1, 6)]    #filenames =[os.path.join(data_dir, 'test_batch.bin')]    for f in filenames: #检验训练数据集文件是否存在        if not tf.gfile.Exists(f):            raise ValueError('fail to find file:'+f)        filename_queue = tf.train.string_input_producer(string_tensor=filenames) # 把文件名输出到队列中,作为整个data pipe的第一阶段    image = read_cifar10(filename_queue) #从文件名队列中读取一个tensor类型的图像    new_img = tf.cast(image.mat, tf.float32)    tf.image_summary('raw_input_image', tf.reshape(new_img, [1, 32, 32, 3]))#输出预处理前图像的summary缓存对象    new_img = tf.random_crop(new_img, size=(fixed_height, fixed_width, 3)) #从原图像中切割出子图像    new_img = tf.image.random_brightness(new_img, max_delta=63) #随机调节图像的亮度    new_img = tf.image.random_flip_left_right(new_img) #随机地左右翻转图像    new_img = tf.image.random_contrast(new_img, lower=0.2, upper=1.8) #随机地调整图像对比度    final_img = tf.image.per_image_whitening(new_img) #对图像进行whiten操作,目的是降低输入图像的冗余性,尽量去除输入特征间的相关性        min_samples_ratio_in_queue = 0.4  #用于确保读取到的batch中样例的随机性,使其覆盖到更多的类别、更多的数据文件!!!    min_samples_in_queue = int(min_samples_ratio_in_queue*train_samples_per_epoch)     return get_batch_samples([final_img, image.label], min_samples_in_queue, batch_size, shuffle_flag=True)

(二)模型本身定义部分(forward_prop.py

       定义模型本身,也就是确定出网络结构(Graph),使得输入信号流在该图中进行forward propagation。在本样例中定义的网络结构为“输入层->卷积层->池化层->规范化层->卷积层->规范化层->池化层->全连接层->全连接层->softmax输出层”。与其他的深度网络模型不同,这里引入了规范化层,原因是Relu(rectified linear unit)激活函数会把输入激励映射到[0, infinite],详细的代码及其解释如下,

# -*- coding: utf-8 -*-import tensorflow as tfimport input_dataset#外部引用input_dataset文件中定义的hyperparametersheight = input_dataset.fixed_heightwidth = input_dataset.fixed_widthtrain_samples_per_epoch = input_dataset.train_samples_per_epochtest_samples_per_epoch = input_dataset.test_samples_per_epoch # 用于描述训练过程的常数moving_average_decay = 0.9999     # The decay to use for the moving average.num_epochs_per_decay = 350.0      # 衰减呈阶梯函数,控制衰减周期(阶梯宽度)learning_rate_decay_factor = 0.1  # 学习率衰减因子initial_learning_rate = 0.1       # 初始学习率 def variable_on_cpu(name, shape, dtype, initializer):    with tf.device("/cpu:0"):  #一个 context manager,用于为新的op指定要使用的硬件        return tf.get_variable(name=name,                                shape=shape,                                initializer=initializer,                               dtype=dtype)     def variable_on_cpu_with_collection(name, shape, dtype, stddev, wd):    with tf.device("/cpu:0"):         weight = tf.get_variable(name=name,                                  shape=shape,                                  initializer=tf.truncated_normal_initializer(stddev=stddev, dtype=dtype))        if wd is not None:            weight_decay = tf.mul(tf.nn.l2_loss(weight), wd, name='weight_loss')            tf.add_to_collection(name='losses', value=weight_decay)                 return weight        def losses_summary(total_loss):#通过使用指数衰减,来维护变量的滑动均值。当训练模型时,维护训练参数的滑动均值是有好处的。在测试过程中使用滑动参数比最终训练的参数值本身,    #会提高模型的实际性能(准确率)。apply()方法会添加trained variables的shadow copies,并添加操作来维护变量的滑动均值到shadow copies。average    #方法可以访问shadow variables,在创建evaluation model时非常有用。#滑动均值是通过指数衰减计算得到的。shadow variable的初始化值和trained variables相同,其更新公式为# shadow_variable = decay * shadow_variable + (1 - decay) * variable    average_op = tf.train.ExponentialMovingAverage(decay=0.9) #创建一个新的指数滑动均值对象    losses = tf.get_collection(key='losses')# 从字典集合中返回关键字'losses'对应的所有变量,包括交叉熵损失和正则项损失    # 创建‘shadow variables’,并添加维护滑动均值的操作    maintain_averages_op = average_op.apply(losses+[total_loss])#维护变量的滑动均值,返回一个能够更新shadow variables的操作    for i in losses+[total_loss]:        tf.scalar_summary(i.op.name+'_raw', i) #保存变量到Summary缓存对象,以便写入到文件中        tf.scalar_summary(i.op.name, average_op.average(i)) #average() returns the shadow variable for a given variable.    return maintain_averages_op  #返回损失变量的更新操作    def one_step_train(total_loss, step):    batch_count = int(train_samples_per_epoch/input_dataset.batch_size) #求训练块的个数     decay_step = batch_count*num_epochs_per_decay #每经过decay_step步训练,衰减lr    lr = tf.train.exponential_decay(learning_rate=initial_learning_rate,                                    global_step=step,                                    decay_steps=decay_step,                                    decay_rate=learning_rate_decay_factor,                                    staircase=True)    tf.scalar_summary('learning_rate', lr)    losses_movingaverage_op = losses_summary(total_loss)    #tf.control_dependencies是一个context manager,控制节点执行顺序,先执行control_inputs中的操作,再执行context中的操作    with tf.control_dependencies(control_inputs=[losses_movingaverage_op]):        trainer = tf.train.GradientDescentOptimizer(learning_rate=lr)        gradient_pairs = trainer.compute_gradients(loss=total_loss) #返回计算出的(gradient, variable) pairs    gradient_update = trainer.apply_gradients(grads_and_vars=gradient_pairs, global_step=step) #返回一步梯度更新操作    #num_updates参数用于动态调整衰减率,真实的decay_rate =min(decay, (1 + num_updates) / (10 + num_updates)     variables_average_op = tf.train.ExponentialMovingAverage(decay=moving_average_decay, num_updates=step)    # tf.trainable_variables() 方法返回所有`trainable=True`的变量,列表结构    maintain_variable_average_op = variables_average_op.apply(var_list=tf.trainable_variables())#返回模型参数变量的滑动更新操作    with tf.control_dependencies(control_inputs=[gradient_update, maintain_variable_average_op]):        gradient_update_optimizor = tf.no_op() #Does nothing. Only useful as a placeholder for control edges    return gradient_update_optimizor                        def network(images):#这一部分主要调用几个常见函数,在上一篇博客‘TensorFlow实现卷积神经网络’中有详细介绍,这里就不再赘述~    with tf.variable_scope(name_or_scope='conv1') as scope:        weight = variable_on_cpu_with_collection(name='weight',                                                  shape=(5, 5, 3, 64),                                                  dtype=tf.float32,                                                  stddev=0.05,                                                 wd = 0.0)        bias = variable_on_cpu(name='bias', shape=(64), dtype=tf.float32, initializer=tf.constant_initializer(value=0.0))        conv1_in = tf.nn.conv2d(input=images, filter=weight, strides=(1, 1, 1, 1), padding='SAME')        conv1_in = tf.nn.bias_add(value=conv1_in, bias=bias)        conv1_out = tf.nn.relu(conv1_in)             pool1 = tf.nn.max_pool(value=conv1_out, ksize=(1, 3, 3, 1), strides=(1, 2, 2, 1), padding='SAME')        norm1 = tf.nn.lrn(input=pool1, depth_radius=4, bias=1.0, alpha=0.001/9.0, beta=0.75)        with tf.variable_scope(name_or_scope='conv2') as scope:        weight = variable_on_cpu_with_collection(name='weight',                                  shape=(5, 5, 64, 64),                                  dtype=tf.float32,                                  stddev=0.05,                                 wd=0.0)        bias = variable_on_cpu(name='bias', shape=(64), dtype=tf.float32, initializer=tf.constant_initializer(value=0.1))        conv2_in = tf.nn.conv2d(norm1, weight, strides=(1, 1, 1, 1), padding='SAME')        conv2_in = tf.nn.bias_add(conv2_in, bias)        conv2_out = tf.nn.relu(conv2_in)         norm2 = tf.nn.lrn(input=conv2_out, depth_radius=4, bias=1.0, alpha=0.001/9.0, beta=0.75)        pool2 = tf.nn.max_pool(value=norm2, ksize=(1, 3, 3, 1), strides=(1, 2, 2, 1), padding='SAME')    # input tensor of shape `[batch, in_height, in_width, in_channels]    reshaped_pool2 = tf.reshape(tensor=pool2, shape=(-1, 6*6*64))        with tf.variable_scope(name_or_scope='fully_connected_layer1') as scope:        weight = variable_on_cpu_with_collection(name='weight',                                                  shape=(6*6*64, 384),                                                  dtype=tf.float32,                                                 stddev=0.04,                                                 wd = 0.004)        bias = variable_on_cpu(name='bias', shape=(384), dtype=tf.float32, initializer=tf.constant_initializer(value=0.1))        fc1_in = tf.matmul(reshaped_pool2, weight)+bias        fc1_out = tf.nn.relu(fc1_in)        with tf.variable_scope(name_or_scope='fully_connected_layer2') as scope:        weight = variable_on_cpu_with_collection(name='weight',                                                  shape=(384, 192),                                                  dtype=tf.float32,                                                 stddev=0.04,                                                 wd=0.004)        bias = variable_on_cpu(name='bias', shape=(192), dtype=tf.float32, initializer=tf.constant_initializer(value=0.1))        fc2_in = tf.matmul(fc1_out, weight)+bias        fc2_out = tf.nn.relu(fc2_in)            with tf.variable_scope(name_or_scope='softmax_layer') as scope:        weight = variable_on_cpu_with_collection(name='weight',                                                  shape=(192, 10),                                                  dtype=tf.float32,                                                 stddev=1/192,                                                 wd=0.0)        bias = variable_on_cpu(name='bias', shape=(10), dtype=tf.float32, initializer=tf.constant_initializer(value=0.0))        classifier_in = tf.matmul(fc2_out, weight)+bias        classifier_out = tf.nn.softmax(classifier_in)    return classifier_out def loss(logits, labels):     labels = tf.cast(x=labels, dtype=tf.int32)  #强制类型转换,使符合sparse_softmax_cross_entropy_with_logits输入参数格式要求    cross_entropy_loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=labels, name='likelihood_loss')    cross_entropy_loss = tf.reduce_mean(cross_entropy_loss, name='cross_entropy_loss') #对batch_size长度的向量取平均        tf.add_to_collection(name='losses', value=cross_entropy_loss) #把张量cross_entropy_loss添加到字典集合中key='losses'的子集中      return tf.add_n(inputs=tf.get_collection(key='losses'), name='total_loss') #返回字典集合中key='losses'的子集中元素之和

(三)模型训练部分(train.py)

       模型训练的实质就是一个“参数寻优”的过程,最常见的优化算法是mini-batch的随机梯度下降法(mini-batch是相对于online learning而言的),寻找使得损失函数值最小的模型参数。为了防止过拟合,这里的损失函数包含了正则化项,具体的代码解释如下,

# -*- coding: utf-8 -*-import input_datasetimport forward_propimport tensorflow as tfimport osimport numpy as np max_iter_num = 100000 #设置参数迭代次数checkpoint_path = './checkpoint' #设置模型参数文件所在路径event_log_path = './event-log' #设置事件文件所在路径,用于周期性存储Summary缓存对象 def train():    with tf.Graph().as_default():    #指定当前图为默认graph        global_step = tf.Variable(initial_value=0, trainable=False)#设置trainable=False,是因为防止训练过程中对global_step变量也进行滑动更新操作        img_batch, label_batch = input_dataset.preprocess_input_data()#输入图像的预处理,包括亮度、对比度、图像翻转等操作        # img_batch, label_batch = input_dataset.input_data(eval_flag=False)        logits = forward_prop.network(img_batch) #图像信号的前向传播过程        total_loss = forward_prop.loss(logits, label_batch) #计算损失        one_step_gradient_update = forward_prop.one_step_train(total_loss, global_step) #返回一步梯度更新操作        #创建一个saver对象,用于保存参数到文件中        saver = tf.train.Saver(var_list=tf.all_variables()) #tf.all_variables return a list of `Variable` objects                all_summary_obj = tf.merge_all_summaries()#返回所有summary对象先merge再serialize后的的字符串类型tensor        initiate_variables = tf.initialize_all_variables()        #log_device_placement参数可以记录每一个操作使用的设备,这里的操作比较多,就不需要记录了,故设置为False        with tf.Session(config=tf.ConfigProto(log_device_placement=False)) as sess:            sess.run(initiate_variables)  #变量初始化                       tf.train.start_queue_runners(sess=sess) #启动所有的queuerunners            Event_writer = tf.train.SummaryWriter(logdir=event_log_path, graph=sess.graph)             for step in range(max_iter_num):                _, loss_value = sess.run(fetches=[one_step_gradient_update, total_loss])                assert not np.isnan(loss_value) #用于验证当前迭代计算出的loss_value是否合理                if step%10 == 0:                    print('step %d, the loss_value is %.2f' % (step, loss_value))                if step%100 == 0:                    # 添加`Summary`协议缓存到事件文件中,故不能写total_loss变量到事件文件中,因为这里的total_loss为普通的tensor类型                    all_summaries = sess.run(all_summary_obj)                    Event_writer.add_summary(summary=all_summaries, global_step=step)                if step%1000 == 0 or (step+1)==max_iter_num:                    variables_save_path = os.path.join(checkpoint_path, 'model-parameters.bin') #路径合并,返回合并后的字符串                    saver.save(sess, variables_save_path, global_step=step)#把所有变量(包括moving average前后的模型参数)保存在variables_save_path路径下                 if __name__ == '__main__':    train()                

(四)模型性能评估部分(evaluate.py

       机器学习模型训练好之后,要在测试数据集上进行测试,从而判断模型的性能,常见的性能指标有准确率、召回率等。顺便提及一下,有的机器学习模型在训练时,会把数据集分成三部分,训练集(training dataset,正则集(validation dataset)和测试集(test dataset,正则集的作用也是为了防止过拟合,但我们这里通过对模型参数正则化来防止过拟合,因此就不用像这样划分数据集了,具体的代码及解释如下,

# -*- coding: utf-8 -*-import tensorflow as tfimport input_datasetimport forward_propimport trainimport mathimport numpy as np def eval_once(summary_op, summary_writer, saver, predict_true_or_false):    with tf.Session() as sess:#从checkpoint文件中返回checkpointstate模板        checkpoint_proto = tf.train.get_checkpoint_state(checkpoint_dir=train.checkpoint_path)        if checkpoint_proto and checkpoint_proto.model_checkpoint_path:            saver.restore(sess, checkpoint_proto.model_checkpoint_path)#恢复模型变量到当前session中        else:            print('checkpoint file not found!')            return        # 启动很多线程,并把coordinator传递给每一个线程            coord = tf.train.Coordinator() #返回一个coordinator类对象,这个类实现了一个简单的机制,可以用来coordinate很多线程的结束        try:            threads = [] #使用coord统一管理所有线程            for queue_runner in tf.get_collection(key=tf.GraphKeys.QUEUE_RUNNERS):                threads.extend(queue_runner.create_threads(sess, coord=coord, daemon=True, start=True))#计算测试数据块的个数,并向上取整            test_batch_num = math.ceil(input_dataset.test_samples_per_epoch/input_dataset.batch_size)            iter_num = 0            true_test_num = 0#这里使用取整后的测试数据块个数,来计算测试样例的总数目,理论上这样算测试样例总数会偏大啊,暂时还未理解???            total_test_num = test_batch_num*input_dataset.batch_size                        while iter_num<test_batch_num and not coord.should_stop():                result_judge = sess.run([predict_true_or_false])                true_test_num += np.sum(result_judge)                iter_num += 1            precision = true_test_num/total_test_num            print("The test precision is %.3f"  % precision)        except:            coord.request_stop()        coord.request_stop()        coord.join(threads)                def evaluate():    with tf.Graph().as_default() as g:        img_batch, labels = input_dataset.input_data(eval_flag=True)#读入测试数据集        logits = forward_prop.network(img_batch)#使用moving average操作前的模型参数,计算模型输出值#判断targets是否在前k个predictions里面,当k=1时等价于常规的计算正确率的方法,sess.run(predict_true_or_false)会执行符号计算        predict_true_or_false = tf.nn.in_top_k(predictions=logits, targets=labels, k=1)        #恢复moving average操作后的模型参数        moving_average_op = tf.train.ExponentialMovingAverage(decay=forward_prop.moving_average_decay)#返回要恢复的names到Variables的映射,也即一个map映射。如果一个变量有moving average,就使用moving average变量名作为the restore# name, 否则就使用变量名        variables_to_restore = moving_average_op.variables_to_restore()        saver = tf.train.Saver(var_list=variables_to_restore)                summary_op = tf.merge_all_summaries() #创建序列化后的summary对象#创建一个event file,用于之后写summary对象到logdir目录下的文件中        summary_writer = tf.train.SummaryWriter(logdir='./event-log-test', graph=g)        eval_once(summary_op, summary_writer, saver, predict_true_or_false)

另外,在自己编写程序的过程中,出现了一些错误提示,在这里一并记录下来,供以后参考,

(1)"SyntaxError: positional argument follows keyword argument"

错误原因:在python中向子函数传递参数时,实参或者全部用关键字参数;或者全部用定位参数;当同时使用关键字参数和定位参数时,一定是定位参数在前,关键字参数在后,样例如下,

              def test(a, b, c):

                  return a+b+c

            则以下三种调用方式均正确,

            test(1,2,c=3)

            test(1,2,3)  

            test(a=1, b=2, c=3) 

(2)语句"with tf.Graph.as_default()"出现错误“TypeError: as_default() missing 1 required positional argument: 'self'

错误原因:应该为tf.Graph().as_default()

(3)打开tensorboard时提示“inner server error

错误原因:在我的电脑上开启了lantern代理,导致启动tensorboard时服务器出错

(4)错误提示“TypeError: int() argument must be a string, a bytes-like object or a number, not 'Variable'

错误原因:tf.get_variable()中的shape参数不能为tensor类型,可以区别下面的两种情况来理解

情况1: reshape = tf.reshape(pool2, [batch_size, -1])

     dim = reshape.get_shape()[1].value  #reshape.get_shape()[1]dimension类型tensor,取其value属性会得到int类型数值

情况2 reshaped_pool2 = tf.reshape(tensor=pool2, shape=(batch_size, -1))

dim = tf.shape(reshaped_pool2)[1]   #dimtensor类型

又因为tf.get_variable(name, shape=[dim, 384], initializer=initializer, dtype=dtype)函数中,shape参数必须为ndarray类型

(5)在每次迭代时,打印出的损失值过大,如下所示,

    step 0, the loss_value is 22439.82

    step 10, the loss_value is 6426354679171382723219403309056.00

    

    错误原因:设置权值参数w时,标准差取了一个过大的constant,

     如设置weight = tf.get_variable(name=name, shape=shape, initializer=tf.truncated_normal_initializer(stddev=0.5, dtype=dtype))

(6)本程序在tensorflow0.8.0版本下也是可以运行的,只不过需要把tf.train.batchtf.train.shuffle_batch函数中的关键字tensors改成tensor_list

(7)错误提示“UnboundLocalError: local variable 'CONSTANT' referenced before assignment

错误原因:可以参见下面这段代码

CONSTANT = 0  

def modifyConstant() :  

         print CONSTANT  

      CONSTANT += 1

在函数内部修改了变量CONSTANTPython认为CONSTANT是局部变量,而print CONSTANT又在CONSTANT += 1之前,所以会发生这种错误。

如果必须在函数内部访问并修改全局变量,应该使用关键字global在函数内声明变量CONSTANT

(8)要注意区别tf.reshape()tf.transpose()函数,前者是按照数据的存储先后顺序重新调整tensor的尺寸,而后者是从空间角度进行维度的旋转。

参考资料:https://www.tensorflow.org/versions/r0.11/tutorials/deep_cnn/index.html#convolutional-neural-networks



7 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 婴儿脸上口水癣怎么办 嘴巴旁边长癣怎么办 美团机票不出票怎么办 东方航空会员锁定怎么办 大众车烧机油怎么办 大众cc烧机油怎么办 叫外卖给差评被打怎么办 发现宿舍被盗后怎么办 知了猴变黑了怎么办 婴儿仙人掌的刺怎么办 仙人掌刺扎进皮肤里怎么办 被仙人掌的小细绒刺扎到怎么办 值机截止了怎么办 社保卡消磁了怎么办 住宾馆没身份证怎么办 社保卡电话错误怎么办 没住过酒店怎么办 上海合规网约车证件怎么办 取票没有身份证怎么办 买车票没有身份证怎么办 登机身份证丢了怎么办 飞机没带身份证怎么办 上飞机没带身份证怎么办 机场没带身份证怎么办 儿童坐飞机没有户口本怎么办 不需要行李托运化妆品怎么办 坐飞机被限制了怎么办 坐飞机没买保险怎么办 飞机起飞时难受怎么办 婴儿坐飞机没座位怎么办 转机行李不直达怎么办 儿童自己坐飞机怎么办手续 两岁宝宝发烧怎么办 网上购票待核验怎么办 老人坐飞机找不到登机口怎么办 儿童不能值机怎么办 飞机上旅客刁难怎么办 飞机上婴儿哭闹怎么办 飞机上婴儿啼哭怎么办 飞机儿童陪护手续怎么办 孕妇感冒鼻子堵怎么办