一、认识张量与算子
1.张量
张量是由以下三个关键属性来定义的。
轴的个数(阶)。例如,3D 张量有 3 个轴,矩阵有 2 个轴。这在 Numpy 等 Python 库中也叫张量的 ndim 。
形状。这是一个整数元组,表示张量沿每个轴的维度大小(元素个数)。例如,前面矩阵示例的形状为 (3, 5) ,3D 张量示例的形状为 (3, 3, 5) 。向量的形状只包含一个元素,比如 (5,) ,而标量的形状为空,即 () 。(张量的形状)
数据类型(在 Python 库中通常叫作 dtype )。这是张量中所包含数据的类型,例如,张量的类型可以是 float32 、 uint8 、 float64 等。在极少数情况下,你可能会遇到字符( char )张量。注意:Numpy(以及大多数其他库)中不存在字符串张量,因为张量存储在预先分配的连续内存段中,而字符串的长度是可变的,无法用这种方式存储。
2. 算子
算子(Operator):构建神经网络模型的基础组件。
在深度学习框架中,数据经常用张量(Tensor)的形式来存储。张量是矩阵的扩展与延伸,可以认为是高阶的矩阵。1阶张量为向量,2阶张量为矩阵。如果你对Numpy熟悉,那么张量是类似于Numpy的多维数组(ndarray)的概念,可以具有任意多的维度。
张量中元素的类型可以是布尔型数据、整数、浮点数或者复数,但同一张量中所有元素的数据类型均相同。因此我们可以给张量定义一个数据类型(dtype)来表示其元素的类型。
3. 差别
向量数据:2D 张量,形状为 (samples, features) 。
时间序列数据或序列数据:3D 张量,形状为 (samples, timesteps, features) 。
图像:4D张量,形状为 (samples, height, width, channels) 或 (samples, channels,
height, width) 。
视频:5D张量,形状为 (samples, frames, height, width, channels) 或 (samples,frames, channels, height, width) 。
函数属于泛函,泛函和变换都属于算子,算子属于映射
4. 理解
- 张量是矩阵的扩展与延伸。
- 算子是构建复杂机器学习模型的基础组件,是深度学习算法的基本单元
二、torch的基本使用
1. 创建张量
# 首先导入包
import torch
1.1 指定数据创建张量
1. 通过指定的Python列表数据[2.0, 3.0, 4.0],创建一个一维张量
t = torch.tensor([1.0,2.1,3.2])
print(t) # tensor([1.0000, 2.1000, 3.2000])
2. 通过指定的Python列表数据来创建类似矩阵(matrix)的二维张量。
t = torch.tensor([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0]])
print(t) # tensor([[1., 2., 3.],[4., 5., 6.]])
3. 同样地,还可以创建维度为3、4…N等更复杂的多维张量。
t = torch.tensor([[[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]],
[[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]]])
print(t)
运行结果:
tensor([[[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10]],
[[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]]])
需要注意的是,张量在任何一个维度上的元素数量必须相等,否则会报错。
1.2 指定形状创建
如果要创建一个指定形状、元素数据相同的张量,可以使用torch.zeros、torch.ones、torch.full等API。
m, n = 2, 3
1. 使用torch.zeros创建数据全为0,形状为[m, n]的Tensor
zeros_Tensor = torch.zeros([m, n])
2. 使用torch.ones创建数据全为1,形状为[m, n]的Tensor
ones_Tensor = torch.ones([m, n])
3. 使用torch.full创建数据全为指定值,形状为[m, n]的Tensor,这里我们指定数据为10
full_Tensor = torch.full([m, n], 10)
输出一下:
print('zeros Tensor: ', zeros_Tensor)
print('ones Tensor: ', ones_Tensor)
print('full Tensor: ', full_Tensor)
运行结果:
zeros Tensor: tensor([[0., 0., 0.],
[0., 0., 0.]])
ones Tensor: tensor([[1., 1., 1.],
[1., 1., 1.]])
full Tensor: tensor([[10, 10, 10],
[10, 10, 10]])
1.3 指定区间创建
如果要在指定区间内创建张量,可以使用torch.arange、torch.linspace等API。
1. 使用torch.arange创建以步长step均匀分隔数值区间[start, end)的一维Tensor
# arange_Tensor = torch.arange(start=1, end=5, step=1)
arange_Tensor = torch.arange(5,10,1) # (开始,结束,间隔),是一个左闭右开区间
2. 使用torch.linspace创建以元素个数num均匀分隔数值区间[start, stop]的Tensor
linspace_Tensor = torch.linspace(3,10,5,dtype=torch.int) # (开始,结束,个数,类型)
输出:
print('arange Tensor: ', arange_Tensor)
print('linspace Tensor: ', linspace_Tensor)
运行结果:
arange Tensor: tensor([5, 6, 7, 8, 9])
linspace Tensor: tensor([ 3, 4, 6, 8, 10], dtype=torch.int32)
2. 张量的属性
2.1 张量的形状
张量具有如下形状属性:
- Tensor.ndim:张量的维度,例如向量的维度为1,矩阵的维度为2。
- Tensor.shape: 张量每个维度上元素的数量。
- Tensor.shape[n]:张量第nnn维的大小。第nnn维也称为轴(axis)。
- Tensor.size:张量中全部元素的个数。
创建一个四维张量,并打印出shape、ndim、shape[n]、size属性。
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) # 表示数据真实大小
print('Number of elements in Tensor: ', ndim_4_Tensor.numel()) # 表示元素个数
运行结果:
Number of dimensions: 4
Shape of Tensor: torch.Size([2, 3, 4, 5])
Elements number along axis 0 of Tensor: 2
Elements number along the last axis of Tensor: 5
Number of elements in Tensor: <built-in method size of Tensor object at 0x0000018DD8987AE0>
Number of elements in Tensor: 120
2.2 形状的改变
除了查看张量的形状外,重新设置张量的在实际编程中也具有重要意义,torch.reshape改变张量的形状。
1. 定义一个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)
运行结果:
the shape of ndim_3_Tensor: torch.Size([3, 2, 5])
2. torch.reshape 可以保持在输入数据不变的情况下,改变数据形状。这里我们设置reshape为[2,5,3]
reshape_Tensor = torch.reshape(ndim_3_Tensor, [2, 5, 3])
print("After reshape:", reshape_Tensor)
运行结果:
After reshape: 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]]])
将张量从[3, 2, 5]的形状reshape为[2, 5, 3]的形状时,张量内的数据不会发生改变,元素顺序也没有发生改变,只有数据形状发生了改变。
使用reshape时存在一些技巧,比如:
- -1表示这个维度的值是从张量的元素总数和剩余维度推断出来的。因此,有且只有一个维度可以被设置为-1。
- 0表示实际的维数是从张量的对应维数中复制出来的,因此shape中0所对应的索引值不能超过张量的总维度。
new_Tensor1 = ndim_3_Tensor.reshape([-1])
print('new Tensor 1 shape: ', new_Tensor1.shape)
运行结果:
new Tensor 1 shape: torch.Size([30])
5. 还可以通过torch.unsqueeze将张量中的一个或多个维度中插入尺寸为1的维度。
ones_Tensor = torch.ones([5,6], dtype=torch.int)
new_Tensor1 = torch.unsqueeze(ones_Tensor, 0)
print('ones Tensor shape: ', ones_Tensor.shape)
print(ones_Tensor )
print('new Tensor 1 shape: ', new_Tensor1.shape)
print(new_Tensor1)
运行结果:
ones Tensor shape: torch.Size([5, 6])
tensor([[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1]], dtype=torch.int32)
new Tensor 1 shape: torch.Size([1, 5, 6])
tensor([[[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1]]], dtype=torch.int32)
2.3 张量的数据类型
可以通过Tensor.dtype来查看张量的数据类型,
类型支持bool、float16、float32、float64、uint8、int8、int16、int32、int64和复数类型数据。
- 通过Python元素创建的张量,可以通过dtype来指定数据类型,如果未指定:
对于Python整型数据,则会创建int64型张量。
对于Python浮点型数据,默认会创建float32型张量。- 通过Numpy数组创建的张量,则与其原来的数据类型保持相同。通过torch.tensor()函数可以将Numpy数组转化为张量。
1. 使用torch.tensor通过已知数据来创建一个Tensor
print(torch.tensor(1).dtype)
print(torch.tensor(1.0).dtype)
运行结果:
torch.int64
torch.float32
2. 定义dtype为float32的Tensor
float32_Tensor = torch.tensor(1.0)
3. Tensor后加.to()可以将输入数据的数据类型转换为指定的dtype并输出,也可以是.long(), .int(), .float(), .double()等
int64_Tensor = float32_Tensor.to(dtype=torch.int64) # 可以这样用
print(int64_Tensor.dtype)
运行结果:
torch.int64
2.4 张量的设备位置
初始化张量时可以通过place来指定其分配的设备位置,可支持的设备位置有三种:CPU、GPU和固定内存。固定内存也称为不可分页内存或锁页内存,它与GPU之间具有更高的读写效率,并且支持异步传输,这对网络整体性能会有进一步提升,但它的缺点是分配空间过多时可能会降低主机系统的性能,因为它减少了用于存储虚拟内存数据的可分页内存。当未指定设备位置时,张量默认设备位置和安装的pytorch版本一致,如安装了GPU版本的pytorch,则设备位置默认为GPU。
如下代码分别创建了CPU、GPU和固定内存上的张量,并通过Tensor.device查看张量所在的设备位置。
1. 创建CPU上的Tensor
cpu_Tensor = torch.tensor(1, device=torch.device('cpu'))
2. 通过Tensor.device查看张量所在设备位置
print('cpu Tensor: ', cpu_Tensor.device)
运行结果:
cpu Tensor: cpu
3. 张量与Numpy数组转换
将Numpy数组转化为张量,也可以通过Tensor.numpy()函数将张量转化为Numpy数组。
ndim_1_Tensor = torch.tensor([1., 2.])
# 将当前 Tensor 转化为 numpy.ndarray
print('Tensor to convert: ', ndim_1_Tensor.numpy())
运行结果:
Tensor to convert: [1. 2.]
4. 张量的访问
4.1 索引和切片
我们可以通过索引或切片方便地访问或修改张量,具有以下特点:
- 基于0−n的下标进行索引,如果下标为负数,则从尾部开始计算。
- 通过冒号“:”分隔切片参数start:stop:step来进行切片操作,也就是访问start到stop范围内的部分元素并生成一个新的序列。其中start为切片的起始位置,stop为切片的截止位置,step是切片的步长,这三个参数均可缺省。
4.2 访问张量
针对一维张量,对单个轴进行索引和切片。
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]) # 步长为3
# print("Reverse:", ndim_1_Tensor[::-1]) # 报错:ValueError: step must be greater than zero
运行结果:
Origin Tensor: tensor([0, 1, 2, 3, 4, 5, 6, 7, 8])
First element: tensor(0)
Last element: tensor(8)
All element: tensor([0, 1, 2, 3, 4, 5, 6, 7, 8])
Before 3: tensor([0, 1, 2])
Interval of 3: tensor([0, 3, 6])
(注:Pytorch不支持负数步长)
针对二维及以上维度的张量,在多个维度上进行索引或切片。
索引或切片的第一个值对应第0维,第二个值对应第1维,
以此类推,如果某个维度上未指定索引,则默认为“:”。
ndim_2_Tensor = torch.tensor([[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11]]) # 先创建一个torch
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]) # 第一行的第二列的元素
运行结果:
Origin Tensor: tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
First row: tensor([0, 1, 2, 3])
First row: tensor([0, 1, 2, 3])
First column: tensor([0, 4, 8])
Last column: tensor([ 3, 7, 11])
All element: tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
First row and second column: tensor(1)
4.3 修改张量
提醒:
- 慎重通过索引或切片操作来修改张量,此操作仅会原地修改该张量的数值,且原值不会被保存。
- 如果被修改的张量参与梯度计算,将仅会使用修改后的数值,这可能会给梯度计算引入风险。
# 定义1个二维Tensor
ndim_2_Tensor = torch.ones([2, 3], dtype=torch.float32)
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)
Origin Tensor: tensor([[1., 1., 1.],
[1., 1., 1.]])
change Tensor: tensor([[0., 0., 0.],
[1., 1., 1.]])
change Tensor: tensor([[2.1000, 2.1000, 2.1000],
[1.0000, 1.0000, 1.0000]])
change Tensor: tensor([[3., 3., 3.],
[3., 3., 3.]])
5. 张量的运算
张量支持包括基础数学运算、逻辑运算、矩阵运算等100余种运算操作,以加法为例,有如下两种实现方式:
- torch.add(x,y)。
- 使用张量类成员函数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))
运行结果:
Method 1: tensor([[ 6.6000, 8.8000],
[11.0000, 13.2000]], dtype=torch.float64)
Method 2: tensor([[ 6.6000, 8.8000],
[11.0000, 13.2000]], dtype=torch.float64)
笔记
由于张量类成员函数操作更为方便,以下均从张量类成员函数的角度,对常用张量操作进行介绍。
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() # 指定维度上元素的和,默认为全部维度
同时,为了更方便地使用张量,飞桨对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) # 逐元素幂
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的全部元素是否接近
5.3 矩阵运算
张量类还包含了矩阵运算相关的函数,如矩阵的转置、范数计算和乘法等。
x.t() # 矩阵转置
x.transpose([1, 0]) # 交换第 0 维与第 1 维的顺序
x.norm('fro') # 矩阵的弗罗贝尼乌斯范数
x.dist(y, p=2) # 矩阵(x-y)的2范数
x.matmul(y) # 矩阵乘法
有些矩阵运算中也支持大于两维的张量,比如matmul函数,对最后两个维度进行矩阵乘。
比如x是形状为[j,k,n,m]的张量,另一个y是[j,k,m,p]的张量,则x.matmul(y)输出的张量形状为[j,k,n,p]。
5.4 广播机制
pytorch的一些API在计算时支持广播(Broadcasting)机制,允许在一些运算时使用不同形状的张量。
通常来讲,如果有一个形状较小和一个形状较大的张量,会希望多次使用较小的张量来对较大的张量执行某些操作,看起来像是形状较小的张量首先被扩展到和较大的张量形状一致,然后再做运算。
飞桨的广播机制主要遵循如下规则(参考Numpy广播机制):
- 每个张量至少为一维张量。
- 从后往前比较张量的形状,当前维度的大小要么相等,要么其中一个等于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)
运行结果:
broadcasting with two same shape tensor: torch.Size([2, 3, 4])
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)
运行结果:
broadcasting with two different shape tensor: torch.Size([2, 3, 4, 5])
从输出结果看,x与y在上述两种情况中均遵循广播规则,因此在张量相加时可以广播。
我们再定义两个shape分别为[2, 3, 4]和[2, 3, 6]的张量,观察这两个张量是否能够通过广播操作相加。
try:
x = torch.ones((2, 3, 4))
y = torch.ones((2, 3, 6))
z = x + y
except:
print("报错了") # 出现错误
从输出结果看,此时x和y是不能广播的,因为在第一次从后往前的比较中,4和6不相等,不符合广播规则。
广播机制的计算规则:
现在我们知道在什么情况下两个张量是可以广播的。两个张量进行广播后的结果张量的形状计算规则如下:
- 如果两个张量shape的长度不一致,那么需要在较小长度的shape前添加1,直到两个张量的形状长度相等。
- 保证两个张量形状相等之后,每个维度上的结果维度就是当前维度上较大的那个。
以张量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]。
由于矩阵乘法函数torch.matmul在深度学习中使用非常多,这里需要特别说明一下它的广播规则:
- 如果两个张量均为一维,则获得点积结果。
- 如果两个张量都是二维的,则获得矩阵与矩阵的乘积。
- 如果张量x是一维,y是二维,则将x的shape转换为[1, D],与y进行矩阵相乘后再删除前置尺寸。
- 如果张量x是二维,y是一维,则获得矩阵与向量的乘积。
- 如果两个张量都是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)
运行结果:
After matmul: torch.Size([10, 3, 5, 5])
从输出结果看,计算张量乘积时会使用到广播机制。
三. 使用pytorch实现数据预处理
1.1 读取数据集 house_tiny.csv
导入包,并读取数据
# 导入包
import pandas as pd
import torch
# 读取数据
data = pd.read_csv('house_tiny.csv')
print(data)
运行结果:
NumRooms Alley Price
0 NaN Pave 127500
1 2.0 NaN 106000
2 4.0 NaN 178100
3 NaN NaN 140000
1.2 处理缺失值
注意:
- NaN项表示缺失值 典型方法是插值法和删除法,其中插值法用一个替代值弥补缺失值,而删除法则直接忽略缺失值。
- 通过位置索引iloc,我们将data分成inputs和outputs, 其中前者为data的前两列,而后者为data的最后一列。 对于inputs中缺少的数值,我们用同一列的均值替换“NaN”项。
inputs,outputs = data.iloc[:,0:2],data.iloc[:,2] # 截取数据,左闭右开
print('inputs:\n',inputs)
print('outputs:\n',outputs)
inputs = inputs.fillna(inputs.mean()) # mean()用来求均值
print('inputs:\n',inputs)
运行结果:
inputs:
NumRooms Alley
0 NaN Pave
1 2.0 NaN
2 4.0 NaN
3 NaN NaN
outputs:
0 127500
1 106000
2 178100
3 140000
Name: Price, dtype: int64
inputs:
NumRooms Alley
0 3.0 Pave
1 2.0 NaN
2 4.0 NaN
3 3.0 NaN
对于inputs中的类别值或离散值,我们将“NaN”视为一个类别。 由于“巷子类型”(“Alley”)列只接受两种类型的类别值“Pave”和“NaN”, pandas可以自动将此列转换为两列“Alley_Pave”和“Alley_nan”。 巷子类型为“Pave”的行会将“Alley_Pave”的值设置为1,“Alley_nan”的值设置为0。 缺少巷子类型的行会将“Alley_Pave”和“Alley_nan”分别设置为0和1。
inputs = pd.get_dummies(inputs, dummy_na=True)
print(inputs)
运行结果:
NumRooms Alley_Pave Alley_nan
0 3.0 1 0
1 2.0 0 1
2 4.0 0 1
3 3.0 0 1
1.3 转换为张量格式
现在inputs和outputs中的所有条目都是数值类型,它们可以转换为张量格式。
当数据采用张量格式后,可以通过在 2.1节中引入的那些张量函数来进一步操作。
X,y = torch.tensor(inputs.values),torch.tensor(outputs.values)
print(X)
print(y)
运行结果:
tensor([[3., 1., 0.],
[2., 0., 1.],
[4., 0., 1.],
[3., 0., 1.]], dtype=torch.float64)
tensor([127500, 106000, 178100, 140000])
2.1 处理boston_house_prices.csv数据集
读取数据
import pandas as pd
import torch
data2 = pd.read_csv('boston_house_prices.csv')
print(data2)
运行结果:
CRIM ZN INDUS CHAS NOX RM AGE DIS RAD TAX PTRATIO LSTAT MEDV
0 0.00632 18.0 2.31 0 0.538 6.575 65.2 4.0900 1 296 15.3 4.98 24.0
1 0.02731 0.0 7.07 0 0.469 6.421 78.9 4.9671 2 242 17.8 9.14 21.6
2 0.02729 0.0 7.07 0 0.469 7.185 61.1 4.9671 2 242 17.8 4.03 34.7
3 0.03237 0.0 2.18 0 0.458 6.998 45.8 6.0622 3 222 18.7 2.94 33.4
4 0.06905 0.0 2.18 0 0.458 7.147 54.2 6.0622 3 222 18.7 5.33 36.2
.. ... ... ... ... ... ... ... ... ... ... ... ... ...
501 0.06263 0.0 11.93 0 0.573 6.593 69.1 2.4786 1 273 21.0 9.67 22.4
502 0.04527 0.0 11.93 0 0.573 6.120 76.7 2.2875 1 273 21.0 9.08 20.6
503 0.06076 0.0 11.93 0 0.573 6.976 91.0 2.1675 1 273 21.0 5.64 23.9
504 0.10959 0.0 11.93 0 0.573 6.794 89.3 2.3889 1 273 21.0 6.48 22.0
505 0.04741 0.0 11.93 0 0.573 6.030 80.8 2.5050 1 273 21.0 7.88 11.9
[506 rows x 13 columns]
2.2 无缺失值
无缺失值,不做处理
2.3 转换为张量格式
inputs = pd.get_dummies(data2)
X = torch.tensor(inputs.values)
print(X)
运行结果:
tensor([[6.3200e-03, 1.8000e+01, 2.3100e+00, ..., 1.5300e+01, 4.9800e+00,
2.4000e+01],
[2.7310e-02, 0.0000e+00, 7.0700e+00, ..., 1.7800e+01, 9.1400e+00,
2.1600e+01],
[2.7290e-02, 0.0000e+00, 7.0700e+00, ..., 1.7800e+01, 4.0300e+00,
3.4700e+01],
...,
[6.0760e-02, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 5.6400e+00,
2.3900e+01],
[1.0959e-01, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 6.4800e+00,
2.2000e+01],
[4.7410e-02, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 7.8800e+00,
1.1900e+01]], dtype=torch.float64)
3.1 处理Iris.csv数据集
data3 = pd.read_csv('Iris.csv')
3.2 无缺失值
无缺失值,不做处理
3.3 转换为张量格式
inputs = pd.get_dummies(data3)
X = torch.tensor(inputs.values)
print(X)
运行结果:
tensor([[ 1.0000, 5.1000, 3.5000, ..., 1.0000, 0.0000, 0.0000],
[ 2.0000, 4.9000, 3.0000, ..., 1.0000, 0.0000, 0.0000],
[ 3.0000, 4.7000, 3.2000, ..., 1.0000, 0.0000, 0.0000],
...,
[148.0000, 6.5000, 3.0000, ..., 0.0000, 0.0000, 1.0000],
[149.0000, 6.2000, 3.4000, ..., 0.0000, 0.0000, 1.0000],
[150.0000, 5.9000, 3.0000, ..., 0.0000, 0.0000, 1.0000]],
dtype=torch.float64)
四、这里加一些pandas的相关知识
1. 导入包
import pandas as pd
2. 创建一个数据,提取特征
data = pd.DataFrame({"学号":[1001,1002,1003,1004],
"性别":["男","女","女","男"],
"学历":["本科","硕士","专科","本科"]})
print(data)
print(pd.get_dummies(data)) # 特征提取
print(pd.get_dummies(data,prefix="A")) # 前缀全部改为A
print(pd.get_dummies(data,prefix=["A","B"],prefix_sep="+")) # 前缀改为A和B,"_"改为"+"
运行结果:
学号 性别 学历
0 1001 男 本科
1 1002 女 硕士
2 1003 女 专科
3 1004 男 本科
学号 性别_女 性别_男 学历_专科 学历_本科 学历_硕士
0 1001 0 1 0 1 0
1 1002 1 0 0 0 1
2 1003 1 0 1 0 0
3 1004 0 1 0 1 0
学号 A_女 A_男 A_专科 A_本科 A_硕士
0 1001 0 1 0 1 0
1 1002 1 0 0 0 1
2 1003 1 0 1 0 0
3 1004 0 1 0 1 0
学号 A+女 A+男 B+专科 B+本科 B+硕士
0 1001 0 1 0 1 0
1 1002 1 0 0 0 1
2 1003 1 0 1 0 0
3 1004 0 1 0 1 0
pandas.get_dummies(data,
prefix=None,
prefix_sep='_',
dummy_na=False,
columns=None,
sparse=False,
drop_first=False,
dtype=None)
代码 | 参数 | 作用 |
---|---|---|
prefix | str, list of str, 或 dict of str, 默认为 None | 用于追加DataFrame列名称的字符串。 |
prefix_sep | str, 默认为 ‘_’ | 如果附加前缀,则使用分隔符/分隔符。或者像这样传递列表或字典prefix。 |
dummy_na | bool, 默认为 False | 如果忽略False NaN。 |
columns | list-like, 默认为 None | 要编码的DataFrame中的列名。如果columns为None,则所有具有的列object或者categorydtype将被转换。 |
sparse | bool, 默认为 False | dummy-encoded列是否应由a支持SparseArray(True)或常规NumPy数组(False)。 |
drop_first | bool, 默认为 False | 是否通过删除第一个级别从k个分类级别中获取k-1个虚拟对象。 |
五、其他
1. 关于张量转numpy,numpy转张量
1.1 numpy转张量
import numpy as np
import torch
# 创建一个numpy
np_data = np.array([1,2,3,4])
np2torch = torch.from_numpy(np_data)
print("numpy数据转torch数据:", np2torch)
运行结果:
numpy数据转torch数据: tensor([1, 2, 3, 4], dtype=torch.int32)
1.2 张量转numpy
# 创建一个torch
torch_data = torch.tensor([1,2,3,4,5])
torch2np = torch_data.numpy()
print("torch数据转numpy数据:", torch2np)
运行结果:
torch数据转numpy数据: [1 2 3 4 5]
2. 求绝对值
import torch
import numpy as np
data = [-1,2,-3,4]
np_abs = np.abs(np.array(data))
print("numpy的abs:", np_abs)
torch_abs = torch.abs(torch.tensor(data))
print("torch的abs:", torch_abs)
运行结果:
numpy的abs: [1 2 3 4]
torch的abs: tensor([1, 2, 3, 4])
3. 抛出异常
如果try中代码报错,就输出except中的代码
try:
可能异常代码
except:
代码
这里补充一下上一篇的遗漏
第15题:利用13题目中的x,y 输出 x*y ,和 np.multiply(x, y) 还有 np.dot(x,y),比较差异。然后自己换一个不是方阵的试试。
x = np.array([[1, 2, 3], [3, 4, 5]], dtype=np.float64)
y = np.array([[5, 6, 7], [7, 8, 9]], dtype=np.float64)
print("x:",x)
print("y:",y)
print("x*y:",x*y) # 对应乘
print("np.multiply(x,y):",np.multiply(x,y)) # 对应相乘
try:
print("np.dot(x,y):",np.dot(x,y)) # 矩阵相乘
except:
print("报错了!!!")
运行结果:
x: [[1. 2. 3.]
[3. 4. 5.]]
y: [[5. 6. 7.]
[7. 8. 9.]]
x*y: [[ 5. 12. 21.]
[21. 32. 45.]]
np.multiply(x,y): [[ 5. 12. 21.]
[21. 32. 45.]]
报错了!!!
np.dot(x,y) 报错了!!!
如果换一个
x = np.array([[1, 2, 3], [3, 4, 5]], dtype=np.float64)
y = np.array([[5, 6], [7, 8],[9,10]], dtype=np.float64)
print("x:",x)
print("y:",y)
try:
print("np.dot(x,y):",np.dot(x,y)) # 矩阵相乘
except:
print("报错了!!!")
运行结果:
x: [[1. 2. 3.]
[3. 4. 5.]]
y: [[ 5. 6.]
[ 7. 8.]
[ 9. 10.]]
np.dot(x,y): [[ 46. 52.]
[ 88. 100.]]
np.dot(x,y) 没有报错!(这里联系一下线性代数)
点赞 + 收藏 + 关注!!!
如有错误与建议,望告知!!!(将于下篇文章更正)
请多多关注我!!!谢谢!!
上一篇:深度学习 实验一 numpy的使用