精华内容
下载资源
问答
  • TF-IDF算法介绍及实现

    万次阅读 多人点赞 2018-08-07 19:17:45
    1、TF-IDF算法介绍 (1)TF是词频(Term Frequency) (2) IDF是逆向文件频率(Inverse Document Frequency) (3)TF-IDF实际上是:TF * IDF 2、TF-IDF应用 3、Python3实现TF-IDF算法 4、NLTK实现TF-IDF算法 5...

    目录

    1、TF-IDF算法介绍

    (1)TF是词频(Term Frequency)

    (2) IDF是逆向文件频率(Inverse Document Frequency)

    (3)TF-IDF实际上是:TF * IDF

    2、TF-IDF应用

    3、Python3实现TF-IDF算法

    4、NLTK实现TF-IDF算法

    5、Sklearn实现TF-IDF算法

    6、Jieba实现TF-IDF算法

    7、TF-IDF算法的不足

    8、TF-IDF算法改进——TF-IWF算法


    1、TF-IDF算法介绍

           TF-IDF(term frequency–inverse document frequency,词频-逆向文件频率)是一种用于信息检索(information retrieval)与文本挖掘(text mining)的常用加权技术

           TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。

           TF-IDF的主要思想是:如果某个单词在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。

    (1)TF是词频(Term Frequency)

            词频(TF)表示词条(关键字)在文本中出现的频率

            这个数字通常会被归一化(一般是词频除以文章总词数), 以防止它偏向长的文件。

            公式:           即:

     

            其中 ni,j 是该词在文件 dj 中出现的次数,分母则是文件 dj 中所有词汇出现的次数总和;

    (2) IDF是逆向文件频率(Inverse Document Frequency)

            逆向文件频率 (IDF) :某一特定词语的IDF,可以由总文件数目除以包含该词语的文件的数目再将得到的商取对数得到

    如果包含词条t的文档越少, IDF越大,则说明词条具有很好的类别区分能力。

            公式:         

            其中,|D| 是语料库中的文件总数 |{j:ti∈dj}| 表示包含词语 ti 的文件数目(即 ni,j≠0 的文件数目)。如果该词语不在语料库中,就会导致分母为零,因此一般情况下使用 1+|{j:ti∈dj}|

            即:

    (3)TF-IDF实际上是:TF * IDF

           某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。

           公式:

         

           注:  TF-IDF算法非常容易理解,并且很容易实现,但是其简单结构并没有考虑词语的语义信息,无法处理一词多义与一义多词的情况。

    2、TF-IDF应用

         (1)搜索引擎;(2)关键词提取;(3)文本相似性;(4)文本摘要

    3、Python3实现TF-IDF算法

    注意:该代码tf计算使用的是整个语料,这里只是举个简单的例子,大家在写的时候按文档计算词频即可!我这里就不做修改了

    # -*- coding: utf-8 -*-
    from collections import defaultdict
    import math
    import operator
    
    """
    函数说明:创建数据样本
    Returns:
        dataset - 实验样本切分的词条
        classVec - 类别标签向量
    """
    def loadDataSet():
        dataset = [ ['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],    # 切分的词条
                       ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
                       ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
                       ['stop', 'posting', 'stupid', 'worthless', 'garbage'],
                       ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
                       ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid'] ]
        classVec = [0, 1, 0, 1, 0, 1]  # 类别标签向量,1代表好,0代表不好
        return dataset, classVec
    
    
    """
    函数说明:特征选择TF-IDF算法
    Parameters:
         list_words:词列表
    Returns:
         dict_feature_select:特征选择词字典
    """
    def feature_select(list_words):
        #总词频统计
        doc_frequency=defaultdict(int)
        for word_list in list_words:
            for i in word_list:
                doc_frequency[i]+=1
    
        #计算每个词的TF值
        word_tf={}  #存储没个词的tf值
        for i in doc_frequency:
            word_tf[i]=doc_frequency[i]/sum(doc_frequency.values())
    
        #计算每个词的IDF值
        doc_num=len(list_words)
        word_idf={} #存储每个词的idf值
        word_doc=defaultdict(int) #存储包含该词的文档数
        for i in doc_frequency:
            for j in list_words:
                if i in j:
                    word_doc[i]+=1
        for i in doc_frequency:
            word_idf[i]=math.log(doc_num/(word_doc[i]+1))
    
        #计算每个词的TF*IDF的值
        word_tf_idf={}
        for i in doc_frequency:
            word_tf_idf[i]=word_tf[i]*word_idf[i]
    
        # 对字典按值由大到小排序
        dict_feature_select=sorted(word_tf_idf.items(),key=operator.itemgetter(1),reverse=True)
        return dict_feature_select
    
    if __name__=='__main__':
        data_list,label_list=loadDataSet() #加载数据
        features=feature_select(data_list) #所有词的TF-IDF值
        print(features)
        print(len(features))
    

    运行结果:

    4、NLTK实现TF-IDF算法

    from nltk.text import TextCollection
    from nltk.tokenize import word_tokenize
    
    #首先,构建语料库corpus
    sents=['this is sentence one','this is sentence two','this is sentence three']
    sents=[word_tokenize(sent) for sent in sents] #对每个句子进行分词
    print(sents)  #输出分词后的结果
    corpus=TextCollection(sents)  #构建语料库
    print(corpus)  #输出语料库
    
    #计算语料库中"one"的tf值
    tf=corpus.tf('one',corpus)    # 1/12
    print(tf)
    
    #计算语料库中"one"的idf值
    idf=corpus.idf('one')      #log(3/1)
    print(idf)
    
    #计算语料库中"one"的tf-idf值
    tf_idf=corpus.tf_idf('one',corpus)
    print(tf_idf)

    运行结果:

    5、Sklearn实现TF-IDF算法

    from sklearn.feature_extraction.text import CountVectorizer
    from sklearn.feature_extraction.text import TfidfTransformer
    
    x_train = ['TF-IDF 主要 思想 是','算法 一个 重要 特点 可以 脱离 语料库 背景',
               '如果 一个 网页 被 很多 其他 网页 链接 说明 网页 重要']
    x_test=['原始 文本 进行 标记','主要 思想']
    
    #该类会将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在i类文本下的词频
    vectorizer = CountVectorizer(max_features=10)
    #该类会统计每个词语的tf-idf权值
    tf_idf_transformer = TfidfTransformer()
    #将文本转为词频矩阵并计算tf-idf
    tf_idf = tf_idf_transformer.fit_transform(vectorizer.fit_transform(x_train))
    #将tf-idf矩阵抽取出来,元素a[i][j]表示j词在i类文本中的tf-idf权重
    x_train_weight = tf_idf.toarray()
    
    #对测试集进行tf-idf权重计算
    tf_idf = tf_idf_transformer.transform(vectorizer.transform(x_test))
    x_test_weight = tf_idf.toarray()  # 测试集TF-IDF权重矩阵
    
    print('输出x_train文本向量:')
    print(x_train_weight)
    print('输出x_test文本向量:')
    print(x_test_weight)

    运行结果:

    6、Jieba实现TF-IDF算法

    import jieba.analyse
    
    text='关键词是能够表达文档中心内容的词语,常用于计算机系统标引论文内容特征、
    信息检索、系统汇集以供读者检阅。关键词提取是文本挖掘领域的一个分支,是文本检索、
    文档比较、摘要生成、文档分类和聚类等文本挖掘研究的基础性工作'
    
    keywords=jieba.analyse.extract_tags(text, topK=5, withWeight=False, allowPOS=())
    print(keywords)

    运行结果:

    注:

    • jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
    • sentence 为待提取的文本
    • topK 为返回几个 TF/IDF 权重最大的关键词,默认值为 20
    • withWeight 为是否一并返回关键词权重值,默认值为 False
    • allowPOS 仅包括指定词性的词,默认值为空,即不筛选

    7、TF-IDF算法的不足

    TF-IDF 采用文本逆频率 IDF 对 TF 值加权取权值大的作为关键词,但 IDF 的简单结构并不能有效地反映单词的重要程度和特征词的分布情况,使其无法很好地完成对权值调整的功能,所以 TF-IDF 算法的精度并不是很高,尤其是当文本集已经分类的情况下。

    在本质上 IDF 是一种试图抑制噪音的加权,并且单纯地认为文本频率小的单词就越重要,文本频率大的单词就越无用。这对于大部分文本信息,并不是完全正确的。IDF 的简单结构并不能使提取的关键词, 十分有效地反映单词的重要程度和特征词的分布情 况,使其无法很好地完成对权值调整的功能。尤其是在同类语料库中,这一方法有很大弊端,往往一些同类文本的关键词被盖。

    TF-IDF算法实现简单快速,但是仍有许多不足之处:

    (1)没有考虑特征词的位置因素对文本的区分度,词条出现在文档的不同位置时,对区分度的贡献大小是不一样的。

    (2)按照传统TF-IDF,往往一些生僻词的IDF(反文档频率)会比较高、因此这些生僻词常会被误认为是文档关键词。

    (3)传统TF-IDF中的IDF部分只考虑了特征词与它出现的文本数之间的关系,而忽略了特征项在一个类别中不同的类别间的分布情况。

    (4)对于文档中出现次数较少的重要人名、地名信息提取效果不佳。

    8、TF-IDF算法改进——TF-IWF算法

    详细改进方法参看论文:改进的 TF-IDF 关键词提取方法

     

    交流学习资料共享欢迎入QQ群:955817470

    展开全文
  •   张量(Tensor)是TensorFlow的核心数据单位。一个张量由一组形成阵列(任意维数)的原始值组成。张量的阶是它的维数,而它的...- tf.Variable - tf.constant - tf.placeholder tf.Variable   Tensorflo...

      张量(Tensor)是TensorFlow的核心数据单位。一个张量由一组形成阵列(任意维数)的原始值组成。张量的阶是它的维数,而它的形状是一个整数元组,指定了阵列每个维度的长度。
    下面会介绍 Tensorflow 中几个特殊张量:
    - tf.Variable
    - tf.constant
    - tf.placeholder

    tf.Variable

      Tensorflow 变量是表示程序处理的共享持久状态的最佳方法。

    创建变量

      创建变量的最佳方式是调用 tf.get_variable函数。此函数需要指定变量的名字与形状。

    # 创建名为‘variable_a’,形状为[1,2,3]的3维张量
    variable_a = tf.get_variable("a",shape=[1,2,3])

      tf.get_variable还可以指定数据类型(默认的是 tf.float32)和初始化器。Tensorflow 提供了许多方便的初始化器,比如

    • tf.zeros_initializer

      初始化为0

      variable_b = tf.get_variable("b", shape=[1, 2, 3], dtype=tf.float32,
                                   initializer=tf.zeros_initializer)
    • tf.constant_initializer

      初始化为常量

      value = np.array([0, 1, 2, 3, 4, 5, 6, 7])
      variable_c = tf.get_variable("c", dtype=tf.float32, shape=value.shape,
                                   initializer=tf.constant_initializer(value))
    • tf.truncated_normal_initializer

      随机初始化

      variable_d = tf.get_variable('d', dtype=tf.float32, shape=[4, 3, 4], initializer=tf.truncated_normal_initializer)
      
    • tf.contrib.layers.xavier_initializer

      随机初始化

      variable_e = tf.get_variable('e', dtype=tf.float32, shape=[4, 3, 4], initializer=xavier_initializer())
      

        此处介绍几种常见的初始化器,其中在初始化方面使用比较多的是后两种,建议使用xavier_initializer初始化器,之前在用 lstm模型进行文本分类过程中,使用truncated_normal_initializer进行初始化,发现在训练过程中,lstm 模型执行少数batch后就收敛,致使模型在训练集和测试集上的准确率都很低。当然,这个也不绝对,具体还是要根据自己的模型而定。

    初始化变量

      变量必须先初始化后才可使用。在低级别的编程中,需要明确初始化,高级别框架下是自动初始化的。此处介绍下低级别编程中初始化的问题。

    • 指定初始化某个变量

      sess=tf.Session()
      sess.run(tf.initialize_variables([variable_c]))
      

      在变量比较少的模型中,使用上述方法是很 ok 的,但是在变量比较多的情况下,使用上述方法可能会很不爽,至少对我是这样的。

    • 初始化全部变量

      sess.run(tf.initialize_all_variables())

    tf.constant

      使用tf.constant来创建一个常量。

    ```
    # 创建0维常量
    tf.constant(0.2,name='a')
    # 创建1维常量
    tf.constant([1,2,3,4],name='b')
    tf.constant(-1.0, shape=[2, 3], name='b')
    ```
    

    tf.placeholder

      此函数的作用可以作为 java 方法中的形参,用于定义过程,在方法执行时再赋予具体的值。

    a = tf.placeholder(dtype=tf.float32, shape=None, name='a')
    b = tf.placeholder(dtype=tf.float32, shape=None, name='b')
    with tf.Session() as sess:
        print(sess.run(a + b, feed_dict={a: 1, b: 2}))
    
    展开全文
  • Tensorflow2.0(Keras)转换TFlite

    千次阅读 2020-07-11 10:09:21
    Tensorflow 2.0(Keras)转换TFlite 以下脚本实现将Tensorflow2.0(Keras)保存的模型(建议保存为*.h5的格式),转换TFlite模型 (1)TensorFlow Lite 转换器 https://tensorflow.google.cn/lite/guide/ops_select 为了...

    Tensorflow 2.0(Keras)转换TFlite

    目录

    Tensorflow 2.0(Keras)转换TFlite

    1. TensorFlow Lite 指南

    (1)TensorFlow Lite 转换器

    (2)转换量化模型

    (3)兼容的算子:Compatible operations

    2. 转换脚本(Python版本)


    1. TensorFlow Lite 指南

    (1)TensorFlow Lite 转换器

    https://tensorflow.google.cn/lite/guide/ops_select

    为了能够转换包含 TensorFlow 运算符的 TensorFlow Lite 模型,可使用位于 TensorFlow Lite 转换器 中的 target_spec.supported_ops 参数。target_spec.supported_ops 的可选值如下:

    • TFLITE_BUILTINS - 使用 TensorFlow Lite 内置运算符转换模型。
    • SELECT_TF_OPS - 使用 TensorFlow 运算符转换模型。已经支持的 TensorFlow 运算符的完整列表可以在白名单lite/delegates/flex/whitelisted_flex_ops.cc 中查看。

    注意:target_spec.supported_ops 是之前 Python API 中的 target_ops

    我们优先推荐使用 TFLITE_BUILTINS 转换模型,然后是同时使用 TFLITE_BUILTINS,SELECT_TF_OPS ,最后是只使用 SELECT_TF_OPS。同时使用两个选项(也就是 TFLITE_BUILTINS,SELECT_TF_OPS)会用 TensorFlow Lite 内置的运算符去转换支持的运算符。有些 TensorFlow 运算符 TensorFlow Lite 只支持部分用法,这时可以使用 SELECT_TF_OPS 选项来避免这种局限性。

    (2)转换量化模型

    训练后:针对特定 CPU 型号的量化模型

    创建小模型的最简单方法是在推理期间将权重量化为 8 位并“在运行中”量化输入/激活。这具有延迟优势,但优先考虑减小尺寸。

    在转换期间,将 optimizations 标志设置为针对大小进行优化:

    converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
    converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
    tflite_quant_model = converter.convert()
    

    训练过程中:仅用于整数执行的量化模型

    仅用于整数执行的量化模型获得具有更低延迟,更小尺寸和仅针对整数加速器兼容模型的模型。目前,这需要训练具有"假量化"节点的模型 。

    转换图表:

    converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
    converter.inference_type = tf.lite.constants.QUANTIZED_UINT8
    input_arrays = converter.get_input_arrays()
    converter.quantized_input_stats = {input_arrays[0] : (0., 1.)}  # mean, std_dev
    tflite_model = converter.convert()
    

    对于全整数模型,输入为 uint8。mean 和 std_dev values 指定在训练模型时这些 UINT8 的值是如何值映射到输入的浮点值。

    mean 是 0 到 255 之间的整数值,映射到浮点数 0.0f。std_dev = 255 /(float_max - float_min)

    对于大多数用户,我们建议使用训练后量化。我们正在研究用于后期训练和训练量化的新工具,我们希望这将简化生成量化模型。

    (3)兼容的算子:Compatible operations

    https://tensorflow.google.cn/lite/guide/ops_compatibility


    2. 转换脚本(Python版本)

    以下脚本实现将Tensorflow2.0(Keras)保存的模型(建议保存为*.h5的格式),转换TFlite模型

    建议版本信息:

    tensorboard==2.0.2                
    tensorflow-estimator==2.0.1                   
    tensorflow-gpu==2.0.0    

    # -*- coding: utf-8 -*-
    """
    # --------------------------------------------------------
    # @Author : panjq
    # @E-mail : pan_jinquan@163.com
    # @Date   : 2020-02-05 11:01:49
    # --------------------------------------------------------
    """
    import os
    import numpy as np
    import glob
    import cv2
    import argparse
    import tensorflow as tf
    
    print("TF version:{}".format(tf.__version__))
    physical_devices = tf.config.experimental.list_physical_devices('GPU')
    assert len(physical_devices) > 0, "Not enough GPU hardware devices available"
    tf.config.experimental.set_memory_growth(physical_devices[0], True)
    
    
    def converer_keras_to_tflite_v1(keras_path, outputs_layer=None, out_tflite=None):
        """
        :param keras_path: keras *.h5 files
        :param outputs_layer
        :param out_tflite: output *.tflite file
        :return:
        """
        model_dir = os.path.dirname(keras_path)
        model_name = os.path.basename(keras_path)[:-len(".h5")]
        # 加载keras模型, 结构打印
        model_keras = tf.keras.models.load_model(keras_path)
        print(model_keras.summary())
        # 从keras模型中提取fc1层, 需先保存成新keras模型, 再转换成tflite
        model_embedding = tf.keras.models.Model(inputs=model_keras.input,
                                                outputs=model_keras.get_layer(outputs_layer).output)
        print(model_embedding.summary())
        keras_file = os.path.join(model_dir, "{}_{}.h5".format(model_name, outputs_layer))
        tf.keras.models.Model.save(model_embedding, keras_file)
    
        # converter = tf.lite.TocoConverter.from_keras_model_file(keras_file)
        converter = tf.lite.TFLiteConverter.from_keras_model_file(keras_file)  # tf1.3
        # converter = tf.lite.TFLiteConverter.from_keras_model(model_keras)  # tf2.0
        tflite_model = converter.convert()
    
        if not out_tflite:
            out_tflite = os.path.join(model_dir, "{}_{}.tflite".format(model_name, outputs_layer))
        open(out_tflite, "wb").write(tflite_model)
        print("successfully convert to tflite done")
        print("save model at: {}".format(out_tflite))
    
    
    def converer_keras_to_tflite_v2(keras_path, outputs_layer=None, out_tflite=None, optimize=False, quantization=False):
        """
        :param keras_path: keras *.h5 files
        :param outputs_layer: default last layer
        :param out_tflite: output *.tflite file
        :param optimize
        :return:
        """
        if not os.path.exists(keras_path):
            raise Exception("Error:{}".format(keras_path))
        model_dir = os.path.dirname(keras_path)
        model_name = os.path.basename(keras_path)[:-len(".h5")]
        # 加载keras模型, 结构打印
        # model = tf.keras.models.load_model(keras_path)
        model = tf.keras.models.load_model(model_path, custom_objects={'tf': tf}, compile=False)
    
        print(model.summary())
        if outputs_layer:
            # 从keras模型中提取层,转换成tflite
            model = tf.keras.models.Model(inputs=model.input, outputs=model.get_layer(outputs_layer).output)
            # outputs = [model.output["bbox"],model.output["scores"]]
            # model = tf.keras.models.Model(inputs=model.input, outputs=outputs)
            print(model.summary())
        # converter = tf.lite.TocoConverter.from_keras_model_file(keras_file)
        # converter = tf.lite.TFLiteConverter.from_keras_model_file(keras_file)  # tf1.3
        converter = tf.lite.TFLiteConverter.from_keras_model(model)  # tf2.0
        prefix = [model_name, outputs_layer]
        # converter.allow_custom_ops = False
        # converter.experimental_new_converter = True
        """"
        https://tensorflow.google.cn/lite/guide/ops_select
        我们优先推荐使用 TFLITE_BUILTINS 转换模型,然后是同时使用 TFLITE_BUILTINS,SELECT_TF_OPS ,
        最后是只使用 SELECT_TF_OPS。同时使用两个选项(也就是 TFLITE_BUILTINS,SELECT_TF_OPS)
        会用 TensorFlow Lite 内置的运算符去转换支持的运算符。
        有些 TensorFlow 运算符 TensorFlow Lite 只支持部分用法,这时可以使用 SELECT_TF_OPS 选项来避免这种局限性。
        """
        # converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS,
        #                                        tf.lite.OpsSet.SELECT_TF_OPS]
        # converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS]
        # converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
        if optimize:
            print("weight quantization")
            # Enforce full integer quantization for all ops and use int input/output
            converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
            prefix += ["optimize"]
        else:
            converter.optimizations = [tf.lite.Optimize.DEFAULT]
    
        if quantization == "int8":
            converter.representative_dataset = representative_dataset_gen
            # converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
            # converter.inference_input_type = tf.int8  # or tf.uint8
            # converter.inference_output_type = tf.int8  # or tf.uint8
            converter.target_spec.supported_types = [tf.int8]
        elif quantization == "float16":
            converter.target_spec.supported_types = [tf.float16]
    
        prefix += [quantization]
        if not out_tflite:
            prefix = [str(n) for n in prefix if n]
            prefix = "_".join(prefix)
            out_tflite = os.path.join(model_dir, "{}.tflite".format(prefix))
        tflite_model = converter.convert()
        open(out_tflite, "wb").write(tflite_model)
        print("successfully convert to tflite done")
        print("save model at: {}".format(out_tflite))
    
    
    def representative_dataset_gen():
        """
        # 生成代表性数据集
        :return:
        """
        image_dir = '/home/dm/panjinquan3/FaceDetector/tf-yolov3-detection/data/finger_images/'
        input_size = [320, 320]
        imgSet = [os.path.join(image_dir, f) for f in os.listdir(image_dir) if os.path.isfile(os.path.join(image_dir, f))]
        for img_path in imgSet:
            orig_image = cv2.imread(img_path)
            rgb_image = cv2.cvtColor(orig_image, cv2.COLOR_BGR2RGB)
            image_tensor = cv2.resize(rgb_image, dsize=tuple(input_size))
            image_tensor = np.asarray(image_tensor / 255.0, dtype=np.float32)
            image_tensor = image_tensor[np.newaxis, :]
            yield [image_tensor]
    
    
    def parse_args():
        # weights_path = "../yolov3-micro.h5"
        weights_path = "../yolov3-micro_freeze_head.h5"
        parser = argparse.ArgumentParser()
        parser.add_argument("-c", "--model_path", help="model_path", default=weights_path, type=str)
        parser.add_argument("--outputs_layer", help="outputs_layer", default=None, type=str)
        parser.add_argument("-o", "--out_tflite", help="out tflite model path", default=None, type=str)
        parser.add_argument("-opt", "--optimize", help="optimize model", default=True, type=bool)
        parser.add_argument("-q", "--quantization", help="quantization model", default="float16", type=str)
        return parser.parse_args()
    
    
    def get_model(model_path):
        if not model_path:
            model_path = os.path.join(os.getcwd(), "*.h5")
            model_list = glob.glob(model_path)
        else:
            model_list = [model_path]
        return model_list
    
    
    def unsupport_tflite_op():
        """
        tf.shape,tf.Size
        error: 'tf.Size' op is neither a custom op nor a flex op
        error: 'tf.Softmax' op is neither a custom op nor a flex op
        ===========================================================
        tf.Softmax-->tf.nn.softmax
        """
        pass
    
    
    if __name__ == '__main__':
    
        args = parse_args()
        # outputs_layer = "fc1"
        outputs_layer = args.outputs_layer
        model_list = get_model(args.model_path)
        out_tflite = args.out_tflite
        optimize = args.optimize
        quantization = args.quantization
        for model_path in model_list:
            converer_keras_to_tflite_v2(model_path, outputs_layer, out_tflite=out_tflite, optimize=optimize,
                                        quantization=quantization)
            # converer_keras_to_tflite_v1(keras_model, outputs_layer, out_tflite=None)
    

     

    3. 常见问题解决方法


    'tf.ResizeNearestNeighbor' op is neither a custom op nor a flex op
    <unknown>:0: error: failed while converting: 'main': Ops that can be supported by the flex runtime (enabled via setting the -emit-select-tf-ops flag): ResizeNearestNeighbor.

    解决方法: https://panjinquan.blog.csdn.net/article/details/107360700


    Quantization not yet supported for op: LEAKY_RELU

    展开全文
  • TensorFlow数据读取机制:文件队列 tf.train.slice_input_producer和tf.data.Dataset机制 之前写了一篇博客,关于《Tensorflow生成自己的图片数据集TFrecord》,项目做多了,你会发现将数据转为TFrecord格式,实在...

    TensorFlow数据读取机制:文件队列 tf.train.slice_input_producer和tf.data.Dataset机制


        之前写了一篇博客,关于《Tensorflow生成自己的图片数据集TFrecord》,项目做多了,你会发现将数据转为TFrecord格式,实在是太麻烦了,灵活性太差!后面就总结一下TensorFlow数据读取机制,主要还是介绍tf.data.Dataset的数据读取机制(Pipeline机制)。

        TensorFlow数据读取机制主要是两种方法:

    (1)一种是使用文件队列方式,如使用slice_input_producer和string_input_producer;这种方法既可以将数据转存为TFrecord数据格式,也可以直接读取文件图片数据,当然转存为TFrecord数据格式进行读取,会更高效点

    (2)另一种是TensorFlow 1.4版本后出现的tf.data.Dataset的数据读取机制(Pipeline机制)。这是TensorFlow强烈推荐的方式,是一种更高效的读取方式。使用tf.data.Dataset模块的pipline机制,可实现CPU多线程处理输入的数据,如读取图片和图片的一些的预处理,这样GPU可以专注于训练过程,而CPU去准备数据。

          本博客Github源码:https://github.com/PanJinquan/tensorflow-learning-tutorials ->tf_record_demo文件夹(觉得可以,还请给个“Star”哦

         之前专门写了一篇博客关于《 Tensorflow生成自己的图片数据集TFrecords(支持多标签label)https://blog.csdn.net/guyuealian/article/details/80857228,主要实现的是使用自己的数据集制作TensorFlow的TFrecord数据格式。


    目录

    目录

    TensorFlow数据读取机制:文件队列 tf.train.slice_input_producer和tf.data.Dataset机制

    1. 文件队列读取方式:slice_input_producer和string_input_producer

    1.1.生成图片数据集TFrecords

    (1)生成单个record文件 (单label)

    (2)生成单个record文件 (多label)

    (3)生成多个record文件的方法

    1.2. 直接文件读取方式 

    2.tf.data.Dataset数据读取机制:Pipeline机制

    prefetch(必须放在最后)

    map

    repeat

    实例代码1:dataset.make_initializable_iterator()

    实例代码2:dataset.make_one_shot_iterator()

    实例代码3:产生用于训练的图和label

    实例代码4:产生用于训练的原始图和target目标图

    实例代码5: tf.data.Dataset.from_generator

    3. 用Python循环产生批量数据batch

    4.参考资料:



    1. 文件队列读取方式:slice_input_producer和string_input_producer

        TensorFlow可以采用tf.train.slice_input_producer或者tf.train.string_input_producer两种方法产生文件队列,其区别就是:前者是输入是tensor_list,因此,可以将多个list组合成一个tensorlist作为输入;而后者只能是一个string_tensor了,例子如下:

        image_dir ='path/to/image_dir/*.jpg'
        image_list = glob.glob(image_dir)
        label_list=...
        image_list = tf.convert_to_tensor(image_list, dtype=tf.string)
        # 可以将image_list,label_list多个list组合成一个tensor_list
        image_que, label_que = tf.train.slice_input_producer([image_list,label_list], num_epochs=1)
        # 只能时string_tensor,所以不能组合多个list
        image = tf.train.string_input_producer(image_list, num_epochs=1)

    1.1.生成图片数据集TFrecords

        假设train.txt保存图片的路径和标签信息,如下,以空格分割,第一项的图片的路径名,第二项是图片对应的labels

    dog/1.jpg 0
    dog/2.jpg 0
    dog/3.jpg 0
    dog/4.jpg 0
    cat/1.jpg 1
    cat/2.jpg 1
    cat/3.jpg 1
    cat/4.jpg 1

        这里提供三种方法将图像数据转存为TFrecords数据格式,当然也包含TFrecords解析的方法,详细的用法都会在函数参数说明,已经封装了很简单了,你只需要改变你图片的路径就可以。

    • 生成单个record文件 (单label)

        这种方法会将所有图片数据和单labels转存为一个record文件,合适单labels小批量的数据

    • 生成单个record文件 (多label)

        这种方法将所有图片数据和多个labels转存为一个record文件,合适多labels的小批量的数据

    • 生成多个record文件的方法

        这种方法将图片数据和labels,切分一个batch_size的大小,并转存为多个record文件,合适大批量的数据

    (1)生成单个record文件 (单label)

         下面是封装好的py文件,可以直接生成单个record文件 ,当然这里假设只有一个label情况。其中get_batch_images函数会产生一个batch的数据,这个batch的数据就可以用于CNN的网络训练的数据。

    # -*-coding: utf-8 -*-
    """
        @Project: create_tfrecord
        @File   : create_tfrecord.py
        @Author : panjq
        @E-mail : pan_jinquan@163.com
        @Date   : 2018-07-27 17:19:54
        @desc   : 将图片数据保存为单个tfrecord文件
    """
    
    ##########################################################################
    
    import tensorflow as tf
    import numpy as np
    import os
    import cv2
    import matplotlib.pyplot as plt
    import random
    from PIL import Image
    
    
    ##########################################################################
    def _int64_feature(value):
        return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
    # 生成字符串型的属性
    def _bytes_feature(value):
        return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
    # 生成实数型的属性
    def float_list_feature(value):
      return tf.train.Feature(float_list=tf.train.FloatList(value=value))
    
    def get_example_nums(tf_records_filenames):
        '''
        统计tf_records图像的个数(example)个数
        :param tf_records_filenames: tf_records文件路径
        :return:
        '''
        nums= 0
        for record in tf.python_io.tf_record_iterator(tf_records_filenames):
            nums += 1
        return nums
    
    def show_image(title,image):
        '''
        显示图片
        :param title: 图像标题
        :param image: 图像的数据
        :return:
        '''
        # plt.figure("show_image")
        # print(image.dtype)
        plt.imshow(image)
        plt.axis('on')    # 关掉坐标轴为 off
        plt.title(title)  # 图像题目
        plt.show()
    
    def load_labels_file(filename,labels_num=1,shuffle=False):
        '''
        载图txt文件,文件中每行为一个图片信息,且以空格隔开:图像路径 标签1 标签2,如:test_image/1.jpg 0 2
        :param filename:
        :param labels_num :labels个数
        :param shuffle :是否打乱顺序
        :return:images type->list
        :return:labels type->list
        '''
        images=[]
        labels=[]
        with open(filename) as f:
            lines_list=f.readlines()
            if shuffle:
                random.shuffle(lines_list)
    
            for lines in lines_list:
                line=lines.rstrip().split(' ')
                label=[]
                for i in range(labels_num):
                    label.append(int(line[i+1]))
                images.append(line[0])
                labels.append(label)
        return images,labels
    
    def read_image(filename, resize_height, resize_width,normalization=False):
        '''
        读取图片数据,默认返回的是uint8,[0,255]
        :param filename:
        :param resize_height:
        :param resize_width:
        :param normalization:是否归一化到[0.,1.0]
        :return: 返回的图片数据
        '''
    
        bgr_image = cv2.imread(filename)
        if len(bgr_image.shape)==2:#若是灰度图则转为三通道
            print("Warning:gray image",filename)
            bgr_image = cv2.cvtColor(bgr_image, cv2.COLOR_GRAY2BGR)
    
        rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)#将BGR转为RGB
        # show_image(filename,rgb_image)
        # rgb_image=Image.open(filename)
        if resize_height>0 and resize_width>0:
            rgb_image=cv2.resize(rgb_image,(resize_width,resize_height))
        rgb_image=np.asanyarray(rgb_image)
        if normalization:
            # 不能写成:rgb_image=rgb_image/255
            rgb_image=rgb_image/255.0
        # show_image("src resize image",image)
        return rgb_image
    
    
    def get_batch_images(images,labels,batch_size,labels_nums,one_hot=False,shuffle=False,num_threads=1):
        '''
        :param images:图像
        :param labels:标签
        :param batch_size:
        :param labels_nums:标签个数
        :param one_hot:是否将labels转为one_hot的形式
        :param shuffle:是否打乱顺序,一般train时shuffle=True,验证时shuffle=False
        :return:返回batch的images和labels
        '''
        min_after_dequeue = 200
        capacity = min_after_dequeue + 3 * batch_size  # 保证capacity必须大于min_after_dequeue参数值
        if shuffle:
            images_batch, labels_batch = tf.train.shuffle_batch([images,labels],
                                                                        batch_size=batch_size,
                                                                        capacity=capacity,
                                                                        min_after_dequeue=min_after_dequeue,
                                                                        num_threads=num_threads)
        else:
            images_batch, labels_batch = tf.train.batch([images,labels],
                                                            batch_size=batch_size,
                                                            capacity=capacity,
                                                            num_threads=num_threads)
        if one_hot:
            labels_batch = tf.one_hot(labels_batch, labels_nums, 1, 0)
        return images_batch,labels_batch
    
    def read_records(filename,resize_height, resize_width,type=None):
        '''
        解析record文件:源文件的图像数据是RGB,uint8,[0,255],一般作为训练数据时,需要归一化到[0,1]
        :param filename:
        :param resize_height:
        :param resize_width:
        :param type:选择图像数据的返回类型
             None:默认将uint8-[0,255]转为float32-[0,255]
             normalization:归一化float32-[0,1]
             standardization:标准化float32-[0,1],再减均值中心化
        :return:
        '''
        # 创建文件队列,不限读取的数量
        filename_queue = tf.train.string_input_producer([filename])
        # create a reader from file queue
        reader = tf.TFRecordReader()
        # reader从文件队列中读入一个序列化的样本
        _, serialized_example = reader.read(filename_queue)
        # get feature from serialized example
        # 解析符号化的样本
        features = tf.parse_single_example(
            serialized_example,
            features={
                'image_raw': tf.FixedLenFeature([], tf.string),
                'height': tf.FixedLenFeature([], tf.int64),
                'width': tf.FixedLenFeature([], tf.int64),
                'depth': tf.FixedLenFeature([], tf.int64),
                'label': tf.FixedLenFeature([], tf.int64)
            }
        )
        tf_image = tf.decode_raw(features['image_raw'], tf.uint8)#获得图像原始的数据
    
        tf_height = features['height']
        tf_width = features['width']
        tf_depth = features['depth']
        tf_label = tf.cast(features['label'], tf.int32)
        # PS:恢复原始图像数据,reshape的大小必须与保存之前的图像shape一致,否则出错
        # tf_image=tf.reshape(tf_image, [-1])    # 转换为行向量
        tf_image=tf.reshape(tf_image, [resize_height, resize_width, 3]) # 设置图像的维度
    
        # 恢复数据后,才可以对图像进行resize_images:输入uint->输出float32
        # tf_image=tf.image.resize_images(tf_image,[224, 224])
    
        # [3]数据类型处理
        # 存储的图像类型为uint8,tensorflow训练时数据必须是tf.float32
        if type is None:
            tf_image = tf.cast(tf_image, tf.float32)
        elif type == 'normalization':  # [1]若需要归一化请使用:
            # 仅当输入数据是uint8,才会归一化[0,255]
            # tf_image = tf.cast(tf_image, dtype=tf.uint8)
            # tf_image = tf.image.convert_image_dtype(tf_image, tf.float32)
            tf_image = tf.cast(tf_image, tf.float32) * (1. / 255.0)  # 归一化
        elif type == 'standardization':  # 标准化
            # tf_image = tf.cast(tf_image, dtype=tf.uint8)
            # tf_image = tf.image.per_image_standardization(tf_image)  # 标准化(减均值除方差)
            # 若需要归一化,且中心化,假设均值为0.5,请使用:
            tf_image = tf.cast(tf_image, tf.float32) * (1. / 255) - 0.5  # 中心化
    
        # 这里仅仅返回图像和标签
        # return tf_image, tf_height,tf_width,tf_depth,tf_label
        return tf_image,tf_label
    
    
    def create_records(image_dir,file, output_record_dir, resize_height, resize_width,shuffle,log=5):
        '''
        实现将图像原始数据,label,长,宽等信息保存为record文件
        注意:读取的图像数据默认是uint8,再转为tf的字符串型BytesList保存,解析请需要根据需要转换类型
        :param image_dir:原始图像的目录
        :param file:输入保存图片信息的txt文件(image_dir+file构成图片的路径)
        :param output_record_dir:保存record文件的路径
        :param resize_height:
        :param resize_width:
        PS:当resize_height或者resize_width=0是,不执行resize
        :param shuffle:是否打乱顺序
        :param log:log信息打印间隔
        '''
        # 加载文件,仅获取一个label
        images_list, labels_list=load_labels_file(file,1,shuffle)
    
        writer = tf.python_io.TFRecordWriter(output_record_dir)
        for i, [image_name, labels] in enumerate(zip(images_list, labels_list)):
            image_path=os.path.join(image_dir,images_list[i])
            if not os.path.exists(image_path):
                print('Err:no image',image_path)
                continue
            image = read_image(image_path, resize_height, resize_width)
            image_raw = image.tostring()
            if i%log==0 or i==len(images_list)-1:
                print('------------processing:%d-th------------' % (i))
                print('current image_path=%s' % (image_path),'shape:{}'.format(image.shape),'labels:{}'.format(labels))
            # 这里仅保存一个label,多label适当增加"'label': _int64_feature(label)"项
            label=labels[0]
            example = tf.train.Example(features=tf.train.Features(feature={
                'image_raw': _bytes_feature(image_raw),
                'height': _int64_feature(image.shape[0]),
                'width': _int64_feature(image.shape[1]),
                'depth': _int64_feature(image.shape[2]),
                'label': _int64_feature(label)
            }))
            writer.write(example.SerializeToString())
        writer.close()
    
    def disp_records(record_file,resize_height, resize_width,show_nums=4):
        '''
        解析record文件,并显示show_nums张图片,主要用于验证生成record文件是否成功
        :param tfrecord_file: record文件路径
        :return:
        '''
        # 读取record函数
        tf_image, tf_label = read_records(record_file,resize_height,resize_width,type='normalization')
        # 显示前4个图片
        init_op = tf.initialize_all_variables()
        with tf.Session() as sess:
            sess.run(init_op)
            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(sess=sess, coord=coord)
            for i in range(show_nums):
                image,label = sess.run([tf_image,tf_label])  # 在会话中取出image和label
                # image = tf_image.eval()
                # 直接从record解析的image是一个向量,需要reshape显示
                # image = image.reshape([height,width,depth])
                print('shape:{},tpye:{},labels:{}'.format(image.shape,image.dtype,label))
                # pilimg = Image.fromarray(np.asarray(image_eval_reshape))
                # pilimg.show()
                show_image("image:%d"%(label),image)
            coord.request_stop()
            coord.join(threads)
    
    
    def batch_test(record_file,resize_height, resize_width):
        '''
        :param record_file: record文件路径
        :param resize_height:
        :param resize_width:
        :return:
        :PS:image_batch, label_batch一般作为网络的输入
        '''
        # 读取record函数
        tf_image,tf_label = read_records(record_file,resize_height,resize_width,type='normalization')
        image_batch, label_batch= get_batch_images(tf_image,tf_label,batch_size=4,labels_nums=5,one_hot=False,shuffle=False)
    
        init = tf.global_variables_initializer()
        with tf.Session() as sess:  # 开始一个会话
            sess.run(init)
            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(coord=coord)
            for i in range(4):
                # 在会话中取出images和labels
                images, labels = sess.run([image_batch, label_batch])
                # 这里仅显示每个batch里第一张图片
                show_image("image", images[0, :, :, :])
                print('shape:{},tpye:{},labels:{}'.format(images.shape,images.dtype,labels))
    
            # 停止所有线程
            coord.request_stop()
            coord.join(threads)
    
    
    if __name__ == '__main__':
        # 参数设置
    
        resize_height = 224  # 指定存储图片高度
        resize_width = 224  # 指定存储图片宽度
        shuffle=True
        log=5
        # 产生train.record文件
        image_dir='dataset/train'
        train_labels = 'dataset/train.txt'  # 图片路径
        train_record_output = 'dataset/record/train.tfrecords'
        create_records(image_dir,train_labels, train_record_output, resize_height, resize_width,shuffle,log)
        train_nums=get_example_nums(train_record_output)
        print("save train example nums={}".format(train_nums))
    
        # 产生val.record文件
        image_dir='dataset/val'
        val_labels = 'dataset/val.txt'  # 图片路径
        val_record_output = 'dataset/record/val.tfrecords'
        create_records(image_dir,val_labels, val_record_output, resize_height, resize_width,shuffle,log)
        val_nums=get_example_nums(val_record_output)
        print("save val example nums={}".format(val_nums))
    
        # 测试显示函数
        # disp_records(train_record_output,resize_height, resize_width)
        batch_test(train_record_output,resize_height, resize_width)
    

    (2)生成单个record文件 (多label)

        对于多label的情况,你可以在单label的基础上增加多个“label': tf.FixedLenFeature([], tf.int64)“,但每次label个数不一样时,都需要修改,挺麻烦的。这里提供一个方法:label数据也可以像图像数据那样,转为string类型来保存:labels_raw = np.asanyarray(labels,dtype=np.float32).tostring() ,解析时也跟图像数据一样进行解析:tf_label = tf.decode_raw(features['labels'],tf.float32) ,这样,不管多少个label,我们都可以保存为record文件了:

       多label的TXT文件:

    0.jpg 0.33 0.55
    1.jpg 0.42 0.73
    2.jpg 0.16 0.75
    3.jpg 0.78 0.66
    4.jpg 0.46 0.59
    5.jpg 0.46 0.09
    6.jpg 0.89 0.93
    7.jpg 0.42 0.82
    8.jpg 0.39 0.76
    9.jpg 0.46 0.40
    
    # -*-coding: utf-8 -*-
    """
        @Project: create_tfrecord
        @File   : create_tf_record_multi_label.py
        @Author : panjq
        @E-mail : pan_jinquan@163.com
        @Date   : 2018-07-27 17:19:54
        @desc   : 将图片数据,多label,保存为单个tfrecord文件
    """
    
    ##########################################################################
    
    import tensorflow as tf
    import numpy as np
    import os
    import cv2
    import matplotlib.pyplot as plt
    import random
    from PIL import Image
    
    
    ##########################################################################
    def _int64_feature(value):
        return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
    
    def _float_feature(value):
        return tf.train.Feature(float_list=tf.train.FloatList(value=[value]))
    
    # 生成字符串型的属性
    def _bytes_feature(value):
        return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
    # 生成实数型的属性
    def float_list_feature(value):
      return tf.train.Feature(float_list=tf.train.FloatList(value=value))
    
    def get_example_nums(tf_records_filenames):
        '''
        统计tf_records图像的个数(example)个数
        :param tf_records_filenames: tf_records文件路径
        :return:
        '''
        nums= 0
        for record in tf.python_io.tf_record_iterator(tf_records_filenames):
            nums += 1
        return nums
    
    def show_image(title,image):
        '''
        显示图片
        :param title: 图像标题
        :param image: 图像的数据
        :return:
        '''
        # plt.figure("show_image")
        # print(image.dtype)
        plt.imshow(image)
        plt.axis('on')    # 关掉坐标轴为 off
        plt.title(title)  # 图像题目
        plt.show()
    
    def load_labels_file(filename,labels_num=1,shuffle=False):
        '''
        载图txt文件,文件中每行为一个图片信息,且以空格隔开:图像路径 标签1 标签2,如:test_image/1.jpg 0 2
        :param filename:
        :param labels_num :labels个数
        :param shuffle :是否打乱顺序
        :return:images type->list
        :return:labels type->list
        '''
        images=[]
        labels=[]
        with open(filename) as f:
            lines_list=f.readlines()
            if shuffle:
                random.shuffle(lines_list)
    
            for lines in lines_list:
                line=lines.rstrip().split(' ')
                label=[]
                for i in range(labels_num):
                    label.append(float(line[i+1]))
                images.append(line[0])
                labels.append(label)
        return images,labels
    
    def read_image(filename, resize_height, resize_width,normalization=False):
        '''
        读取图片数据,默认返回的是uint8,[0,255]
        :param filename:
        :param resize_height:
        :param resize_width:
        :param normalization:是否归一化到[0.,1.0]
        :return: 返回的图片数据
        '''
    
        bgr_image = cv2.imread(filename)
        if len(bgr_image.shape)==2:#若是灰度图则转为三通道
            print("Warning:gray image",filename)
            bgr_image = cv2.cvtColor(bgr_image, cv2.COLOR_GRAY2BGR)
    
        rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)#将BGR转为RGB
        # show_image(filename,rgb_image)
        # rgb_image=Image.open(filename)
        if resize_height>0 and resize_width>0:
            rgb_image=cv2.resize(rgb_image,(resize_width,resize_height))
        rgb_image=np.asanyarray(rgb_image)
        if normalization:
            # 不能写成:rgb_image=rgb_image/255
            rgb_image=rgb_image/255.0
        # show_image("src resize image",image)
        return rgb_image
    
    
    def get_batch_images(images,labels,batch_size,labels_nums,one_hot=False,shuffle=False,num_threads=1):
        '''
        :param images:图像
        :param labels:标签
        :param batch_size:
        :param labels_nums:标签个数
        :param one_hot:是否将labels转为one_hot的形式
        :param shuffle:是否打乱顺序,一般train时shuffle=True,验证时shuffle=False
        :return:返回batch的images和labels
        '''
        min_after_dequeue = 200
        capacity = min_after_dequeue + 3 * batch_size  # 保证capacity必须大于min_after_dequeue参数值
        if shuffle:
            images_batch, labels_batch = tf.train.shuffle_batch([images,labels],
                                                                        batch_size=batch_size,
                                                                        capacity=capacity,
                                                                        min_after_dequeue=min_after_dequeue,
                                                                        num_threads=num_threads)
        else:
            images_batch, labels_batch = tf.train.batch([images,labels],
                                                            batch_size=batch_size,
                                                            capacity=capacity,
                                                            num_threads=num_threads)
        if one_hot:
            labels_batch = tf.one_hot(labels_batch, labels_nums, 1, 0)
        return images_batch,labels_batch
    
    def read_records(filename,resize_height, resize_width,type=None):
        '''
        解析record文件:源文件的图像数据是RGB,uint8,[0,255],一般作为训练数据时,需要归一化到[0,1]
        :param filename:
        :param resize_height:
        :param resize_width:
        :param type:选择图像数据的返回类型
             None:默认将uint8-[0,255]转为float32-[0,255]
             normalization:归一化float32-[0,1]
             standardization:归一化float32-[0,1],再减均值中心化
        :return:
        '''
        # 创建文件队列,不限读取的数量
        filename_queue = tf.train.string_input_producer([filename])
        # create a reader from file queue
        reader = tf.TFRecordReader()
        # reader从文件队列中读入一个序列化的样本
        _, serialized_example = reader.read(filename_queue)
        # get feature from serialized example
        # 解析符号化的样本
        features = tf.parse_single_example(
            serialized_example,
            features={
                'image_raw': tf.FixedLenFeature([], tf.string),
                'height': tf.FixedLenFeature([], tf.int64),
                'width': tf.FixedLenFeature([], tf.int64),
                'depth': tf.FixedLenFeature([], tf.int64),
                'labels': tf.FixedLenFeature([], tf.string)
            }
        )
        tf_image = tf.decode_raw(features['image_raw'], tf.uint8)#获得图像原始的数据
    
        tf_height = features['height']
        tf_width = features['width']
        tf_depth = features['depth']
        # tf_label = tf.cast(features['labels'], tf.float32)
        tf_label = tf.decode_raw(features['labels'],tf.float32)
    
        # PS:恢复原始图像数据,reshape的大小必须与保存之前的图像shape一致,否则出错
        # tf_image=tf.reshape(tf_image, [-1])    # 转换为行向量
        tf_image=tf.reshape(tf_image, [resize_height, resize_width, 3]) # 设置图像的维度
    
        tf_label=tf.reshape(tf_label, [2]) # 设置图像的维度
    
    
        # 恢复数据后,才可以对图像进行resize_images:输入uint->输出float32
        # tf_image=tf.image.resize_images(tf_image,[224, 224])
    
        # [3]数据类型处理
        # 存储的图像类型为uint8,tensorflow训练时数据必须是tf.float32
        if type is None:
            tf_image = tf.cast(tf_image, tf.float32)
        elif type == 'normalization':  # [1]若需要归一化请使用:
            # 仅当输入数据是uint8,才会归一化[0,255]
            # tf_image = tf.cast(tf_image, dtype=tf.uint8)
            # tf_image = tf.image.convert_image_dtype(tf_image, tf.float32)
            tf_image = tf.cast(tf_image, tf.float32) * (1. / 255.0)  # 归一化
        elif type == 'standardization':  # 标准化
            # tf_image = tf.cast(tf_image, dtype=tf.uint8)
            # tf_image = tf.image.per_image_standardization(tf_image)  # 标准化(减均值除方差)
            # 若需要归一化,且中心化,假设均值为0.5,请使用:
            tf_image = tf.cast(tf_image, tf.float32) * (1. / 255) - 0.5  # 中心化
    
        # 这里仅仅返回图像和标签
        # return tf_image, tf_height,tf_width,tf_depth,tf_label
        return tf_image,tf_label
    
    
    def create_records(image_dir,file, output_record_dir, resize_height, resize_width,shuffle,log=5):
        '''
        实现将图像原始数据,label,长,宽等信息保存为record文件
        注意:读取的图像数据默认是uint8,再转为tf的字符串型BytesList保存,解析请需要根据需要转换类型
        :param image_dir:原始图像的目录
        :param file:输入保存图片信息的txt文件(image_dir+file构成图片的路径)
        :param output_record_dir:保存record文件的路径
        :param resize_height:
        :param resize_width:
        PS:当resize_height或者resize_width=0是,不执行resize
        :param shuffle:是否打乱顺序
        :param log:log信息打印间隔
        '''
        # 加载文件,仅获取一个label
        labels_num=2
        images_list, labels_list=load_labels_file(file,labels_num,shuffle)
    
        writer = tf.python_io.TFRecordWriter(output_record_dir)
        for i, [image_name, labels] in enumerate(zip(images_list, labels_list)):
            image_path=os.path.join(image_dir,images_list[i])
            if not os.path.exists(image_path):
                print('Err:no image',image_path)
                continue
            image = read_image(image_path, resize_height, resize_width)
            image_raw = image.tostring()
            if i%log==0 or i==len(images_list)-1:
                print('------------processing:%d-th------------' % (i))
                print('current image_path=%s' % (image_path),'shape:{}'.format(image.shape),'labels:{}'.format(labels))
            # 这里仅保存一个label,多label适当增加"'label': _int64_feature(label)"项
            # label=labels[0]
            # labels_raw="0.12,0,15"
            labels_raw = np.asanyarray(labels,dtype=np.float32).tostring()
    
            example = tf.train.Example(features=tf.train.Features(feature={
                'image_raw': _bytes_feature(image_raw),
                'height': _int64_feature(image.shape[0]),
                'width': _int64_feature(image.shape[1]),
                'depth': _int64_feature(image.shape[2]),
                'labels': _bytes_feature(labels_raw),
    
            }))
            writer.write(example.SerializeToString())
        writer.close()
    
    def disp_records(record_file,resize_height, resize_width,show_nums=4):
        '''
        解析record文件,并显示show_nums张图片,主要用于验证生成record文件是否成功
        :param tfrecord_file: record文件路径
        :return:
        '''
        # 读取record函数
        tf_image, tf_label = read_records(record_file,resize_height,resize_width,type='normalization')
        # 显示前4个图片
        init_op = tf.initialize_all_variables()
        with tf.Session() as sess:
            sess.run(init_op)
            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(sess=sess, coord=coord)
            for i in range(show_nums):
                image,label = sess.run([tf_image,tf_label])  # 在会话中取出image和label
                # image = tf_image.eval()
                # 直接从record解析的image是一个向量,需要reshape显示
                # image = image.reshape([height,width,depth])
                print('shape:{},tpye:{},labels:{}'.format(image.shape,image.dtype,label))
                # pilimg = Image.fromarray(np.asarray(image_eval_reshape))
                # pilimg.show()
                show_image("image:{}".format(label),image)
            coord.request_stop()
            coord.join(threads)
    
    
    def batch_test(record_file,resize_height, resize_width):
        '''
        :param record_file: record文件路径
        :param resize_height:
        :param resize_width:
        :return:
        :PS:image_batch, label_batch一般作为网络的输入
        '''
        # 读取record函数
        tf_image,tf_label = read_records(record_file,resize_height,resize_width,type='normalization')
        image_batch, label_batch= get_batch_images(tf_image,tf_label,batch_size=4,labels_nums=2,one_hot=False,shuffle=True)
    
        init = tf.global_variables_initializer()
        with tf.Session() as sess:  # 开始一个会话
            sess.run(init)
            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(coord=coord)
            for i in range(4):
                # 在会话中取出images和labels
                images, labels = sess.run([image_batch, label_batch])
                # 这里仅显示每个batch里第一张图片
                show_image("image", images[0, :, :, :])
                print('shape:{},tpye:{},labels:{}'.format(images.shape,images.dtype,labels))
    
            # 停止所有线程
            coord.request_stop()
            coord.join(threads)
    
    
    if __name__ == '__main__':
        # 参数设置
    
        resize_height = 224  # 指定存储图片高度
        resize_width = 224  # 指定存储图片宽度
        shuffle=True
        log=1000
        # 产生train.record文件
        image_dir='dataset_regression/images'
        train_labels = 'dataset_regression/train.txt'  # 图片路径
        train_record_output = 'dataset_regression/record/train.tfrecords'
        create_records(image_dir,train_labels, train_record_output, resize_height, resize_width,shuffle,log)
        train_nums=get_example_nums(train_record_output)
        print("save train example nums={}".format(train_nums))
        # 测试显示函数
        # disp_records(train_record_output,resize_height, resize_width)
        # 产生val.record文件
        image_dir='dataset_regression/images'
        val_labels = 'dataset_regression/val.txt'  # 图片路径
        val_record_output = 'dataset_regression/record/val.tfrecords'
        create_records(image_dir,val_labels, val_record_output, resize_height, resize_width,shuffle,log)
        val_nums=get_example_nums(val_record_output)
        print("save val example nums={}".format(val_nums))
        #
        # # 测试显示函数
        # # disp_records(train_record_output,resize_height, resize_width)
        # batch_test(val_record_output,resize_height, resize_width)
    

    (3)生成多个record文件的方法

          上述该代码只能保存为单个record文件,当图片数据很多时候,会导致单个record文件超级巨大的情况,解决方法就是,将数据分成多个record文件保存,读取时,只需要将多个record文件的路径列表交给“tf.train.string_input_producer”。可以设置参数batchSize的大小,比如batchSize=2000,表示每2000张图片保存为一个*.tfrecords,这样可以避免单个record文件过大的情况。

          完整代码如下:

    # -*-coding: utf-8 -*-
    """
        @Project: tf_record_demo
        @File   : tf_record_batchSize.py
        @Author : panjq
        @E-mail : pan_jinquan@163.com
        @Date   : 2018-07-27 17:19:54
        @desc   : 将图片数据保存为多个record文件
    """
    
    ##########################################################################
    
    import tensorflow as tf
    import numpy as np
    import os
    import cv2
    import math
    import matplotlib.pyplot as plt
    import random
    from PIL import Image
    
    
    ##########################################################################
    def _int64_feature(value):
        return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
    # 生成字符串型的属性
    def _bytes_feature(value):
        return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
    # 生成实数型的属性
    def float_list_feature(value):
      return tf.train.Feature(float_list=tf.train.FloatList(value=value))
    
    def show_image(title,image):
        '''
        显示图片
        :param title: 图像标题
        :param image: 图像的数据
        :return:
        '''
        # plt.figure("show_image")
        # print(image.dtype)
        plt.imshow(image)
        plt.axis('on')    # 关掉坐标轴为 off
        plt.title(title)  # 图像题目
        plt.show()
    
    def load_labels_file(filename,labels_num=1):
        '''
        载图txt文件,文件中每行为一个图片信息,且以空格隔开:图像路径 标签1 标签2,如:test_image/1.jpg 0 2
        :param filename:
        :param labels_num :labels个数
        :return:images type->list
        :return:labels type->list
        '''
        images=[]
        labels=[]
        with open(filename) as f:
            for lines in f.readlines():
                line=lines.rstrip().split(' ')
                label=[]
                for i in range(labels_num):
                    label.append(int(line[i+1]))
                images.append(line[0])
                labels.append(label)
        return images,labels
    
    def read_image(filename, resize_height, resize_width):
        '''
        读取图片数据,默认返回的是uint8,[0,255]
        :param filename:
        :param resize_height:
        :param resize_width:
        :return: 返回的图片数据是uint8,[0,255]
        '''
    
        bgr_image = cv2.imread(filename)
        if len(bgr_image.shape)==2:#若是灰度图则转为三通道
            print("Warning:gray image",filename)
            bgr_image = cv2.cvtColor(bgr_image, cv2.COLOR_GRAY2BGR)
    
        rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)#将BGR转为RGB
        # show_image(filename,rgb_image)
        # rgb_image=Image.open(filename)
        if resize_height>0 and resize_width>0:
            rgb_image=cv2.resize(rgb_image,(resize_width,resize_height))
        rgb_image=np.asanyarray(rgb_image)
        # show_image("src resize image",image)
    
        return rgb_image
    
    
    def create_records(image_dir,file, record_txt_path, batchSize,resize_height, resize_width):
        '''
        实现将图像原始数据,label,长,宽等信息保存为record文件
        注意:读取的图像数据默认是uint8,再转为tf的字符串型BytesList保存,解析请需要根据需要转换类型
        :param image_dir:原始图像的目录
        :param file:输入保存图片信息的txt文件(image_dir+file构成图片的路径)
        :param output_record_txt_dir:保存record文件的路径
        :param batchSize: 每batchSize个图片保存一个*.tfrecords,避免单个文件过大
        :param resize_height:
        :param resize_width:
        PS:当resize_height或者resize_width=0是,不执行resize
        '''
        if os.path.exists(record_txt_path):
            os.remove(record_txt_path)
    
        setname, ext = record_txt_path.split('.')
    
        # 加载文件,仅获取一个label
        images_list, labels_list=load_labels_file(file,1)
        sample_num = len(images_list)
        # 打乱样本的数据
        # random.shuffle(labels_list)
        batchNum = int(math.ceil(1.0 * sample_num / batchSize))
    
        for i in range(batchNum):
            start = i * batchSize
            end = min((i + 1) * batchSize, sample_num)
            batch_images = images_list[start:end]
            batch_labels = labels_list[start:end]
            # 逐个保存*.tfrecords文件
            filename = setname + '{0}.tfrecords'.format(i)
            print('save:%s' % (filename))
    
            writer = tf.python_io.TFRecordWriter(filename)
            for i, [image_name, labels] in enumerate(zip(batch_images, batch_labels)):
                image_path=os.path.join(image_dir,batch_images[i])
                if not os.path.exists(image_path):
                    print('Err:no image',image_path)
                    continue
                image = read_image(image_path, resize_height, resize_width)
                image_raw = image.tostring()
                print('image_path=%s,shape:( %d, %d, %d)' % (image_path,image.shape[0], image.shape[1], image.shape[2]),'labels:',labels)
                # 这里仅保存一个label,多label适当增加"'label': _int64_feature(label)"项
                label=labels[0]
                example = tf.train.Example(features=tf.train.Features(feature={
                    'image_raw': _bytes_feature(image_raw),
                    'height': _int64_feature(image.shape[0]),
                    'width': _int64_feature(image.shape[1]),
                    'depth': _int64_feature(image.shape[2]),
                    'label': _int64_feature(label)
                }))
                writer.write(example.SerializeToString())
            writer.close()
    
            # 用txt保存*.tfrecords文件列表
            # record_list='{}.txt'.format(setname)
            with open(record_txt_path, 'a') as f:
                f.write(filename + '\n')
    
    def read_records(filename,resize_height, resize_width):
        '''
        解析record文件
        :param filename:保存*.tfrecords文件的txt文件路径
        :return:
        '''
        # 读取txt中所有*.tfrecords文件
        with open(filename, 'r') as f:
            lines = f.readlines()
            files_list=[]
            for line in lines:
                files_list.append(line.rstrip())
    
        # 创建文件队列,不限读取的数量
        filename_queue = tf.train.string_input_producer(files_list,shuffle=False)
        # create a reader from file queue
        reader = tf.TFRecordReader()
        # reader从文件队列中读入一个序列化的样本
        _, serialized_example = reader.read(filename_queue)
        # get feature from serialized example
        # 解析符号化的样本
        features = tf.parse_single_example(
            serialized_example,
            features={
                'image_raw': tf.FixedLenFeature([], tf.string),
                'height': tf.FixedLenFeature([], tf.int64),
                'width': tf.FixedLenFeature([], tf.int64),
                'depth': tf.FixedLenFeature([], tf.int64),
                'label': tf.FixedLenFeature([], tf.int64)
            }
        )
        tf_image = tf.decode_raw(features['image_raw'], tf.uint8)#获得图像原始的数据
    
        tf_height = features['height']
        tf_width = features['width']
        tf_depth = features['depth']
        tf_label = tf.cast(features['label'], tf.int32)
        # tf_image=tf.reshape(tf_image, [-1])    # 转换为行向量
        tf_image=tf.reshape(tf_image, [resize_height, resize_width, 3]) # 设置图像的维度
        # 存储的图像类型为uint8,这里需要将类型转为tf.float32
        # tf_image = tf.cast(tf_image, tf.float32)
        # [1]若需要归一化请使用:
        tf_image = tf.image.convert_image_dtype(tf_image, tf.float32)# 归一化
        # tf_image = tf.cast(tf_image, tf.float32) * (1. / 255)  # 归一化
        # [2]若需要归一化,且中心化,假设均值为0.5,请使用:
        # tf_image = tf.cast(tf_image, tf.float32) * (1. / 255) - 0.5 #中心化
        return tf_image, tf_height,tf_width,tf_depth,tf_label
    
    def disp_records(record_file,resize_height, resize_width,show_nums=4):
        '''
        解析record文件,并显示show_nums张图片,主要用于验证生成record文件是否成功
        :param tfrecord_file: record文件路径
        :param resize_height:
        :param resize_width:
        :param show_nums: 默认显示前四张照片
    
        :return:
        '''
        tf_image, tf_height, tf_width, tf_depth, tf_label = read_records(record_file,resize_height, resize_width)  # 读取函数
        # 显示前show_nums个图片
        init_op = tf.initialize_all_variables()
        with tf.Session() as sess:
            sess.run(init_op)
            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(sess=sess, coord=coord)
            for i in range(show_nums):
                image,height,width,depth,label = sess.run([tf_image,tf_height,tf_width,tf_depth,tf_label])  # 在会话中取出image和label
                # image = tf_image.eval()
                # 直接从record解析的image是一个向量,需要reshape显示
                # image = image.reshape([height,width,depth])
                print('shape:',image.shape,'label:',label)
                # pilimg = Image.fromarray(np.asarray(image_eval_reshape))
                # pilimg.show()
                show_image("image:%d"%(label),image)
            coord.request_stop()
            coord.join(threads)
    
    
    def batch_test(record_file,resize_height, resize_width):
        '''
        :param record_file: record文件路径
        :param resize_height:
        :param resize_width:
        :return:
        :PS:image_batch, label_batch一般作为网络的输入
        '''
    
        tf_image,tf_height,tf_width,tf_depth,tf_label = read_records(record_file,resize_height, resize_width) # 读取函数
    
        # 使用shuffle_batch可以随机打乱输入:
        # shuffle_batch用法:https://blog.csdn.net/u013555719/article/details/77679964
        min_after_dequeue = 100#该值越大,数据越乱,必须小于capacity
        batch_size = 4
        # capacity = (min_after_dequeue + (num_threads + a small safety margin∗batchsize)
        capacity = min_after_dequeue + 3 * batch_size#容量:一个整数,队列中的最大的元素数
    
        image_batch, label_batch = tf.train.shuffle_batch([tf_image, tf_label],
                                                          batch_size=batch_size,
                                                          capacity=capacity,
                                                          min_after_dequeue=min_after_dequeue)
    
        init = tf.global_variables_initializer()
        with tf.Session() as sess:  # 开始一个会话
            sess.run(init)
            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(coord=coord)
            for i in range(4):
                # 在会话中取出images和labels
                images, labels = sess.run([image_batch, label_batch])
                # 这里仅显示每个batch里第一张图片
                show_image("image", images[0, :, :, :])
                print(images.shape, labels)
            # 停止所有线程
            coord.request_stop()
            coord.join(threads)
    
    
    if __name__ == '__main__':
        # 参数设置
        image_dir='dataset/train'
        train_file = 'dataset/train.txt'  # 图片路径
        output_record_txt = 'dataset/record/record.txt'#指定保存record的文件列表
        resize_height = 224  # 指定存储图片高度
        resize_width = 224  # 指定存储图片宽度
        batchSize=8000     #batchSize一般设置为8000,即每batchSize张照片保存为一个record文件
        # 产生record文件
        create_records(image_dir=image_dir,
                       file=train_file,
                       record_txt_path=output_record_txt,
                       batchSize=batchSize,
                       resize_height=resize_height,
                       resize_width=resize_width)
    
        # 测试显示函数
        disp_records(output_record_txt,resize_height, resize_width)
    
        # batch_test(output_record_txt,resize_height, resize_width)
    

    1.2. 直接文件读取方式 

        上面介绍的是如何将数据转存为TFrecord文件,训练时再解析TFrecord。这种转存为TFrecord数据格式的方法,虽然高效,但也丧失了灵活性,特别是新增数据或者删除相关数据时,这时就不得不重新制作TFrecord数据了。这就挺麻烦啦,如果不想转为TFrecord文件,可以直接读取图像文件进行训练。

        这种方法比较简单,灵活性很强,但效率很低,因为每次迭代训练,GPU/CPU都要等待数据读取I/O操作,图像文件读取以及预处理过程本身就很耗时,甚至比你迭代一次网络还耗时。解决的方法,就是采用tf.data.Dataset数据读取机制。

        直接文件读取方式的完整代码可以参考如下:

        假设我们有train.txt的文件数据如下:

    0.jpg 0
    1.jpg 0
    2.jpg 0
    3.jpg 0
    4.jpg 0
    5.jpg 1
    6.jpg 1
    7.jpg 1
    8.jpg 1
    9.jpg 1

        可以使用下面的方法直接读取图像数据,并产生一个batch的训练数据:

    # -*-coding: utf-8 -*-
    """
        @Project: tf_record_demo
        @File   : tf_read_files.py
        @Author : panjq
        @E-mail : pan_jinquan@163.com
        @Date   : 2018-10-14 10:44:06
    """
    import tensorflow as tf
    import glob
    import numpy as np
    import os
    import matplotlib.pyplot as plt
    
    import cv2
    def show_image(title, image):
        '''
        显示图片
        :param title: 图像标题
        :param image: 图像的数据
        :return:
        '''
        # plt.imshow(image, cmap='gray')
        plt.imshow(image)
        plt.axis('on')  # 关掉坐标轴为 off
        plt.title(title)  # 图像题目
        plt.show()
    
    
    def tf_read_image(filename, resize_height, resize_width):
        '''
        读取图片
        :param filename:
        :param resize_height:
        :param resize_width:
        :return:
        '''
        image_string = tf.read_file(filename)
        image_decoded = tf.image.decode_jpeg(image_string, channels=3)
        # tf_image = tf.cast(image_decoded, tf.float32)
        tf_image = tf.cast(image_decoded, tf.float32) * (1. / 255.0)  # 归一化
        if resize_width>0 and resize_height>0:
            tf_image = tf.image.resize_images(tf_image, [resize_height, resize_width])
        # tf_image = tf.image.per_image_standardization(tf_image)  # 标准化[0,1](减均值除方差)
        return tf_image
    
    
    def get_batch_images(image_list, label_list, batch_size, labels_nums, resize_height, resize_width, one_hot=False, shuffle=False):
        '''
        :param image_list:图像
        :param label_list:标签
        :param batch_size:
        :param labels_nums:标签个数
        :param one_hot:是否将labels转为one_hot的形式
        :param shuffle:是否打乱顺序,一般train时shuffle=True,验证时shuffle=False
        :return:返回batch的images和labels
        '''
        # 生成队列
        image_que, tf_label = tf.train.slice_input_producer([image_list, label_list], shuffle=shuffle)
        tf_image = tf_read_image(image_que, resize_height, resize_width)
        min_after_dequeue = 200
        capacity = min_after_dequeue + 3 * batch_size  # 保证capacity必须大于min_after_dequeue参数值
        if shuffle:
            images_batch, labels_batch = tf.train.shuffle_batch([tf_image, tf_label],
                                                                batch_size=batch_size,
                                                                capacity=capacity,
                                                                min_after_dequeue=min_after_dequeue)
        else:
            images_batch, labels_batch = tf.train.batch([tf_image, tf_label],
                                                        batch_size=batch_size,
                                                        capacity=capacity)
        if one_hot:
            labels_batch = tf.one_hot(labels_batch, labels_nums, 1, 0)
        return images_batch, labels_batch
    
    
    def load_image_labels(filename):
        '''
        载图txt文件,文件中每行为一个图片信息,且以空格隔开:图像路径 标签1,如:test_image/1.jpg 0
        :param filename:
        :return:
        '''
        images_list = []
        labels_list = []
        with open(filename) as f:
            lines = f.readlines()
            for line in lines:
                # rstrip:用来去除结尾字符、空白符(包括\n、\r、\t、' ',即:换行、回车、制表符、空格)
                content = line.rstrip().split(' ')
                name = content[0]
                labels = []
                for value in content[1:]:
                    labels.append(int(value))
                images_list.append(name)
                labels_list.append(labels)
        return images_list, labels_list
    
    
    def batch_test(filename, image_dir):
        labels_nums = 2
        batch_size = 4
        resize_height = 200
        resize_width = 200
        image_list, label_list = load_image_labels(filename)
        image_list=[os.path.join(image_dir,image_name) for image_name in image_list]
    
        image_batch, labels_batch = get_batch_images(image_list=image_list,
                                                     label_list=label_list,
                                                     batch_size=batch_size,
                                                     labels_nums=labels_nums,
                                                     resize_height=resize_height, resize_width=resize_width,
                                                     one_hot=False, shuffle=True)
        with tf.Session() as sess:  # 开始一个会话
            sess.run(tf.global_variables_initializer())
            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(coord=coord)
            for i in range(4):
                # 在会话中取出images和labels
                images, labels = sess.run([image_batch, labels_batch])
                # 这里仅显示每个batch里第一张图片
                show_image("image", images[0, :, :, :])
                print('shape:{},tpye:{},labels:{}'.format(images.shape, images.dtype, labels))
    
            # 停止所有线程
            coord.request_stop()
            coord.join(threads)
    
    
    if __name__ == "__main__":
        image_dir = "./dataset/train"
        filename = "./dataset/train.txt"
        batch_test(filename, image_dir)
    
    
    

    2.tf.data.Dataset数据读取机制:Pipeline机制

        要执行训练步骤,您必须首先提取并转换训练数据,然后将其提供给在加速器上运行的模型。然而,在一个简单的同步执行中,当 CPU 正在准备数据时,加速器则处于空闲状态。相反,当加速器正在训练模型时,CPU 则处于空闲状态。因此,训练步骤时间是 CPU 预处理时间和加速器训练时间的总和

    prefetch(必须放在最后)

         TensorFlow引入了tf.data.Dataset模块,使其数据读入的操作变得更为方便,而支持多线程(进程)的操作,也在效率上获得了一定程度的提高。使用tf.data.Dataset模块的pipline机制,可实现CPU多线程处理输入的数据,如读取图片和图片的一些的预处理,这样GPU可以专注于训练过程,而CPU去准备数据。

        参考资料:

    https://blog.csdn.net/u014061630/article/details/80776975

    (五星推荐)TensorFlow全新的数据读取方式:Dataset API入门教程:http://baijiahao.baidu.com/s?id=1583657817436843385&wfr=spider&for=pc

        Pipelining 将一个训练步骤的预处理和模型执行重叠。当加速器正在执行训练步骤 N 时,CPU 正在准备步骤 N + 1 的数据。这样做的目的是可以将步骤时间缩短到极致,包含训练以及提取和转换数据所需时间(而不是总和)。

        如果没有使用 pipelining,则 CPU 和 GPU / TPU 在大部分时间处于闲置状态:

        而使用 pipelining 技术后,空闲时间显著减少:

        tf.data API 通过 tf.data.Dataset.prefetch 转换提供了一个软件 pipelining 操作机制,该转换可用于将数据生成的时间与所消耗时间分离。特别是,转换使用后台线程和内部缓冲区,以便在请求输入数据集之前从输入数据集中预提取元素。因此,为了实现上面说明的 pipelining 效果,您可以将 prefetch(1) 添加为数据集管道的最终转换(如果单个训练步骤消耗 n 个元素,则添加 prefetch(n))。

        tf.data.Dataset.prefetch 提供了 software pipelining 机制。该函数解耦了 数据产生的时间 和 数据消耗的时间。具体来说,该函数有一个后台线程和一个内部缓存区,在数据被请求前,就从 dataset 中预加载一些数据(进一步提高性能)。prefech(n) 一般作为最后一个 transformation,其中 n 为 batch_size。 prefetch 的使用方法如下:   

        要将此更改应用于我们的运行示例,请将:

    dataset = dataset.batch(batch_size=FLAGS.batch_size)
    return dataset

        更改为:

    dataset = dataset.batch(batch_size=FLAGS.batch_size)
    dataset = dataset.prefetch(buffer_size=FLAGS.prefetch_buffer_size)
    return dataset

        请注意,在任何时候只要有机会将 “制造者” 的工作与 “消费者” 的工作重叠,预取转换就会产生效益。前面的建议只是最常见的应用程序。

    map

        使用 tf.data.Dataset.map,我们可以很方便地对数据集中的各个元素进行预处理。因为输入元素之间时独立的,所以可以在多个 CPU 核心上并行地进行预处理。map 变换提供了一个 num_parallel_calls参数去指定并行的级别。

        准备批处理时,可能需要预处理输入元素。为此,tf.data API 提供了 tf.data.Dataset.map 转换,它将用户定义的函数(例如,运行示例中的 parse_fn)应用于输入数据集的每个元素。由于输入元素彼此独立,因此可以跨多个 CPU 内核并行化预处理。为了实现这一点,map 转换提供了 thenum_parallel_calls 参数来指定并行度。例如,下图说明了将 num_parallel_calls = 2 设置为 map 转换的效果:

    dataset = dataset.map(map_func=parse_fn, num_parallel_calls=FLAGS.num_parallel_calls)
    

    repeat

        repeat的功能就是将整个序列重复多次,主要用来处理机器学习中的epoch,假设原先的数据是一个epoch,使用repeat(5)就可以将之变成5个epoch:

        如果直接调用repeat()的话,生成的序列就会无限重复下去,没有结束,因此也不会抛出tf.errors.OutOfRangeError异常

    实例代码1:dataset.make_initializable_iterator()

    # -*-coding: utf-8 -*-
    """
        @Project: fine tuning
        @File   : pipeline.py
        @Author : panjq
        @E-mail : pan_jinquan@163.com
        @Date   : 2018-11-17 20:18:54
    """
    import tensorflow as tf
    import numpy as np
    import glob
    import matplotlib.pyplot as plt
    
    width=0
    height=0
    def show_image(title, image):
        '''
        显示图片
        :param title: 图像标题
        :param image: 图像的数据
        :return:
        '''
        # plt.figure("show_image")
        # print(image.dtype)
        plt.imshow(image)
        plt.axis('on')  # 关掉坐标轴为 off
        plt.title(title)  # 图像题目
        plt.show()
    
    
    def tf_read_image(filename, label):
        image_string = tf.read_file(filename)
        image_decoded = tf.image.decode_jpeg(image_string, channels=3)
        image = tf.cast(image_decoded, tf.float32)
        if width>0 and height>0:
            image = tf.image.resize_images(image, [height, width])
        image = tf.cast(image, tf.float32) * (1. / 255.0)  # 归一化
        return image, label
    
    
    def input_fun(files_list, labels_list, batch_size, shuffle=True):
        '''
        :param files_list:
        :param labels_list:
        :param batch_size:
        :param shuffle:
        :return:
        '''
        # 构建数据集
        dataset = tf.data.Dataset.from_tensor_slices((files_list, labels_list))
        if shuffle:
            dataset = dataset.shuffle(100)
        dataset = dataset.repeat()  # 空为无限循环
        dataset = dataset.map(tf_read_image, num_parallel_calls=4)  # num_parallel_calls一般设置为cpu内核数量
        dataset = dataset.batch(batch_size)
        dataset = dataset.prefetch(2)  # software pipelining 机制
        return dataset
    
    
    if __name__ == '__main__':
        data_dir = 'dataset/image/*.jpg'
        # labels_list = tf.constant([0,1,2,3,4])
        # labels_list = [1, 2, 3, 4, 5]
        files_list = glob.glob(data_dir)
        labels_list = np.arange(len(files_list))
        num_sample = len(files_list)
        batch_size = 1
        dataset = input_fun(files_list, labels_list, batch_size=batch_size, shuffle=False)
    
        # 需满足:max_iterate*batch_size <=num_sample*num_epoch,否则越界
        max_iterate = 3
        with tf.Session() as sess:
            iterator = dataset.make_initializable_iterator()
            init_op = iterator.make_initializer(dataset)
            sess.run(init_op)
            iterator = iterator.get_next()
            for i in range(max_iterate):
                images, labels = sess.run(iterator)
                show_image("image", images[0, :, :, :])
                print('shape:{},tpye:{},labels:{}'.format(images.shape, images.dtype, labels))
    

    实例代码2:dataset.make_one_shot_iterator()

         上面的迭代器是使用dataset.make_initializable_iterator(),当然一个更简单的方法是使用dataset.make_one_shot_iterator(),下面的代码,可把dataset.make_one_shot_iterator()放在input_fun函数中,直接返回一个迭代器iterator

    # -*-coding: utf-8 -*-
    """
        @Project: fine tuning
        @File   : pipeline.py
        @Author : panjq
        @E-mail : pan_jinquan@163.com
        @Date   : 2018-11-17 20:18:54
    """
    import tensorflow as tf
    import numpy as np
    import glob
    import matplotlib.pyplot as plt
    
    width = 224
    height = 224
    
    
    def show_image(title, image):
        '''
        显示图片
        :param title: 图像标题
        :param image: 图像的数据
        :return:
        '''
        # plt.figure("show_image")
        # print(image.dtype)
        plt.imshow(image)
        plt.axis('on')  # 关掉坐标轴为 off
        plt.title(title)  # 图像题目
        plt.show()
    
    
    def tf_read_image(filename, label):
        image_string = tf.read_file(filename)
        image_decoded = tf.image.decode_jpeg(image_string, channels=3)
        image = tf.cast(image_decoded, tf.float32)
        if width > 0 and height > 0:
            image = tf.image.resize_images(image, [height, width])
        image = tf.cast(image, tf.float32) * (1. / 255.0)  # 归一化
        return image, label
    
    
    def input_fun(files_list, labels_list, batch_size, shuffle=True):
        '''
        :param files_list:
        :param labels_list:
        :param batch_size:
        :param shuffle:
        :return:
        '''
        # 构建数据集
        dataset = tf.data.Dataset.from_tensor_slices((files_list, labels_list))
        if shuffle:
            dataset = dataset.shuffle(100)
        dataset = dataset.repeat()  # 空为无限循环
        dataset = dataset.map(tf_read_image, num_parallel_calls=4)  # num_parallel_calls一般设置为cpu内核数量
        dataset = dataset.batch(batch_size)
        dataset = dataset.prefetch(2)  # software pipelining 机制
    
        iterator = dataset.make_one_shot_iterator()
        return iterator
    
    
    if __name__ == '__main__':
        data_dir = './data/demo_data/*.jpg'
        # labels_list = tf.constant([0,1,2,3,4])
        # labels_list = [1, 2, 3, 4, 5]
        files_list = glob.glob(data_dir)
        labels_list = np.arange(len(files_list))
        num_sample = len(files_list)
        batch_size = 4
        iterator = input_fun(files_list, labels_list, batch_size=batch_size, shuffle=False)
    
        # 需满足:max_iterate*batch_size <=num_sample*num_epoch,否则越界
        max_iterate = 3
        with tf.Session() as sess:
            # iterator = dataset.make_initializable_iterator()
            # init_op = iterator.make_initializer(dataset)
            # sess.run(init_op)
            iterator = iterator.get_next()
            for i in range(max_iterate):
                images, labels = sess.run(iterator)
                show_image("image", images[0, :, :, :])
                print('shape:{},tpye:{},labels:{}'.format(images.shape, images.dtype, labels))
    

    实例代码3:产生用于训练的图和label

    假设train.txt的数据如下:

    0_8354.jpg 8 3 5 4
    1_3621.jpg 3 6 2 1
    2_4326.jpg 4 3 2 6
    3_7711.jpg 7 7 1 1
    
    # -*-coding: utf-8 -*-
    """
        @Project: verification_code
        @File   : dataset.py
        @Author : panjq
        @E-mail : pan_jinquan@163.com
        @Date   : 2019-03-03 18:45:13
    """
    import tensorflow as tf
    import numpy as np
    import glob
    import os
    import matplotlib.pyplot as plt
    from utils import file_processing,image_processing
    
    print("TF Version:{}".format(tf.__version__))
    
    resize_height = 0  # 指定存储图片高度
    resize_width = 0  # 指定存储图片宽度
    
    def load_image_labels(filename):
        '''
        载图txt文件,文件中每行为一个图片信息,且以空格隔开:图像路径 标签1 标签1,如:test_image/1.jpg 0 2
        :param filename:
        :return:
        '''
        images_list=[]
        labels_list=[]
        with open(filename) as f:
            lines = f.readlines()
            for line in lines:
                #rstrip:用来去除结尾字符、空白符(包括\n、\r、\t、' ',即:换行、回车、制表符、空格)
                content=line.rstrip().split(' ')
                name=content[0]
                labels=[]
                for value in content[1:]:
                    labels.append(int(value))
                images_list.append(name)
                labels_list.append(labels)
        return images_list,labels_list
    
    def show_image(title, image):
        '''
        显示图片
        :param title: 图像标题
        :param image: 图像的数据
        :return:
        '''
        # plt.figure("show_image")
        # print(image.dtype)
        plt.imshow(image)
        plt.axis('on')  # 关掉坐标轴为 off
        plt.title(title)  # 图像题目
        plt.show()
    
    def tf_resize_image(image, width=0, height=0):
        if (width is None) or (height is None):  # 错误写法:resize_height and resize_width is None
            return image
        image = tf.image.resize_images(image, [height, width])
        return image
    
    
    def tf_read_image(file, width, height):
        image_string = tf.read_file(file)
        image_decoded = tf.image.decode_jpeg(image_string, channels=3)
        image = tf.cast(image_decoded, tf.float32)
        image=tf_resize_image(image, width, height)
        image = tf.cast(image, tf.float32) * (1. / 255.0)  # 归一化
        return image
    
    def map_read_image(files_list, labels_list):
        tf_image=tf_read_image(files_list,resize_width,resize_height)
        return tf_image,labels_list
    
    def input_fun(files_list, labels_list, batch_size, shuffle=True):
        '''
        :param orig_image:
        :param dest_image:
        :param batch_size:
        :param num_epoch:
        :param shuffle:
        :return:
        '''
        # 构建数据集
        dataset = tf.data.Dataset.from_tensor_slices((files_list, labels_list))#TF version>=1.4
        # dataset = tf.contrib.data.Dataset.from_tensor_slices((files_list, labels_list))#TF version<1.4
    
        if shuffle:
            dataset = dataset.shuffle(100)
        dataset = dataset.repeat()  # 空为无限循环
        # dataset = dataset.map(map_read_image, num_parallel_calls=4)  # num_parallel_calls一般设置为cpu内核数量
        dataset = dataset.map(map_read_image)  # num_parallel_calls一般设置为cpu内核数量
    
        dataset = dataset.batch(batch_size)
        dataset = dataset.prefetch(2)  # software pipelining 机制
        dataset = dataset.make_one_shot_iterator()
        return dataset
    
    
    def get_image_data(images_list, image_dir,labels_list, batch_size, re_height, re_width, shuffle=False):
        global resize_height
        global resize_width
        resize_height = re_height  # 指定存储图片高度
        resize_width = re_width    # 指定存储图片宽度
        image_list = [os.path.join(image_dir, name) for name in images_list]
        dataset = input_fun(image_list, labels_list, batch_size, shuffle)
        return dataset
    
    if __name__ == '__main__':
        filename='../dataset/train.txt'
        image_dir="E:/TensoFlow/verification_code/dataset/train"
        images_list, labels_list=load_image_labels(filename)
        batch_size = 4
        dataset=get_image_data(images_list, image_dir,labels_list, batch_size, re_height=None, re_width=None, shuffle=False)
        # 需满足:max_iterate*batch_size <=num_sample*num_epoch,否则越界
        max_iterate = 3
        with tf.Session() as sess:
            # dataset = dataset.make_initializable_iterator()
            # init_op = dataset.make_initializer(dataset)
            # sess.run(init_op)
            dataset = dataset.get_next()
            for i in range(max_iterate):
                images, labels = sess.run(dataset)
                print('shape:{},tpye:{},labels:{}'.format(images.shape, images.dtype, labels))
                show_image("image", images[0, :, :, :])
    
    

    实例代码4:产生用于训练的原始图和target目标图

    # -*-coding: utf-8 -*-
    """
        @Project: triple_path_networks
        @File   : load_data.py
        @Author : panjq
        @E-mail : pan_jinquan@163.com
        @Date   : 2018-11-29 11:40:37
    """
    
    import tensorflow as tf
    
    import glob
    import numpy as np
    import utils.image_processing as image_processing
    import os
    print("TF Version:{}".format(tf.__version__))
    
    resize_height = 0  # 指定存储图片高度
    resize_width = 0   # 指定存储图片宽度
    
    def write_data(file, content_list, model):
        with open(file, mode=model) as f:
            for line in content_list:
                f.write(line + "\n")
    
    def read_data(file):
        with open(file, mode="r") as f:
            content_list = f.readlines()
            content_list = [content.rstrip() for content in content_list]
        return content_list
    
    def read_train_val_data(filename,factor=0.8):
        image_list = read_data(filename)
        trian_num=int(len(image_list)*factor)
        train_list = image_list[:trian_num]
        val_list = image_list[trian_num:]
        print("data info***************************")
        print("--train nums:{}".format(len(train_list)))
        print("--val   nums:{}".format(len(val_list)))
        print("************************************")
        return train_list,val_list
    
    def tf_resize_image(image,width=0,height=0):
        if height>0 and width>0:
            image = tf.image.resize_images(image, [height, width])
        return image
    
    def tf_read_image(file,width=224,height=224):
        image_string = tf.read_file(file)
        image_decoded = tf.image.decode_jpeg(image_string, channels=3)
        image = tf.cast(image_decoded, tf.float32)
        if height>0 and width>0:
            image = tf.image.resize_images(image, [height, width])
        image = tf.cast(image, tf.float32) * (1. / 255.0)  # 归一化
        return image
    
    def map_read_image(orig_file, dest_file):
        orig_image=tf_read_image(orig_file,resize_width,resize_height)
        dest_image=tf_read_image(dest_file,resize_width,resize_height)
        return orig_image,dest_image
    
    def input_fun(orig_image, dest_image, batch_size, shuffle=True):
        '''
        :param orig_image:
        :param dest_image:
        :param batch_size:
        :param num_epoch:
        :param shuffle:
        :return:
        '''
        # 构建数据集
        # dataset = tf.data.Dataset.from_tensor_slices((orig_image, dest_image))
        dataset = tf.contrib.data.Dataset.from_tensor_slices((orig_image, dest_image))
    
        if shuffle:
            dataset = dataset.shuffle(100)
        dataset = dataset.repeat()  #空为无限循环
        # dataset = dataset.map(map_read_image, num_parallel_calls=4)  # num_parallel_calls一般设置为cpu内核数量
        dataset = dataset.map(map_read_image)  # num_parallel_calls一般设置为cpu内核数量
    
        dataset = dataset.batch(batch_size)
        # dataset = dataset.prefetch(2)  # software pipelining 机制
        return dataset
    
    def get_image_data(file_list,orig_dir,dest_dir,batch_size,re_height,re_width,shuffle=False):
        global resize_height
        global resize_width
        resize_height = re_height  # 指定存储图片高度
        resize_width = re_width  # 指定存储图片宽度
    
        orig_image_list=[os.path.join(orig_dir,name) for name in file_list]
        dest_image_list=[os.path.join(dest_dir,name) for name in file_list]
        dataset = input_fun(orig_image_list, dest_image_list, batch_size=batch_size,shuffle=shuffle)
        return dataset
    
    if __name__ == '__main__':
        orig_dir="../dataset/blackberry/blackberry"
        dest_dir="../dataset/blackberry/canon"
        filename="../dataset/blackberry/filelist.txt"
        batch_size = 1
        file_list=read_data(filename)
        dataset = get_image_data(file_list,orig_dir, dest_dir, batch_size=batch_size,shuffle=False)
        # 迭代次数:max_iterate=10
        # 需满足:max_iterate*batch_size <=num_sample*num_epoch,否则越界
        max_iterate = 5
        with tf.Session() as sess:
            iterator = dataset.make_initializable_iterator()
            init_op = iterator.make_initializer(dataset)
            sess.run(init_op)
            iterator = iterator.get_next()
            for i in range(max_iterate):
                orig_image, dest_image = sess.run(iterator)
                image_processing.show_image("orig_image", orig_image[0, :, :, :])
                image_processing.show_image("dest_image", dest_image[0, :, :, :])
                print('orig_image:{},dest_image:{}'.format(orig_image.shape, dest_image.shape))
    

    实例代码5: tf.data.Dataset.from_generator

        tf.data.Dataset.from_tensor_slices并不支持输入长度不同list,比如以下代码

    t = [[4,2], [3,4,5]]
    dataset = tf.data.Dataset.from_tensor_slices(t)

        将会报错:

    ValueError: Argument must be a dense tensor: [[4, 2], [3, 4, 5]] - got shape [2], but wanted [2, 2].

        一种决解的方法,采用  tf.data.Dataset.from_generator生成器:

    import tensorflow as tf
    import numpy as np
    data1 = np.array([[1], [2, 3], [3, 4]])
    data2 = np.array([[10], [20, 30], [30, 40]])
    
    def data_generator():
        for el, e2 in zip(data1, data2):
            yield el, e2
    
    dataset = tf.data.Dataset.from_generator(data_generator,
                                             output_types=(tf.int32, tf.int32),
                                             output_shapes=(None, None)) #或者output_shapes=(tf.TensorShape([None]), tf.TensorShape([None]))
    
    iterator = dataset.make_one_shot_iterator()
    next_element = iterator.get_next()
    max_iter = 3
    with tf.Session() as sess:
        for i in range(max_iter):
            d1, d2 = sess.run(next_element)
            print("d1:{}".format(d1))
            print("d2:{}".format(d2))
            print("******************************")
    

      输出:

    d1:[1]
    d2:[10]
    ******************************
    d1:[2 3]
    d2:[20 30]
    ******************************
    d1:[3 4]
    d2:[30 40]
    ******************************

    参考资料:

    https://stackoverflow.com/questions/47580716/how-to-input-a-list-of-lists-with-different-sizes-in-tf-data-dataset

    https://blog.csdn.net/foreseerwang/article/details/80572182

    https://blog.csdn.net/dqcfkyqdxym3f8rb0/article/details/79342369(五星推荐)


    3. 用Python循环产生批量数据batch

         这部分请参考本人的博客《Python循环产生批量数据batch》  https://blog.csdn.net/guyuealian/article/details/83473298

        上面提到的方法都是在TensorFlow提高API接口完成的,数据预处理也必须依赖TensorFlow的API接口。当遇到一些特殊处理,而TensorFlow没有相应的接口时,就比较尴尬。比如要对输入的图像进行边缘检测处理时,这时能想到就是用OpenCV的Canny算法,一种简单的方法就是,每次sess.run()获得图像数据后,再调用OpenCV的Canny算法……是的,有的麻烦!

         这里提供一个我自己设计方法,不依赖TensorFlow,灵活性很强,你可以对数据进行任意的操作,可以使用OpenCV,numpy等任意的库函数。

       TXT文本如下,格式:图片名 label1 label2 ,注意label可以多个

    1.jpg 1 11
    2.jpg 2 12
    3.jpg 3 13
    4.jpg 4 14
    5.jpg 5 15
    6.jpg 6 16
    7.jpg 7 17
    8.jpg 8 18

        要想产生batch数据,关键是要用到Python的关键字yield,实现一个batch一个batch的返回数据,代码实现主要有两个方法:

    def get_data_batch(inputs, batch_size=None, shuffle=False):
        '''
        循环产生批量数据batch
        :param inputs: list数据
        :param batch_size: batch大小
        :param shuffle: 是否打乱inputs数据
        :return: 返回一个batch数据
        '''
    def get_next_batch(batch):
        return batch.__next__()

        使用时,将数据传到 get_data_batch( )方法,然后使用get_next_batch( )获得一个batch数据,完整的Python代码如下:

    # -*-coding: utf-8 -*-
    """
        @Project: create_batch_data
        @File   : create_batch_data.py
        @Author : panjq
        @E-mail : pan_jinquan@163.com
        @Date   : 2017-10-27 18:20:15
    """
    import math
    import random
    import os
    import glob
    import numpy as np
    
    
    def get_data_batch(inputs, batch_size=None, shuffle=False):
        '''
        循环产生批量数据batch
        :param inputs: list类型数据,多个list,请[list0,list1,...]
        :param batch_size: batch大小
        :param shuffle: 是否打乱inputs数据
        :return: 返回一个batch数据
        '''
        rows = len(inputs[0])
        indices = list(range(rows))
        # 如果输入是list,则需要转为list
        if shuffle:
            random.seed(100)
            random.shuffle(indices)
        while True:
            batch_indices = np.asarray(indices[0:batch_size])  # 产生一个batch的index
            indices = indices[batch_size:] + indices[:batch_size]  # 循环移位,以便产生下一个batch
            batch_data = []
            for data in inputs:
                data = np.asarray(data)
                temp_data=data[batch_indices] #使用下标查找,必须是ndarray类型类型
                batch_data.append(temp_data.tolist())
            yield batch_data
    
    def get_data_batch2(inputs, batch_size=None, shuffle=False):
        '''
        循环产生批量数据batch
        :param inputs: list类型数据,多个list,请[list0,list1,...]
        :param batch_size: batch大小
        :param shuffle: 是否打乱inputs数据
        :return: 返回一个batch数据
        '''
        # rows,cols=inputs.shape
        rows = len(inputs[0])
        indices = list(range(rows))
        if shuffle:
            random.seed(100)
            random.shuffle(indices)
        while True:
            batch_indices = indices[0:batch_size]  # 产生一个batch的index
            indices = indices[batch_size:] + indices[:batch_size]  # 循环移位,以便产生下一个batch
            batch_data = []
            for data in inputs:
                temp_data = find_list(batch_indices, data)
                batch_data.append(temp_data)
            yield batch_data
    
    
    def find_list(indices, data):
        out = []
        for i in indices:
            out = out + [data[i]]
        return out
    
    
    def get_list_batch(inputs, batch_size=None, shuffle=False):
        '''
        循环产生batch数据
        :param inputs: list数据
        :param batch_size: batch大小
        :param shuffle: 是否打乱inputs数据
        :return: 返回一个batch数据
        '''
        if shuffle:
            random.shuffle(inputs)
        while True:
            batch_inouts = inputs[0:batch_size]
            inputs = inputs[batch_size:] + inputs[:batch_size]  # 循环移位,以便产生下一个batch
            yield batch_inouts
    
    
    def load_file_list(text_dir):
        text_dir = os.path.join(text_dir, '*.txt')
        text_list = glob.glob(text_dir)
        return text_list
    
    
    def get_next_batch(batch):
        return batch.__next__()
    
    
    def load_image_labels(finename):
        '''
        载图txt文件,文件中每行为一个图片信息,且以空格隔开:图像路径 标签1 标签1,如:test_image/1.jpg 0 2
        :param test_files:
        :return:
        '''
        images_list = []
        labels_list = []
        with open(finename) as f:
            lines = f.readlines()
            for line in lines:
                # rstrip:用来去除结尾字符、空白符(包括\n、\r、\t、' ',即:换行、回车、制表符、空格)
                content = line.rstrip().split(' ')
                name = content[0]
                labels = []
                for value in content[1:]:
                    labels.append(float(value))
                images_list.append(name)
                labels_list.append(labels)
        return images_list, labels_list
    
    
    if __name__ == '__main__':
        filename = './training_data/test.txt'
        images_list, labels_list = load_image_labels(filename)
    
        # 若输入为np.arange数组,则需要tolist()为list类型,如:
        # images_list = np.reshape(np.arange(8*3), (8,3))
        # labels_list = np.reshape(np.arange(8*3), (8,3))
        # images_list=images_list.tolist()
        # labels_list=labels_list.tolist()
    
        iter = 5  # 迭代3次,每次输出一个batch个
        # batch = get_data_batch([images_list, labels_list], batch_size=3, shuffle=False)
        batch = get_data_batch2(inputs=[images_list,labels_list], batch_size=5, shuffle=True)
    
        for i in range(iter):
            print('**************************')
            batch_images, batch_labels = get_next_batch(batch)
            print('batch_images:{}'.format(batch_images))
            print('batch_labels:{}'.format(batch_labels))
    
    
    

       运行输出结果为:

    **************************
    batch_images:['1.jpg', '2.jpg', '3.jpg']
    batch_labels:[[1.0, 11.0], [2.0, 12.0], [3.0, 13.0]]
    **************************
    batch_images:['4.jpg', '5.jpg', '6.jpg']
    batch_labels:[[4.0, 14.0], [5.0, 15.0], [6.0, 16.0]]
    **************************
    batch_images:['7.jpg', '8.jpg', '1.jpg']
    batch_labels:[[7.0, 17.0], [8.0, 18.0], [1.0, 11.0]]
    **************************
    batch_images:['2.jpg', '3.jpg', '4.jpg']
    batch_labels:[[2.0, 12.0], [3.0, 13.0], [4.0, 14.0]]
    **************************
    batch_images:['5.jpg', '6.jpg', '7.jpg']
    batch_labels:[[5.0, 15.0], [6.0, 16.0], [7.0, 17.0]]

    Process finished with exit code 0

     


    4.参考资料:

    [1]https://blog.csdn.net/happyhorizion/article/details/77894055  (五星推荐)

    [2]https://blog.csdn.net/ywx1832990/article/details/78462582

    [3]https://blog.csdn.net/csuzhaoqinghui/article/details/51377941

    [4]《tf.data API,构建高性能 TensorFlow 输入管道

     

     

    展开全文
  • ROS专题----tftf2坐标变换

    万次阅读 2017-03-14 20:11:24
    ROS专题----tftf2坐标变换----工作区设置如果您尚未创建用于完成教程...将TransformListener从tf迁移到tf2这是一个将tf TransformListener类转换为tf2监听器类的指南将TransformBroadcaster从tf迁移到tf2这是一个将t
  • 前言:前面在介绍使用tensorflow进行data pipeline的时候,遇到了一些问题,特意整理了两篇文章,请参见: ...本系列文章将深入详解这是哪个函数,即tf.py_function()、tf.py_func、tf.numpy_function
  • 目录 产品基本介绍 产品基本FAQ 与开源硬件的基本匹配 其他(I²C版参考方案) ...TFmini Plus 是基于 TFmini 的升级项目,它是一款小型化,单点测距的产品,基于 TOF(飞行 时间)原理,配合独特...
  • TensorFlow tf.data 导入数据(tf.data官方教程) * * * * *

    万次阅读 多人点赞 2018-06-19 12:47:30
    # ==> (tf.float32, (tf.float32, tf.int32)) print ( dataset3 . output_shapes ) # ==> "(10, ((), (100,)))" 为 Dataset 中的元素的各个组件命名通常会带来便利性(例如,元素的各个组件表示不同特征时)...
  • tf.feature_column详解

    千次阅读 2020-06-19 11:08:52
    在tensorflow2.0 环境下的tfrecord读写及tf.io.parse_example和tf.io.parse_single_example的区别中已经降到了从tfrecord 中读取数据需要提供一个dict,里面包含了特征名称和特征的类型,如果我们特征很少,只需要...
  • 前面不管是直接使用python的print函数,还是使用tf.Print都需要构建一个会话对象session,然后再会话里面运行,而tf.print()则不在需要了,但是需要用到eager_execution模式。 3.1 tf.print()函数的定义 def...
  • tf函数说明

    千次阅读 2017-11-04 10:41:58
    tensorflow的基本运作 ...import tensorflow as tf #定义‘符号’变量,也称为占位符 a = tf.placeholder("float") b = tf.placeholder("float") y = tf.mul(a, b) #构造一个op节点 sess = tf.Session
  • 在程序中有一处不理解的地方 import basic.util.prints这个basic包找不到也搜不到,有知道的帮忙留言,谢谢 ...tf.zeros(shape, dtype=tf.float32, name=None) tf.zeros_like(tensor, dtype=None,
  • 【Tensorflow】TF中的字符串tf.string

    万次阅读 2019-09-23 19:47:57
    目录 string 的定义 ...tf.as_string() tf.substr() tf.string_to_number() tf.string_split() tf.string_join() tf.reduce_join() 总结 Tesorflow 版本:1.7.0,1.14.0 string 的定义 Tensorflow ...
  • TF-IDF 原理及sklearn中的tf-idf实例分析

    万次阅读 2018-08-18 22:32:20
    背景介绍 在一个大的文本语料库中,一些单词将出现很多次(例如 “the”, “a”, “is” 是英文),因此对文档的实际内容没有什么有意义的信息。 如果我们将直接计数数据直接...Tf表示术语频率,而 tf-idf 表示术语...
  • TensorFlow2教程-TF fuction和AutoGraph 要获得最佳性能并使模型可在任何地方部署,请使用tf.function从程序中构建图。 因为有AutoGraph,可以使用tf.function构建高效性能的Python代码,但仍有一些陷阱需要警惕。 ...
  • 导入数据(Reading data) ...TensorFlow读取数据的四种方法:tf.data、Feeding、QueueRunner、Preloaded data。 本篇的内容主要介绍 tf.data API的使用 目录 导入数据(Reading data) 1....
  • tf.gradients()和tf.stop_gradient()

    千次阅读 2019-06-17 10:47:34
    1、tf.gradients() tf.gradients( ys, xs, grad_ys=None, name='gradients', colocate_gradients_with_ops=False, gate_gradients=False, aggregation_method=None, stop_gradient...
  • 笔者近来在tensorflow中使用batch_norm时,由于事先不熟悉其...笔者最先使用时只是了解到了在tensorflow中tf.layers.batch_normalization这个函数,就在函数中直接将其使用,该函数中有一个参数为training,在训练阶...
  • tf.add()、tf.subtract()、tf.multiply()、tf.div()函数介绍和示例 1. tf.add() 释义:加法操作 示例: x = tf.constant(2, dtype=tf.float32, name=None) y = tf.constant(3, dtype=tf.float32, name=None) z = tf....
  • TensorFlow 2.0 常用模块5:@tf.function

    千次阅读 多人点赞 2020-01-09 20:21:31
    正如同正文里的例子一样,你可以在被 @tf.function 修饰的函数里调用 tf.Variable 、 tf.keras.optimizers 、 tf.keras.Model 等包含有变量的数据结构。一旦被调用,这些结构将作为隐含的参数提供给函数。当这些结构...
  • ROS之tf空间坐标变换完全详解

    万次阅读 多人点赞 2018-11-30 10:46:12
    本博文主要汇总了自己在使用ROS中tf坐标变换包时查找的一些参考资料和博客,包括了tf和部分tf2的使用,在此感谢所有博客中出现的博客链接! 参考资源: ROS官网详细介绍: http://wiki.ros.org/tf/Tutorials ...
  • [机器学习] TF-IDF算法

    千次阅读 2019-06-10 18:17:50
    1.文本数据的向量化 1.1名词解释 CF:文档集的频率,是指词在文档集中出现的次数 DF:文档频率,是指出现词的文档数 ...TF-IDF:TF-IDF= TF*IDF 1.2 TF-IDF算法 TF-IDF(词频-逆文档频率)算法是一...
  • tf.stack() 详解 —》理解为主

    万次阅读 多人点赞 2019-04-18 21:07:41
    tensorflow用于矩阵拼接的方法:tf.stack() 个人参考感觉还不错的一个理解(tf.stack() 和 tf.concat()的区别):https://blog.csdn.net/Gai_Nothing/article/details/88416782 def stack(values, axis=0, name...
  • 在计算机视觉的项目中,会遇到...常用的函数有tf.gather , tf.gather_nd 和 tf.batch_gather。 1.tf.gather(params,indices,validate_indices=None,name=None,axis=0) 主要参数:params:被索引的张量  indic...
  • Reusing模式会被子vs继承 ...print('"'+tf.get_variable_scope().name+'"', tf.get_variable_scope().reuse) with tf.variable_scope('ss'): # ss是默认vs的子vs,故虽然没有使用reuse=True,wit...
  • tf.get_variable()和tf.Variable()的区别(最清晰的解释)

    千次阅读 多人点赞 2019-04-27 14:27:01
    ==== 1、tf.Variable()
  • tf好朋友之tf.nn.dropout的使用

    千次阅读 2019-07-23 11:45:49
    tf好朋友之tf.nn.dropout的使用tf.nn.dropout函数介绍例子代码keep_prob = 0.5keep_prob = 1 神经网络在设置的神经网络足够复杂的情况下,可以无限逼近一段非线性连续函数,但是如果神经网络设置的足够复杂,将会...
  • 终于弄懂tf.reduce_sum()函数和tf.reduce_mean()函数

    万次阅读 多人点赞 2019-08-07 16:54:31
    loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction), reduction_indices=[1])) 刚开始照着up主写的代码是这样滴: loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction))) 然后就...
  • 各种SD卡 SIM卡 TF卡封装

    热门讨论 2011-10-29 09:19:34
    这个封装库里有SD卡、TF卡封装各四种,SIM卡封装3种,几乎这三种卡封装都覆盖了,非常实用啊!
  • 这里用到的是tf.summary的类,主要包括 tf.summary.histogram,tf.summary.scalar, tf.summary.image, tf.summary.FileWriter(分别生成日志) tf.summary.merge_all,(整理日志操作的,sess.run一次就不用对上述...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 344,807
精华内容 137,922
关键字:

tf