- 1.线性代数引入:在线性代数中,常见的基本数学单元是:行列式、向量、矩阵。
- 行列式:实质是指一个实数,它实际上是一种计算手段;
- 向量:从表示形式上看有行向量和列向量两种(可以通过转置相互转换),简单点可以理解为一组数的有序排列(类似于各种编程语言中的列表,不过在这个列表中只能存放数字)。
- 矩阵:是指一个按照长方形阵列排列的实数或虚数集合。可以理解为是一张表格。
- 2.张量:在计算机中,只有线性代数中的行列式,向量,矩阵是不够的,因为实际情况中我们会遇到超过维度数为2的数学单元,所以引入张量;个人理解:张量就是一个名字,但他可以表示从0维到n维的数学数据。
- 0维张量:就是标量,在深度学习分类任务中,可用表示类别
- 1维张量:也就是向量,可抽象的表示一个数据,向量中的每一个元素就是这个数据抽象出来的特征。
- 2维张量:矩阵,可以用来表示黑白图像或者灰度图像。
- 3维张量:可以用来表示单张彩色图片,在二维张量上扩张了通道这一维度(注意:通道数不一定是3,例如在遥感图像中可能有更多的维度);虽然3维张量也可以表示一个批次的灰度图像,但在实际的应用中,我们经常将一个批次的灰度图像也用一个批次的彩色图像表示,不过在通道数上是1而不是3.
- (width, height, channel) = 3D;
- 4维张量:可以理解为单个的视频,亦或者是一个批次的3维张量。
- (batch_size, width, height, channel) = 4D
- 3.tensor基本操作:
- 1)创建:
- a.随机初始化:
- torch.rand()方法
import torch a = torch.rand(5, 6, 3) # 创建一个5通道,6行,3列的张量 print(a) # 打印a print(a.shape) # 或print(a.size())
输出:其打印的tensor中的每一个值都是从区间[0, 1]的均匀分布中抽取的随机数
tensor([[[0.2512, 0.0754, 0.5254], [0.7569, 0.5339, 0.1608], [0.7013, 0.6424, 0.5533], [0.3275, 0.2094, 0.8940], [0.0358, 0.6873, 0.3650], [0.1200, 0.9824, 0.9345]], [[0.5813, 0.3151, 0.3075], [0.5461, 0.9380, 0.4024], [0.4387, 0.1736, 0.6139], [0.5841, 0.1288, 0.6711], [0.0482, 0.6064, 0.3039], [0.6604, 0.1150, 0.8711]], [[0.4828, 0.6829, 0.2325], [0.3047, 0.3977, 0.6882], [0.5027, 0.0049, 0.3798], [0.8563, 0.4973, 0.6633], [0.8528, 0.3553, 0.9099], [0.3714, 0.1334, 0.8464]], [[0.8258, 0.4027, 0.1122], [0.0456, 0.1765, 0.1347], [0.4605, 0.1179, 0.3105], [0.7372, 0.0663, 0.2409], [0.1751, 0.2907, 0.9303], [0.6384, 0.1184, 0.7696]], [[0.7160, 0.2935, 0.2707], [0.0643, 0.4972, 0.0936], [0.3103, 0.7884, 0.0406], [0.1640, 0.5265, 0.9636], [0.8147, 0.0701, 0.1994], [0.5739, 0.4212, 0.7736]]]) torch.Size([5, 6, 3])
- torch.randn()方法
import torch b = torch.randn(6, 3) print(b) print(b.shape) # 或print(b.size())
输出:其打印的tensor中的每一个数值都服从标准正态分布。
tensor([[-0.5691, -0.1960, 0.0624], [ 0.3880, -0.5484, 0.0718], [-0.1414, -0.4525, -0.1813], [ 3.0790, 0.8768, -2.5193], [ 1.2124, 0.6179, -1.0690], [ 0.7950, -0.1661, 0.4205]]) torch.Size([6, 3])
- torch.rand()方法
- b.全零矩阵构建:torch.zeros()方法:
import torch c = torch.zeros(5, 5, dtype=torch.float32) # dtype是指tensor中数值的类型 print(c) print(c.shape) # 或print(c.size())
输出:
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., 0.]]) torch.Size([5, 5])
- dtype说明:pytorch中一共有8种不同的数据类型
Data type dtype Tensor types 32-bit floating point torch.float32 or torch.float torch.*.FloatTensor 64-bit floating point torch.float64 or torch.double torch.*.DoubleTensor 16-bit floating point torch.float16 or torch.half torch.*.HalfTensor 8-bit integer (unsigned) torch.uint8 torch.*.ByteTensor 8-bit integer (signed) torch.int8 torch.*.CharTensor 16-bit integer (signed) torch.int16 or torch.short torch.*.ShortTensor 32-bit integer (signed) torch.int32 or torch.int torch.*.IntTensor 64-bit integer (signed) torch.int64 or torch.long torch.*.LongTensor - c.全一矩阵构建:torch.ones()方法:
import torch a = torch.ones(3, 2) print(a) print(a.shape) # 或print(a.size())
输出:
tensor([[1., 1.], [1., 1.], [1., 1.]]) torch.Size([3, 2])
- d.单位矩阵构建:torch.eye()方法:
import torch a = torch.eye(3, 3) print(a) print(a.shape) # 或print(a.size())
输出:
tensor([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]) torch.Size([3, 3])
注意:该方法并未要求张量形状一定为方阵,如:
import torch a = torch.eye(3, 5) print(a) print(a.shape) # 或print(a.size())
输出则为:
tensor([[1., 0., 0., 0., 0.], [0., 1., 0., 0., 0.], [0., 0., 1., 0., 0.]]) torch.Size([3, 5])
- e.正态分布矩阵:torch.normal(mean, std)方法(均值为mean,标准差为std):
import torch a = torch.normal(mean=0, std=1, size=(3, 3)) print(a) print(a.shape) # 或print(a.size())
输出:
tensor([[ 1.7324, -0.9390, 0.7721], [ 0.0488, 1.0510, 0.7274], [ 0.5267, 0.1345, -1.1278]]) torch.Size([3, 3])
- f.创建同型的矩阵:基于一个已经存在的张量数据,创建一个和他形状相同的张量数据;方法:_like(已有张量)
import torch a = torch.ones(size=(5, 5)) print(f"a:{a}") print(f"a的形状:{a.shape}") b = torch.zeros_like(a) print(f"b:{b}") print(f"b的形状:{b.shape}")
输出:
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.]]) a的形状:torch.Size([5, 5]) b: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., 0.]]) b的形状:torch.Size([5, 5])
- g.有序排列矩阵创建:torch.arange(s,e,step)方法:
import torch a = torch.arange(start=0, end=10, step=1) print(f"a:{a}") print(f"a的形状:{a.shape}")
输出:
a:tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) a的形状:torch.Size([10])
注意:该方法中生成张量并不包含最后结束的数值。如果要改变张量的形状,可以用resize()方法或者reshape()方法,如:
import torch a = torch.arange(start=0, end=10, step=1) print(f"a:{a}") print(f"a的形状:{a.shape}") b = a.resize(2, 5) print(f"b:{b}") print(f"b的形状:{b.shape}") c = a.reshape(5, 2) print(f"c:{c}") print(f"c的形状:{c.shape}")
输出:
a:tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) a的形状:torch.Size([10]) b:tensor([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) b的形状:torch.Size([2, 5]) c:tensor([[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]) c的形状:torch.Size([5, 2])
- a.随机初始化:
- 2)基本操作:
- 加减乘除:太简单了,小学数学水平,最多考虑一下数据的类型,此处不再赘述。
- 索引:此处参考numpy,注意:索引出来的结果是原数据本身,修改索引出来的值就是修改原数据;当然,可以换一种思路,将原数据进行拷贝,方法:clone()
import torch a = torch.arange(start=0, end=10, step=1).reshape(2, 5) print(f"a:{a}") print(f"a的形状:{a.shape}") b = a[:, 2:4] print(f"b:{b}") print(f"b的形状:{b.shape}") b[1][1] = 0 print(f"b:{b}") print(f"a:{a}")
输出:
a:tensor([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) a的形状:torch.Size([2, 5]) b:tensor([[2, 3], [7, 8]]) b的形状:torch.Size([2, 2]) b:tensor([[2, 3], [7, 0]]) a:tensor([[0, 1, 2, 3, 4], [5, 6, 7, 0, 9]])
clone()方法:
import torch a = torch.arange(start=0, end=10, step=1).reshape(2, 5) print(f"a:{a}") print(f"a的形状:{a.shape}") b = a[:, 2:4] c = b.clone() print(f"c:{c}") print(f"c的形状:{c.shape}") c[1][1] = 0 print(f"c:{c}") print(f"a:{a}")
输出:
a:tensor([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) a的形状:torch.Size([2, 5]) c:tensor([[2, 3], [7, 8]]) c的形状:torch.Size([2, 2]) c:tensor([[2, 3], [7, 0]]) a:tensor([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])
- 维度变换:
- reshape()方法:注意:此方法共享内存
import torch a = torch.arange(start=0, end=10, step=1) print(f"a:{a}") print(f"a的形状:{a.shape}") b = a.reshape(5, 2) b[1][1] = 9 print(f"b:{b}") print(f"b的形状:{b.shape}") print(f"a:{a}") print(f"a的形状:{a.shape}")
输出:
a:tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) a的形状:torch.Size([10]) b:tensor([[0, 1], [2, 9], [4, 5], [6, 7], [8, 9]]) b的形状:torch.Size([5, 2]) a:tensor([0, 1, 2, 9, 4, 5, 6, 7, 8, 9]) a的形状:torch.Size([10])
- view()方法:注意,此方法共享内存
import torch a = torch.arange(start=0, end=10, step=1).reshape(2, 5) print(f"a:{a}") print(f"a的形状:{a.shape}") b = a.view(5, 2) b[1][1] = 9 print(f"b:{b}") print(f"b的形状:{b.shape}") print(f"a:{a}") print(f"a的形状:{a.shape}")
输出:
a:tensor([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) a的形状:torch.Size([2, 5]) b:tensor([[0, 1], [2, 9], [4, 5], [6, 7], [8, 9]]) b的形状:torch.Size([5, 2]) a:tensor([[0, 1, 2, 9, 4], [5, 6, 7, 8, 9]]) a的形状:torch.Size([2, 5])
若要不改变原数据,可以将原数据先clone()再进行相应维度转换。
- reshape()方法:注意:此方法共享内存
- 广播机制:抱歉,强迫症犯了,虽然大概理解这个方法的具体操作,但基于数学的严谨性,我一般不用这个(个人建议初学者一般也不要用这个,有坑),有需求的请看吴恩达老师的机器学习的相关课程,里面有详细的讲解。
- 1)创建:
- 4.pytorch中的自动求导
- 1)深度学习模型在训练过程中,需要构建计算图(实际上就是各变量之间的函数关系),计算图的最后输出是一个损失函数的标量值,从标量值反推计算图权重张量的梯度,这个过程被称为自动求导。
- 2)神经网络的核心是autograd包,它为张量上的所有操作提供了自动求导机制,支持对任意计算图的自动梯度计算。可以在创建tensor时设置requires_grad = True来支持梯度计算,或者后续使用.requires_grad_(True)来设置。
- 3)例子:创建一个简单的计算图:Y = WX+b
- 其中:输入:X,输出:Y,理想输出结果:Z
- 代码:
import torch x = torch.arange(0, 5, dtype=torch.float32) z = torch.ones(3, dtype=torch.float32) w = torch.randn(5, 3, requires_grad=True) # 使用requires_grad=True来追踪计算历史 b = torch.randn(3, requires_grad=True) y = torch.matmul(x, w)+b # x 和 w 矩阵相乘,再加上 bias b loss = torch.nn.functional.binary_cross_entropy_with_logits(y, z) print('Gradient function for y =', y.grad_fn) # 若上面未设置requires_grad=True,此处会报错 print('Gradient function for loss =', loss.grad_fn) loss.backward() print(w.grad) print(b.grad)
输出:
Gradient function for y = <AddBackward0 object at 0x0000027E40BBFFC8> Gradient function for loss = <BinaryCrossEntropyWithLogitsBackward0 object at 0x0000027E40BBFFC8> tensor([[-0.0000, -0.0000, -0.0000], [-0.0058, -0.0826, -0.3307], [-0.0116, -0.1653, -0.6614], [-0.0173, -0.2479, -0.9922], [-0.0231, -0.3305, -1.3229]]) tensor([-0.0058, -0.0826, -0.3307])
Pytorch系列 1.张量基础知识
最新推荐文章于 2024-06-04 23:32:03 发布