zoukankan      html  css  js  c++  java
  • 人脸识别智能小程序 | Tensorflow基础 | 03


    TensorFlow概念介绍-Graph

    TensorFlow:Google开源的基于数据流图的科学计算库,适用于机器学习、深度学习等人工智能领域。

    TensorFlow的源码是开源的,可以在github上进行下载。

    安装可以直接通过pip直接安装,也可以把源码下载到本地自己进行编译。

    然后TF中提供了很多模型,包括计算机视觉和自然语言处理的,在搭建模型的时候可以直接调用这里面的model。

    • 前端:编程模型、构造计算图、Python、Cpp、Java

    网络也被称为计算图。

    通过构造这样的一个图结构,并定好数据流向,来完成整个推理运算。

    • 后端:运行计算图,C++

    前端使用Python搭建网络模型,构造出来的计算图是不会运算的。前端搭建好计算图,并给定数据,后端再经过运算,得到输出。

    Graph:描述了整个计算过程。

    • 声明(单个/多个)

    一个图表示一个网络,如果需要用到多个网络来解决一个任务,那就需要声明多个图,也就是多个Graph。

    • 保存为pb文件

    pb文件包括了网络的结构和网络的参数。

    • 从pb中恢复Graph

    • Tensorboard可视化

    Graph是在前端来完成的,并且可以通过tf进行可视化展示。

    上图是一个图形化的结果。

    Session-Tensor-Operation-Feed-Fetch介绍

    Session

    • Graph必须在Session的上下文中执行
    • Session将Graph的op分发到诸如CPU或GPU之类的设备上运行

    Graph <=> Session <=> 后端

    Session相当于是Graph和后端的一个沟通的桥梁。

    注入机制: 实际上就是Session具体完成计算图的过程,也是在注入机制中完成了前端和后端这个桥梁的作用。

    Tensor

    • 在tf中,所有在节点之间传递的数据都为Tensor对象
    • N维数组,图像:((batch*height*width*channel))

    上图是tensor常用的定义方式,重点掌握前三种。

    tf.constant() # 常量
    tf.Variable() # 变量
    tr.placeholder() # 占位符
    

    Operation(op)

    • tf Graph中的计算节点,输入输出均为Tensor
    • 调用Session.run(tensor)或者tensor.eval()方可获取该Tensor的值

    上图中的两个add,一个maltiply都是op。

    具体计算图的op(操作)在哪里完成,可以通过Session来指定完成这些op的设备资源。

    Feed:通过feed为计算图注入值

    Feed为Tensor完成具体值的注入,这里注入的值通常是那些占位符。

    占位符是在构造计算图时,那些没有办法确定的Tensor。

    Fetch: 使用Fetch获取计算结果

    TensorFlow中核心API接口

    上面是常用的op操作。

    tf.nn 是常用的网络搭建API。

    tf.train 定义了很多和优化相关的一些函数。

    TFRecord: tf提供了TFRcord的格式来统一存储数据

    TFRecord将图像数据和标签放在一起的二进制文件(protocol buffer),能更好的利用内存,实现快速的复制、移动、读取、存储。

    TensorFlow数据读取机制与API方法

    如果直接从磁盘读取数据,那么IO的等待时间会造成计算资源的浪费。

    文件名队列有什么用呢?这里就涉及到我们模型训练的一个概念——Epoch。

    训练样本是分为一个一个batch的,意思就是每次从训练样本中取出一部分样本,用这个一部分样本来对网络参数进行调整,进行模型的训练。

    假如训练样本有10000个,batch的数量为100,那么一个Epoch就有100个batch。每取完100个batch(不重复),就叫做跑完了一个Epoch。一个Epoch就意味着全部的样本都在网络中进行了一遍计算。

    通过文件名队列,可以完成对Epoch更好的管理。比如在文件名队列中构造出3个Epoch,用A,B,C表示,那么它们都是包含了所有的文件列表的,那么就可以方便进行shuffle。

    Cifar10数据解析编程案例

    接下来以Cifar-10为例,介绍如何使用tf进行数据读取&数据打包。

    Cifar-10也是图像分类任务,在卷积神经网中,我们评价一个模型效果的好坏,可以使用ImageNet数据集对模型进行性能评估,也可以使用Cifar-10或Cifar-100。

    按照如下设置,本地连接远程编程环境!

    cifar10数据集下载地址

    http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
    

    下载好cifar10数据,解压后,发现其是二进制格式存放的,为了更方便的展示读写的效果,会对这些二进制文件进行解析,将其解析成具体的图片,并将其存放在data/image/的train/和test/下。

    下面的代码是对cifar-10图片进行解码。

    import urllib
    import urllib.request
    import os
    import sys
    import tarfile
    import glob
    import pickle
    import numpy as np
    import cv2  # pip install opencv-python
    
    
    def download_and_uncompress_tarball(tarball_url, dataset_dir):
        """
        完成对cifar10数据的下载和解压
        Downloads the `tarball_url` and uncompresses it locally.
        Args:
          tarball_url: The URL of a tarball file.
          dataset_dir: The directory where the temporary files are stored.
    
        """
        filename = tarball_url.split('/')[-1]
        filepath = os.path.join(dataset_dir, filename)
    
        def _progress(count, block_size, total_size):
            sys.stdout.write('
    >> Downloading %s %.1f%%' % (
                filename, float(count * block_size) / float(total_size) * 100.0))
            sys.stdout.flush()
    
        filepath, _ = urllib.request.urlretrieve(tarball_url, filepath, _progress)
        print()
        statinfo = os.stat(filepath)
        print('Successfully downloaded', filename, statinfo.st_size, 'bytes.')
        tarfile.open(filepath, 'r:gz').extractall(dataset_dir)
    
    
    DATA_URL = 'http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz'  # cifar10数据集
    DATA_DIR = 'data'
    
    # cifar10的10个分类
    classification = ['airplane',
                      'automobile',
                      'bird',
                      'cat',
                      'deer',
                      'dog',
                      'frog',
                      'horse',
                      'ship',
                      'truck']
    
    
    def unpickle(file):
        """
        这是cifar10网站给的关于文件解析的脚本
        :param file: 二进制文件
        :return: 解析好的键值对
        """
        import pickle
        with open(file, 'rb') as fo:
            dict = pickle.load(fo, encoding='bytes')
        return dict
    
    
    def to_image(from_file, to_file):
        """
        将cifar10还原成图片
        保存至  to_file/train/   to_file/test/
        :param from_file: 图片二进制文件
        :param to_file: 图片保存路径
        :return: 
        """
        # 下面将二进制文件解析成图片
        folders = from_file
        # glob模块的主要方法就是glob,该方法返回所有匹配的文件路径列表(list)
        # train_test_file = ["/data_batch*", "/test_batch*"]
        for x in ["train", "test"]:
            if x == "train":
                t_files = glob.glob(folders + "/data_batch*")
            else:
                t_files = glob.glob(folders + "/test_batch*")
            # 定义数据和标签为一个空格list
            data = []
            labels = []
            # 将每个文件都进行解码,得到解码后的数据
            for file in t_files:
                dt = unpickle(file)
                data += list(dt[b"data"])
                labels += list(dt[b"labels"])
    
            print(labels)  # 打印标签 进行查看
    
            # 在cifar10是通道优先的
            imgs = np.reshape(data, [-1, 3, 32, 32])
    
            for i in range(imgs.shape[0]):  # imgs.shape[0] 图片数据总量
                im_data = imgs[i, ...]  # 获取第i张图片
                im_data = np.transpose(im_data, [1, 2, 0])  # 将channel交换到最后一维
                im_data = cv2.cvtColor(im_data, cv2.COLOR_RGB2BGR)  # 将RGB转换为BGR模式
    
                f = "{}/{}/{}".format("data/image", x, classification[labels[i]])
                print(f)
                if not os.path.exists(f):
                    os.makedirs(f)
    
                # 命名 编号.jpg
                cv2.imwrite("{}/{}.jpg".format(f, str(i)), im_data)
        print("Finish!")
    
    
    if __name__ == '__main__':
        # 下载和解压cifar10数据
        # download_and_uncompress_tarball(DATA_URL, DATA_DIR)
        to_image("data/cifar-10-batches-py", "data/image/")
    
    

    Tensorflow中TFRecord数据打包编程案例

    然后需要对解码好的图片进行打包,生成TFRecord Writer。

    import tensorflow as tf
    import cv2
    import numpy as np
    import glob
    import os
    import warnings
    from tqdm import tqdm
    warnings.filterwarnings("ignore")
    
    classification = ['airplane',
                      'automobile',
                      'bird',
                      'cat',
                      'deer',
                      'dog',
                      'frog',
                      'horse',
                      'ship',
                      'truck']
    
    
    if __name__ == "__main__":
        for x in ["test", "train"]:
            idx = 0
            im_data = []
            im_labels = []
            for path in classification:
                path = "data/image/%s/" % x + path
                im_list = glob.glob(path + "/*")
                im_label = [idx for i in range(im_list.__len__())]
                idx += 1
                im_data += im_list
                im_labels += im_label
    
            print(im_labels[:10])
            print(im_data[:10])
    
            tfrecord_file = "data/%s.tfrecord" % x
            with tf.python_io.TFRecordWriter(tfrecord_file) as writer:
                # 使用shuffle进行打乱
                index = [i for i in range(im_data.__len__())]
                np.random.shuffle(index)
    
                for i in tqdm(range(im_data.__len__())):
                    im_d = im_data[index[i]]
                    im_l = im_labels[index[i]]
                    data = cv2.imread(im_d)  # 使用opencv读取图片
                    # 下面是另一种图片读取方式
                    #data = tf.gfile.FastGFile(im_d, "rb").read()
    
                    # 使用tf.train.Example将features编码数据封装成特定的PB协议格式
                    ex = tf.train.Example(
                        features=tf.train.Features(
                            feature={
                                "image": tf.train.Feature(
                                    bytes_list=tf.train.BytesList(
                                        value=[data.tobytes()])),
                                "label": tf.train.Feature(
                                    int64_list=tf.train.Int64List(
                                        value=[im_l])),
                            }
                        )
                    )
                    # 将example数据系列化为字符串,并将系列化为字符串的example数据写入协议缓冲区
                    writer.write(ex.SerializeToString())
    
    

    如何使用tf.train.slice_input_producer读取文件列表中的样本

    从文件列表中读取样本。

    import tensorflow as tf
    
    images = ['image1.jpg', 'image2.jpg', 'image3.jpg', 'image4.jpg']
    labels = [1, 2, 3, 4]
    
    """
    tf.train.slice_input_producer是一个tensor生成器,作用是按照设定,每次从一个tensor列表中按顺序或者随机抽取出一个tensor放入文件名队列。
    """
    [images, labels] = tf.train.slice_input_producer([images, labels],num_epochs=None,shuffle=True)
    
    with tf.Session() as sess:
        sess.run(tf.local_variables_initializer())
        tf.train.start_queue_runners(sess=sess)
        for i in range(10):
            print(sess.run([images, labels]))
    
    

    如何使用tf.train.string_input_producer读取文件列表中的样本

    从文件数据中读取样本。

    import tensorflow as tf
    
    filename = ['data/A.csv', 'data/B.csv', 'data/C.csv']
    
    file_queue = tf.train.string_input_producer(filename,
                                                shuffle=True,
                                                num_epochs=None)
    reader = tf.WholeFileReader()
    key, value = reader.read(file_queue)
    
    with tf.Session() as sess:
        sess.run(tf.local_variables_initializer())
        tf.train.start_queue_runners(sess=sess)
        for i in range(10):
            print(sess.run([key, value]))
    
    

    train.slice_input_producer 和 train.string_input_producer 的差别

    主要的区别就是string_input_producer输出的结果是一个队列,而slice_input_producer输出的结果是一个tensor。后者可以直接用sess.run()的方式获得tensor的值,但是对于string_input_producer 没有办法这样直接获取。

    如何通过TF对已经打包过的数据进行解析

    import tensorflow as tf
    import cv2
    filelist = ['data/train.tfrecord']
    file_queue = tf.train.string_input_producer(filelist,
                                                num_epochs=None,
                                                shuffle=True)
    reader = tf.TFRecordReader()
    _, ex = reader.read(file_queue)  # 解码得到打包的数据
    
    
    # 定义好feature
    feature = {
        'image': tf.FixedLenFeature([], tf.string),
        'label': tf.FixedLenFeature([], tf.int64)
    }
    
    batchsize = 2
    batch = tf.train.shuffle_batch([ex], batchsize, capacity=batchsize*10,
                                   min_after_dequeue=batchsize*5)
    
    example = tf.parse_example(batch, features=feature)
    
    image = example['image']
    label = example['label']
    
    image = tf.decode_raw(image, tf.uint8)
    image = tf.reshape(image, [-1, 32, 32, 3])
    
    with tf.Session() as sess:
        sess.run(tf.local_variables_initializer())
        tf.train.start_queue_runners(sess=sess)
    
        for i in range(1):
            image_bth, _ = sess.run([image, label])
            cv2.imshow("image", image_bth[0, ...])
            cv2.waitKey(0)
    
    

    上面的示例代码完成了对TFRecord数据的读取,并且每次读取的时候都是读取了一个batch_size的数据,也进行了可视化。

    在进行模型训练的时候,就是这样,每次读取一个batch_size的数据,并且将这个batch_size的数据喂给网络训练。

    TF中的高级API接口

    之前介绍的是一些tf的基本api接口,如果我们在设计网路的时候,使用这些基本的api接口,这时候就需要写大量的代码。

    在tf中,有更加高层的封装,其中用的最多的就是slim和keras。

    TF中的数据增强

    数据增强是防止过拟合非常常见的一个手段,在tf中可以通过 tf.image来对图像进行数据增强。

    对图像数据进行扰动,进而提高模型对噪声的鲁棒性。

    第一幅图是原图,后面的都是经过数据增强之后获取到的图像,这时候就相当于是产生了一些新的样本,而深度学习是要依赖于大数据的,数据越充分,那么学到的模型就更加的鲁棒。因此在进行模型训练的时候,数据增强是必须要使用的一种手段。

    Tensorboard 调试技巧

    Tensorboard:可以进行网络可视化/训练中间结果可视化。

    训练中间结果采用sess.run()打印出来,或可以添加到tensorboard中,进行可视化展示。

    小结

    Tensorflow是什么?

    TensorFlow:Google开源的基于数据流图的科学计算库,适用于机器学习、深度学习等人工智能领域。
    
    TensorFlow的源码是开源的,可以在github上进行下载。
    
    安装可以直接通过pip直接安装,也可以把源码下载到本地自己进行编译。
    
    **然后TF中提供了很多模型,包括计算机视觉和自然语言处理的,在搭建模型的时候可以直接调用这里面的model。**
    

    TensorFlow的架构

    *   前端:编程模型、构造计算图、Python、Cpp、Java
    
    网络也被称为计算图。
    
    通过构造这样的一个图结构,并定好数据流向,来完成整个推理运算。
    
    *   后端:运行计算图,C++
    
    前端使用Python搭建网络模型,构造出来的计算图是不会运算的。前端搭建好计算图,并给定数据,后端再经过运算,得到输出。
    

    Graph

    Graph:描述了整个计算过程。
    *   声明(单个/多个)
    
    一个图表示一个网络,如果需要用到多个网络来解决一个任务,那就需要声明多个图,也就是多个Graph。
    *   保存为pb文件
    
    pb文件包括了网络的结构和网络的参数。
    *   从pb中恢复Graph
    *   Tensorboard可视化
    
    
    
    Graph是在前端来完成的,并且可以通过tf进行可视化展示。
    上图是一个图形化的结果。
    

    Session

    Session
    *   Graph必须在Session的上下文中执行
    *   Session将Graph的op分发到诸如CPU或GPU之类的设备上运行
    
    Graph <=> Session <=> 后端
    Session相当于是Graph和后端的一个沟通的桥梁。
    
    
    注入机制: 实际上就是Session具体完成计算图的过程,也是在注入机制中完成了前端和后端这个桥梁的作用。
    
    

    Tensor

    Tensor
    *   在tf中,所有在节点之间传递的数据都为Tensor对象
    *   N维数组,图像:$(batch*height*width*channel)$
    
    上图是tensor常用的定义方式,重点掌握前三种。
    tf.constant() # 常量
    tf.Variable() # 变量
    tr.placeholder() # 占位符
    

    Operation

    Operation(op)
    *   tf Graph中的**计算节点**,输入输出均为Tensor
    *   调用Session.run(tensor)或者tensor.eval()方可获取该Tensor的值
    
    上图中的两个add,一个maltiply都是op。
    具体计算图的op(操作)在哪里完成,可以通过Session来指定完成这些op的设备资源。
    

    Feed & Fetch

    Feed:通过feed为计算图注入值
    Feed为Tensor完成具体值的注入,这里注入的值通常是那些占位符。
    占位符是在构造计算图时,那些没有办法确定的Tensor。
    
    Fetch: 使用Fetch获取计算结果
    

    TFRecord

    TFRecord: tf提供了TFRcord的格式来统一存储数据
    
    TFRecord将图像数据和标签放在一起的二进制文件(protocol buffer),能更好的利用内存,实现快速的复制、移动、读取、存储。
    

    tf的数据读取机制

    输入数据 -> 文件名队列 -> 内存队列 -> 计算
    
    文件名队列有什么用呢?这里就涉及到我们模型训练的一个概念——Epoch。
    
    训练样本是分为一个一个batch的,意思就是每次从训练样本中取出一部分样本,用这个一部分样本来对网络参数进行调整,进行模型的训练。
    
    假如训练样本有10000个,batch的数量为100,那么一个Epoch就有100个batch。每取完100个batch(不重复),就叫做跑完了一个Epoch。一个Epoch就意味着全部的样本都在网络中进行了一遍计算。
    
    通过文件名队列,可以完成对Epoch更好的管理。比如在文件名队列中构造出3个Epoch,用A,B,C表示,那么它们都是包含了所有的文件列表的,那么就可以方便进行shuffle。
    

    关于TFRecord的Writer和Reader

    这是一个模板代码的.. 
    知道这个东西,然后用的时候在对照着进行修改!
    

    train.slice_input_producer 和 train.string_input_producer 的差别

    主要的区别就是string_input_producer输出的结果是一个队列,而slice_input_producer输出的结果是一个tensor。后者可以直接用sess.run()的方式获得tensor的值,但是对于string_input_producer 没有办法这样直接获取。
    

    tf的高层接口

    之前介绍的是一些tf的基本api接口,如果我们在设计网路的时候,使用这些基本的api接口,这时候就需要写大量的代码。
    
    在tf中,有更加高层的封装,其中用的最多的就是slim和keras。
    

    数据增强

    数据增强是防止过拟合非常常见的一个手段,在tf中可以通过 tf.image来对图像进行数据增强。
    
    对图像数据进行扰动,进而提高模型对噪声的鲁棒性。
    
    
    第一幅图是原图,后面的都是经过数据增强之后获取到的图像,这时候就相当于是产生了一些新的样本,而深度学习是要依赖于大数据的,数据越充分,那么学到的模型就更加的鲁棒。**因此在进行模型训练的时候,数据增强是必须要使用的一种手段。**
    
    
    
  • 相关阅读:
    java 新建文件夹保存
    android AppWidgwtProvider学习
    GPS定位
    android ContentProvider学习
    Android 解屏幕锁与点亮屏幕(来电时效果)
    RecyclerView 分页滑动,设置可以滑动下一页,下一个item作为起点方法
    Glide 加载图片 到动态ImageView
    一个例子了解 HandlerThread,Looper,ThreadLocal,Handler,MessageQueue,Message的关系
    android TabLayout 相关
    屏幕相关
  • 原文地址:https://www.cnblogs.com/Rowry/p/15091359.html
Copyright © 2011-2022 走看看