NNDL Pytorch入门之张量、算子与数据预处理

目录

一. 概念:张量、算子

二. 使用pytorch实现张量运算

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.3 张量与Numpy数组转换

1.2.4 张量的访问

1.2.4.1 索引和切片

1.2.4.2 访问张量

1.2.4.3 修改张量

1.2.5 张量的运算

1.2.5.1 数学运算

1.2.5.2 逻辑运算

1.2.5.3 矩阵运算

1.2.5.4 广播机制

三. 数据预处理

1. 读取数据集 house_tiny.csv、boston_house_prices.csv、Iris.csv

2. 处理缺失值

3. 转换为张量格式

一. 概念:张量、算子


张量:在深度学习框架中,数据经常用张量(Tensor)的形式来存储。张量是矩阵的扩展与延伸,可以认为是高阶的矩阵。1阶张量为向量,2阶张量为矩阵。如果你对Numpy熟悉,那么张量是类似于Numpy的多维数组(ndarray)的概念,可以具有任意多的维度(阶)。

算子:算子是构建复杂机器学习模型的基础组件,包含一个函数f(x)f(x)f(x)的前向函数和反向函数。可以认为是一块块基础的积木,最后用来组合完成一个复杂的机器人

二. 使用pytorch实现张量运算


1.2.1 创建张量


1.2.1.1 指定数据创建张量

import numpy as np
import torch
# 指定数据创建张量
a = np.array([1, 2, 3])
b = np.array([[1, 2, 3], [4, 5, 6]])
c = np.array([[[1, 2, 3], [4, 5, 6]],
              [[7, 8, 9], [10, 11, 12]]])
# 需要注意的是,张量在任何一个维度上的元素数量必须相等。
t1 = torch.tensor(a)
t2 = torch.tensor(b)
t3 = torch.tensor(c)
print(t1)
print(t2)
print(t3)

运行结果:

1.2.1.2 指定形状创建张量

# 指定形状创建张量
# 创建一个3行2列的全0张量
t1 = torch.zeros([3,2])
print(t1)
# 创建一个3行2列的全1张量
t2 = torch.ones([3,2])
print(t2)
# 创建一个3行2列的随机值张量
t3 = torch.randint(1,10,size=[3,2])
print(t3)

运行结果:

1.2.1.3 指定区间创建

# 指定区间创建张量
# torch.arange不包含end,类型为int
t1= torch.arange(start=1, end=10,step=1)
# torch.arange包含end,steps是指一共取几个数
t2 = torch.linspace(start=1, end=5,steps=5)
print(t1)
print(t2)

运行结果:

1.2.2 张量的属性


1.2.2.1 张量的形状

张量具有如下形状属性:

  • Tensor.ndim:张量的维度,例如向量的维度为1,矩阵的维度为2。
  • Tensor.shape: 张量每个维度上元素的数量。
  • Tensor.shape[n]:张量第n维的大小。第n维也称为轴(axis)。
  • Tensor.size:张量中全部元素的个数
t1 = torch.ones([3,4,5])
print('张量的维度是:',t1.ndim)
print('张量每个维度上元素的数量:',t1.shape)
print('张量第1维的大小:',t1.shape[1])
print('张量中全部元素的数量:',t1.numel())

运行结果:

1.2.2.2 形状的改变

t1 = torch.ones([2,2,3])
print(t1.shape)
print(t1)
t2 = torch.reshape(t1,[2,3,2])
print(t2.shape)
print(t2)

运行结果:

1.2.2.3 张量的数据类型

通过Tensor.dtype来查看张量的数据类型,类型支持bool、float16、float32、float64、uint8、int8、int16、int32、int64和复数类型数据。

1)通过Python元素创建的张量,可以通过dtype来指定数据类型,如果未指定:

  • 对于Python整型数据,则会创建int64型张量。
  • 对于Python浮点型数据,默认会创建float32型张量。
print('Tensor dtype from python integers:', torch.tensor(1).dtype)
print('Tensor dtype from python floating point:', torch.tensor(1.0).dtype)

运行结果:

2)通过tensor.type()函数可以改变数组的数据类型。

t1 = torch.tensor(1)
t2 = t1.type(torch.float32)
print(t1.dtype)
print(t2.dtype)

运行结果:

1.2.2.4 张量的设备位置

初始化张量时可以通过place来指定其分配的设备位置,可支持的设备位置有三种:CPU、GPU和固定内存。

固定内存也称为不可分页内存或锁页内存,它与GPU之间具有更高的读写效率,并且支持异步传输,这对网络整体性能会有进一步提升,但它的缺点是分配空间过多时可能会降低主机系统的性能,因为它减少了用于存储虚拟内存数据的可分页内存。

例:创建了CPU上的张量

t1 = np.array([[1,0,0],[1,1,1]])
t1_cpu = torch.tensor(t1,device=torch.device("cpu"))
print("The position of num1_tensor(CPU):",t1_cpu.device)

运行结果:

1.2.3 张量与Numpy数组转换

t1 = torch.tensor([1., 2.])
# 将当前Tensor转化为numpy.ndarray
print('Tensor to convert:', t1.numpy())

运行结果:

1.2.4 张量的访问


1.2.4.1 索引和切片

我们可以通过索引或切片方便地访问或修改张量。飞桨使用标准的Python索引规则与Numpy索引规则,具有以下特点:

  • 基于0−n0-n0−n的下标进行索引,如果下标为负数,则从尾部开始计算。
  • 通过冒号“:”分隔切片参数start:stop:step来进行切片操作,也就是访问start到stop范围内的部分元素并生成一个新的序列。其中start为切片的起始位置,stop为切片的截止位置,step是切片的步长,这三个参数均可缺省。

运行结果:

1.2.4.2 访问张量

# 定义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])
# 定义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 修改张量

ndim_2_Tensor = torch.ones([2, 3], dtype=torch.float32)
print('Origin Tensor:\n ', ndim_2_Tensor)
# 修改第1维为0
ndim_2_Tensor[0] = 0
print('change Tensor:\n ', ndim_2_Tensor)
# 修改第1维为2.1
ndim_2_Tensor[0:1] = 2.1
print('change Tensor: \n', ndim_2_Tensor)
# 修改全部Tensor
ndim_2_Tensor[...] = 3
print('change Tensor:\n ', ndim_2_Tensor)

运行结果:

1.2.5 张量的运算

张量支持包括基础数学运算、逻辑运算、矩阵运算等100余种运算操作,以加法为例,有如下两种实现方式:
1)使用pytorch torch.add(x,y)。
2)使用张量类成员函数x.add(y)


# 定义两个Tensor
x = torch.tensor([[1.1, 2.2], [3.3, 4.4]], dtype=torch.float64)
y = torch.tensor([[5.5, 6.6], [7.7, 8.8]], dtype=torch.float64)
# 第一种调用方法,paddle.add逐元素相加算子,并将各个位置的输出元素保存到返回结果中
print('Method 1: ', torch.add(x, y))
# 第二种调用方法
print('Method 2: ', x.add(y))

运行结果:


1.2.5.1 数学运算

张量类的基础数学函数如下:
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()                       # 指定维度上元素的和,默认为全部维度

1.2.5.2 逻辑运算

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的全部元素是否接近

1.2.5.3 矩阵运算

x.t()                         # 矩阵转置
x.transpose([1, 0])           # 交换第 0 维与第 1 维的顺序
x.norm('fro')                 # 矩阵的弗罗贝尼乌斯范数
x.dist(y, p=2)                # 矩阵(x-y)的2范数
x.matmul(y)                   # 矩阵乘法

1.2.5.4 广播机制

pytorch的一些API在计算时支持广播(Broadcasting)机制,允许在一些运算时使用不同形状的张量。通常来讲,如果有一个形状较小和一个形状较大的张量,会希望多次使用较小的张量来对较大的张量执行某些操作,看起来像是形状较小的张量首先被扩展到和较大的张量形状一致,然后再做运算。

广播机制的条件

pytorch的广播机制主要遵循如下规则(参考Numpy广播机制):

1)每个张量至少为一维张量。
2)从后往前比较张量的形状,当前维度的大小要么相等,要么其中一个等于1,要么其中一个不存在。
 

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)

运行结果:

从输出结果看,x与y在上述两种情况中均遵循广播规则,因此在张量相加时可以广播。我们再定义两个shape分别为[2, 3, 4]和[2, 3, 6]的张量,观察这两个张量是否能够通过广播操作相加。

x = torch.ones((2, 3, 4))
y = torch.ones((2, 3, 6))
z = x + y

运行结果会抛出错误,从输出结果看,此时x和y是不能广播的,因为在第一次从后往前的比较中,4和6不相等,不符合广播规则。

广播机制的计算规则

现在我们知道在什么情况下两个张量是可以广播的。两个张量进行广播后的结果张量的形状计算规则如下:

1)如果两个张量shape的长度不一致,那么需要在较小长度的shape前添加1,直到两个张量的形状长度相等。

2) 保证两个张量形状相等之后,每个维度上的结果维度就是当前维度上较大的那个。

以张量x和y进行广播为例,x的shape为[2, 3,
1,5],张量y的shape为[3,4,1]。首先张量y的形状长度较小,因此要将该张量形状补齐为[1, 3, 4,
1],再对两个张量的每一维进行比较。从第一维看,x在一维上的大小为2,y为1,因此,结果张量在第一维的大小为2。以此类推,对每一维进行比较,得到结果张量的形状为[2,
3, 4, 5]。

由于矩阵乘法函数paddle.matmul在深度学习中使用非常多,这里需要特别说明一下它的广播规则:

1)如果两个张量均为一维,则获得点积结果。

2) 如果两个张量都是二维的,则获得矩阵与矩阵的乘积。

3) 如果张量x是一维,y是二维,则将x的shape转换为[1, D],与y进行矩阵相乘后再删除前置尺寸。

4) 如果张量x是二维,y是一维,则获得矩阵与向量的乘积。

5) 如果两个张量都是N维张量(N >
2),则根据广播规则广播非矩阵维度(除最后两个维度外其余维度)。比如:如果输入x是形状为[j,1,n,m]的张量,另一个y是[k,m,p]的张量,则输出张量的形状为[j,k,n,p]。
x = torch.ones([10, 1, 5, 2])
y = torch.ones([3, 2, 5])
z = torch.matmul(x, y)
print('After matmul:', z.shape)

运行结果:

从输出结果看,计算张量乘积时会使用到广播机制

三. 数据预处理


1. 读取数据集 house_tiny.csv、boston_house_prices.csv、Iris.csv

import pandas as pd
import torch
# 读入数据
data_iris = pd.read_csv('Iris.csv')
data_house_tiny = pd.read_csv('house_tiny.csv')
data_boston_house_prices = pd.read_csv('boston_house_prices.csv')
# 输出数据
print(data_iris)
print(data_house_tiny)
print(data_boston_house_prices)

2. 处理缺失值

# 处理缺失值与离散值
t1 = data_iris
t2 = data_house_tiny
t3 = data_boston_house_prices
# 使用均值处理缺失值
t1 = t1.fillna(value=t1.mean())
t2 = t2.fillna(value=t2.mean())
t3 = t3.fillna(value=t3.mean())
print(t1)
print(t2)
print(t3)
# 处理离散值
t1 = pd.get_dummies(t1)
t2 = pd.get_dummies(t2)
t3 = pd.get_dummies(t3)
print(t1)
print(t2)
print(t3)

运行结果:

 Id  SepalLengthCm  ...  PetalWidthCm         Species
0      1            5.1  ...           0.2     Iris-setosa
1      2            4.9  ...           0.2     Iris-setosa
2      3            4.7  ...           0.2     Iris-setosa
3      4            4.6  ...           0.2     Iris-setosa
4      5            5.0  ...           0.2     Iris-setosa
..   ...            ...  ...           ...             ...
145  146            6.7  ...           2.3  Iris-virginica
146  147            6.3  ...           1.9  Iris-virginica
147  148            6.5  ...           2.0  Iris-virginica
148  149            6.2  ...           2.3  Iris-virginica
149  150            5.9  ...           1.8  Iris-virginica

[150 rows x 6 columns]
   NumRooms Alley   Price
0       3.0  Pave  127500
1       2.0   NaN  106000
2       4.0   NaN  178100
3       3.0   NaN  140000
        CRIM    ZN  INDUS  CHAS    NOX  ...  RAD  TAX  PTRATIO  LSTAT  MEDV
0    0.00632  18.0   2.31     0  0.538  ...    1  296     15.3   4.98  24.0
1    0.02731   0.0   7.07     0  0.469  ...    2  242     17.8   9.14  21.6
2    0.02729   0.0   7.07     0  0.469  ...    2  242     17.8   4.03  34.7
3    0.03237   0.0   2.18     0  0.458  ...    3  222     18.7   2.94  33.4
4    0.06905   0.0   2.18     0  0.458  ...    3  222     18.7   5.33  36.2
..       ...   ...    ...   ...    ...  ...  ...  ...      ...    ...   ...
501  0.06263   0.0  11.93     0  0.573  ...    1  273     21.0   9.67  22.4
502  0.04527   0.0  11.93     0  0.573  ...    1  273     21.0   9.08  20.6
503  0.06076   0.0  11.93     0  0.573  ...    1  273     21.0   5.64  23.9
504  0.10959   0.0  11.93     0  0.573  ...    1  273     21.0   6.48  22.0
505  0.04741   0.0  11.93     0  0.573  ...    1  273     21.0   7.88  11.9

[506 rows x 13 columns]
      Id  SepalLengthCm  ...  Species_Iris-versicolor  Species_Iris-virginica
0      1            5.1  ...                        0                       0
1      2            4.9  ...                        0                       0
2      3            4.7  ...                        0                       0
3      4            4.6  ...                        0                       0
4      5            5.0  ...                        0                       0
..   ...            ...  ...                      ...                     ...
145  146            6.7  ...                        0                       1
146  147            6.3  ...                        0                       1
147  148            6.5  ...                        0                       1
148  149            6.2  ...                        0                       1
149  150            5.9  ...                        0                       1

[150 rows x 8 columns]
   NumRooms   Price  Alley_Pave
0       3.0  127500           1
1       2.0  106000           0
2       4.0  178100           0
3       3.0  140000           0
        CRIM    ZN  INDUS  CHAS    NOX  ...  RAD  TAX  PTRATIO  LSTAT  MEDV
0    0.00632  18.0   2.31     0  0.538  ...    1  296     15.3   4.98  24.0
1    0.02731   0.0   7.07     0  0.469  ...    2  242     17.8   9.14  21.6
2    0.02729   0.0   7.07     0  0.469  ...    2  242     17.8   4.03  34.7
3    0.03237   0.0   2.18     0  0.458  ...    3  222     18.7   2.94  33.4
4    0.06905   0.0   2.18     0  0.458  ...    3  222     18.7   5.33  36.2
..       ...   ...    ...   ...    ...  ...  ...  ...      ...    ...   ...
501  0.06263   0.0  11.93     0  0.573  ...    1  273     21.0   9.67  22.4
502  0.04527   0.0  11.93     0  0.573  ...    1  273     21.0   9.08  20.6
503  0.06076   0.0  11.93     0  0.573  ...    1  273     21.0   5.64  23.9
504  0.10959   0.0  11.93     0  0.573  ...    1  273     21.0   6.48  22.0
505  0.04741   0.0  11.93     0  0.573  ...    1  273     21.0   7.88  11.9

[506 rows x 13 columns]

3. 转换为张量格式
 

t1 = np.array(t1)
t1 = torch.tensor(t1)
print(t1)
t2 = np.array(t2)
t2 = torch.tensor(t2)
print(t2)
t3 = np.array(t3)
t3 = torch.tensor(t3)
print(t3)

运行结果:

本文章参考神经网络与深度学习-案例与实践教程进行学习。

 心得体会:
本次实验的难度比上次实验要高,而这次由于没有提前进行学习规,所以在做这次试验时最后为了赶时间导致了质量上比较差,而且对于知识点的掌握也比较浅薄,还没有认真的取钻研每个函数的使用规则与各种用途。所以还需在提交完实验和进行一定的复习与补充。这是一次警醒,由于实验一次比一次难,所以往后要提前进行实验规划,力争每个实验都提前认真完成,知识点也学的更加深刻与全面些。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值