张量对于深度学习领域是非常重要的,重要到Google的TensorFlow都是以它来命名的,接下来我们将学习有关张量的一些基本知识。
张量其实就是一个数据容量,它包含的数据几乎是数值数据,因此它也是数字的容器。神经网络示例中的数据都是储存在多维numpy数组(张量)中。一般来说,所有机器学习系统都是使用张量作为基本数据结构。
这些关键属性都会在python代码中出现,所以是非常重要的。
1.点积运算:relu(dot(w,x)+b)
x=(a,b,c,d)、y=(d,e)
dot(x,y)=(a,b,c,e)
''''
向量点积
t1:array([1,2,3,4])
t2:array([4,5,6,7])
dot:1*4+2*5+3*6+4*7=60
''''
import numpy as np
t1=np.array((1,2,3,4))
t2=np.array((4,5,6,7))
dot=np.dot(t1,t2)
''''
张量点积
t1:array([1,2],
[3,4])
t2:array([4,5],
[6,7])
dot:t1^T(t2)
t1^T:array([1,3],
[2,4])
dot:array([1*4+2*6,1*5+2*7],
[3*4+4*6,3*5+4*7])----->array([16,19],
[36,43])
''''
import numpy as np
t1=np.array(([1,2],[3,4]))
t2=np.array(([4,5],[6,7]))
dot=np.dot(t1,t2)
2.逐元素运算:relu运算和加法都是逐元素运算,即该运算可以应用于张量中的每个元素. z=x+y
# 逐元素运算
# relu 函数
def naive_relu(x):
assert len(x.shape) == 2
x = x.copy()
for i in range(x.shape[0]):
for j in range(x.shape[1]):
x[i, j] = max(x[i, j], 0)
return x
3.广播:对于两个形状不同的张量相加,较小的张量会被添加轴,使其与较大的相同。
import numpy as np
A = np.zeros((2,5,3,4))
B = np.zeros((3,4))
print((A+B).shape) # 输出 (2, 5, 3, 4)
A = np.zeros((4))
B = np.zeros((3,4))
print((A+B).shape) # 输出(3,4)
4.张量变形:张量变形是指改变张量的行和列,以得到想要的形状。变形后的张量的元素总个数与初始张量相同。
x= np.array([[0., 1.],
[2., 3.],
[4., 5.]])
>>> print(x.shape)
(3, 2)
>>> x = x.reshape((6, 1))
>>> x
array([[ 0.],
[ 1.],
[ 2.],
[ 3.],
[ 4.],
[ 5.]])
>>> x = x.reshape((2, 3))
>>> x
array([[ 0., 1., 2.],
[ 3., 4., 5.]])
在前面的例子中,我们使用语法 train_images[i] 来选择沿着第一个轴的特定数字。选择张量的特定元素叫作张量切片(tensor slicing)。我们来看一下 Numpy 数组上的张量切片运算
下面这个例子选择第 10~100 个数字(不包括第 100 个),并将其放在形状为 (90, 28, 28) 的数组中
# 在 NumPy 中操作张量
my_slice = train_images[10:100]
print(my_slice.shape)
# (90, 28, 28)
一般来说,你可以沿着每个张量轴在任意两个索引之间进行选择。例如,你可以在所有图像的右下角选出 14 像素×14 像素的区域
my_slice = train_images[:, 14:, 14:]
print(my_slice.shape)
# (60000, 14, 14)
通常来说,深度学习中所有数据张量的第一个轴(0 轴,因为索引从 0 开始)都是样本轴 (samples axis,有时也叫样本维度)。在 MNIST 的例子中,样本就是数字图像。
此外,深度学习模型不会同时处理整个数据集,而是将数据拆分成小批量。具体来看,下面是 MNIST 数据集的一个批量,批量大小为 128。
batch = train_images[:128],然后下一个批量为batch = train_images[128:256]
我们用几个你未来会遇到的示例来具体介绍数据张量。你需要处理的数据几乎总是以下类别之一。
向量数据: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)。
这是最常见的数据。对于这种数据集,每个数据点都被编码为一个向量,因此一个数据批量就被编码为 2D 张量(即向量组成的数组),其中第一个轴是样本轴,第二个轴是特征轴。
我们来看两个例子。
1.人口统计数据集,其中包括每个人的年龄、邮编和收入。每个人可以表示为包含 3 个值的向量,而整个数据集包含 100 000 个人,因此可以存储在形状为 (100000, 3) 的 2D 张量中。
2.文本文档数据集,我们将每个文档表示为每个单词在其中出现的次数(字典中包含 20 000 个常见单词)。每个文档可以被编码为包含 20 000 个值的向量(每个值对应于字典中每个单词的出现次数),整个数据集包含 500 个文档,因此可以存储在形状为 (500, 20000) 的张量中
当时间(或序列顺序)对于数据很重要时,应该将数据存储在带有时间轴的 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) 的张量中。
图像通常具有三个维度:高度、宽度和颜色深度。虽然灰度图像(比如MNIST 数字图像)只有一个颜色通道,因此可以保存在2D张量中,但按照惯例,图像张量始终都是3D张量,灰度图像的彩色通道只有一维。因此,如果图像大小为256×256,那么128张灰度图像组成的批量可以保存在一个形状为(128, 256, 256, 1)的张量中,而128张彩色图像组成的批量则可以保存在一个形状为(128,256,256,3)的张量中。
图像张量的形状有两种形式:通道在后(channels-last)的形式(在TensorFlow 中使用)和通道在前(channels-first)的形式(在Theano 中使用)。Google的TensorFlow 机器学习框架将颜色深度轴放在最后:(samples, height, width, color_depth)。与此相反,Theano将图像深度轴放在批量轴之后:(samples, color_depth, height, width)。如果采用Theano 约定,前面的两个例子将变(128, 1, 256, 256) 和(128, 3, 256, 256),Keras 框架同时支持这两种格式。
视频数据是现实生活中需要用到5D 张量的少数数据类型之一。视频可以看作一系列帧,每一帧都是一张彩色图像。由于每一帧都可以保存在一个形状为(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)的张量中。总共有106168320个值!如果张量的数据类型(dtype是float32,每个值都是32位,那么这个张量共有405MB。