TensorFlow2 构建模型-境界3


有三种计算图的构建方式:静态计算图,动态计算图,以及Autograph。 TensorFlow 2.0主要使用的是动态计算图和Autograph。 动态计算图易于调试,编码效率较高,但执行效率偏低。 静态计算图执行效率很高,但较难调试。 而Autograph机制可以将动态图转换成静态计算图,兼收执行效率和编码效率之利。 当然Autograph机制能够转换的代码并不是没有任何约束的,有一些编码规范需要遵循,否则可能会转换失败或者不符合预期。 我们将着重介绍Autograph的编码规范和Autograph转换成静态图的原理。
Autograph编码规范:
• 1.被@tf.function修饰的函数应尽可能使用TensorFlow中的函数而不是Python中的其他函数。例如使用tf.print而不是print,使用tf.range而不是range,使用tf.constant(True)而不是True.
• 2.避免在@tf.function修饰的函数内部定义tf.Variable.
• 3.被@tf.function修饰的函数不可修改该函数外部的Python列表或字典等数据结构变量。

1.导入CIFAR-10数据集

CIFAR-10是由 Hinton 的学生 Alex Krizhevsky 和 Ilya Sutskever 整理的一个用于识别普适物体的小型数据集。一共包含 10 个类别的 RGB 彩色图片:飞机( a叩lane )、汽车( automobile )、鸟类( bird )、猫( cat )、鹿( deer )、狗( dog )、蛙类( frog )、马( horse )、船( ship )和卡车( truck )。图片的尺寸为 32×32,3个通道 ,数据集中一共有 50000 张训练圄片和 10000 张测试图片。 CIFAR-10数据集有3个版本,这里使用python版本。

1.1 导入需要的库

1.2 定义批量导入数据的函数

1.3 定义加载数据函数

1.4 加载数据

运行结果
loading data\cifar-10-batches-py\data_batch_1
loading data\cifar-10-batches-py\data_batch_2
loading data\cifar-10-batches-py\data_batch_3
loading data\cifar-10-batches-py\data_batch_4
loading data\cifar-10-batches-py\data_batch_5
finished loadding CIFAR-10 data

1.5 可视化加载数据

运行结果

2 .数据预处理并设置超参数

3.使用tf,data构建数据管道

4.定义卷积层及池化层

5.构建模型

6.定义训练模型函数

自定训练过程:
(1)打开一个遍历各epoch的for循环
(2)对于每个epoch,打开一个分批遍历数据集的 for 循环
(3)对于每个批次,打开一个 GradientTape() 作用域
(4)在此作用域内,调用模型(前向传递)并计算损失
(5)在作用域之外,检索模型权重相对于损失的梯度
(6)根据梯度使用优化器来更新模型的权重
(7)评估模型指标

train_model(model,train_data,training_steps,display_step)
运行结果
step =1000,loss = 1.3011,accuracy =0.5781 ,times=0.0000
step =2000,loss = 1.2720,accuracy =0.6094 ,times=0.0000
step =3000,loss = 1.2153,accuracy =0.5469 ,times=0.0000
step =4000,loss = 0.8636,accuracy =0.7500 ,times=0.0000
step =5000,loss = 0.7936,accuracy =0.7500 ,times=0.0000
step =6000,loss = 0.9527,accuracy =0.6875 ,times=0.0156
step =7000,loss = 0.9352,accuracy =0.7344 ,times=0.0000
step =8000,loss = 0.6892,accuracy =0.7969 ,times=0.0000
step =9000,loss = 0.7949,accuracy =0.7031 ,times=0.0000
step =10000,loss = 0.4768,accuracy =0.8438 ,times=0.0000
step =11000,loss = 0.7983,accuracy =0.7188 ,times=0.0000
step =12000,loss = 0.5601,accuracy =0.8281 ,times=0.0000
step =13000,loss = 0.7934,accuracy =0.7031 ,times=0.0000
step =14000,loss = 0.6450,accuracy =0.8438 ,times=0.0000
step =15000,loss = 0.5681,accuracy =0.7656 ,times=0.0000
step =16000,loss = 0.5413,accuracy =0.8125 ,times=0.0000
step =17000,loss = 0.3914,accuracy =0.8438 ,times=0.0000
step =18000,loss = 0.3687,accuracy =0.8906 ,times=0.0000
step =19000,loss = 0.4534,accuracy =0.8750 ,times=0.0000
step =20000,loss = 0.3855,accuracy =0.8438 ,times=0.0000

从运行结果来看,运行时间快了很多!

7.可视化运行结果

8.测试模型

运行结果
Test accuracy:0.720653
性能也有一定提升!

Tensorflow2构建模型-境界2

1.导入CIFAR-10数据集

CIFAR-10是由 Hinton 的学生 Alex Krizhevsky 和 Ilya Sutskever 整理的一个用于识别普适物体的小型数据集。一共包含 10 个类别的 RGB 彩色图片:飞机( a叩lane )、汽车( automobile )、鸟类( bird )、猫( cat )、鹿( deer )、狗( dog )、蛙类( frog )、马( horse )、船( ship )和卡车( truck )。图片的尺寸为 32×32,3个通道 ,数据集中一共有 50000 张训练圄片和 10000 张测试图片。 CIFAR-10数据集有3个版本,这里使用python版本。

1.1 导入需要的库

1.2 定义批量导入数据的函数

1.3 定义加载数据函数

1.4 加载数据

运行结果
loading data\cifar-10-batches-py\data_batch_1
loading data\cifar-10-batches-py\data_batch_2
loading data\cifar-10-batches-py\data_batch_3
loading data\cifar-10-batches-py\data_batch_4
loading data\cifar-10-batches-py\data_batch_5
finished loadding CIFAR-10 data

1.5 可视化加载数据

运行结果

2 .数据预处理并设置超参数

3.使用tf.data构建数据管道

4.定义卷积层及池化层

5.构建模型

6.定义训练模型函数

自定义训练过程:
(1)打开一个遍历各epoch的for循环
(2)对于每个epoch,打开一个分批遍历数据集的 for 循环
(3)对于每个批次,打开一个 GradientTape() 作用域
(4)在此作用域内,调用模型(前向传递)并计算损失
(5)在作用域之外,检索模型权重相对于损失的梯度
(6)根据梯度使用优化器来更新模型的权重
(7)评估模型指标

train_model(model,train_data,training_steps,display_step)
运行结果
step =1000,loss = 1.2807,accuracy =0.5781 ,times=0.0080
step =2000,loss = 1.1832,accuracy =0.6562 ,times=0.0080
step =3000,loss = 0.9727,accuracy =0.6562 ,times=0.0080
step =4000,loss = 1.0398,accuracy =0.6406 ,times=0.0050
step =5000,loss = 0.8615,accuracy =0.6406 ,times=0.0156
step =6000,loss = 0.7207,accuracy =0.7188 ,times=0.0000
step =7000,loss = 1.0945,accuracy =0.5938 ,times=0.0090
step =8000,loss = 0.7337,accuracy =0.7656 ,times=0.0080
step =9000,loss = 0.5792,accuracy =0.7812 ,times=0.0080
step =10000,loss = 0.7154,accuracy =0.7500 ,times=0.0080
step =11000,loss = 0.6398,accuracy =0.8125 ,times=0.0156
step =12000,loss = 0.6413,accuracy =0.7500 ,times=0.0080
step =13000,loss = 0.5555,accuracy =0.7812 ,times=0.0156
step =14000,loss = 0.6729,accuracy =0.8281 ,times=0.0156
step =15000,loss = 0.5163,accuracy =0.7500 ,times=0.0156
step =16000,loss = 0.5521,accuracy =0.7969 ,times=0.0000
step =17000,loss = 0.4475,accuracy =0.8594 ,times=0.0156
step =18000,loss = 0.3158,accuracy =0.8594 ,times=0.0080
step =19000,loss = 0.3829,accuracy =0.9062 ,times=0.0090
step =20000,loss = 0.2731,accuracy =0.9062 ,times=0.0080

7.可视化运行结果

8.测试型

运行结果
Test accuracy:0.712640

TensorFlow2构建模型-境界1

1.导入CIFAR-10数据集

CIFAR-10是由 Hinton 的学生 Alex Krizhevsky 和 Ilya Sutskever 整理的一个用于识别普适物体的小型数据集。一共包含 10 个类别的 RGB 彩色图片:飞机( a叩lane )、汽车( automobile )、鸟类( bird )、猫( cat )、鹿( deer )、狗( dog )、蛙类( frog )、马( horse )、船( ship )和卡车( truck )。图片的尺寸为 32×32,3个通道 ,数据集中一共有 50000 张训练圄片和 10000 张测试图片。 CIFAR-10数据集有3个版本,这里使用python版本。

1.1 导入需要的库

1.2 定义批量导入数据的函数

1.3 定义加载数据函数

1.4 加载数据

运行结果
loading data\cifar-10-batches-py\data_batch_1
loading data\cifar-10-batches-py\data_batch_2
loading data\cifar-10-batches-py\data_batch_3
loading data\cifar-10-batches-py\data_batch_4
loading data\cifar-10-batches-py\data_batch_5
finished loadding CIFAR-10 data

1.5 可视化加载数据

运行结果

2 .数据预处理并设置超参数

3.使用tf,data构建数据管道

4.定义卷积层及池化层

5.定义并初始化权重参数

6.构建模型

7.定义损失函数、评估函数

8.定义梯度计算函数

自定义梯度计算过程:
(1)打开一个 GradientTape() 作用域
(2)在此作用域内,调用模型(正向传播)并计算损失
(3)在作用域之外,检索模型权重相对于损失的梯度
(4)根据梯度使用优化器来更新模型的权重
(5)利用优化器进行反向传播(更新梯度)

9.训练模型

10.可视化运行结果

运行结果

11.测试模型

运行结果
Test accuracy:0.704327

TensorFlow2构建模型的五个境界

一、纯手工

定制化程度高,非常灵活,如自定义层、损失函数、优化器、性能评估、训练模型方法等,但编程难度较高。
具体实例

二、继承tf.Module

定制化程度高,如自定义层、损失函数、优化器、性能评估、训练模型方法等,且可以使用保存或恢复模型。
具体实例

三、继承tf.Module且使用AutoGraph

定制化程度高,如自定层、损失函数、优化器、性能评估、训练模型方法等,且可以使用保存或恢复模型。通过使用Autograph可达到静态图的性能,极大提升训练模型效率。不过使用Autograph时要注意对应的编码规范,如被@tf,function装饰的函数尽可能tensorflow函数,如tf.print,tf.range等(控制语句无此限制),避免在被@tf,function装饰的函数内部定义tf.Variabe等。
具体实例

四、网络层和模型使用子类方法构建

用子类方法构建网络层、网络模型是tensorflow2才有的,这种风格类似于PyTorch构建方法。TensorFlow1构建网络一般使用Sequential按层顺序构建模型,使用函数式API构建任意结构模型。当然,这两种方法在TensorFlow2也是常用方法。构建网络层时继承
tf.keras.layers.Layer,构建网络模型继承tf.keras.Model, 然后使用compile编辑模型,用fit训练模型。这样构建的网络既有一定的灵活性,又不失简洁性。
具体实例

五、使用tf,keras的Sequential模型按层顺序构建模型

最简洁,构建模型很简单,可是直接使用内置的层、损失函数、优化器、评估指标等,训练也可直接使用函数fit即可。Keras 提供了称为tf.keras.Model 的全功能模型类。它继承自 tf.keras.layers.Layer,使用SaveModel保存模型,可以非常方便移植到其他非Python环境(具体环境可参考下图)。

如何有效使用tf.data(基于TensorFlow2)?

1.机器学习一般流程

机器学习、深度学习的一般流程:
(1)分析业务需求
(2)确定数据源
(3)构建数据处理管道(pipeline)
(4)构建模型
(5)训练模型
(6)评估、优化模型
其中构建数据处理管道,在整个过程中,从时间上来说往往占60%左右,面对大数据其挑战更大。如何解决质量问题?如何解决内存瓶颈问题?如何解决处理效率问题等等。
接下来我们重点介绍如何使用TensorFlow2提供的tf.data工具有效构建数据流。

2.为何要构建数据管道?

使用tf.data API,我们可以使用简单的代码来构建复杂的输入 pipeline。
实现从从内存读取数据、从分布式文件系统中读取数据、进行预处理、合成为 batch、训练中使用数据集等。使用 tf.data API 可以轻松处理大量数据、不同的数据格式以及复杂的转换。
如果数据比较小,我们可以一次性处理后直接加入内存就可以了;但如果数据比较大,而且在数据训练过程中还需要一些动态的处理方法,如分批处理、添加数据增强方法、数据采样等等,此时,通过构建一个数据流就显得非常必要。
数据流可有效提高我们管理数据得效率,此外还可以帮助我们解耦数据的预处理和数据执行的过程,能够帮我们更高效的应用硬件资源,例如当分布式训练的时候,一个好的数据流能够帮我们高效的分发数据到不同的硬件上,从而提高整体的训练效率。
一个合理的数据流,能够让你模型训练更加的高效。数据流的本质就是 ETL。一般来说,数据流由三部分组成,具体如下:
(1)抽取、初始化源数据 (E:即Extract)
(2)添加各种预处理过程 (T: 即Transform)
(3)遍历数据流,把大数据导入模型、训练数据等 (L:Load)
在 Tensorflow2里,我们使用 tf.data 来构建数据管道。

3.tf.data简介

tf.data是TensorFlow提供的构建数据管道的一个工具,与PyTorch的utils.data类似,使用tf.data构建数据集(Dataset),构建和管理数据管道非常方便,它提供了很多操作,如:
shuffle、repeat、map、batch、padded_batch、prefetch等等,这些操作功能很实用,但使用的顺序是有讲究的,如果次序不当,将严重影响数据流的效率和质量,这些操作的顺利大致为:
(1)map->shuffle -> repeat -> map(parse) -> batch -> prefetch ;
(2)有些 map 操作放在 batch 前,有些 map 操作放在 batch 后;
(3)尽量把进行数据过滤和采样放数据流的前面,以提高后续处理效率;
(4)使用 AUTOTUNE 来设置并行执行的数量,不要去手动调节;
(5)使用 cache / interleave / prefetch 这些空间换时间的操作。

为便于更好理解这些操作,通过以下示例进行具体说明。

3.1 生成数据集

这里以手工创建一个非常简单的数据集,该数据包含10个样本,每个样本对应一个标签。

运行结果:
[0.1,0]
[0.4,0]
[0.6,1]
[0.2,0]
[0.8,1]
[0.8,1]
[0.4,0]
[0.9,1]
[0.3,0]
[0.2,0]

3.2 map

map对dataset中每个元素做出来,这里每个元素为[x,y],函数为one-hot
该函数把标签转换为one-hot编码。
介绍map()这一核心函数。该函数的输入参数map_func应为一个函数,在该函数中实现我们需要的对数据的变换。
具体应用场景如图片加载、数据增强、标签one hot化等。下面以one hot化和添加噪声为例具体说明。
one hot化的函数实现如下

运行结果
[0.1,[1 0]]
[0.4,[1 0]]
[0.6,[0 1]]
[0.2,[1 0]]
[0.8,[0 1]]
[0.8,[0 1]]
[0.4,[1 0]]
[0.9,[0 1]]
[0.3,[1 0]]
[0.2,[1 0]]

3.3 shuffle

shuffle()是随机打乱样本次序,参数buffer_size建议设为样本数量,过大会浪费内存空间,过小会导致打乱不充分。

运行结果
[0.6,[0 1]]
[0.2,[1 0]]
[0.3,[1 0]]
[0.8,[0 1]]
[0.4,[1 0]]
[0.8,[0 1]]
[0.2,[1 0]]
[0.4,[1 0]]
[0.1,[1 0]]
[0.9,[0 1]]

3.4 repeat

使用repeat方法,repeat的功能就是将整个序列或数据集重复多次, 完成整个数据集的一次训练是一个epoch,使用repeat(5)就可以将之变成5个epoch 如果直接调用repeat()的话,生成的序列就会无限重复下去,没有结束,因此也不会抛出tf.errors.OutOfRangeError异常。

运行结果
[0.8,[0 1]]
[0.8,[0 1]]
[0.1,[1 0]]
[0.9,[0 1]]
[0.2,[1 0]]
[0.2,[1 0]]
[0.4,[1 0]]
[0.3,[1 0]]
[0.6,[0 1]]
[0.4,[1 0]]
[0.4,[1 0]]
[0.2,[1 0]]
[0.4,[1 0]]
[0.3,[1 0]]
[0.8,[0 1]]
[0.2,[1 0]]
[0.8,[0 1]]
[0.9,[0 1]]
[0.6,[0 1]]
[0.1,[1 0]]

3.5 batch

batch()是使数据集一次获取多个样本

运行结果
[[0.4 0.3 0.6 0.2],[[1 0]
[1 0]
[0 1]
[1 0]]]
[[0.4 0.2 0.8 0.9],[[1 0]
[1 0]
[0 1]
[0 1]]]
[[0.8 0.1 0.6 0.9],[[0 1]
[1 0]
[0 1]
[0 1]]]
[[0.2 0.2 0.4 0.1],[[1 0]
[1 0]
[1 0]
[1 0]]]
[[0.3 0.8 0.8 0.4],[[1 0]
[0 1]
[0 1]
[1 0]]]

3.6map

map()函数,该函数的输入参数map_func应为一个函数,在该函数中实现我们需要的对数据的变换。具体应用场景如图片加载、数据增强、标签one hot化等。
对数据进行固定形式上的变化,可将函数直接作为参数输入。但是,包含随机信息的数据变化则需要tf.py_function辅助实现,
如数据增强中数据添加随机噪声、图像的随机翻转都属于包含随机信息。

运行结果
[[1.5635917 1.6635917 2.2635917 2.0635917],[[1 0]
[1 0]
[0 1]
[0 1]]]
[[1.29330552 0.89330552 1.39330552 0.79330552],[[0 1]
[1 0]
[0 1]
[1 0]]]
[[-0.04628853 -0.24628853 -0.04628853 -0.24628853],[[1 0]
[1 0]
[1 0]
[1 0]]]
[[-0.46844772 -0.96844772 -1.16844772 -0.66844772],[[0 1]
[1 0]
[1 0]
[0 1]]]
[[0.40181042 0.20181042 0.80181042 0.90181042],[[1 0]
[1 0]
[0 1]
[0 1]]]
在map()函数中,还有个很重要的参数num_parallel_calls,可以将数据加载与变换过程并行到多个CPU线程上。由于python语言本身的全局解释锁,想要实现真正的并行计算是非常困难的,所以这个参数实际上非常实用,通常的使用情景是网络训练时,GPU做模型运算的同时CPU加载数据。 还可以直接设置num_parallel_calls=tf.data.experimental.AUTOTUNE,这样会自动设置为最大的可用线程数,可充分利用机器算资源。

3.7 prefetch

prefetch(buffer_size)创建一个Dataset,从源数据集中预提取元素的,注意:examples.prefetch(2) 将预取2个元素(2个示例),
而examples.batch(20).prefetch(2) 将预取2个元素(2个批次,每个20个示例),buffer_size 表示预取时将缓冲的最大元素数,返回 Dataset。
使用prefetch可有效使用读取数据与模型处理之间松耦合。如下图所示

从上图可以看出,使用prefetch函数之后,读取数据与训练数据就可并发处理了,这就大大提升数据处理效率。

4.tf.data读取输入数据

tf.data的架构如下图所示:

从上图可知,Dataset是一个基类,这个类可实例化成迭代器(Iterator),

4.1 Dataset类

Dataset类下有多个子类,常见的有TextLineDataset、tf.data.FixedLengthRecordDataset、TFRecordDataset等,可用使用这些Dateset的子类获取数据,此外,Dataset还有很多方法,如from_tensor_slices、list_files、map、batch、repeat等等,Dataset的这些方法或子类通常用来读取或处理数据,当使用场景有些不同,tf.data常见的读取数据方式有以下几种:
(1)直接从内存中读取(如NumPy数据),tf.data.Dataset.from_tensor_slices()
(2)使用一个 python 生成器 (generator) 初始化,从生成器中读取数据可以使用
tf.data.Dataset.from_generator()
(3)从 TFrecords格式文件读取数据, 可使用tf.data.TFRecordDataset()
(4)读取文本数据,可使用tf.data.TextLineDataset()
(5)从二进制文件读取数据,可用tf.data.FixedLengthRecordDataset()
(6)读取cvs数据,可使用tf.data.experimental.make_csv_dataset()
(7)从文件集中读取数据,可使用tf.data.Dataset.list_files()

4.2对象Iterator

Iterator是Dataset中迭代方法的实例化,主要对数据进行访问,包括四种迭代方法,单次、可初始化、可重新初始化、可馈送等,可实现对数据集中元素的快速迭代,供模型训练使用。

TensorFlow2 如何构建自己的数据集?

1.背景说明

我们平时在网上、书上看到的有关深度学习的案例大多使用处理好、教规格的数据集,如MNIST, CIFAR10/100等数据集,这些数据集一般无需(或很少)做预处理,就看导入到模型中使用。但是很多情况下需要处理自己的数据集,这些数据集往往不规范,而且一般比较大。如何把自己的数据集转换成这些TensorFlow框架能够使用的数据形式至关重要,接下来将对TensorFlow2中官方推荐数据格式及预处理方法进行说明,小数据集处理方法很多,处理也比较方便,这里就不展开来说。这里主要介绍大中数据集,对大中数据集TensorFlow建议转换为TFRecord格式,使用TFRecord格式有哪些优势呢?

2.TFRecord的优势

正常情况下我们用于训练的文件夹内部往往会存着成千上万的图片或文本等文件,这些文件通常被散列存放。这种存储方式有一些缺点:
(1)占用磁盘空间;
(2)在一个个读取的时候会非常耗时;
(3)占用大量内存空间(有的大型数据不足以一次性加载)。
此时 TFRecord 格式的文件存储形式会很合理的帮我们存储数据。TFRecord 内部使用了 “Protocol Buffer” 二进制数据编码方案,它只占用一个内存块,只需要一次性加载一个二进制文件的方式即可,简单,快速,尤其对大型训练数据很友好。而且当我们的训练数据量比较大的时候,可以将数据分成多个 TFRecord 文件,来提高处理效率。

3.使用TFRecord的一般步骤

3.1 Exmple含义

freocrd的核心是其包含一系列的example,每个example可以认为是一条样本。example是tensorflow中的对象类型,用法是tf.train.example。
Example含义: 如下图,假设有样本 (example): (x,y) :输入x 和 输出y一起叫做样本。这里每个x是六维向量,每个y是一维向量。
(1)表征 (representation):x集合了代表个人的全部特征。
其中特征 (feature): x 中的某个维:如学历,年龄,职业。是某人的一个特点。
(2)标签 (label):y为输出。

对上表的数据的存储,通常我们把输入特征x与标签y分开进行保存。假设有100个样本,把所有输入存储在100x6的numpy矩阵中,把标签存储在100x1的向量中。
Example协议块格式:

以TFRecord方式存储,输入和标签将以字典方式存放在一起,具体格式请参考下图。

3.2 TFRecord文件数据格式

3.3 加载TFRecord文件流程

TFRecord做好了,可以通过tf.data来生成一个迭代器,每次调用都返回一个大小为batch_size的batch。读取TFRecord可以通过tensorflow两个个重要的函数实现如下图所示,分别是读取器(Reader): tf.data.TFRecordDataset和解码器(Decoder):tf.io.parse_single_example解析器。如下图:

4.代码实例

整个过程为:
(1)先把源数据(可以是文本、图像、音频、Embedding等,这里是小猫、小狗图片)导入内存(如NumPy)
(2)把内存数据转换为TFRecord格式数据
(3)读取TFRecord数据
(4)构建模型
(5)训练模型

4.1 导入数据

导入模块及数据,这里是windows环境,如果是linux环境,请修改路径格式。
数据集下载

4.2 把数据转换为TFRecord格式

构建example的时候,这个tf.train.Feature()函数可以接收三种数据:
• bytes_list: 可以存储string 和byte两种数据类型。
• float_list: 可以存储float(float32)与double(float64) 两种数据类型。
• int64_list: 可以存储:bool, enum, int32, uint32, int64, uint64。
对于只有一个值(比如label)可以用float_list或int64_list,而像图片、视频、embedding这种列表型的数据,通常转化为bytes格式储存

4.3 从TFRecord读取数据

这里使用 tf.data.TFRecordDataset 类来读取 TFRecord 文件
使用 TFRecordDataset 对于标准化输入数据和优化性能十分有用。可以使用tf.io.parse_single_example函数对每个样本进行解析(tf.io.parse_example对批量样本进行解析)。 请注意,这里的 feature_description 是必需的,因为数据集使用计算图执行,并且需要这些描述来构建它们的形状和类型签名。
使用 tf.data.Dataset.map 方法可将函数应用于 Dataset 的每个元素。

显示图片

4.4 构建模型

模型由两层卷积和两层全连接层构成。

4.5 训练模型

训练模型使用@tf.function装饰器将普通Python函数转换成对应的TensorFlow计算图构建代码。使用tf.GradientTape实现自动求导,使用TensorFlow2 autograph机制,该机制可以把动态图转换成静态图加速。

运行结果:
Epoch 1, Acc 50.98039627075195, Test Acc 57.5
Epoch 2, Acc 68.13725280761719, Test Acc 52.499996185302734
Epoch 3, Acc 80.39215850830078, Test Acc 47.5
Epoch 4, Acc 91.66667175292969, Test Acc 57.5
Epoch 5, Acc 93.13725280761719, Test Acc 57.5
Epoch 6, Acc 97.54901885986328, Test Acc 52.499996185302734
Epoch 7, Acc 100.0, Test Acc 52.499996185302734
Epoch 8, Acc 100.0, Test Acc 50.0
Epoch 9, Acc 100.0, Test Acc 50.0
Epoch 10, Acc 100.0, Test Acc 52.499996185302734
有兴趣的读者可以从以下几方面提升性能
5.利用数据增强方法提升性能
6.利用现代经典网络提升性能
7.利用数据迁移方法提升性能
8.结合Transformer技术提升性能

Pandas提高篇

2.Pandas提高篇

2.1 如何提高数据的颜值?

很多时候面对各种数据,我们想要让不同DataFrame有不同的颜色或格式来显示(styling),这时可以使用pandas Styler底下的format函式来实现,如何实现?以下通过一个实例来说明。
(1)生成数据

(2)数据浏览

(3)对dataframe不同数据设置不同的显示风格

(4)显示结果

2.2如何使你的分析更专业?

通常的数据分析有:排序、分组汇总平均分析、同比、环比等等,如何使你的分析更专业?可以通过引入一些更具专业的KPI指标分析,如反应客户偏好的TGI分析、反应客户价值的RMF指标、投资回报比(ROI)等等,这里以TGI分析为例,这也是用户画像中的一个重要指标。

2.2.1 TGI指标解释

1.TGI(Target Group Index的简称)指标计算公式:

2.TGI关键特征
TGI计算公式中,有三个关键点:总体,目标群体,某一特征。
 总体:是我们研究的所有对象,比如一个学校里的所有人;
 目标群体:是总体中我们感兴趣的一个分组,比如一个班;
 某一特征:想要分析的某种行为或者状态,比如打篮球。
3、TGI计算示例
假设一个学校有1000人,有300个人喜欢打篮球,那么这个比例就是30%,即“总体中具有相同特征的群体所占比例” = 30%。
假设一个班有50个人,有20个人喜欢打篮球,那么这个比例就是40%,即“目标群体中具有某一特征的群体所占比例” = 40%。
TGI指数 = (40% / 30%) * 100 = 133
TGI指数大于100,代表着某类用户更具有相应的倾向或者偏好,数值越大则倾向和偏好越强;小于100,则说明该类用户相关倾向较弱(和平均相比);而等于100则表示在平均水平。

2.2.2 导入数据

本数据为客户购买商品的订单信息,具体数据包括品牌名、买家姓名、付款时间、订单状态和地域等字段,一共28832条数据。
1、导入数据

2、数据浏览

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 28832 entries, 0 to 28831
Data columns (total 9 columns):
品牌名称 28832 non-null object
买家昵称 28832 non-null object
付款日期 28832 non-null datetime64[ns]
订单状态 28832 non-null object
实付金额 28832 non-null float64
邮费 28832 non-null int64
省份 28832 non-null object
城市 28832 non-null object
购买数量 28832 non-null int64
dtypes: datetime64[ns](1), float64(1), int64(2), object(5)
memory usage: 2.0+ MB

2.2.3 选择一个特征

这里我们以每个客户平均销售额50为界限,划分“高客单”或"低客单",接下来我们以“高客单”为特征进行TGI分析。
1、对dataframe进行分组汇总

2、增加一个客单类别指标

2.2.4 获取客户地域信息

df_users有单个用户的金额和客户类型,为便于各省市消费情况的比较,接下来就是添加每个用户的地域字段, 这个可以同pd.merge函数实现,具体与两表关联类型。由于源数据是未去重的,我们得先按昵称去重,不然匹配的结果会有许多重复的数据。
1、关联前对原df进行预处理

【说明】
DataFrame.duplicated函数格式为:
DataFrame.duplicated(subset=None, keep='first') 参数说明:
 subset可选
 keep{‘first’, ‘last’, False}, default ‘first’ df.loc函数功能:
通过标签或布尔数组访问一组行和列

2.2.5 计算高客单TGI指标

这样得到的结果包含了层次化索引,要索引得到“高客单”列,需要先索引“买家昵称”,再索引“高客单”。

这样,拿到了每个省市的高客单人数,然后再拿到低客单的人数,进行横向合并:

再看看每个城市总人数以及高客单人数占比,来完成“目标群体(如:高客单)中具有某一特征的群体所占比例”这个分子的计算:

有些非常小众的城市,高客单或者低客单人数等于1甚至没有,而这些值尤其是空值会影响结果的计算,我们要提前检核数据:

0.41528303343887557
最后一步,就是TGI指数的计算,顺便排个序

2.2.6 重要结论

基于各城市高客单TGI指数,我们发现福州、珠海、北京、厦门、佛山、南昌、成都、上海、无锡和深圳,是高客单偏好排名前10的城市!咱们要试销的高客单新产品,如果仅从客单角度,可以优先考虑他们!

2.3 如何使你的分析结果更具震撼效果?

为使分析结果更直观、更具震撼效果,可以采用pycharts工具,该工具提供了很多富有感染力的画图模块,除通常的图形外,Pycharts还提供热力图、日历图、迁徙图、地图等等,这里我们以地图为例。
1、导入需要的库

2、对tgi增加一个字段
为便于使用中国地图,这里增加一个中国字段。

3、创建画图函数

运行该函数

显示各省或直辖市,高客单的用户数。

另外,向大家提供一个有关如何提升数据分析能力的博客,供大家参考
月薪3000和30000的数据分析师差在哪?

pandas基础篇

1. Pandas基础篇

Python有了NumPy的Pandas,用Python处理数据就像使用Exel或SQL一样简单方便。
Pandas是基于NumPy的Python 库,它被广泛用于快速分析数据,以及数据清洗和准备等工作。可以把 Pandas 看作是 Python版的Excel或Table。Pandas 有两种数据结构:
Series和DataFrame,Pandas经过几个版本的更新,目前已经成为数据清洗、处理和分析的不二选择。

1.1 问题:Pandas有哪些优势?

科学计算方面NumPy是优势,但NumPy中没有标签,数据清理、数据处理就不是其强项了。而DataFrame有标签,就像SQL中的表一样,所以在数据处理方面DataFrame就更胜一筹了,具体包含以下几方面:
(1)读取数据方面
Pandas提供强大的IO读取工具,csv格式、Excel文件、数据库等都可以非常简便地读取,对于大数据,pandas也支持大文件的分块读取。
(2)在数据清洗方面
面对数据集,我们遇到最多的情况就是存在缺失值,Pandas把各种类型数据类型的缺失值统一称为NaN,Pandas提供许多方便快捷的方法来处理这些缺失值NaN。
(3)分析建模阶段
在分析建模阶段,Pandas自动且明确的数据对齐特性,非常方便地使新的对象可以正确地与一组标签对齐,由此,Pandas就可以非常方便地将数据集进行拆分-重组操作。
(4)结果可视化方面
结果展示方面,我们都知道Matplotlib是个数据视图化的好工具,Pandas与Matplotlib搭配,不用复杂的代码,就可以生成多种多样的数据视图。

1.2 Pandas数据结构

Pandas中两个最常用的对象是Series和DataFrame。使用pandas前,需导入以下内容:

Pandas主要采用Series和DataFrame两种数据结构。Series是一种类似一维数据的数据结构,由数据(values)及索引(indexs)组成,而DataFrame是一个表格型的数据结构,它有一组序列,每列的数据可以为不同类型(NumPy数据组中数据要求为相同类型),它既有行索引,也有列索引。

图1-1 DataFrame结构

1.3 Series

上章节我们介绍了多维数组(ndarray),当然,它也包括一维数组,Series类似一维数组,为啥还要介绍Series呢?或Series有哪些特点?
Series一个最大特点就是可以使用标签索引,序列及ndarray也有索引,但都是位置索引或整数索引,这种索引有很多局限性,如根据某个有意义标签找对应值,切片时采用类似[2:3]的方法,只能取索引为2这个元素等等,无法精确定位。
Series的标签索引(它位置索引自然保留)使用起来就方便多了,且定位也更精确,不会产生歧义。以下通过实例来说明。
(1)使用Series

0 1
1 3
2 6
3 -1
4 2
5 8
dtype: int64
(2)使用Series的索引

a 1
c 3
d 6
e -1
b 2
g 8
dtype: int64
(3)根据索引找对应值

1.4 DataFrame

DataFrame除了索引有位置索引也有标签索引,而且其数据组织方式与MySQL的表极为相似,除了形式相似,很多操作也类似,这就给操作DataFrame带来极大方便。这些是DataFrame特色的一小部分,它还有比数据库表更强大的功能,如强大统计、可视化等等。
DataFrame有几个要素:index、columns、values等,columns就像数据库表的列表,index是索引,values就是值。

图1-2 DataFrame结果

1.4.1 生成DataFrame

生成DataFrame有很多,比较常用的有导入等长列表、字典、numpy数组、数据文件等。

1.4.2 获取数据

获取DataFrame结构中数据可以采用obj[]操作、obj.iloc[]、obj.loc[]等命令。
(1)使用obj[]来获取列或行

(2)使用obj.loc[] 或obj.iloc[]获取行或列数据。
loc通过行标签获取行数据,iloc通过行号获取行数据。
loc 在index的标签上进行索引,范围包括start和end.
iloc 在index的位置上进行索引,不包括end.
这两者的主要区别可参考如下示例:

【说明】
除使用iloc及loc外,早期版本还有ix格式。pandas0.20.0及以上版本,ix已经丢弃,请尽量使用loc和iloc;

1.4.3 修改数据

我们可以像操作数据库表一样操作DataFrame,删除数据、插入数据、修改字段名、索引名、修改数据等,以下通过一些实例来说明。

图1-3 数据结构

1.4.4 汇总统计

Pandas有一组常用的统计方法,可以根据不同轴方向进行统计,当然也可按不同的列或行进行统计,非常方便。
常用的统计方法有:
表1-1 Pandas统计方法

以下通过实例来说明这些方法的使用
(1)把csv数据导入pandas

(2)查看df的统计信息

【说明】

即各项-均值的平方求和后再除以N 。
std:表示标准差,是var的平方根。

1.4.5选择部分列

这里选择学生代码、课程代码、课程名称、程程成绩,注册日期等字段

1.4.6删除重复数据

如果有重复数据(对df1的所有列),则删除最后一条记录。

1.4.7补充缺省值

(1)用指定值补充NaN值
这里要求把stat_date的缺省值(NaN)改为'2018-09-01'

(2)可视化,并在图形上标准数据

结果为:

(3)导入一些库及支持中文的库

(4)画图

运行结果


图1-4 可视化结果

1.4.8 Pandas操作MySQL数据库

(1)从MySQL数据库中获取学生基本信息表

(2)查看df_info前3行数据

(3)选择前两个字段

(4)df2 与df_info1 根据字段stud_code 进行内关联

(5)对df3 根据字段stud_code,sub_code进行分组,并求平均每个同学各科的平均成绩。

【备注】
如果需要合计各同学的成绩,可用如下语句。

(6)选择数学分析课程,并根据成绩进行降序。

(7)取前5名

注:DataFrame数据结构的函数或方法有很多,大家可以通过df.[Tab键]方式查看,具体命令的使用方法,如df.count(),可以在Ipython命令行下输入:?df.count() 查看具体使用,退出帮助界面,按q即可。

1.4.9 Pandas操作excel

把DataFrame数据写入excel中的多个sheet中

1.4.10 Pandas的三板斧

我们知道数据库中有很多函数可用作用于表中元素,DataFrame也可将函数(内置或自定义)应用到各列或行上,而且非常方便和简洁,具体可用通过DataFrame的apply、applymap和map来实现,其中apply、map对数据集中的每列或每行的逐元操作,applymap对dataframe的每个元素进行操作,这些函数对数据处理的强大工具。以下通过实例说明具体使用。

1.4.11 处理时间序列

pandas最基本的时间序列类型就是以时间戳(时间点)(通常以python字符串或datetime对象表示)为索引的Series:

索引为日期的DataFrame数据的索引、选取以及子集构造

1.4.12 数据离散化

如何离散化连续性数据?在一般开发语言中,可以通过控制语句来实现,但如果分类较多时,这种方法不但繁琐,效率也比较低。在Pandas中是否有更好方法?如果有,又该如何实现呢?
pandas有现成方法,如cut或qcut等,不需要编写代码,至于如何使用还是通过实例来说明。

现在需要对age字段进行离散化, 划分为(20,30],(30,40],(40,50].

1.4.13 交叉表

我们平常看到的数据格式大多像数据库中的表,如购买图书的基本信息:
表1-2 客户购买图书信息

这样的数据比较规范,比较适合于一般的统计分析。但如果我们想查看客户购买各种书的统计信息,就需要把以上数据转换为如下格式:
表1-3 客户购买图书的对应关系

我们观察一下不难发现,把表1-3中书代码列旋转为行就得到表2数据。如何实现行列的互换呢?编码能实现,但比较麻烦,还好,pandas提供了现成的方法或函数,如stack、unstack、pivot_table函数等。以下以pivot_table为例说明具体实现。

实现行列互换,把书代码列转换为行或索引

第1章 NumPy基础

第1章 NumPy基础

在机器学习和深度学习中,图像、声音、文本等输入数据最终都要转换为数组或矩阵。如何有效进行数组和矩阵的运算?这就需要充分利用NumPy。NumPy是数据科学的通用语言,而且与Pytorch关系非常密切,它是科学计算、深度学习的基石。尤其对Pytorch而言,其重要性更加明显。Pytorch中的Tensor与NumPy非常相似,它们之间可以非常方便地进行转换,掌握NumPy是学好Pytorch的重要基础,故我们把它列为全书第1章。
为什么是NumPy?实际上Python本身含有列表(list)和数组(array),但对于大数据来说,这些结构有很多不足。因列表的元素可以是任何对象,因此列表中所保存的是对象的指针。例如为了保存一个简单的[1,2,3],都需要有3个指针和三个整数对象。对于数值运算来说这种结构显然比较浪费内存和CPU等宝贵资源。 至于array对象,它直接保存数值,和C语言的一维数组比较类似。但是由于它不支持多维,在上面的函数也不多,因此也不适合做数值运算。
NumPy(Numerical Python 的简称)的诞生弥补了这些不足,NumPy提供了两种基本的对象:ndarray(N-dimensional array object)和 ufunc(universal function object)。ndarray是存储单一数据类型的多维数组,而ufunc则是能够对数组进行处理的函数。
NumPy的主要特点:
(1)ndarray,快速和节省空间的多维数组,提供数组化的算术运算和高级的广播功能。
(2)使用标准数学函数对整个数组的数据进行快速运算,而不需要编写循环。
(3)读取/写入磁盘上的阵列数据和操作存储器映像文件的工具。
(4)线性代数,随机数生成,和傅里叶变换的能力。
(5)集成C,C++,Fortran代码的工具。
本章主要内容如下:
 如何生成NumPy数组
 如何存取元素
 NumPy的算术运算
 数组变形
 批量处理
 NumPy的通用函数
 NumPy的广播机制

1.1 生成NumPy数组

NumPy是Python的外部库,不在标准库中。因此,若要使用它,需要先导入NumPy。

导入NumPy后,可通过np.+Tab键,查看可使用的函数,如果对其中一些函数的使用不很清楚,还可以在对应函数+?,再运行,就可很方便的看到如何使用函数的帮助信息。
np.然后按'Tab'键,将出现如下界面:

运行如下命令,便可查看函数abs的详细帮助信息。

NumPy不但强大,而且还非常友好。
接下来我们将介绍NumPy的一些常用方法,尤其是与机器学习、深度学习相关的一些内容。
NumPy封装了一个新的数据类型ndarray(n-dimensional array),它是一个多维数组对象。该对象封装了许多常用的数学运算函数,方便我们做数据处理、数据分析等。如何生成ndarray呢?这里我们介绍生成ndarray的几种方式,如从已有数据中创建、利用random创建、创建特殊多维数组、使用arange函数等。

1.1.1 从已有数据中创建数组

直接对 Python 的基础数据类型(如列表、元组等) 进行转换来生成 ndarray:
(1)将列表转换成 ndarray

(2)嵌套列表可以转换成多维 ndarray

如果把上面示例中的列表换成元组也同样适合。

1.1.2 利用 random 模块生成数组

在深度学习中,我们经常需要对一些参数进行初始化,为了更有效训练模型,提高模型的性能,有些初始化还需要满足一定条件,如满足正态分布或均匀分布等。这里我们介绍几种常用的方法,表1-1列举了 np.random 模块常用的函数。
表1-1 np.random模块常用函数

下面我们来看看一些函数的具体使用:

为了每次生成同一份数据,可以指定一个随机种子,使用shuffle函数打乱生成的随机数。

输出结果:
[[-1.0856306 0.99734545 0.2829785 ]
[-1.50629471 -0.57860025 1.65143654]]
随机打乱后数据:
[[-1.50629471 -0.57860025 1.65143654]
[-1.0856306 0.99734545 0.2829785 ]]

1.1.3 创建特定形状的多维数组

参数初始化时,有时需要生成一些特殊矩阵,如全是 0 或 1 的数组或矩阵,这时我们可以利用np.zeros、np.ones、np.diag来实现,如表1-2所示。
表1-2 NumPy 数组创建函数

下面我们通过几个示例来说明:

有时我们可能需要把生成的数据暂时保存起来,以备后续使用。

输出结果:
[[0.41092437 0.5796943 0.13995076 0.40101756 0.62731701]
[0.32415089 0.24475928 0.69475518 0.5939024 0.63179202]
[0.44025718 0.08372648 0.71233018 0.42786349 0.2977805 ]
[0.49208478 0.74029639 0.35772892 0.41720995 0.65472131]
[0.37380143 0.23451288 0.98799529 0.76599595 0.77700444]]

1.1.4 利用 arange、linspace 函数生成数组

arange 是 numpy 模块中的函数,其格式为:

其中start 与 stop 指定范围,step 设定步长,生成一个 ndarray,start 默认为 0,步长 step 可为小数。Python有个内置函数range功能与此类似。

linspace 也是 numpy 模块中常用的函数,其格式为:

它可以根据输入的指定数据范围以及等份数量,自动生成一个线性等分向量,其中endpoint (包含终点)默认为 True,等分数量num默认为 50。如果将retstep设置为 True,则会返回一个带步长的 ndarray。

值得一提的,这里并没有像我们预期的那样,生成 0.1, 0.2, ... 1.0 这样步长为0.1的 ndarray,这是因为 linspace 必定会包含数据起点和终点,那么其步长则为(1-0) / 9 = 0.11111111。如果需要产生 0.1, 0.2, ... 1.0 这样的数据,只需要将数据起点 0 修改为 0.1 即可。
除了上面介绍到的 arange 和 linspace,NumPy还提供了 logspace 函数,该函数使用方法与 linspace 使用方法一样,读者不妨自己动手试一下。

1.2 获取元素

上节我们介绍了生成ndarray的几种方法,数据生成后,如何读取我们需要的数据?这节我们介绍几种常用方法。

如果对上面这些获取方式还不是很清楚,没关系,下面我们通过图形的方式进一步说明,如图1-1所示,左边为表达式,右边为表达式获取的元素。注意不同的边界,表示不同的表达式。

图1-1 获取多维数组中的元素
获取数组中的部分元素除通过指定索引标签外,还可以使用一些函数来实现,如通过random.choice函数可以从指定的样本中进行随机抽取数据。

打印结果:
随机可重复抽取
[[ 7. 22. 19. 21.]
[ 7. 5. 5. 5.]
[ 7. 9. 22. 12.]]
随机但不重复抽取
[[ 21. 9. 15. 4.]
[ 23. 2. 3. 7.]
[ 13. 5. 6. 1.]]
随机但按制度概率抽取
[[ 15. 19. 24. 8.]
[ 5. 22. 5. 14.]
[ 3. 22. 13. 17.]]

1.3 NumPy的算术运算

在机器学习和深度学习中,涉及大量的数组或矩阵运算,这节我们重点介绍两种常用的运算。一种是对应元素相乘,又称为逐元乘法(element-wise product),运算符为np.multiply(), 或 *。另一种是点积或内积元素,运算符为np.dot()。

1.3.1对应元素相乘

对应元素相乘(element-wise product)是两个矩阵中对应元素乘积。np.multiply 函数用于数组或矩阵对应元素相乘,输出与相乘数组或矩阵的大小一致,其格式如下:

其中x1,x2之间的对应元素相乘遵守广播规则,NumPy的广播规则本章第7小节将介绍。以下我们通过一些示例来进一步说明。

矩阵A和B的对应元素相乘,用图1-2直观表示为:

图1-2 对应元素相乘示意图
NumPy数组不仅可以和数组进行对应元素相乘,也可以和单一数值(或称为标量)进行运算。运算时,NumPy数组每个元素和标量进行运算,其间会用到广播机制(1.7小节将详细介绍)。

[[ 2. 4.]
[-2. 8.]]
[[ 0.5 1. ]
[-0.5 2. ]]
由此,推而广之,数组通过一些激活函数后,输出与输入形状一致。

输入参数X的形状: (2, 3)
激活函数softmoid输出形状: (2, 3)
激活函数relu输出形状: (2, 3)
激活函数softmax输出形状: (2, 3)

1.3.2 点积运算

点积运算(dot product)又称为内积,在NumPy用np.dot表示,其一般格式为:

以下通过一个示例来说明dot的具体使用及注意事项。

[[21 24 27]
[47 54 61]]
以上运算,用图1-3可表示为:

图1-3 矩阵的点积示意图,对应维度的元素个数需要保持一致
如图1-3所示,矩阵X1和矩阵X2进行点积运算,其中X1和X2对应维度(即X1的第2个维度与X2的第1个维度)的元素个数必须保持一致,此外,矩阵X3的形状是由矩阵X1的行数与矩阵X2的列数构成的。

1.4 数组变形

在机器学习以及深度学习的任务中,通常需要将处理好的数据以模型能接受的格式喂给模型,然后模型通过一系列的运算,最终返回一个处理结果。然而,由于不同模型所接受的输入格式不一样,往往需要先对其进行一系列的变形和运算,从而将数据处理成符合模型要求的格式。最常见的是矩阵或者数组的运算,经常会遇到需要把多个向量或矩阵按某轴方向合并,或需要展平(如在卷积或循环神经网络中,在全连接层之前,需要把矩阵展平)。下面介绍几种常用数据变形方法。

1.4.1 更改数组的形状

修改指定数组的形状是 NumPy 中最常见的操作之一,常见的方法有很多,表1-3 列出了一些常用函数。
表1-3 NumPy中改变向量形状的一些函数

下面我们来看一些示例:
(1)reshape

输出结果:
[0 1 2 3 4 5 6 7 8 9]
[[0 1 2 3 4]
[5 6 7 8 9]]
[[0 1]
[2 3]
[4 5]
[6 7]
[8 9]]
[[0 1 2 3 4]
[5 6 7 8 9]]
值得注意的是,reshape 函数支持只指定行数或列数,剩余的设置为-1即可。所指定的行数或列数一定要能被整除(如10不能被3整除),例如上面代码如果修改为arr.reshape(3,-1)将报错误。
(2)resize

输出结果:
[0 1 2 3 4 5 6 7 8 9]
[[0 1 2 3 4]
[5 6 7 8 9]]
(3).T

输出结果:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[ 0 4 8]
[ 1 5 9]
[ 2 6 10]
[ 3 7 11]]
(4)ravel

输出结果:
[[0 1 2]
[3 4 5]]
按照列优先,展平
[0 3 1 4 2 5]
按照行优先,展平
[0 1 2 3 4 5]
(5)flatten
把矩阵转换为向量,这种需求经常出现在卷积网络与全连接层之间。

输出结果:
[[4. 0. 8. 5.]
[1. 0. 4. 8.]
[8. 2. 3. 7.]]
[4. 0. 8. 5. 1. 0. 4. 8. 8. 2. 3. 7.]
(6)squeeze
这是一个重要用来降维的函数,把矩阵中含1的维度去掉。在Pytorch中还有一种与之相反的操作,torch.unsqueeze这个后面将介绍。

(7)transpose
对高维矩阵进行轴对换,这个在深度学习中经常使用,比如把图片表示颜色的RGB顺序,改为GBR的顺序。

1.4.2 合并数组

合并数组也是最常见的操作之一,表1-4列举了常用的用于数组或向量合并的方法。
表1-4 NumPy 数组合并方法

[说明]
①append、concatnate以及stack都有一个 axis 参数,用于控制数组合并是按行还是按列。
②对于append和concatnate,待合并的数组必须有相同的行数或列数(满足一个即可)。
③stack、hstack、dstack待合并的数组必须具有相同的形状( shape)。
下面选择一些常用函数进行说明。
(1)append
合并一维数组

合并多维数组

输出结果:
按行合并后的结果
[[0 1]
[2 3]
[0 1]
[2 3]]
合并后数据维度 (4, 2)
按列合并后的结果
[[0 1 0 1]
[2 3 2 3]]
合并后数据维度 (2, 4)
(2)concatenate
沿指定轴连接数组或矩阵

输出结果:
[[1 2]
[3 4]
[5 6]]
[[1 2 5]
[3 4 6]]
(3)stack
沿指定轴堆叠数组或矩阵

输出结果:
[[[1 2]
[3 4]]

[[5 6]
[7 8]]]

1.5 批量处理

在深度学习中,由于源数据都比较大,所以通常需要采用批处理。如利用批量来计算梯度的随机梯度法(SGD),就是一个典型应用。深度学习的计算一般比较复杂,加上数据量一般比较大,如果一次处理整个数据,往往出现资源瓶颈。为了更有效的计算,一般将整个数据集分成小批量。与处理整个数据集的另一个极端是每次处理一条记录,这种方法也不科学,一次处理一条记录无法充分发挥GPU、NumPy平行处理优势。因此,实际使用中往往采用批量处理(mini-batch)。
如何把大数据拆分成多个批次呢?可采用如下步骤:
(1)得到数据集
(2)随机打乱数据
(3)定义批大小
(4)批处理数据集
以下我们通过一个示例来具体说明: