飞道的博客

机器学习的数据结构——张量(详细介绍及Python中对张量的操作)

480人阅读  评论(0)

张量

一、张量的轴、阶和形状

张量是机器学习程序中的数字容器,本质上就是各种不同维度的数组,我们把张量的维度称为轴(axis),轴的个数称为阶(rank)(也就是俗称的维度,但是为了把张量的维度和每个阶的具体维度区分开,这里统一把张量的维度称为正脸那个的阶,Numpy中把它叫做数组的秩)

张量的形状(shape)就是张量的阶,加上每个阶的维度(每个阶的元素数目)

张量都可以通过Numpy来定义、操作。因此把Numpy数学函数库里面的数组用好,就可以搞定机器学习里面的数据结构。

二、标量——0D(阶)张量

仅包含一个数字的张量叫做标量(scalar),既0阶张量或0D张量。

标量的功能主要在于程序流程控制、设置参数值等。

下面创建一个NumPy标量:

import numpy as np #导入NumPy
X = np.array(5) # 创建0D张量,也就是标量
print("X的值",X)
print("X的阶",X.ndim) #ndim属性显示张量轴的个数
print("X的数据类型",X.dtype) # dtype属性显示张量数据类型
print("X的形状",X.shape) # shape属性显示张量形状


此处标量的形状为(),既标量的阶为0.

Numpy中,不管是阶的索引,还是数组的索引,永远是从0开始的。

三、向量——1D(阶)张量

由一组数字组成的数组叫做向量(vector),也就是一阶张量,或称1D张量。一阶张量只有一个轴。

下面创建一个NumPy向量:

X = np.array([5,6,7,8,9]) #创建1D张量,也就是向量
print("X的值",X)
print("X的阶",X.ndim) #ndim属性显示张量轴的个数
print("X的形状",X.shape) # shape属性显示张量形状


创建向量的时候要把数字元素放进方括号里面,形成一个包含5个元素的1D张量。需要再次强调的是,机器学习中把5个元素的向量称为5维向量。千万不要把5维向量和5阶向量混淆。

创建一个一维向量:

X = np.array([5]) # 1维的向量,就是1D数组里面只有一个元素

1.机器学习中的向量数据

向量非常的重要。在机器学习中,普通的连续数值数据集中的每一个独立样本都是一个向量,因此普通的连续数值数据集也可以叫做向量数据集。而数据集中的标签列也可以视为一个向量。

向量数据集是说数据集中的每一行或每一列,都可以视为向量,但是数据集整体是一个矩阵。

载入波士顿房价数据集查看:

from keras.datasets import boston_housing # 波士顿房价数据集
(X_train, y_train), (X_test, y_test) = boston_housing.load_data()
print("X_train的形状:", X_train.shape)
print("X_train中第一个样本的形状:", X_train[0].shape)
print("y_train的形状:", y_train.shape)


这个是Keras内置的波士顿房价数据集,是一个2D的普通数值数据集。

X_train是一个2D矩阵,是404个样本数据的集合。
X_train[0]代表的是X_train训练集的第一行数据,是一个13维向量(也是1D张量)。也就是说,训练集的每行数据都包含13个特征。

2.向量的点积

两个向量之间可以进行乘法运算,而且不止一种,有点积和叉积,其运算法则不同。

点积运算法则:就是两个相同维度的向量对应元素先相乘,后相加。
用代码展示:

python
weight = np.array([1,-1.8,1,1,2]) # 权重向量(也就是多项式的参数)
X = np.array([1,6,7,8,9]) # 特征向量(也就是一个特定样本中的特征值)
y_hat = np.dot(X,weight) # 通过点积运算构建预测函数
print('函数返回结果:', y_hat) # 输出预测结果

下面语句也可以实现相同的功能:

y_hat = weight.dot(X) # X.dot(weight)也可以实现同样结果

注意向量点积的结果是一个值,也就是一个标量,而不是一个向量。

四、矩阵——2D(阶)张量

矩阵是一组一组向量的集合。矩阵中的个元素横着、竖着、斜着都能构成不同的向量。而矩阵,也就是二阶张量,或称2D张量,其形状维(m,n)
矩阵里面横向的元素称为“行”,纵向的元素称为“列”。

1.机器学习中的矩阵数据

矩阵式2D张量,形状维(样本,特征)。第一个轴式样本轴,第二个式特征轴。

print("X_train的内容:", X_train) #X_train是2D张量,即矩阵


每一行实际包括13个特征,输出时通过省略号忽略了中间8个特征列的输出。整个张量(404行)。

2.矩阵的点积

矩阵之间也可以进行点积,是把第一个矩阵的行向量,和第二个矩阵的列向量进行点积,然后把结果标量放进新矩阵,作为结果矩阵中的一个元。
当相乘时,第一个矩阵的列数必须等于第二个矩阵的行数,既(m,n)的矩阵成语形状维(n,m)的矩阵,得到一个矩阵(m,m)。如果形状不符合规格,则不能进行点积运算。

五、序列数据——3D(阶)张量

在矩阵数据的基础上再增加一个阶,就形成了3D张量。
NumPy的3D张量数据结构是这样定义的:

# 创建3D张量
X = np.array([[[1, 22, 4, 78, 2],
               [2, 59, 6, 56, 1],
               [3, 31, 8, 54, 0]],
              [[4, 56, 9, 34, 1],
               [5, 78, 8, 35, 2],
               [6, 34, 7, 36, 0]],
              [[7, 45,5, 34, 5],
               [8, 53, 6, 35, 4],
               [9, 81, 4, 36, 5]]])

在实际应用中,序列数据集才是机器学习中的3D张量。而时间序列是最为常见的序列数据集。
对于时间序列数据来说,就是时间戳,也叫时间步。
因为增加了时戳,所以表里面的行列结构显得更为复杂。

第一个轴:样本轴,如:一年记录下来的数据共365个,也就是365维
第二个轴:时间步轴,如:每天一共是24小时,每小时4个15分钟,共96维
第三个轴:特征轴,如:一共是温度、湿度、风力3个维度
也就是说,时序数据集的形状为3D张量:(样本、时戳、标签)。

文字序列数据的形状维3D张量:(样本、序号、字编码)

六、图像数据——4D(阶)张量

图像数据本身包括高度、宽度,再加上一个颜色深度通道。MNIST数据集中是灰度图像只有一个颜色深度通道;而GRB格式的彩色图像,颜色深度通道的维度为3.

因此,对于图像数据集来说,长、宽、深再加上数据集大小这个维度 ,就形成了4D张量,其形状为(样本、图像高度、图像宽度、颜色深度),如MNIST特征数据集的形状(60000,28,28,1)。

在机器学习中,不是对上千万个数据样本同时进行处理,那样的话机器也受不了,而是一批一批地并行处理。

七、视频数据——5D(阶)张量

机器学习的初学者很少有机会见到比4D更高阶的张量,如果有,视频数据的结构是其中的一种。

视频可以看作是由一帧一帧的彩色图像组成的数据集。
每一帧都保存在一个形状为(高度、宽度、颜色深度)的3D张量中。
一系列帧则保存在一个形状为(帧、高度、宽度、颜色深度)的4D张量中。
因此,视频数据集需要5D张量才放得下,其形状为(样本、帧、高度、宽度、颜色深度)。

可以想象,视频数据的数据量是非常大的。面对这种规模的数据,普通的机器学习模型会感到手足无措,只有深度学习模型才能够搞定。

八、数据的维度和空间的维度

1.数据的维度

维度是指在一个数据轴上的许多点,也就是样本的个数或者特征的个数。一万个不同的特征,就是一万维;而一万个数据样本,也同样可以称为一万维。

为了标准化叙述,我们把张量的每一个数据轴,统称为阶。因此,我们说一阶(1D)向量,二阶向量,三阶向量,而不是说维。

2.空间的维度

当维度很大的时候我们无法想象是什么样子的,但是我们可以采用应用降维算法处理数据,把数据降维到二维以内。
多维特征的函数图象是存在的,多元凸函数也一定可以梯度下降到全局最低点。

九、Python中的张量运算

通过代码和结果来展现Python中运算:

1.张量创建

import numpy as np # 导入NumPy数学工具集
list=[1,2,3,4,5] # 创建列表
array_01=np.array([1,2,3,4,5]) # 列表转化成数组
array_02=np.array((6,7,8,9,10)) # 元组转化成数组
array_03=np.array([[1,2,3],[4,5,6]]) # 列表转化成2D数组
print ('列表:', list)
print ('列表转化为数组:', array_01)
print ('元组转化为数组:', array_02)
print ('2D数组:', array_03)
print ('数组的形状:', array_01.shape)
# print ('列表的形状:', list.shape) # 列表没有形状,程序会报错

array_04=np.arange(1,5,1) # 通过arange函数生成数组
array_05=np.linspace(1,5,5) # 通过linspace函数生成数组
print (array_04)
print (array_05)

2.通过索引和切片访问张量中的数据

array_06 = np.arange(10)
print (array_06)
index_01 = array_06[3] # 索引-第4个元素
print ('第4个元素', index_01)
index_02 = array_06[-1] # 索引-最后一个元素
print ('第-1个元素', index_02)
slice_01 = array_06[:4] # 从0到4切片
print ('从0到4切片', slice_01)
slice_02 = array_06[0:12:4] # 从0到12切片,步长为2
print ('从0到12切片,步长为4', slice_02)

from keras.datasets import mnist #需要打开internet选项)
(X_train, y_train), (X_test, y_test) = mnist.load_data()
print (X_train.shape)
X_train_slice = X_train[10000:15000,:,:]

array_07 = np.array([[1,2,3],[4,5,6]])
print (array_07[1:2],'它的形状是', array_07[1:2].shape) 
print (array_07[1:2][0], '它的形状又不同了', array_07[1:2][0].shape)

3.张量的整体操作和逐元素运算

array_07 += 1 # 数组内全部元素加1
print (array_07)

for i in range(array_07.shape[0]):
    for j in range(array_07.shape[1]):
        array_07[i,j] += 1
print (np.sqrt(array_07)) #打印每一个元素的平方根

4.张量的变形和转置

print (array_07,'形状是', array_07.shape) 
print (array_07.reshape(3,2), '形状是', array_07.reshape(3,2).shape)

array_07 = array_07.reshape(3,2) #进行赋值才能改变数组本身
array_07 = array_07.T # 矩阵的转置
array_06 = np.arange(10)
print (array_06,'形状是', array_06.shape,'阶为', array_06.ndim) 
array_06 = array_06.reshape(10,1)
print (array_06,'形状是', array_06.shape,'阶为', array_06.ndim)

5.Python中的广播

array_08 = np.array([[0,0,0], [10,10,10], [20,20,20], [30,30,30]])
array_09 = np.array([[0,1,2]])
array_10 = np.array([[0],[1],[2],[3]])
list_11 = [[0,1,2]]
print ('array_09的形状:', array_09.shape )
print ('array_10的形状:', array_10.shape )
array_12 = array_09.reshape(3)
print ('array_12的形状:', array_12.shape )
array_13 = np.array([1])
print ('array_13的形状:', array_13.shape )
array_14 = array_13.reshape(1,1)
print ('array_14的形状:', array_14.shape )
print ('08 + 09结果:',array_08 + array_09)
print ('08 + 10结果:',array_08 + array_10)
print ('08 + 11结果:',array_08 + list_11)
print ('08 + 12结果:',array_08 + array_12)
print ('08 + 13结果:',array_08 + array_13)
print ('08 + 14结果:',array_08 + array_14)

6.向量和矩阵的点积运算

向量:

vector_01 = np.array([1,2,3])
vector_02 = np.array([[1],[2],[3]])
vector_03 = np.array([2])
vector_04 = vector_02.reshape(1,3)
print ('vector_01的形状:', vector_01.shape)
print ('vector_02的形状:', vector_02.shape)
print ('vector_03的形状:', vector_03.shape)
print ('vector_04的形状:', vector_04.shape)
print ('01和01的点积:', np.dot(vector_01,vector_01))
print ('01和02的点积:', np.dot(vector_01,vector_02))
print ('04和02的点积:', np.dot(vector_04,vector_02))
print ('01和数字的点积:', np.dot(vector_01,2))
print ('02和03的点积:', np.dot(vector_02,vector_03))
print ('02和04的点积:', np.dot(vector_02,vector_04))
# print ('01和03的点积:', np.dot(vector_01,vector_03)) # 程序会报错
# print ('02和02的点积:', np.dot(vector_02,vector_02))


矩阵:

matrix_01 = np.arange(0,6).reshape(2,3)
matrix_02 = np.arange(0,6).reshape(3,2)
print(matrix_01)
print(matrix_02)
print ('01和02的点积:', np.dot(matrix_01,matrix_02))
print ('02和01的点积:', np.dot(matrix_02,matrix_01))
print ('01和01的点积:', np.dot(matrix_01,matrix_01))

总结:

  1. 机器学习中的数据结构称为张量,下面是几种重要的张量格式,用于处理不同类型的数据集。
    ·普通向量数据集结构:2D张量,形状为(样本,标签)
    ·时间序列数据集或序列数据集:3D张量,形状为(样本,时戳,特征)
    ·图像数据集:4D 张量,形状为(样本、图像高度、图像宽度、颜色深度)
  2. Python语句操作方面,NumPy数组的操作都是重点内容。
    ·张量的切片操作
    ·用reshape进行张量变形
    ·Python的广播功能
    ·向量和矩阵的点积操作之异同,向量的点积得到的是一个数
    ·要记得不定时检查张量的维度

转载:https://blog.csdn.net/sjjsaaaa/article/details/115915942
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场