动手学pytorch之tensor数据(一)

tensor数据类型

Tensor在使用时可以有不同的数据类型,官方给出了 7种CPU Tensor类型与8种GPU Tensor类型。16位半精度浮点是专为GPU模型设计的,以尽可能地节省GPU显存占用,但这种节省显存空间的方式也缩小了所能表达数据的大小。PyTorch中默认的数据类型是 torch.FloatTensor,即torch.Tensor等同于torch.FloatTensor。
在这里插入图片描述
PyTorch可以通过set_default_tensor_type函数设置默认使用的Tensor 类型,在局部使用完后如果需要其他类型,则还需要重新设置回所需的 类型。

torch.set_default_tensor_type('torch.DoubleTensor')

类型转换

对于Tensor之间的类型转换,可以通过type(new_type)、type_as()、 int()等多种方式进行操作,尤其是type_as()函数,在后续的模型学习中 可以看到,我们想保持Tensor之间的类型一致,只需要使用type_as()即 可,并不需要明确具体是哪种类型。下面分别举例讲解这几种方法的使 用方式。

# 创建新Tensor,默认类型为torch.FloatTensor 
>>> a = torch.Tensor(2, 2) 
>>> a tensor(1.00000e-36 * 
		[[-4.0315, 0.0000], 
		[ 0.0700, 0.0000]]) 
# 使用int()、float()、double()等直接进行数据类型转换 
>>> b = a.double() 
>>> b tensor(1.00000e-36 * 
		[[-4.0315, 0.0000], 
		[ 0.0700, 0.0000]], dtype=torch.float64) 
# 使用type()函数 >>> c = a.type(torch.DoubleTensor) 
>>> c 
tensor(1.00000e-36 * 
				[[-4.0315, 0.0000], 
				[ 0.0700, 0.0000]], dtype=torch.float64) 
# 使用type_as()函数 
>>> d = a.type_as(b)
>>> d
 tensor(1.00000e-36 *
   [[-4.0315, 0.0000],
    [ 0.0700, 0.0000]], dtype=torch.float64)

Tensor的创建与维度查看

Tensor有多种创建方法,如基础的构造函数Tensor(),还有多种与 NumPy十分类似的方法,如ones()、eye()、zeros()和randn()等,图2.1列 举了常见的Tensor创建方法。
在这里插入图片描述

# 最基础的Tensor()函数创建方法,参数为Tensor的每一维大小 
>>> a=torch.Tensor(2,2) 
>>> a 
tensor(1.00000e-18 *
				 [[-8.2390, 0.0000],
				[ 0.0000, 0.0000]])
>>> b = torch.DoubleTensor(2,2) 
>>> b 
tensor(1.00000e-310 *
		[[ 0.0000, 0.0000], 
		[ 6.9452, 0.0000]], dtype=torch.float64)
# 使用Python的list序列进行创建 
>>> c = torch.Tensor([[1, 2], [3, 4]]) 
>>> c 
tensor([[ 1., 2.], [ 3., 4.]]) 
# 使用zeros()函数,所有元素均为0 
>>> d = torch.zeros(2, 2) 
>>> d
tensor([[ 0., 0.], [ 0., 0.]]) 
# 使用ones()函数,所有元素均为1 >>> e = torch.ones(2, 2) 
>>> e 
tensor([[ 1., 1.], [ 1., 1.]]) 
# 使用eye()函数,对角线元素为1,不要求行列数相同,生成二维矩阵 

>>> f = torch.eye(2, 2) 
>>> f
 tensor([[ 1., 0.], [ 0., 1.]]) 
# 使用randn()函数,生成随机数矩阵
>>> g = torch.randn(2, 2)
>>> g
 tensor([[-0.3979, 0.2728], [ 1.4558, -0.4451]])
# 使用arange(start, end, step)函数,表示从start到end,间距为step,一维向量 
>>> h = torch.arange(1, 6, 2) 
>>> h
 tensor([ 1., 3., 5.]) 
# 使用linspace(start, end, steps)函数,表示从start到end,一共steps份,一维向量 
>>> i = torch.linspace(1, 6, 2) 
>>> i
 tensor([ 1., 6.]) .
# 使用randperm(num)函数,生成长度为num的随机排列向量
>>> j = torch.randperm(4) 
>>> j 
tensor([ 1, 2, 0, 3]) 
# PyTorch 0.4中增加了torch.tensor()方法,参数可以为Python的list、NumPy的ndarray等 
>>> k = torch.tensor([1, 2, 3]) 
			tensor([ 1, 2, 3])

对于Tensor的维度,可使用Tensor.shape或者size()函数查看每一维 的大小,两者等价。

>>> a=torch.randn(2,2)
# 使用shape查看Tensor维度 
>>> a.shape
torch.Size([2, 2]) 
# 使用size()函数查看Tensor维度 torch.Size([2, 2])
 >>> a.size() 
 torch.Size([2, 2])

查看Tensor中的元素总个数,可使用Tensor.numel()或者 Tensor.nelement()函数,两者等价。

# 查看Tensor中总的元素个数 
>> a.numel() 
4
>>> a.nelement() 
4

Tensor的组合与分块

组合与分块是将Tensor相互叠加或者分开,是十分常用的两个功 能,PyTorch提供了多种操作函数,如图2.2所示。
在这里插入图片描述
组合操作是指将不同的Tensor叠加起来,主要有torch.cat()和 torch.stack()两个函数。cat即concatenate的意思,是指沿着已有的数据的 某一维度进行拼接,操作后数据的总维数不变,在进行拼接时,除了拼 接的维度之外,其他维度必须相同。而torch.stack()函数指新增维度,并 按照指定的维度进行叠加,具体示例如下:

# 创建两个2×2的Tensor
>>> a=torch.Tensor([[1,2],[3,4]]) 
>>> a tensor([[ 1., 2.], [ 3., 4.]]) 
>>> b = torch.Tensor([[5,6], [7,8]]) 
>>> b
 tensor([[ 5., 6.], [ 7., 8.]]) 
# 以第一维进行拼接,则变成4×2的矩阵 
>>> torch.cat([a,b], 0) 
tensor([[ 1., 2.], [ 3., 4.], [ 5., 6.], [ 7., 8.]]) 

# 以第二维进行拼接,则变成24的矩阵 
>>> torch.cat([a,b], 1) 
tensor([[ 1., 2., 5., 6.], [ 3., 4., 7., 8.]]) 
# 以第0维进行stack,叠加的基本单位为序列本身,即a与b,因此输出[a, b],输出维度为2×2×2 
>>> torch.stack([a,b], 0) 
tensor([[[ 1., 2.], [ 3., 4.]], [[ 5., 6.], [ 7., 8.]]]) 

# 以第1维进行stack,叠加的基本单位为每一行,输出维度为2×2×2
>>> torch.stack([a,b], 1) 
tensor([[[ 1., 2.], [ 5., 6.]], [[ 3., 4.], [ 7., 8.]]]) 

# 以第2维进行stack,叠加的基本单位为每一行的每一个元素,输出维度为2×2×2 
>>> torch.stack([a,b], 2) 
tensor([[[ 1., 5.], [ 2., 6.]], [[ 3., 7.], [ 4., 8.]]])

分块则是与组合相反的操作,指将Tensor分割成不同的子Tensor, 主要有torch.chunk()与torch.split()两个函数,前者需要指定分块的数量, 而后者则需要指定每一块的大小,以整型或者list来表示。具体示例如 下:

>>> a=torch.Tensor([[1,2,3],[4,5,6]]) 
>>> a tensor([[ 1., 2., 3.], [ 4., 5., 6.]]) 
# 使用chunk,沿着第0维进行分块,一共分两块,因此分割成两个1×3的Tensor 

>>> torch.chunk(a, 2, 0) 
(tensor([[ 1., 2., 3.]]), tensor([[ 4., 5., 6.]])) 
# 沿着第1维进行分块,因此分割成两个Tensor,当不能整除时,最后一个的维数会小于前面的因此第一个Tensor为2×2,第二个为2×1 

>>> torch.chunk(a, 2, 1) 
(tensor([[ 1., 2.], [ 4., 5.]]), tensor([[ 3.], [ 6.]])) # 使用split,沿着第0维分块,每一块维度为2,由于第一维维度总共为2,因此相当于没有分割 
>>> torch.split(a, 2, 0) 
(tensor([[ 1., 2., 3.], [ 4., 5., 6.]]),) 
# 沿着第1维分块,每一块维度为2,因此第一个Tensor为2×2,第二个为2×1 
>>>> torch.split(a, 2, 1) 
(tensor([[ 1., 2.], [ 4., 5.]]), tensor([[ 3.], [ 6.]])) 
# split也可以根据输入的list进行自动分块,list中的元素代表了每一个块占的维度 
>>> torch.split(a, [1,2], 1) 
(tensor([[ 1.], [ 4.]]), tensor([[ 2., 3.], [ 5., 6.]]))
### 动手学深度学习 PyTorch 练习题及答案 #### 线性回归练习题解析 在深入探讨具体题目之前,了解如何使用PyTorch构建和训练模型是非常重要的。对于线性回归问题,主要步骤包括创建数据集、定义模型结构、设定损失函数以及优化算法的选择。 ##### 数据准备与预处理 为了更好地理解实际应用中的流程,可以参照如下方式生成模拟数据: ```python import torch from torch.utils.data import TensorDataset, DataLoader # 假设真实参数 w = [2, -3.4], b = 4.2 true_w = torch.tensor([2, -3.4]) true_b = 4.2 features = torch.randn((1000, 2)) labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b labels += torch.normal(0, 0.01, labels.shape) dataset = TensorDataset(features, labels) data_iter = DataLoader(dataset, batch_size=10, shuffle=True) ``` 这段代码展示了如何利用`torch.randn()`方法生成带有噪声的样本点,并通过`DataLoader`对象方便地获取批量数据用于后续训练过程[^1]。 ##### 定义模型架构 接着就是搭建神经网络模型的部分,在这里只需要简单的层全连接层即可完成任务需求: ```python class LinearRegressionModel(torch.nn.Module): def __init__(self): super().__init__() self.linear = torch.nn.Linear(in_features=2, out_features=1) def forward(self, x): y_pred = self.linear(x) return y_pred ``` 上述实现了自定义模块继承自`torch.nn.Module`基类,并重写了前向传播逻辑以适应特定的任务场景。 ##### 训练配置 选择合适的损失函数和优化器是至关重要的环节之。针对此案例推荐采用均方误差作为衡量标准,并借助随机梯度下降法来进行权重调整: ```python model = LinearRegressionModel() criterion = torch.nn.MSELoss(reduction='mean') optimizer = torch.optim.SGD(model.parameters(), lr=0.03) for epoch in range(num_epochs): for X, y in data_iter: output = model(X).squeeze(-1) # 移除多余的维度 loss = criterion(output, y) optimizer.zero_grad() # 清空过往梯度 loss.backward() # 反向传播求导数 optimizer.step() # 更新所有参数 if (epoch+1) % display_step == 0: print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}') ``` 以上片段体现了完整的训练循环机制,其中包括正向计算预测值、评估当前差距大小、反向累积梯度信息直至最终执行步式的参数修正操作。 ##### 解决潜在问题 当运用随机梯度下降(SGD)算法时可能会遇到收敛速度慢或者震荡不稳的情况。这是因为随着迭代次数增加接近最优解的过程中步长过大容易造成数值不稳定现象。对此可以通过引入动量项(Momentum),或是动态调节学习率(Learning Rate Schedule)等方式加以改善[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猛男技术控

感谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值