TensorFlow:Google开源的基于数据流图的科学计算库,适用于机器学习、深度学习等人工智能领域。
TensorFlow的源码是开源的,可以在github上进行下载。
安装可以直接通过pip直接安装,也可以把源码下载到本地自己进行编译。
然后TF中提供了很多模型,包括计算机视觉和自然语言处理的,在搭建模型的时候可以直接调用这里面的model。
网络也被称为计算图。
通过构造这样的一个图结构,并定好数据流向,来完成整个推理运算。
前端使用Python搭建网络模型,构造出来的计算图是不会运算的。前端搭建好计算图,并给定数据,后端再经过运算,得到输出。
Graph:描述了整个计算过程。
一个图表示一个网络,如果需要用到多个网络来解决一个任务,那就需要声明多个图,也就是多个Graph。
pb文件包括了网络的结构和网络的参数。
从pb中恢复Graph
Tensorboard可视化
Graph是在前端来完成的,并且可以通过tf进行可视化展示。
上图是一个图形化的结果。
Session
Graph <=> Session <=> 后端
Session相当于是Graph和后端的一个沟通的桥梁。
注入机制: 实际上就是Session具体完成计算图的过程,也是在注入机制中完成了前端和后端这个桥梁的作用。
Tensor
上图是tensor常用的定义方式,重点掌握前三种。
tf.constant() # 常量 tf.Variable() # 变量 tr.placeholder() # 占位符
Operation(op)
上图中的两个add,一个maltiply都是op。
具体计算图的op(操作)在哪里完成,可以通过Session来指定完成这些op的设备资源。
Feed:通过feed为计算图注入值
Feed为Tensor完成具体值的注入,这里注入的值通常是那些占位符。
占位符是在构造计算图时,那些没有办法确定的Tensor。
Fetch: 使用Fetch获取计算结果
上面是常用的op操作。
tf.nn 是常用的网络搭建API。
tf.train 定义了很多和优化相关的一些函数。
TFRecord: tf提供了TFRcord的格式来统一存储数据
TFRecord将图像数据和标签放在一起的二进制文件(protocol buffer),能更好的利用内存,实现快速的复制、移动、读取、存储。
如果直接从磁盘读取数据,那么IO的等待时间会造成计算资源的浪费。
文件名队列有什么用呢?这里就涉及到我们模型训练的一个概念——Epoch。
训练样本是分为一个一个batch的,意思就是每次从训练样本中取出一部分样本,用这个一部分样本来对网络参数进行调整,进行模型的训练。
假如训练样本有10000个,batch的数量为100,那么一个Epoch就有100个batch。每取完100个batch(不重复),就叫做跑完了一个Epoch。一个Epoch就意味着全部的样本都在网络中进行了一遍计算。
通过文件名队列,可以完成对Epoch更好的管理。比如在文件名队列中构造出3个Epoch,用A,B,C表示,那么它们都是包含了所有的文件列表的,那么就可以方便进行shuffle。
接下来以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('\r>> 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/")
然后需要对解码好的图片进行打包,生成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())
从文件列表中读取样本。
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]))
从文件数据中读取样本。
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 没有办法这样直接获取。
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接口,如果我们在设计网路的时候,使用这些基本的api接口,这时候就需要写大量的代码。
在tf中,有更加高层的封装,其中用的最多的就是slim和keras。
数据增强是防止过拟合非常常见的一个手段,在tf中可以通过 tf.image来对图像进行数据增强。
对图像数据进行扰动,进而提高模型对噪声的鲁棒性。
第一幅图是原图,后面的都是经过数据增强之后获取到的图像,这时候就相当于是产生了一些新的样本,而深度学习是要依赖于大数据的,数据越充分,那么学到的模型就更加的鲁棒。因此在进行模型训练的时候,数据增强是必须要使用的一种手段。
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来对图像进行数据增强。 对图像数据进行扰动,进而提高模型对噪声的鲁棒性。 第一幅图是原图,后面的都是经过数据增强之后获取到的图像,这时候就相当于是产生了一些新的样本,而深度学习是要依赖于大数据的,数据越充分,那么学到的模型就更加的鲁棒。**因此在进行模型训练的时候,数据增强是必须要使用的一种手段。**