目录
一、概念:张量、算子
1.2.1 创建张量
1.2.1.1 指定数据创建张量
1.2.1.2 指定形状创建
1.2.1.3 指定区间创建
1.2.2 张量的属性
1.2.2.1 张量的形状
1.2.2.2 形状的改变
1.2.2.3 张量的数据类型
1.2.2.4 张量的设备位置
1.2.2.5 张量与Numpy数组转换
1.2.3 张量的访问
1.2.3.1 索引和切片
1.2.3.2 访问张量
1.2.3.3 修改张量
编辑
1.2.4 张量的运算
1.2.4.1 数学运算
1.2.4.2 逻辑运算
1.2.4.3 矩阵运算
1.2.4.4 广播机制
三、数据预处理
1. 读取数据集 house_tiny.csv、boston_house_prices.csv、Iris.csv
2. 处理缺失值
3. 转换为张量格式
总结
张量:张量是矩阵的扩展与延伸,可以认为是高阶的矩阵,可以认为是一种n维数组,类似于numpy数组,可以有任意维度。
算子:深度学习算法由一个个计算单元组成,我们称这些计算单元为算子。
二、使用pytorch实现张量运算
import torch # 导入pytorch
data = torch.tensor([2, 3, 4]) # 指定数据创建一维张量
print(data)
运行结果如下:
import torch
zeros_data2 = torch.zeros([m, n]) # 创建数据全为0,形状为[m,n]的Tensor
ones_data2 = torch.ones([m, n]) # 创建数据全为1,形状为[m,n]的Tensor
full_data2 = torch.full([m, n], 10) # 创建数据全为指定值10,形状为[m,n]的Tensor
print('zeros Tensor: ', zeros_data2)
print('ones Tensor: ', ones_data2)
print('full Tensor: ', full_data2)
运行结果如下:
import torch
arange_data3 = torch.arange(start=1, end=5, step=1)# 使用torch.arange创建以步长step均匀分隔数值区间[start, end)的一维Tensor
linspace_data3 = torch.linspace(start=1, end=5, steps=5)# 使用torch.linspace创建以元素个数steps均匀分隔数值区间[start, stop]的Tensor
print('arange Tensor: ', arange_data3)
print('linspace Tensor: ', linspace_data3)
运行结果如下:
张量具有如下形状属性:
Tensor.ndim
:张量的维度,例如向量的维度为1,矩阵的维度为2。Tensor.shape
: 张量每个维度上元素的数量。Tensor.shape[n]
:张量第nn维的大小。第nn维也称为轴(axis)。Tensor.numel()
:张量中全部元素的个数。import torch
data4 = torch.ones([2, 3, 4, 5]) # 创建数据全为1的四维张量
print("张量的维度:", data4.ndim) # 张量的维度
print("张量每个维度的元素数量:", data4.shape) # 张量每个维度元素的数量
print("张量第0维的元素个数:", data4.shape[0]) # 张量第N维大小
print("张量最后一个维度元素个数:", data4.shape[-1])
print('张量全部元素的个数:', data4.numel()) # 张量中全部元素个数
运行结果如下:
import torch
data5=torch.rand([3,2,5])#定义一个随机数据,形状为[3,2,5]的三维张量
print("原张量为:",data5)
re_data5=data5.reshape([2,5,3])#将原张量形状改变为[2,5,3]的三维张量
print("改变形状后的张量为:",re_data5)
re1_data5=data5.flatten()#将原张量改变为一维张量
print("压缩成一维张量后的结果:",re1_data5)
运行结果如下:
1)通过Python元素创建的张量,可以通过dtype来指定数据类型,如果未指定:
2)通过Numpy数组创建的张量,则与其原来的数据类型保持相同。通过dtype函数可以将Numpy数组转化为张量。
import torch
import numpy as np
arr = np.ones((3, 3)) # 创建一个3*3的全一数组
print("数组数据类型为:", arr.dtype)
data6 = torch.tensor(arr) # 将arr转为张量
print(data6)
int_data6 = torch.tensor(arr, dtype=int)
print("改变后的数据类型:", int_data6.type())
运行结果如下:
import torch
cpu_data7 = torch.rand([3, 3], device="cpu") # 指定cpu,随机创建形状为[3,3]的二维张量
gpu_data7 = torch.rand([3, 3], device="cuda:0") # 指定0号GPU,创建二维张量
print("cpu_data7的设备位置:",cpu_data7.device)#获取当前张量的设备
print("gpu_data7的设备位置:",gpu_data7.device)#获取当前张量的设备
运行结果如下:
import torch
data8 = torch.tensor([1., 2.])# 将当前 Tensor 转化为 numpy.ndarray
print('Tensor to convert: ', data8.numpy())
运行结果如下:
我们可以通过索引或切片方便地访问或修改张量。飞桨使用标准的Python索引规则与Numpy索引规则,具有以下特点:
针对一维张量,对单个轴进行索引和切片。
import torch
data9 = torch.tensor([0, 1, 2, 3, 4, 5, 6, 7, 8]) # 定义1个一维Tensor
print("Origin Tensor:", data9)
print("First element:", data9[0]) # 输出一维张量第一个元素
print("Last element:", data9[-1]) # 输出一位张量最后一个元素
print("All element:", data9[:]) # 输出所有的元素
print("Before 3:", data9[:3]) # 输出一维张量从第一个元素到第3个元素之间的所有元素
print("Interval of 3:", data9[::3]) # 步长为3,依次输出元素
print("Reverse:", data9[::-1]) # 倒叙输出所有元素
运行结果如下:
针对二维及以上维度的张量,在多个维度上进行索引或切片。索引或切片的第一个值对应第0维,第二个值对应第1维,以此类推,如果某个维度上未指定索引,则默认为“:”。
import torch
ndim_2_Tensor = torch.tensor([[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11]]) # 定义1个二维Tensor
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])
运行结果如下:
import torch
data10 = torch.ones([2, 3]) # 定义1个二维Tensor
print('Origin Tensor: ', ndim_2_Tensor)
data10[0] = 0 # 修改第1维为0
print('change Tensor: ', ndim_2_Tensor)
data10[0:1] = 2.1 # 修改第1维为2.1
print('change Tensor: ', ndim_2_Tensor)
data10[...] = 3 # 修改全部Tensor
print('change Tensor: ', ndim_2_Tensor)
运行结果如下:
张量类的基础数学函数如下:
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() # 指定维度上元素的和,默认为全部维度
张量类的逻辑运算函数如下:
x.isfinite() # 判断Tensor中元素是否是有限的数字,即不包括inf与nan
x.equal_all(y) # 判断两个Tensor的全部元素是否相等,并返回形状为[1]的布尔类Tensor
x.equal(y) # 判断两个Tensor的每个元素是否相等,并返回形状相同的布尔类Tensor
x.not_equal(y) # 判断两个Tensor的每个元素是否不相等
x.less_than(y) # 判断Tensor x的元素是否小于Tensor y的对应元素
x.less_equal(y) # 判断Tensor x的元素是否小于或等于Tensor y的对应元素
x.greater_than(y) # 判断Tensor x的元素是否大于Tensor y的对应元素
x.greater_equal(y) # 判断Tensor x的元素是否大于或等于Tensor y的对应元素
x.allclose(y) # 判断两个Tensor的全部元素是否接近
x.t() # 矩阵转置
x.transpose([1, 0]) # 交换第 0 维与第 1 维的顺序
x.norm('fro') # 矩阵的弗罗贝尼乌斯范数
x.dist(y, p=2) # 矩阵(x-y)的2范数
x.matmul(y) # 矩阵乘法
pytorch的一些API在计算时支持广播(Broadcasting)机制,允许在一些运算时使用不同形状的张量。通常来讲,如果有一个形状较小和一个形状较大的张量,会希望多次使用较小的张量来对较大的张量执行某些操作,看起来像是形状较小的张量首先被扩展到和较大的张量形状一致,然后再做运算。
广播机制的条件
Pytorch的广播机制主要遵循如下规则(参考Numpy广播机制):
1)每个张量至少为一维张量。
2)从后往前比较张量的形状,当前维度的大小要么相等,要么其中一个等于1,要么其中一个不存在。
# 当两个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)
运行结果如下:
import pandas as pd
house_tiny=pd.read_csv('house_tiny.csv')#读取house_tiny.csv数据集
boston_house_prices=pd.read_csv('boston_house_prices.csv')#读取boston_house_prices.csvs数据集
Iris=pd.read_csv('Iris.csv')
print('house_tiny',house_tiny)
print('boston_house_prices',boston_house_prices)
print('Iris',Iris)
运行结果如下:
import pandas as pd
house_tiny = pd.read_csv('house_tiny.csv') # 读取house_tiny.csv数据集
boston_house_prices = pd.read_csv('boston_house_prices.csv') # 读取boston_house_prices.csvs数据集
Iris = pd.read_csv('Iris.csv') # 读取Iris数据集
print('缺失数据:', house_tiny.isnull().sum()) # 检查数据集house_tiny缺失数据,
print('修改前:', house_tiny)
house_tiny = house_tiny.fillna('*') # 将house_tiny数据集中缺失数据替换为’*‘
boston_house_prices=boston_house_prices.fillna('*')
Iris=Iris.fillna('*')
print('***************')
print('修改后:', house_tiny) # 检查数据集house_tiny缺失数据,
运行结果如下:
import pandas as pd
import torch
import numpy as np
house_tiny = pd.read_csv('house_tiny.csv') # 读取house_tiny.csv数据集
boston_house_prices = pd.read_csv('boston_house_prices.csv') # 读取boston_house_prices.csvs数据集
Iris = pd.read_csv('Iris.csv') # 读取Iris数据集
house_tiny = house_tiny.fillna('*') # 将house_tiny数据集中缺失数据替换为’*‘
boston_house_prices = boston_house_prices.fillna('*')
Iris = Iris.fillna('*')
array = np.array(boston_house_prices) # 先将读取的数据转化为数组的形式
array = array.astype(float) # 再强制转换类型,统一格式
t = torch.from_numpy(array) # 数组与张量的转换
print('转换后的张量',t) # 输出结果
运行结果:
了解了张量及算子的概念,掌握了创建张量的三种方法,了解了张量的基本属性以及张量与数组间的相互转化,学会了张量之间的数学运算和逻辑运算,对数据集的预处理有了初步了解。