写出定义,并用通俗易懂的语言描述自己的理解。
张量:张量(tensor)理论是数学的一个分支学科,在力学中有重要应用。张量这一术语起源于力学,它最初是用来表示弹性介质中各点应力状态的,后来张量理论发展成为力学和物理学的一个有力的数学工具。张量之所以重要,在于它可以满足一切物理定律必须与坐标系的选择无关的特性。张量概念是矢量概念的推广,矢量是一阶张量。张量是一个可用来表示在一些矢量、标量和其他张量之间的线性关系的多线性函数。
–来自百度百科
算子:算子是一个函数空间到函数空间上的映射O:X→X。广义上的算子可以推广到任何空间,如内积空间等。
–来自百度百科
个人理解:张量实际上就是一种多维数组,也可以描述矩阵、向量等,他的功能和numpy里的数组差不多,当然,具体实现上会有差别,调用的函数可能不一样。算子就是通常理解的函数,是一种映射关系,在神经网络中,每一个神经元就像是一个算子。
1.2.1 创建张量
1.2.1.1 指定数据创建张量
import torch
import numpy as np
'''指定数据创建张量'''
x=torch.tensor([[0,1,2],[4,5,6]])
y=torch.tensor(((0,1,2),(4,5,6)))
z=torch.tensor(np.array([[0,1,2],[4,5,6]]))
print(x)
print(y)
print(z)
运行结果:
tensor([[0, 1, 2],
[4, 5, 6]])
tensor([[0, 1, 2],
[4, 5, 6]])
tensor([[0, 1, 2],
[4, 5, 6]], dtype=torch.int32)
1.2.1.2 指定形状创建
'''自定形状创建张量'''
x=torch.zeros([2,3],dtype=float)#全0矩阵
y=torch.ones([2,3],dtype=float)#全1矩阵
z=torch.empty([2,3],dtype=float)#初始化矩阵
print(x)
print(y)
print(z)
x=torch.eye(3)#单位矩阵
y=torch.full([2,3],2)#填充指定元素
y=torch.full_like(y,3)#按照指定tansor的形状填充元素
z=torch.rand([2,3])#0-1分布
print(x)
print(y)
print(z)
x=torch.randn([2,3])#标准正态分布
y=torch.diag(x)#取指定对象的对角矩阵
'''TypeError: diag(): argument 'input' (position 1) must be Tensor, not list'''
z=torch.normal(2,3,size=[2,3])#指定正态分布,均值和标准差
print(x)
print(y)
print(z)
运行结果:
tensor([[0., 0., 0.],
[0., 0., 0.]], dtype=torch.float64)
tensor([[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
tensor([[1.6912e-306, 1.7802e-306, 1.0681e-306],
[8.0110e-307, 1.7802e-306, 7.5660e-307]], dtype=torch.float64)
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
tensor([[3, 3, 3],
[3, 3, 3]])
tensor([[0.2701, 0.0938, 0.8314],
[0.2146, 0.5977, 0.3202]])
tensor([[0.4947, 1.2388, 0.8188],
[0.5496, 0.0506, 0.8186]])
tensor([0.4947, 0.0506])
tensor([[-1.0636, 2.5217, 3.3210],
[ 3.4817, -1.8444, -4.4325]])
1.2.1.3 指定区间创建
'''知道那个区间创建张量'''
x=torch.randint(2,5,[2,3])#指定区间随机整数
y=torch.arange(5)#从零取整
z=torch.linspace(1,8,10)#指定区间等间隔采样
print(x)
print(y)
print(z)
运行结果:
tensor([[4, 2, 3],
[2, 3, 3]])
tensor([0, 1, 2, 3, 4])
tensor([1.0000, 1.7778, 2.5556, 3.3333, 4.1111, 4.8889, 5.6667, 6.4444, 7.2222,
8.0000])
1.2.2 张量的属性
1.2.2.1 张量的形状
x=torch.tensor([[1,2,3],[4,5,6]])
print(x.shape)
torch.Size([2, 3])
1.2.2.2 形状的改变
print(x.reshape([3,2]))
print(x.shape)
tensor([[1, 2],
[3, 4],
[5, 6]])
torch.Size([2, 3])
1.2.2.3 张量的数据类型
print(x.dtype)
torch.int64
1.2.2.4 张量的设备位置
print(x.__pos__)
1.2.3 张量与Numpy数组转换
y=np.array(x)
x=torch.tensor(y)
print(y)
print(x)
[[1 2 3]
[4 5 6]]
tensor([[1, 2, 3],
[4, 5, 6]])
1.2.4 张量的访问
1.2.4.1 索引和切片
x=torch.tensor([[1,2,3],[4,5,6]])
print(x[:,1])
print(x[1:,1:])
print(x[1:,-1])
print(x[-1,:])
print(x.split([1,2],dim=1))#将tensor按指定数组分割,dim代表维度,这里将x的一维分割成了数量分别为1,2的两个tensor,分割的tensor越多时优势越明显
tensor([2, 5])
tensor([[5, 6]])
tensor([6])
tensor([4, 5, 6])
(tensor([[1],
[4]]), tensor([[2, 3],
[5, 6]]))
1.2.4.2 访问张量
print(x[0][2])
3
1.2.4.3 修改张量
x[1][1]=2
print(x)
tensor([[1, 2, 3],
[4, 2, 6]])
1.2.5 张量的运算
1.2.5.1 数学运算
x=torch.randn([3,5])
print(x)
print(torch.sum(x))
print(torch.sum(x,dim=1))
print(torch.prod(x))
print(torch.prod(x,dim=0))
print(torch.mean(x))
print(torch.mean(x,dim=1))
print(torch.var(x))#方差
print(torch.var(x,dim=1))
print(torch.max(x))
print(torch.max(x,dim=0))
print(torch.min(x))
print(torch.min(x,dim=1))
print(torch.abs(x))
print(torch.div(x,3))
print(torch.mul(x,2))
print(torch.pow(x,2))
tensor([[-0.5559, -1.5585, 1.9536, -1.0272, 0.7323],
[-1.4767, 0.2154, -0.1574, 0.7497, -0.9933],
[-1.4635, 0.7762, 2.2465, 1.0094, 2.4138]])
tensor(2.8645)
tensor([-0.4558, -1.6622, 4.9825])
tensor(-0.2953)
tensor([-1.2014, -0.2606, -0.6909, -0.7773, -1.7557])
tensor(0.1910)
tensor([-0.0912, -0.3324, 0.9965])
tensor(1.8597)
tensor([2.0262, 0.8119, 2.4179])
tensor(2.4138)
torch.return_types.max(
values=tensor([-0.5559, 0.7762, 2.2465, 1.0094, 2.4138]),
indices=tensor([0, 2, 2, 2, 2]))
tensor(-1.5585)
torch.return_types.min(
values=tensor([-1.5585, -1.4767, -1.4635]),
indices=tensor([1, 0, 0]))
tensor([[0.5559, 1.5585, 1.9536, 1.0272, 0.7323],
[1.4767, 0.2154, 0.1574, 0.7497, 0.9933],
[1.4635, 0.7762, 2.2465, 1.0094, 2.4138]])
tensor([[-0.1853, -0.5195, 0.6512, -0.3424, 0.2441],
[-0.4922, 0.0718, -0.0525, 0.2499, -0.3311],
[-0.4878, 0.2587, 0.7488, 0.3365, 0.8046]])
tensor([[-1.1119, -3.1171, 3.9072, -2.0544, 1.4646],
[-2.9533, 0.4309, -0.3148, 1.4994, -1.9865],
[-2.9269, 1.5525, 4.4931, 2.0187, 4.8276]])
tensor([[0.3091, 2.4290, 3.8166, 1.0552, 0.5363],
[2.1806, 0.0464, 0.0248, 0.5620, 0.9866],
[2.1417, 0.6025, 5.0469, 1.0188, 5.8265]])
1.2.5.2 逻辑运算
#返回布尔值的
y=torch.rand([3,5])
print(x.eq(y))
print(x.equal(y))
print(x.not_equal(y))
tensor([[False, False, False, False, False],
[False, False, False, False, False],
[False, False, False, False, False]])
False
tensor([[True, True, True, True, True],
[True, True, True, True, True],
[True, True, True, True, True]])
1.2.5.3 矩阵运算
x=torch.randn([3,5])
y=torch.randn([5,3])
print(x)
print(y)
#矩阵相乘
print(torch.mm(x,y))
#矩阵x向量
y=torch.randn(5)
print(torch.mv(x,y))
tensor([[-0.0435, 0.9967, -0.9208, -0.6463, -0.7509],
[-0.2110, 2.0390, 0.5550, 2.6597, -0.4820],
[ 0.0033, 0.1798, 2.3355, -1.2065, -1.3224]])
tensor([[ 0.1830, 0.6038, 0.4774],
[-0.8246, 0.2279, -0.0947],
[-2.2393, -0.3154, -0.1343],
[-0.5778, -0.4758, -0.1362],
[-0.8536, -0.7041, 2.0728]])
tensor([[ 2.2466, 1.3275, -1.4600],
[-4.0882, -0.7638, -1.7298],
[-3.5518, 0.8115, -2.9059]])
tensor([ 1.9973, 3.9096, -5.1271])
1.2.5.4 广播机制
定义:
如果PyTorch操作支持广播,则其Tensor参数可以自动扩展为相等大小(无需复制数据)
参考:pytorch0-广播机制(BROADCASTING SEMANTICS)
条件:
每个张量至少有一个维度。
当比较维度大小时,从尾维度开始向首迭代,对应的维度大小必须相等、或者其中之一为1、或者其中之一不存在。
拓展过程:
如果两个张量的维数不相等,则在维数较少的张量的维数前(首)加上1,使它们的长度相等。
对于每个维度大小,生成的维度大小是两个张量在该维度大小的最大值。
深入理解:
import torch
x=torch.tensor([[1,2,3,4,5]])
y=torch.tensor([[1],[2],[3]])
print(x.size())
print(y.size())
print(x+y)
'''
x变成
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
'''
'''
y变成:
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
'''
'''
相加变成
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
'''
运行结果:
torch.Size([1, 5])
torch.Size([3, 1])
tensor([[2, 3, 4, 5, 6],
[3, 4, 5, 6, 7],
[4, 5, 6, 7, 8]])
使用到的第三方库
其中前三个用于读取,处理数据集,os用于创建house_tiny.csv数据集,因为实在找不到。
import os
data_file = os.path.join('house_tiny.csv')
with open(data_file, 'w') as f:
f.write('NumRooms,Alley,Price\n') # Column names
f.write('NA,Pave,127500\n') # Each row represents a data example
f.write('2,NA,106000\n')
f.write('4,NA,178100\n')
f.write('NA,NA,140000\n')
波士顿房价数据集 Boston house prices dataset
Iris.csv数据集很好找
下面我将三个数据集都放在了根目录下编写代码
def read(csv_path):
df=pd.read_csv(csv_path)
print(df)
print(df.shape)
data_array=np.array(df)
print(data_array)
data_tensor=torch.tensor(data_array)
print(data_tensor)
path=['house_tiny.csv','boston_house_prices.csv','Iris.csv']
for i in path:
read(i)
很显然,创建的数据集中含有缺失值,即NA,报错如下:
TypeError: can’t convert np.ndarray of type numpy.object_. The only supported types are: float64, float32, float16, complex64, complex128, int64, int32, int16, int8, uint8, and bool.
意思是字符串不能直接转换为数组,进而也不能转换为tensor。
而后两种的数据集没有这种问题,因此不需要缺失值处理。
dataframe处理缺失值有两种方式,第一种是dropna()直接将含缺失值的行删除,另一种是fillna()用数据替换掉缺失值。
在这个问题中,我们自建的数据集中每个行都有缺失值,显然不能把每一行都删掉,所以采用第二种方法。另一个问题是字符串不能直接转换为tensor,查阅相关资料找到一种方法,一开始以为真的是字符串进到了tensor,实际上是用数字序号代替了不同的字符串,而且相同的字符串序号一致。
原文链接:pytorch图像和张量的相互转换,如何在pytorch中将字符串列表转换为张量?
总结来说,
第一步
将房间数的NaN替换为0,将小巷名的NaN转换为NoName
df['NumRooms'].fillna(0,inplace=True)
df['Alley'].fillna('NoName',inplace=True)
NumRooms Alley Price
0 0.0 Pave 127500
1 2.0 NoName 106000
2 4.0 NoName 178100
3 0.0 NoName 140000
第二步
将字符串的一列转换为序号列
labels=df['Alley'].tolist()
le=preprocessing.LabelEncoder()
targets=le.fit_transform(labels)
print(targets)
df['Alley']=targets
NumRooms Alley Price
0 0.0 1 127500
1 2.0 0 106000
2 4.0 0 178100
3 0.0 0 140000
这样就能直接转换为tensor了
全部代码:
from sklearn import preprocessing
import torch
import pandas as pd
import numpy as np
def read(csv_path):
if csv_path=='house_tiny.csv':
df = pd.read_csv('house_tiny.csv')
# print(df)
# Alley小巷 NumRooms房屋数量
df['NumRooms'].fillna(0, inplace=True)
df['Alley'].fillna('NoName', inplace=True)
# print(df)
labels = df['Alley'].tolist()
le = preprocessing.LabelEncoder()
targets = le.fit_transform(labels)
# print(targets)
df['Alley'] = targets
# print(df)
else:
df=pd.read_csv(csv_path)
#print(df)
#print(df.shape)
data_array=np.array(df)
#print(data_array)
data_tensor=torch.tensor(data_array)
print('==============',csv_path,'===============')
print(data_tensor)
print(data_tensor.shape)
path=['house_tiny.csv','boston_house_prices.csv','Iris.csv']
for i in path:
read(i)
运行结果:
============== house_tiny.csv ===============
tensor([[0.0000e+00, 1.0000e+00, 1.2750e+05],
[2.0000e+00, 0.0000e+00, 1.0600e+05],
[4.0000e+00, 0.0000e+00, 1.7810e+05],
[0.0000e+00, 0.0000e+00, 1.4000e+05]], dtype=torch.float64)
torch.Size([4, 3])
============== boston_house_prices.csv ===============
tensor([[6.3200e-03, 1.8000e+01, 2.3100e+00, …, 3.9690e+02, 4.9800e+00,
2.4000e+01],
[2.7310e-02, 0.0000e+00, 7.0700e+00, …, 3.9690e+02, 9.1400e+00,
2.1600e+01],
[2.7290e-02, 0.0000e+00, 7.0700e+00, …, 3.9283e+02, 4.0300e+00,
3.4700e+01],
…,
[6.0760e-02, 0.0000e+00, 1.1930e+01, …, 3.9690e+02, 5.6400e+00,
2.3900e+01],
[1.0959e-01, 0.0000e+00, 1.1930e+01, …, 3.9345e+02, 6.4800e+00,
2.2000e+01],
[4.7410e-02, 0.0000e+00, 1.1930e+01, …, 3.9690e+02, 7.8800e+00,
1.1900e+01]], dtype=torch.float64)
torch.Size([506, 14])
============== Iris.csv ===============
tensor([[5.1000, 3.5000, 1.4000, 0.2000, 1.0000],
[4.9000, 3.0000, 1.4000, 0.2000, 1.0000],
[4.7000, 3.2000, 1.3000, 0.2000, 1.0000],
[6.3000, 2.5000, 5.0000, 1.9000, 3.0000],
…,
[6.5000, 3.0000, 5.2000, 2.0000, 3.0000],
[6.2000, 3.4000, 5.4000, 2.3000, 3.0000],
[5.9000, 3.0000, 5.1000, 1.8000, 3.0000]], dtype=torch.float64)
torch.Size([150, 5])
总结:
学习了pytorch里的tensor相关函数,并且简单学习了数据的预处理,对tensor类型的数据有了更为深刻的理解,对大数据处理的预处理过程更加熟悉了。