在深度学习框架中,数据经常用张量(Tensor)的形式来存储。张量是矩阵的扩展与延伸,可以认为是高阶的矩阵。1阶张量为向量,2阶张量为矩阵。如果你对Numpy熟悉,那么张量是类似于Numpy的多维数组(ndarray)的概念,可以具有任意多的维度。
张量的大小可以用形状(shape)来描述。比如一个三维张量的形状是 [2,2,5][2,2,5],表示每一维(也称为轴(axis))的元素的数量,即第0轴上元素数量是2,第1轴上元素数量是2,第2轴上的元素数量为5。
图1.5给出了3种纬度的张量可视化表示。
张量中元素的类型可以是布尔型数据、整数、浮点数或者复数,但同一张量中所有元素的数据类型均相同。因此我们可以给张量定义一个数据类型(dtype)来表示其元素的类型
1.2.1.1 指定数据创建张量
1)通过指定的Python列表数据[2.0, 3.0, 4.0],创建一个一维张量。
# 导入torch
import torch
# 创建一维Tensor
from numpy import shape
data = torch.Tensor([2.0,3.0,4.0])
print(data)
print(shape(data))
print(data.dtype)
(2)通过指定的Python列表数据来创建类似矩阵(matrix)的二维张量。
# 导入torch
import torch
# 创建一维Tensor
from numpy import shape
data = torch.Tensor([[1.0,2.0,3.0],[4.0,5.0,6.0]])
print(data)
print(shape(data))
print(data.dtype)
(3)同样地,还可以创建维度为3、4...N等更复杂的多维张量。
# 导入torch
import torch
# 创建一维Tensor
from numpy import shape
data = torch.Tensor([[[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]],
[[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]]])
print(data)
print(shape(data))
print(data.dtype)
1.2.1.2 指定形状创建
# 导入torch
import torch
m,n=2,3
zeros_tensor=torch.zeros([m,n])
ones_tensor=torch.ones([m,n])
full_tensor=torch.full([m,n],10)
print('zeros tensor',zeros_tensor)
print('ones tensor',ones_tensor)
print('full tensor',full_tensor)
1.2.1.3 指定区间创建
# 导入torch
import torch
m,n=2,3
arange_tensor=torch.arange(start=1,end=5,step=1)
linspace_tensor=torch.linspace(1,5,5)
print('arange tensor',arange_tensor,arange_tensor.shape,arange_tensor.dtype)
print('linspace tensor',linspace_tensor,linspace_tensor.shape,linspace_tensor.dtype)
1.2.2 张量的属性
1.2.2.1 张量的形状
张量具有如下形状属性:
Tensor.ndim
:张量的维度,例如向量的维度为1,矩阵的维度为2。Tensor.shape
: 张量每个维度上元素的数量。Tensor.shape[n]
:张量第n维的大小。第n维也称为轴(axis)。Tensor.size
:张量中全部元素的个数。
为了更好地理解ndim、shape、axis、size四种属性间的区别,创建一个四维张量。
# 导入torch
import torch
ndim_4_Tensor = torch.ones([2, 3, 4, 5])
print("Number of dimensions:", ndim_4_Tensor.ndim)
print("Shape of Tensor:", ndim_4_Tensor.shape)
print("Elements number along axis 0 of Tensor:", ndim_4_Tensor.shape[0])
print("Elements number along the last axis of Tensor:", ndim_4_Tensor.shape[-1])
print('Number of elements in Tensor: ', ndim_4_Tensor.size)
1.2.2.2 形状的改变
# 导入torch
import torch
# 定义一个shape为[3,2,5]的三维Tensor
ndim_3_Tensor =torch.tensor([[[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, 30]]])
print("the shape of ndim_3_Tensor:", ndim_3_Tensor.shape)
# torch.reshape 可以保持在输入数据不变的情况下,改变数据形状。这里我们设置reshape为[2,5,3]
reshape_Tensor = torch.reshape(ndim_3_Tensor, [2, 5, 3])
print("After reshape:", reshape_Tensor)
torch.reshape 可以保持在输入数据不变的情况下,改变数据形状。
new_Tensor2 = ndim_3_Tensor.reshape([-1, 5, 2])中-1的值:总元素的个数/其他维度的个数
分别对上文定义的ndim_3_Tensor进行reshape为[-1]和reshape为[0, 5, 2]两种操作,观察新张量的形状。
new_Tensor1 = ndim_3_Tensor.reshape([-1])
print('new Tensor 1 shape: ', new_Tensor1.shape)
new_Tensor2 = ndim_3_Tensor.reshape([-1, 5, 2])
print('new Tensor 2 shape: ', new_Tensor2.shape)
1.2.2.3 张量的数据类型
1)通过Python元素创建的张量,可以通过dtype来指定数据类型,如果未指定:
- 对于Python整型数据,则会创建int64型张量。
- 对于Python浮点型数据,默认会创建float32型张量。
- 可以使用torch.dtype查看数据类型
import torch
# 使用paddle.to_tensor通过已知数据来创建一个Tensor
# 定义一个shape为[3,2,5]的三维Tensor
ndim_3_Tensor =torch.tensor([[[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, 30]]])
print("Tensor dtype from Python integers:",ndim_3_Tensor.dtype)
print("Tensor dtype from Python floating point:",ndim_3_Tensor.dtype)
1.2.2.4 张量的设备位置
可以用device函数查看位置
import torch
data = torch.ones([2, 3])
print(data.device)
1.2.3 张量与Numpy数组转换
import torch
ndim_1_Tensor = torch.tensor([1, 2])
# 将当前 Tensor 转化为 numpy.ndarray
print('Tensor to convert: ', ndim_1_Tensor.numpy())
1.2.4 张量的访问
1.2.4.1 索引和切片
- 基于0−n的下标进行索引,如果下标为负数,则从尾部开始计算。
- 通过冒号“:”分隔切片参数start:stop:step来进行切片操作,也就是访问start到stop范围内的部分元素并生成一个新的序列。其中start为切片的起始位置,stop为切片的截止位置,step是切片的步长,这三个参数均可缺省。
1.2.4.2 访问张量
针对一维张量,对单个轴进行索引和切片。
import torch
# 定义1个一维Tensor
ndim_1_Tensor = torch.tensor([0, 1, 2, 3, 4, 5, 6, 7, 8])
print("Origin Tensor:", ndim_1_Tensor)
print("First element:", ndim_1_Tensor[0])
print("Last element:", ndim_1_Tensor[-1])
print("All element:", ndim_1_Tensor[:])
print("Before 3:", ndim_1_Tensor[:3])
print("Interval of 3:", ndim_1_Tensor[::3])
print("Reverse:", ndim_1_Tensor.flip(-1))
针对二维及以上维度的张量,在多个维度上进行索引或切片
import torch
# 定义1个二维Tensor
ndim_2_Tensor = torch.tensor([[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11]])
print("Origin Tensor:", ndim_2_Tensor)
print("First row:", ndim_2_Tensor[0])
print("First row:", ndim_2_Tensor[0, :])
print("First column:", ndim_2_Tensor[:, 0])
print("Last column:", ndim_2_Tensor[:, -1])
print("All element:", ndim_2_Tensor[:])
print("First row and second column:", ndim_2_Tensor[0, 1])
1.2.4.3 修改张量
与访问张量类似,可以在单个或多个轴上通过索引或切片操作来修改张量。
import torch
# 定义1个二维Tensor
ndim_2_Tensor = torch.ones([2, 3])
print('Origin Tensor: ', ndim_2_Tensor)
# 修改第1维为0
ndim_2_Tensor[0] = 0
print('change Tensor: ', ndim_2_Tensor)
# 修改第1维为2.1
ndim_2_Tensor[0:1] = 2.1
print('change Tensor: ', ndim_2_Tensor)
# 修改全部Tensor
ndim_2_Tensor[...] = 3
print('change Tensor: ', ndim_2_Tensor)
1.2.5 张量的运算
以加法为例子
1、torch.add(x,y)
2、a.add(y)
import torch
# 定义两个Tensor
x = torch.tensor([[1.1, 2.2], [3.3, 4.4]])
y = torch.tensor([[5.5, 6.6], [7.7, 8.8]])
# 第一种调用方法,torch.add逐元素相加算子,并将各个位置的输出元素保存到返回结果中
print('Method 1: ', torch.add(x, y))
# 第二种调用方法
print('Method 2: ', x.add(y))
张量类的基础数学函数如下:
x.abs() # 逐元素取绝对值
x.ceil() # 逐元素向上取整
x.floor() # 逐元素向下取整
x.round() # 逐元素四舍五入
x.exp() # 逐元素计算自然常数为底的指数
x.log() # 逐元素计算x的自然对数
x.reciprocal() # 逐元素求倒数
x.square() # 逐元素计算平方
x.sqrt() # 逐元素计算平方根
x.sin() # 逐元素计算正弦
x.cos() # 逐元素计算余弦
x.add(y) # 逐元素加
x.subtract(y) # 逐元素减
x.multiply(y) # 逐元素乘(积)
x.divide(y) # 逐元素除
x.mod(y) # 逐元素除并取余
x.pow(y) # 逐元素幂
x.max() # 指定维度上元素最大值,默认为全部维度
x.min() # 指定维度上元素最小值,默认为全部维度
x.prod() # 指定维度上元素累乘,默认为全部维度
x.sum() # 指定维度上元素的和,默认为全部维度
同时,为了更方便地使用张量,飞桨对Python数学运算相关的魔法函数进行了重写,以下操作与上述结果相同。
x + y -> x.add(y) # 逐元素加
x - y -> x.subtract(y) # 逐元素减
x * y -> x.multiply(y) # 逐元素乘(积)
x / y -> x.divide(y) # 逐元素除
x % y -> x.mod(y) # 逐元素除并取余
x ** y -> x.pow(y) # 逐元素幂
import torch
# 定义两个Tensor
x = torch.tensor([[1.1, 2.2], [3.3, 4.4]])
y = torch.tensor([[5.5, 6.6], [7.7, 8.8]])
print("加法运算结果:", x + y)
print("减法运算结果:", x - y)
print("乘法运算结果:", x * y)
print("除法运算结果:", x / y)
print("幂运算结果:", x ** y)
1.2.5.2 逻辑运算
import torch
# 定义两个Tensor
x = torch.tensor([[1.1, 2.2], [3.3, 4.4]])
y = torch.tensor([[5.5, 6.6], [7.7, 8.8]])
print("判断两个张量对应位置元素是否相同:", x == y)
1.2.5.3 矩阵运算
import torch
# 定义两个Tensor
x = torch.tensor([[1.1, 2.2], [3.3, 4.4]])
y = torch.tensor([[5.5, 6.6], [7.7, 8.8]])
print("按行连结结果", torch.cat((x, y), dim=0))
print("按列连结结果:", torch.cat((x, y), dim=1))
1.2.5.4 广播机制
。通常来讲,如果有一个形状较小和一个形状较大的张量,会希望多次使用较小的张量来对较大的张量执行某些操作,看起来像是形状较小的张量首先被扩展到和较大的张量形状一致,然后再做运算。
广播机制的条件
飞桨的广播机制主要遵循如下规则(参考Numpy广播机制):
1)每个张量至少为一维张量。
2)从后往前比较张量的形状,当前维度的大小要么相等,要么其中一个等于1,要么其中一个不存在。
import torch
# 当两个Tensor的形状一致时,可以广播
x = torch.ones((2, 3, 4))
y = torch.ones((2, 3, 4))
z = x + y
print('broadcasting with two same shape tensor: ', z.shape)
x = torch.ones((2, 3, 1, 5))
y = torch.ones((3, 4, 1))
# 从后往前依次比较:
# 第一次:y的维度大小是1
# 第二次:x的维度大小是1
# 第三次:x和y的维度大小相等,都为3
# 第四次:y的维度不存在
# 所以x和y是可以广播的
z = x + y
print('broadcasting with two different shape tensor:', z.shape)
广播机制的计算规则
现在我们知道在什么情况下两个张量是可以广播的。两个张量进行广播后的结果张量的形状计算规则如下:
1)如果两个张量shape的长度不一致,那么需要在较小长度的shape前添加1,直到两个张量的形状长度相等。
2) 保证两个张量形状相等之后,每个维度上的结果维度就是当前维度上较大的那个。
矩阵乘法
import torch
x = torch.ones([10, 1, 5, 2])
y = torch.ones([3, 2, 5])
z = torch.matmul(x, y)
print('After matmul: ', z.shape)
1.2.6数据预处理
1. 读取数据集 house_tiny.csv、boston_house_prices.csv、Iris.csv
pandas库可用于读取xls,csv,txt多种文件,在此用于读取csv文件导入pandas
import pandas as pd
data_file1 = r"C:\Users\hp\Desktop\house_tiny.csv"
data_file2 = r"C:\Users\hp\Desktop\boston_house_prices.csv"
data_file3 = r"C:\Users\hp\Desktop\Iris.csv"
data1 = pd.read_csv(data_file1)
data2 = pd.read_csv(data_file2)
data3 = pd.read_csv(data_file3)
# print(data1)
print(data3)
# print(data3)
2. 处理缺失值
常用函数
- df.isnull()、df.notnull():两个函数互为取反
- df.isna():等同于df.isnull()
- df.dropna():删除缺失值
- df.fillna():填充缺失值
df.isnull():是缺失值为True,反之为False
下述代码可以查看缺失值
import pandas as pd
data_file1 = r"C:\Users\hp\Desktop\house_tiny.csv"
data_file2 = r"C:\Users\hp\Desktop\boston_house_prices.csv"
data_file3 = r"C:\Users\hp\Desktop\Iris.csv"
data1 = pd.read_csv(data_file1)
data2 = pd.read_csv(data_file2)
data3 = pd.read_csv(data_file3)
print(data1.isnull())
print(data2.isnull())
print(data3.isnull())
3、将缺失的数据补齐
inputs, outputs = data1.iloc[:, 0:2], data1.iloc[:, 2]
inputs = inputs.fillna(inputs.mean()) # 用输入的平均值填充NA
# Alley作为string没有均值,使用one hot编码
inputs = pd.get_dummies(inputs, dummy_na=True)
inputs['Price']=data1['Price']
print(inputs)
4、转换为张量格式
import pandas as pd
import torch
data_file1 = r"C:\Users\hp\Desktop\house_tiny.csv"
data_file2 = r"C:\Users\hp\Desktop\boston_house_prices.csv"
data_file3 = r"C:\Users\hp\Desktop\Iris.csv"
data1 = pd.read_csv(data_file1)
data2 = pd.read_csv(data_file2)
data3 = pd.read_csv(data_file3)
data3.replace({"Species":{'Iris-setosa':0,'Iris-versicolor':1,'Iris-virginica':2}},inplace=True)
tensor_iris=torch.tensor(data3.values)
print(tensor_iris)
只展示部分结果
1.2.7实验心得
1、new_Tensor2 = ndim_3_Tensor.reshape([-1, 5, 2])中-1的值:总元素的个数/其他维度的个数
2、张量在任何一个维度上的元素数量必须相等
3、平时在python中让一个数组发生反转,一般用reverse()函数,在张量中不能用reverse()会报错,用flip()函数。
4、注意:广播机制中是从后往前比较,缺少的部分用1代替
例如:对应位置进行相加运算,结果的shape是:x.shape和y.shape对应位置的最大值,比如:x.shape=(2,3,1,5),y.shape=(3,4,1),那么A+B的shape是(2,3,4,5)
5、不匹配的两个矩阵,如果让它们相加,它们的形状不匹配。 我们将两个矩阵广播为一个更大的矩阵,如上所示:矩阵a将复制列, 矩阵b将复制行,然后再按元素相加
6、数据预处理很多函数的具体使用方法可以csdn
df.isnull()、df.notnull():两个函数互为取反
df.isna():等同于df.isnull()
df.dropna():删除缺失值
df.fillna():填充缺失值