日期:2020.03.18-2020.03.20
Ref: <tensorflow工程化项目实战>
章节:chapter5
tf代码分析
p85 line57 image = tf.image.decode_jpeg(image_string, channels=3)
解释:网络能够处理的图像是三维矩阵,但由于图像在存储时并不是直接记录这些矩阵中的数字,而是记录经过压缩编码之后的结果。所以要将一张图象还原成一个三维矩阵需要解码的过程。tf内置的解码图片过程分为两个函数,读取和解码,即这里的:
image_string = tf.read_file(filename)
image = tf.image.decode_jpeg(image_string, channels=3)
p87 line71 dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
解释:将输入的张量的第一个维度看做样本的个数,沿其第一个维度将tensor切片,得到的每个切片是一个样本数据。实现了输入张量的自动切片。在这里传入的是一组元组,也是可以分开逐一处理的,但必须保证第一位维度相同。
链接: tf.data.Dataset.from_tensor_slices.
这里给出一个tf五步加载数据集的案例,和本代码基本一致。
链接: tf.data.Dataset.from_tensor_slices使用方法.
p89 line27 global_step = tf.train.get_or_create_global_step()
解释:这个函数主要用于返回或者创建(如果有必要的话)一个全局步数的tensor。参数只有一个,就是图,如果没有指定那么就是默认的图。
p89 line34
variables_to_restore = slim.get_variables_to_restore(exclude=exclude)
解释:获取所有变量,包括模型变量(如权重和参数)和常规变量(如global step),可以传入scope进行过滤。如这里传入由final_layer和aux_7两个作用域的列表进行过滤。
p89 line36
init_fn = slim.assign_from_checkpoint_fn(model_path, variables_to_restore,ignore_missing_vars=True)
解释:返回一个函数,它从checkpoint文件读取变量值并分配给给特定变量。如果ignore_missing_vars为True,并且在检查点中找不到变量,则返回None。这行代码结合上行代码实现了所需变量的恢复操作。
链接: 参考资料.
p91 line86 tf.train.exponential_decay
解释:指定学习率动态衰减。
链接: tf.train.exponential_decay.
p91 line96 update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)解释:配合tf.control_dependencies()使用,先执行完成该函数传递的参数再执行其作用域里的操作。在这里tf.GraphKeys.UPDATE_OPS下有很多需要在训练过程之前就要完成的操作例如每一个cell层参数的滑动平均与方差更新。
链接: tf.control_dependencies&tf.GraphKeys.UPDATE_OPS.
p93 line139
iterator = tf.data.Iterator.from_structure(dataset.output_types, dataset.output_shapes)
解释:创建可初始化的迭代器,方便接下来可以不断从迭代器里拿出batchsize大小的数据。
链接: tf.data.Iterator.from_structure().
p93 line131 tf.get_default_graph().finalize()
解释:将后续图设为只读,即不能在图中添加任何op。
p111 line43-line48
解释:加载pb文件。
链接: tf.gfile文件操作模块.
tensorflow加载pb模型文件.
p111 line53 result = fenlei_graph.get_tensor_by_name(‘final_result:0’)
解释:从恢复的图中得到节点名称对应的变量。
python语法分析
p85 line22 labels.sort()
解释:将labels列表进行排序,labels列表有两个元素,‘man’,‘woman’,由于上面os.listdir是随机读取的,这样确保训练,验证的时候能有相同的顺序。即都先处理‘man’,再处理’woman’。
p86 line28 f.lower()
解释:将字符串字符大写变成小写。
p86 line32 filenames, labels = zip(*files_and_labels)
解释:zip的反操作,相当于解压列表里的各个元组元素,这里实现图片路径与标签信息全部分开存放。
p86 line37 unique_labels = list(set(labels))
解释:set可用于去除重复元素,返回可迭代对象。
链接: set()用法.
p90 line53
self.accuracy_top_5 = tf.reduce_mean(tf.cast(tf.nn.in_top_k(predictions=self.logits, targets=labels, k=5),tf.float32))
解释:取出预测当中前k个来判断标签类别是否在其中。
链接: tf.nn.in_top_k()用法.
p86 line41 for i, label in enumerate(sorted(unique_labels))
解释:
1 . sorted(),sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
2 . enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列。
链接: enumerate() 用法.
p111 line14 os.walk(sample_dir)
解释:用于通过在目录树中游走输出在目录中的文件名,向上或者向下。
p111 line17 filename_path = os.sep.join([dirpath, filename])
解释:可跨系统进行路径拼接。
p111 line28 np.asarray
解释:array和asarray都可将结构数据转换为ndarray类型。但是主要区别就是当数据源是ndarray时,array仍会copy出一个副本,占用新的内存,但asarray不会。
链接: np.array和np.asarray区别.
还未解决的问题
p86 line40 此处标注是{‘woman’: 2, ‘man’: 1,none:0},但是我debug出来的结果是
p90 line52 此处注释是取5个得分最高的类别,但是self.logits的shape为3??