本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.
一、张量
张量表示由一个数值组成的数组,这个数组可能有多个维度
import torch
x = torch.arange(15) x # tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
1,shape
shape属性可以访问 张量的形状
x.shape # torch.Size([15])
2,numel()
numel()函数可以访问 张量中元素的总数
x.numel() # 15
3,reshape()
可以调用reshape()函数, 改变一个张量的形状而不改变元素数量和元素值
x = x.reshape(3,5) x """ tensor([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14]]) """
4,使用全0、全1、其他常量或者从特定分布中随机采样的数字
torch.zeros((2, 3, 4)) """ tensor([[[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]], [[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]]]) """
torch.ones((2, 3, 4)) """ 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.]]]) """
torch.ones((3,4,5))*8 """ tensor([[[8., 8., 8., 8., 8.], [8., 8., 8., 8., 8.], [8., 8., 8., 8., 8.], [8., 8., 8., 8., 8.]], [[8., 8., 8., 8., 8.], [8., 8., 8., 8., 8.], [8., 8., 8., 8., 8.], [8., 8., 8., 8., 8.]], [[8., 8., 8., 8., 8.], [8., 8., 8., 8., 8.], [8., 8., 8., 8., 8.], [8., 8., 8., 8., 8.]]]) """
torch.randn(3, 4) """ tensor([[-2.9078, 0.4283, -0.7296, 0.0575], [-1.3947, 0.5494, 0.9782, -0.3510], [-0.2191, -3.2434, -1.6111, 2.0091]]) """
5,为所需张量中的每个元素赋予确定值
通过提供包含数值的 Python 列表(或嵌套列表)来为所需张量中的每个元素赋予确定值
torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) """ tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) """
6,标准算术运算
+、-、*、/、**、^
a1 = torch.tensor([1,2,4,8],dtype=torch.float32) a2 = torch.tensor([2,2,2,2]) a1 + a2, a1 - a2, a1 * a2, a1 / a2, a1 ** a2 , torch.exp(a2) """ (tensor([ 3., 4., 6., 10.]), tensor([-1., 0., 2., 6.]), tensor([ 2., 4., 8., 16.]), tensor([0.5000, 1.0000, 2.0000, 4.0000]), tensor([ 1., 4., 16., 64.]), tensor([7.3891, 7.3891, 7.3891, 7.3891])) """
7,cat()
可以调用cat()函数, 把多个张量连结(concatenate)在一起
dim=0张量 列 连接
dim=1张量 行 连接
X = torch.arange(12, dtype=torch.float32).reshape((3, 4)) Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) X, Y, torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1) """ (tensor([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.]]), tensor([[2., 1., 4., 3.], [1., 2., 3., 4.], [4., 3., 2., 1.]]), tensor([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [ 2., 1., 4., 3.], [ 1., 2., 3., 4.], [ 4., 3., 2., 1.]]), tensor([[ 0., 1., 2., 3., 2., 1., 4., 3.], [ 4., 5., 6., 7., 1., 2., 3., 4.], [ 8., 9., 10., 11., 4., 3., 2., 1.]])) """
8,sum()
对张量中的所有元素进行求和,产生一个只有一个元素的张量
X = torch.arange(12, dtype=torch.float32).reshape((3, 4)) X, X.sum() """ (tensor([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.]]), tensor(66.)) """
9,广播机制
即使形状不同,仍然可以通过调用广播机制(broadcasting mechanism)来执行按元素操作
例如:a和b形状不同,相加不报错,为啥捏?系统会通过广播机制将a和b自动扩充,进行相加
a = torch.arange(3).reshape((3, 1)) b = torch.arange(2).reshape((1, 2)) a, b, a + b """ (tensor([[0], [1], [2]]), tensor([[0, 1]]), tensor([[0, 1], [1, 2], [2, 3]])) """
10,内存分配
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) print(id(Y)) Y = Y + X print(id(Y)) """ 1426209183608 1426209185448 """
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) Z = torch.zeros_like(Y) print(id(Z)) Z = X + Y print(id(Z)) """ 1426207453976 1426198282056 """
如果在后续计算中没有重复使用 X,可以使用 X[:] = X + Y
或 X += Y
来减少操作的内存开销
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) print(id(Y)) Y += X print(id(Y)) """ 1426209185608 1426209185608 """
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) Z = torch.zeros_like(Y) print(id(Z)) Z[:] = X + Y print(id(Z)) """ 1426198282056 1426198282056 """
11,NumPy张量
X = torch.arange(12, dtype=torch.float32).reshape((3, 4)) A = X.numpy() B = torch.tensor(A) type(X), type(A), type(B) """ (torch.Tensor, numpy.ndarray, torch.Tensor) """
12,Python 标量
a = torch.tensor([3.5]) a, a.item(), float(a), int(a) """ (tensor([3.5000]), 3.5, 3.5, 3) """
二、数据预处理
1,创建数据集
首先创建一个人工数据集,并存储在CSV(逗号分隔值)文件 ../data/beyond.csv
中
import os os.makedirs(os.path.join('..', 'data'), exist_ok=True) data_file = os.path.join('..', 'data', 'house_tiny.csv') with open(data_file, 'w') as f: f.write('NumRooms,Alley,Price ') # 列名 f.write('NA,Pave,127500 ') # 每行表示一个数据样本 f.write('2,NA,106000 ') f.write('4,NA,178100 ') f.write('NA,NA,140000 ')
房间数量(“NumRooms”)、巷子类型(“Alley”)、房屋价格(“Price”)
2,加载原始数据集
导入pandas包并调用read_csv函数
“NaN”项代表缺失值
import pandas as pd data = pd.read_csv(data_file) print(data) """ NumRooms Alley Price 0 NaN Pave 127500 1 2.0 NaN 106000 2 4.0 NaN 178100 3 NaN NaN 140000 """
3,处理缺失值
为了处理缺失的数据,典型的方法包括 插值法 和 删除法
插值法用一个替代值弥补缺失值
删除法则直接忽略缺失值
在这里,考虑 插值法
通过位置索引 iloc
,将data分成inputs和outputs, 其中前者为data的前两列,而后者为data的最后一列
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2] inputs, outputs """ ( NumRooms Alley 0 NaN Pave 1 2.0 NaN 2 4.0 NaN 3 NaN NaN, 0 127500 1 106000 2 178100 3 140000 Name: Price, dtype: int64) """
对于inputs中缺少的数值,用同一列的均值替换“NaN”项
inputs = inputs.fillna(inputs.mean()) print(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 """
4,转换为张量格式
import torch x, y = torch.tensor(inputs.values), torch.tensor(outputs.values) x, y """ (tensor([[3., 1., 0.], [2., 0., 1.], [4., 0., 1.], [3., 0., 1.]], dtype=torch.float64), tensor([127500, 106000, 178100, 140000])) """
三、线性代数
1,标量
标量由只有一个元素的张量表示
from mxnet import np, npx import torch npx.set_np() x = np.array(3.0) y = np.array(2.0) x + y, x * y, x / y, x ** y """ (array(5.), array(6.), array(1.5), array(9.)) """
2,向量
可以将向量视为标量值组成的列表,这些标量值称为向量的元素(element)或分量(component)
通过一维张量处理向量
x = torch.arange(4) x """ x = torch.arange(4) x 1 x = torch.arange(4) 2 x tensor([0, 1, 2, 3]) """
使用下标来引用向量的任一元素
x[2] """ tensor(2) """
2.1,len()
通过调用Python的内置len()函数来访问张量的长度
len(x) """ 4 """
2.2,shape
当用张量表示一个向量(只有一个轴)时,可以通过.shape属性访问向量的长度
形状(shape)是一个元素组,列出了张量沿每个轴的长度(维数)
对于只有一个轴的张量,形状只有一个元素。
x.shape """ torch.Size([4]) """
向量或轴的维度被用来表示向量或轴的长度,即向量或轴的元素数量。
然而,张量的维度用来表示张量具有的轴数。
在这个意义上,张量的某个轴的维数就是这个轴的长度。
3,矩阵
矩阵,在代码中表示为具有两个轴的张量。
指定两个分量和来创建一个形状为m×n的矩阵
A = torch.arange(20).reshape(5, 4) A """ tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19]]) """
矩阵的转置T
A.T """ tensor([[ 0, 4, 8, 12, 16], [ 1, 5, 9, 13, 17], [ 2, 6, 10, 14, 18], [ 3, 7, 11, 15, 19]]) """
4,张量
向量是标量的推广,矩阵是向量的推广
向量是一阶张量,矩阵是二阶张量
张量用特殊字体的大写字母表示(例如:X、Y、Z)
X = torch.arange(24).reshape(2, 3, 4) X """ tensor([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]]) """
5,张量算法的基本性质
将两个相同形状的矩阵相加,会在这两个矩阵上执行元素加法
A = torch.arange(20, dtype=torch.float32).reshape(5, 4) B = A.clone() # 通过分配新内存,将A的一个副本分配给B A, A + B """ (tensor([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [12., 13., 14., 15.], [16., 17., 18., 19.]]), tensor([[ 0., 2., 4., 6.], [ 8., 10., 12., 14.], [16., 18., 20., 22.], [24., 26., 28., 30.], [32., 34., 36., 38.]])) """
两个矩阵的按元素乘法称为Hadamard积(Hadamard product)
即,对应元素相乘
A * B """ tensor([[ 0., 1., 4., 9.], [ 16., 25., 36., 49.], [ 64., 81., 100., 121.], [144., 169., 196., 225.], [256., 289., 324., 361.]]) """
将张量乘以或加上一个标量不会改变张量的形状,其中张量的每个元素都将与标量相加或相乘。
a = 2 X = torch.arange(24).reshape(2, 3, 4) X, a + X, (a * X).shape """ (tensor([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]]), tensor([[[ 2, 3, 4, 5], [ 6, 7, 8, 9], [10, 11, 12, 13]], [[14, 15, 16, 17], [18, 19, 20, 21], [22, 23, 24, 25]]]), torch.Size([2, 3, 4])) """
6,降维
6.1,sum()
计算任意张量元素的和
x = torch.arange(5, dtype=torch.float32) x, x.sum() """ (tensor([0., 1., 2., 3., 4.]), tensor(10.)) """
也可以表示任意形状张量的元素和
A = torch.arange(6).reshape(2, 3) A, A.shape, A.sum() """ (tensor([[0, 1, 2], [3, 4, 5]]), torch.Size([2, 3]), tensor(15)) """
默认情况下,调用求和函数会沿所有的轴降低张量的维度,使它变为一个标量
也可以指定张量沿哪一个轴来通过求和降低维度
axis=0,同一列所在的所有行元素相加
axis=1,同一行所在的所有列元素相加
A_sum_axis0 = A.sum(axis)#同一列所在的所有行元素相加 A_sum_axis0, A_sum_axis0.shape """ (tensor([3, 5, 7]), torch.Size([3])) """
指定axis=1将通过汇总所有列的元素降维(轴1)
因此,输入轴1的维数在输出形状中消失
A_sum_axis1 = A.sum(axis=1) A_sum_axis1, A_sum_axis1.shape """ (tensor([ 3, 12]), torch.Size([2])) """
沿着行和列对矩阵求和,等价于对矩阵的所有元素进行求和
A.sum(axis=[0, 1]), A.sum() """ (tensor(15), tensor(15)) """
6.2,mean()
总和除以元素总数来计算平均值
也可以调用函数来计算任意形状张量的平均值
A = torch.arange(6,dtype=torch.float32).reshape(2, 3) A, A.mean(), A.sum() / A.numel() """ (tensor([[0., 1., 2.], [3., 4., 5.]]), tensor(2.5000), tensor(2.5000)) """
计算平均值的函数也可以沿指定轴降低张量的维度
A.mean(axis=0), A.sum(axis=0) / A.shape[0] """ (tensor([1.5000, 2.5000, 3.5000]), tensor([1.5000, 2.5000, 3.5000])) """
6.3,非降维求和
调用函数来计算总和或均值时保持轴数不变会很有用
也就是 keepdims=True
,不会因为 axis
而把某个维度给去掉,而是置为一
A = torch.arange(6,dtype=torch.float32).reshape(2, 3) sum_A = A.sum(axis=1, keepdims=True) A, sum_A """ (tensor([[0., 1., 2.], [3., 4., 5.]]), tensor([[ 3.], [12.]])) """
keepdims默认为False,axis=1
a = torch.ones((2,5,4)) a.shape # torch.Size([2, 5, 4]) a.sum(axis=1).shape # torch.Size([2, 4]) a.sum(axis=1) """ tensor([[5., 5., 5., 5.], [5., 5., 5., 5.]]) """ a """ 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., 1., 1.], [1., 1., 1., 1.], [1., 1., 1., 1.]]]) """
keepdims默认为True,axis=1
a.sum(axis=1,keepdims=True).shape # torch.Size([2, 1, 4]) a.sum(axis=1,keepdims=True) """ tensor([[[5., 5., 5., 5.]], [[5., 5., 5., 5.]]]) """
keepdims默认为False,axis=[0,2]
a.sum(axis=[0,2]).shape # torch.Size([5]) a.sum(axis=[0,2]) # tensor([8., 8., 8., 8., 8.])
keepdims默认为True,axis=[0,2]
a.sum(axis=[0,2],keepdims=True).shape # torch.Size([1, 5, 1]) a.sum(axis=[0,2],keepdims=True) """ tensor([[[8.], [8.], [8.], [8.], [8.]]]) """
由于sum_A在对每行进行求和后仍保持两个轴,我们可以通过广播将A除以sum_A
A / sum_A """ tensor([[0.0000, 0.3333, 0.6667], [0.2500, 0.3333, 0.4167]]) """
6.4,cumsum()
如果想沿某个轴计算A元素的累积总和, 比如axis=0(按行计算)
可以调用cumsum函数。 此函数不会沿任何轴降低输入张量的维度
A = torch.arange(6,dtype=torch.float32).reshape(2, 3) A, A.cumsum(axis=0) """ (tensor([[0., 1., 2.], [3., 4., 5.]]), tensor([[0., 1., 2.], [3., 5., 7.]])) """
7,点积
相同位置的按元素乘积的和
按元素乘法,然后进行求和来表示两个向量的点积
x = torch.arange(4, dtype=torch.float32) y = torch.tensor([2.0, 1, 4, 3]) x, y, torch.dot(x, y), torch.sum(x * y) """ (tensor([0., 1., 2., 3.]), tensor([2., 1., 4., 3.]), tensor(18.), tensor(18.)) """
8,向量积
矩阵A和向量x调用 torch.mv(A, x)
时,会执行矩阵-向量积
A的列维数(沿轴1的长度)必须与x的维数(其长度)相同
A = torch.arange(20, dtype=torch.float32).reshape(5, 4) x = torch.arange(4, dtype=torch.float32) A, x, A.shape, x.shape, torch.mv(A, x) """ (tensor([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [12., 13., 14., 15.], [16., 17., 18., 19.]]), tensor([0., 1., 2., 3.]), torch.Size([5, 4]), torch.Size([4]), tensor([ 14., 38., 62., 86., 110.])) """
9,矩阵乘法
矩阵A和矩阵B调用 torch.mm(A, B)
时,会执行矩阵乘法操作
前行成后列
A是一个5行4列的矩阵,B是一个4行3列的矩阵,两者相乘后,得到了一个5行3列的矩阵
A = torch.arange(20, dtype=torch.float32).reshape(5, 4) B = torch.tensor([[2,3,4],[1,5,9],[7,5,3],[4,5,6]],dtype=torch.float32) A, B, torch.mm(A, B) """ (tensor([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [12., 13., 14., 15.], [16., 17., 18., 19.]]), tensor([[2., 3., 4.], [1., 5., 9.], [7., 5., 3.], [4., 5., 6.]]), tensor([[ 27., 30., 33.], [ 83., 102., 121.], [139., 174., 209.], [195., 246., 297.], [251., 318., 385.]])) """
10,范数
一个向量的范数告诉我们一个向量有多大,这里考虑的大小(size)概念不涉及维度,而是分量的大小。
有Lp范数衍生出了L1、L2等范数,这些都是针对的 向量
10.1,L1范数
L1范数:向量元素的绝对值之和
先通过绝对值函数,然后按元素求和
q = torch.tensor([10.0,14.0]) q, torch.abs(q).sum() """ (tensor([10., 14.]), tensor(24.)) """
10.2,L2范数
L2范数:向量元素平方和的平方根
norm()
函数进行求解
q = torch.tensor([3.0,4.0]) q, torch.norm(q) """ (tensor([3., 4.]), tensor(5.)) """
10.3,Frobenius范数
Frobenius范数: 矩阵 元素平方和的平方根
norm()函数进行求解
Frobenius范数满足向量范数的所有性质,它就像是 矩阵形向量 的L2范数
q = torch.tensor([[1.0,2.0],[3.0,4.0]]) q ,torch.norm(q) """ (tensor([[1., 2.], [3., 4.]]), tensor(5.4772)) """
在深度学习中,经常试图解决优化问题: 最大化分配给观测数据的概率; 最小化预测和真实观测之间的距离。
用向量表示物品(如单词、产品或新闻文章),以便最小化相似项目之间的距离,最大化不同项目之间的距离。
目标,或许是深度学习算法最重要的组成部分(除了数据),通常被表达为范数。
Be First to Comment