电子说
我们在 深度学习框架(4)-TensorFlow中执行计算,不同激活函数各有妙用 中学习了TensorFlow中执行张量的计算,并重点讨论一下不同的激活函数。
今天我们在TensorFlow中对Tensor进行“拆”和“装”。
说明
(1)张量创建、转化请参考 深度学习框架(3)-TensorFlow中张量创建和转化,妙用“稀疏性”提升效率 (2)张量计算请参考 深度学习框架(4)-TensorFlow中执行计算,不同激活函数各有妙用
1、矩阵运算的必要性
(1)Tensor是基础的数据结构
我们在 深度学习框架(1)-各显神通提升Tensor效率,让Tensor流动还靠深度学习框架 中讨论过深度学习依赖Tensor运算,我们再补充一点背景知识。
Tensor是深度学习中广泛使用的数据结构,TensorFlow虽然形象的把它加入到命名中,但它并不是TensorFlow特有的,在Pytroch、PaddlePaddle等众多深度学习框架中Tensor也是基本的数据结构。
Tensor本质上就是一个高维的矩阵,在深度学习领域中,以它作为基本数据结构是出于实际应用的需求。
深度学习当前最成熟的应用方向有计算机视觉(CV,Compute Vision)和自然语言处理(NLP,Natural Language Processing)两大领域。其中CV对象主要是图像和视频,NLP的对象以语音和文本为主;CV的基础模块是卷积神经网络(CNN,Convolutional Neural Network),NLP的基础模块是循环神经网络(RNN,Recurrent Neural Network)。这两个应用中标准的输入数据集都至少是三维以上,例如:
图像数据:包含三个维度,N×H×W,即样本数×图像高×图像宽;如果是彩色图像,那么还要增加一个通道C,变为N×C×H×W;如果是视频图像,那么可能还要再增加一个维度T,N×C×H×W×T。
文本数据:包含三个维度:N×L×H,即样本数×序列长度×特征数。
源于应用需要,深度学习模型的输入数据结构一般都要三维以上,而Tensor是好的选择,用于支撑深度学习模型和训练时更为便利。
(2)矩阵运算是基础
我们在 深度学习框架(4)-TensorFlow中执行计算,不同激活函数各有妙用 用TensorFlow中的不同函数执行了加法、乘法等各种运算。
加法:矩阵的加法只有同型矩阵之间才可以进行加法,所谓同型矩阵是两个矩阵的行数、列数必须相等。
转置:把矩阵的行和列互相交换所产生的矩阵称转置矩阵。
乘法:两个矩阵乘法的必要条件是,第一个矩阵A的列数和另一个矩阵B的行数相等时才能相乘。如矩阵A是m×n矩阵和B是n×p矩阵,它们的乘积C是一个m×p矩阵。
分解:矩阵分解是将一个矩阵分解为简单的或具有某种特性的若干矩阵的和或乘积 ,矩阵分解法有三角分解、谱分解、奇异值分解、满秩分解等。
我们可以把矩阵的各种操作想象为它在一定空间内,按照一定的规则进行的运动(或变换)。比如一个向量和一个矩阵相乘,我们可以想象为在线性空间中,向量刻画了对象,矩阵刻画了对象的运动,用矩阵与向量的乘法施加了运动。因此,“矩阵的本质是运动的描述”,而想要执行运动必须要要有约束,包括自身的形状,运动的规则等等。
(3)从英伟达的Tensor Core了解Tenosr索引、重构、切片的价值
我们在 深度学习框架(1)-各显神通提升Tensor效率,让Tensor流动还靠深度学习框架 中讨论过,为满足深度学习激增的计算量,英伟达在volta架构上推出了第一代TensorCore,以后每一代产品都对TensorCore不断升级优化。
TensorCore是专为深度学习而设计的,它在Tensor场景下算得更快,对于特定大小和精度的矩阵乘法实现了性能的突破,与前一代Pascal相比,Volta用于训练的峰值性能提升12倍,用于推理的峰值性能提升了6倍。
TensorCore改进的方向就是针对矩阵乘法(GEMM,General Matrix Mulitiplicaiton)运算进行优化。矩阵运算是神经网络训练和推理的核心,下图以4×4矩阵为例,每个TensorCore都在重复执行以下操作 D = A×B + C
Tensor Core在执行矩阵乘法和加法运算时整个装置可简化为下图,我们在前面几章中讨论的Tensor的convert,matual,add等操作这里均包含了,我们要注意的是,比如上图D =A×B+C是以4×4矩阵为基础的,那么在执行这个指令前,矩阵必须通过裁剪或者整型成为一个4×4矩阵,标准的input才能在这个装置结构中完成指令。
Tensor的索引、切片、重构、填充等操作非常常见,因为整个计算系统中从实际应用的输入数据转为了Tensor形式的数据结构,到转化为适合放置于内存中的数据模块,再到转化为计算装置执行计算指令的数据单元,这每个步骤中都涉及到了Tensor的“拆”和“装”的操作。对Tensor进行索引、重构、切片都是程序员的必备技能。
2、如何对一个Tensor进行“拆”和“装”?
(1)导入TensorFlow,创建tensor
import tensorflow as tf import numpy as np rank_1_tensor = tf.constant([0, 1, 1, 2, 3, 5, 8, 13, 21, 34]) rank_2_tensor = tf.constant([[1, 2], [3, 4], [5, 6]]) rank_3_tensor = tf.constant([ [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]], [[10, 11, 12, 13, 14], [15, 16, 17, 18, 19]], [[20, 21, 22, 23, 24], [25, 26, 27, 28, 29]],])
(2)索引(indexing)
通过索引我们可以在Tensor中提取数据,包括单轴索、多轴索引等。
单轴索引(single-axis indexing)
print("First:", rank_1_tensor[0].numpy()) print("From 4 to the end:", rank_1_tensor[4:].numpy()) print("From 2, before 7:", rank_1_tensor[2:7].numpy())
打印结果 >>>
First: 0 From 4 to the end: [ 3 5 8 13 21 34] From 2, before 7: [1 2 3 5 8]
多轴索引(muti-axis indexing)
print(rank_3_tensor[:, :, 4])
打印结果 >>>
tf.Tensor( [[ 4 9] [14 19] [24 29]], shape=(3, 2), dtype=int32)
(3)切片(Slice)
通过tf.slice()函数可以对不同维度的张量进行切片,通过tf.gather_nd()函数可以从多个轴中提取切片。
Tensor slice
print(tf.slice(rank_3_tensor, begin=[1,1,0],size=[1,1,2]))
打印结果 >>>
tf.Tensor([[[15 16]]], shape=(1, 1, 2), dtype=int32)
Tensor gather
print(tf.gather_nd(rank_3_tensor, indices=[[2],[0]]))
打印结果 >>>
tf.Tensor( [[[20 21 22 23 24] [25 26 27 28 29]] [[ 0 1 2 3 4] [ 5 6 7 8 9]]], shape=(2, 2, 5), dtype=int32)
(4)形状的整理变换(Reshaping)
通过tf.reshape()可改变张量形状,重构速度快,资源消耗低。
reshape matrix
var_x = tf.Variable(tf.constant([[1], [2], [3]])) print(var_x.shape.as_list) reshaped = tf.reshape(var_x, [1,3]) print(var_x.shape) print(reshaped.shape)
打印结果 >>>
(3, 1) (1, 3)
reshape tensor
print(tf.reshape(rank_3_tensor, [3*2, 5]), "n")
打印结果 >>>
tf.Tensor( [[ 0 1 2 3 4] [ 5 6 7 8 9] [10 11 12 13 14] [15 16 17 18 19] [20 21 22 23 24] [25 26 27 28 29]], shape=(6, 5), dtype=int32)
reshape tensor
print(tf.reshape(rank_3_tensor, [3, -1]))
打印结果 >>>
tf.Tensor( [[ 0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16 17 18 19] [20 21 22 23 24 25 26 27 28 29]], shape=(3, 10), dtype=int32)
(5)数据的插入(insert)
通过tf.tensor_scatter_nd()可实现在不同维度的张量中插入数据。
insert data into vector
t1 = tf.constant([10]) indices = tf.constant([[1], [3], [5], [7], [9]]) data = tf.constant([2, 4, 6, 8, 10]) print(tf.scatter_nd(indices=indices, updates=data, shape=t1))
打印结果 >>>
tf.Tensor([ 0 2 0 4 0 6 0 8 0 10], shape=(10,), dtype=int32)
insert data into tensor
t2 = tf.constant([[2, 7, 0], [9, 0, 1], [0, 3, 8]]) print(tf.tensor_scatter_nd_add(t2, indices=[[0,2],[1,1],[2,0]], updates=[6,5,4]))
打印结果 >>>
tf.Tensor( [[2 7 6] [9 5 1] [4 3 8]], shape=(3, 3), dtype=int32)
今天我们学习了如何在TensorFlow中对Tensor进行“拆”和“装”,掌握对Tensor进行索引、重构、切片等操作非常重要。到这里我们张量部分知识讨论了很多了,下一步我们学习如何使用TensorFlow中的变量
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !