/* */

神经网络的数据表示

前面例子使用的数据存储在多维 Numpy 数组中,也叫张量(tensor)。 张量这一概念的核心在于,它是一个数据容器。它包含的数据几乎总是数值数据,因此它是数字的容器。你可能对矩阵很熟悉,它是二维张量。张量是矩阵向任意维度的推广, 张量的维度(dimension)通常叫作轴(axis)。

1、标量(0D 张量)

仅包含一个数字的张量叫作标量(scalar,也叫标量张量、零维张量、0D 张量)。在 Numpy 中,一个 float32 或 float64 的数字就是一个标量张量(或标量数组)。你可以用 ndim 属性来查看一个 Numpy 张量的轴的个数。标量张量有 0 个轴(ndim == 0)。张量轴的个数也叫作(rank)。

import numpy as np 
x = np.array(12) 
x
#输出array(12) 
x.ndim 
#输出0
一个 Numpy 标量

2、向量(1D 张量)

数字组成的数组叫作向量(vector)或一维张量(1D 张量)。一维张量只有一个轴。维度 (dimensionality)可以表示沿着某个轴上的元素个数(比如 5D 向量),也可以表示张量中轴的个 数(比如 5D 张量)。

x = np.array([12, 3, 6, 14, 7]) 
x 
#输出array([12, 3, 6, 14, 7])
x.ndim 
#输出1
#这个向量5个元素,所以被称为5D向量。
#不要把5D向量和5D张量弄混。5D 向量只有一个轴,沿着轴有5个维度,而5D张量有5个轴(沿着每个轴可能有任意个维度)。
一个 Numpy 向量

3、矩阵(2D 张量)

向量组成的数组叫作矩阵(matrix)或二维张量(2D 张量)。矩阵有 2 个轴(通常叫作行和 列)。你可以将矩阵直观地理解为数字组成的矩形网格。

x = np.array([[5, 78, 2, 34, 0], 
                     [6, 79, 3, 35, 1], 
                     [7, 80, 4, 36, 2]]) 
x.ndim 
#输出2 
#第一个轴上的元素叫作行(row),第二个轴上的元素叫作列(column)。在上面的例子中, [5, 78, 2, 34, 0] 是 x 的第一行,[5, 6, 7] 是第一列。                   
一个Numpy矩阵

4、3D张量与更高维张量

将多个矩阵组合成一个新的数组,可以得到一个 3D 张量,你可以将其直观地理解为数字组成的立方体。

x = np.array([[[5, 78, 2, 34, 0],
                      [6, 79, 3, 35, 1],
                      [7, 80, 4, 36, 2]],
                     [[5, 78, 2, 34, 0],
                      [6, 79, 3, 35, 1], 
                      [7, 80, 4, 36, 2]],
                     [[5, 78, 2, 34, 0],
                      [6, 79, 3, 35, 1], 
                     [7, 80, 4, 36, 2]]]) 
x.ndim
#输出3
一个Numpy的3D张量

将多个3D张量组合成一个数组,可以创建一个 4D 张量,以此类推。深度学习处理的一般是 0D 到 4D 的张量,但处理视频数据时可能会遇到 5D 张量。

5、关键属性

张量是由以下三个关键属性来定义的。

轴的个数(阶)——例如,3D 张量有 3 个轴,矩阵有 2 个轴。这在 Numpy 等 Python 库中也叫张量的 ndim。

形状——这是一个整数元组,表示张量沿每个轴的维度大小(元素个数)。例如,前面矩阵示例的形状为 (3, 5),3D 张量示例的形状为 (3, 3, 5)。向量的形状只包含一个元素,比如 (5,),而标量的形状为空,即 ()。

数据类型(在 Python 库中通常叫作 dtype——这是张量中所包含数据的类型,例如,张量的类型可以是 float32、uint8、float64 等。在极少数情况下,你可能会遇到字符 (char)张量。注意,Numpy(以及大多数其他库)中不存在字符串张量,因为张量存储在预先分配的连续内存段中,而字符串的长度是可变的,无法用这种方式存储。

#首先加载 MNIST 数据集。
from keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
#给出张量 train_images 的轴的个数,即 ndim 属性。
print(train_images.ndim) 3 
#形状。
print(train_images.shape) (60000, 28, 28) 
#数据类型,即 dtype 属性。
 print(train_images.dtype) uint8

#这里 train_images 是一个由8位整数组成的3D张量。更确切地说,它是 60 000个矩阵组成的数组,每个矩阵由 28×28 个整数组成。每个这样的矩阵都是一张灰度图像,元素取值范围为 0~255。
#我们用 Matplotlib 库(Python 标准科学套件的一部分)来显示这个 3D 张量中的第 4 个数字
digit = train_images[4]
import matplotlib.pyplot as plt
plt.imshow(digit, cmap=plt.cm.binary)
plt.show()
MNIST例子中处理的数据

6、在 Numpy 中操作张量

在前面的例子中,使用语法 train_images[i] 来选择沿着第一个轴的特定数字。选择张量的特定元素叫作张量切片(tensor slicing)。

#下面这个例子选择第10~100个数字(不包括第 100 个),并将其放在形状为 (90, 28, 28) 的数组中。
my_slice = train_images[10:100] 
print(my_slice.shape
#(90, 28, 28) 

#它等同于下面这个更复杂的写法,给出了切片沿着每个张量轴的起始索引和结束索引。 注意,: 等同于选择整个轴。 
my_slice = train_images[10:100, :, :] 
my_slice.shape 
#(90, 28, 28) 

#等同于前面的例子
my_slice = train_images[10:100, 0:28, 0:28] 
my_slice.shape 
#(90, 28, 28) 
Numpy数组上的张量切片运算

一般来说,可以沿着每个张量轴在任意两个索引之间进行选择。例如,你可以在所有图像的右下角选出14 像素×14 像素的区域:

my_slice = train_images[:, 14:, 14:]

也可以使用负数索引。与 Python 列表中的负数索引类似,它表示与当前轴终点的相对位置。 你可以在图像中心裁剪出 14 像素×14 像素的区域:

my_slice = train_images[:, 7:-7, 7:-7]

7、数据批量的概念

深度学习中所有数据张量的第一个轴(0 轴,因为索引从 0 开始)都是样本轴 (samples axis,有时也叫样本维度)。在 MNIST 的例子中,样本就是数字图像。 此外,深度学习模型不会同时处理整个数据集,而是将数据拆分成小批量。

#批量大小为 128。
batch = train_images[:128] 
#然后是下一个批量。 
batch = train_images[128:256]
#然后是第 n 个批量。 
batch = train_images[128 * n:128 * (n + 1)] 
#对于这种批量张量,第一个轴(0 轴)叫作批量轴(batch axis)或批量维度(batch dimension)。 
MNIST 数据集的一个批量

8、现实世界中的数据张量

你需要处理的数据总是以下类别之一。

向量数据:2D 张量,形状为 (samples, features)。

时间序列数据或序列数据:3D 张量,形状为 (samples, timesteps, features)。

图像:4D 张量,形状为 (samples, height, width, channels) 或 (samples, channels, height, width)。

视频:5D 张量,形状为 (samples, frames, height, width, channels) 或 (samples, frames, channels, height, width)。

9、向量数据

这是最常见的数据。对于这种数据集,每个数据点都被编码为一个向量,因此一个数据批量就被编码为 2D 张量(即向量组成的数组),其中第一个轴是样本轴,第二个轴是特征轴。 

#人口统计数据集,
其中包括每个人的年龄、邮编和收入。
每个人可以表示为包含3个值的向量,而整个数据集包含100000个人,因此可以存储在形状为 (100000, 3) 的 2D 张量中。 
#文本文档数据集,
将每个文档表示为每个单词在其中出现的次数(字典中包含20000个单词)。
每个文档被编码为包含20000个值的向量(每个值对应于字典中每个单词的出现次数)
整个数据集包含500个文档,因此可以存储在形状为 (500, 20000) 的张量中
示例

10、时间序列数据或序列数据

当时间(或序列顺序)对于数据很重要时,应该将数据存储在带有时间轴的 3D 张量中。 每个样本可以被编码为一个向量序列(即 2D 张量),因此一个数据批量就被编码为一个 3D 张 量。根据惯例,时间轴始终是第 2 个轴(索引为 1 的轴)。

#股票价格数据集
每一分钟,我们将股票的当前价格、前一分钟的最高价格和前一分钟的最低价格保存下来,因此每分钟被编码为一个3D向量。
整个交易日被编码为一个形状为 (390, 3) 的2D张量(一个交易日有 390 分钟),而250天的数据则可以保存在一个形状为 (250, 390, 3) 的3D张量中。
这里每个样本是一天的股票数据。 
#推文数据集。
我们将每条推文编码为280个字符组成的序列,而每个字符又来自于128个字符组成的字母表。
每个字符可以被编码为大小为128的二进制向量(只有在该字符对应的索引位置取值为 1,其他元素都为 0。
那么每条推文可以被编码为一个形状为 (280, 128) 的 2D 张量,而包含100万条推文的数据集则可以存储在一个形状为 (1000000, 280, 128) 的张量中。
例子

11、图像数据

图像通常具有三个维度:高度、宽度和颜色深度。虽然灰度图像(比如 MNIST 数字图像) 只有一个颜色通道,因此可以保存在 2D 张量中,但按照惯例,图像张量始终都是 3D 张量,灰度图像的彩色通道只有一维。因此,如果图像大小为 256×256,那么128张灰度图像组成的批量可以保存在一个形状为 (128, 256, 256, 1) 的张量中,而128张彩色图像组成的批量则可以保存在一个形状为 (128, 256, 256, 3) 的张量中。

#通道在后(channels-last)的约定(在 TensorFlow 中使用)
ensorFlow 机器学习框架将颜色深度轴放在最后:(samples, height, width, color_depth)。,
#通道在前(channels-first)的约定(在 Theano 中使用)
Theano 将图像深度轴放在批量轴之后:(samples, color_depth, height, width)。

如果采用Theano 约定,前面的两个例子将变成 (128, 1, 256, 256) 和 (128, 3, 256, 256)。 Keras 框架同时支持这两种格式。
图像张量的形状的两种约定

12、视频数据

视频可以看作一系列帧, 每一帧都是一张彩色图像。由于每一帧都可以保存在一个形状为 (height, width, color_ depth) 的 3D 张量中,因此一系列帧可以保存在一个形状为 (frames, height, width, color_depth) 的 4D 张量中,而不同视频组成的批量则可以保存在一个 5D 张量中,其形状为 (samples, frames, height, width, color_depth)。 

一个以每秒4帧采样的60秒YouTube视频片段。视频尺寸为144×256,这个 视频共有240帧。
4个这样的视频片段组成的批量将保存在形状为 (4, 240, 144, 256, 3) 的张量中。总共有 106 168 320 个值!
如果张量的数据类型(dtype)是 float32,每个值都是 32 位,那么这个张量共有 405MB。
现实生活中遇到的视频要小得多,因为它们不以 float32 格式存储,而且通常被大大压缩,比如 MPEG 格式。
示例

 

 

以上内容来自《python深度学习》,仅作学习笔记记录~

posted @ 2020-12-14 15:48  柚柚汁呀  阅读(315)  评论(0编辑  收藏  举报
/*
*/