学习PyTorch 的张量(Tensor)
PyTorch 是一个强大的深度学习框架,张量(Tensor)是其核心数据结构。学习 PyTorch 中的张量运算是掌握深度学习的基础。
1. **张量的创建**
张量是 PyTorch 中的多维数组,类似于 NumPy 的 `ndarray`,但支持 GPU 加速。
import torch
# 创建未初始化的张量
x = torch.empty(2, 3) # 2行3列的空张量
# 创建随机初始化的张量
x = torch.rand(2, 3) # 2行3列的随机张量(值在0到1之间)
# 创建全零张量
x = torch.zeros(2, 3) # 2行3列的全零张量
# 创建全一张量
x = torch.ones(2, 3) # 2行3列的全一张量
# 从 Python 列表创建张量
x = torch.tensor([1.0, 2.0, 3.0]) # 1维张量
# 创建指定范围的张量
x = torch.arange(0, 10, 2) # 0到10,步长为2
2. **张量的基本属性**
张量有一些重要的属性,如形状、数据类型和设备(CPU 或 GPU)。
x = torch.rand(2, 3)
# 查看张量的形状
print(x.shape) # 或 x.size()
# 查看张量的数据类型
print(x.dtype) # 默认是 torch.float32
# 查看张量的设备
print(x.device) # 默认是 CPU
# 将张量移动到 GPU(如果有 GPU)
if torch.cuda.is_available():
x = x.to("cuda")
3. **张量的基本运算**
PyTorch 支持多种张量运算,包括逐元素运算、矩阵运算等。
逐元素运算
x = torch.tensor([1.0, 2.0, 3.0])
y = torch.tensor([4.0, 5.0, 6.0])
# 加法
z = x + y # 或 torch.add(x, y)
# 减法
z = x - y
# 乘法(逐元素)
z = x * y
# 除法(逐元素)
z = x / y
# 指数运算
z = torch.exp(x) # e^x
矩阵运算
x = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
y = torch.tensor([[5.0, 6.0], [7.0, 8.0]])
# 矩阵乘法
z = torch.matmul(x, y) # 或 x @ y
# 转置
z = x.T
广播机制
PyTorch 支持广播机制,允许不同形状的张量进行运算。
x = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
y = torch.tensor([1.0, 2.0])
# 广播加法
z = x + y # y 会被广播为 [[1.0, 2.0], [1.0, 2.0]]
4. **张量的索引和切片**
张量的索引和切片与 NumPy 类似。
x = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
# 获取第一行
print(x[0]) # tensor([1.0, 2.0, 3.0])
# 获取第二列
print(x[:, 1]) # tensor([2.0, 5.0])
# 修改某个元素
x[0, 1] = 10.0
5. **张量的形状操作**
PyTorch 提供了多种方法来改变张量的形状。
x = torch.arange(6) # tensor([0, 1, 2, 3, 4, 5])
# 改变形状
y = x.view(2, 3) # 2行3列的张量
# 展平张量
z = y.flatten() # 回到1维张量
# 增加维度
y = x.unsqueeze(0) # 在第0维增加一个维度
# 减少维度
z = y.squeeze(0) # 去掉第0维
6. **张量的梯度计算**
PyTorch 支持自动微分,可以通过 `requires_grad=True` 启用梯度计算。
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
y = x * 2 # y = [2.0, 4.0, 6.0]
z = y.sum() # z = 12.0
# 计算梯度
z.backward()
# 查看 x 的梯度
print(x.grad) # tensor([2.0, 2.0, 2.0])
7. **常用函数**
以下是一些常用的张量操作函数:
- **求和**:`torch.sum(x)`
- **均值**:`torch.mean(x)`
- **最大值**:`torch.max(x)`
- **最小值**:`torch.min(x)`
- **连接张量**:`torch.cat([x, y], dim=0)`
- **堆叠张量**:`torch.stack([x, y], dim=0)`
8. **GPU 加速**
PyTorch 支持将张量移动到 GPU 上进行加速。
# 检查是否有 GPU
if torch.cuda.is_available():
device = torch.device("cuda")
x = torch.tensor([1.0, 2.0, 3.0]).to(device)
y = torch.tensor([4.0, 5.0, 6.0]).to(device)
z = x + y
print(z)
- 参考 PyTorch 官方文档:PyTorch Documentation
https://pytorch.org/docs/stable/tensors.html
以下是一些 PyTorch 张量运算的课后小题目,帮助你巩固所学知识。每个题目都涵盖了不同的知识点,需动手编写代码并运行验证。
### **题目 1:张量创建与基本属性**
1. 创建一个形状为 `(3, 4)` 的随机张量,并打印它的形状、数据类型和设备。
2. 创建一个全零张量,形状为 `(2, 2)`,并将其数据类型设置为 `torch.float64`。
3. 从 Python 列表 `[1, 2, 3, 4, 5]` 创建一个张量,并将其移动到 GPU(如果有 GPU)。
### **题目 2:张量运算**
1. 创建两个形状为 `(2, 3)` 的随机张量 `x` 和 `y`,计算它们的逐元素加法、减法和乘法。
2. 创建一个形状为 `(3, 3)` 的随机张量 `x`,计算它的转置。
3. 创建两个形状为 `(2, 2)` 的随机张量 `x` 和 `y`,计算它们的矩阵乘法。
### **题目 3:广播机制**
1. 创建一个形状为 `(3, 1)` 的张量 `x` 和一个形状为 `(1, 3)` 的张量 `y`,计算它们的逐元素加法。
2. 创建一个形状为 `(2, 3)` 的张量 `x` 和一个标量 `2.0`,计算它们的逐元素乘法。
### **题目 4:索引与切片**
1. 创建一个形状为 `(4, 4)` 的随机张量 `x`,提取它的第 2 行和第 3 列。
2. 创建一个形状为 `(5, 5)` 的随机张量 `x`,将其第 2 到第 4 行的第 1 到第 3 列设置为 `1.0`。
### **题目 5:形状操作**
1. 创建一个形状为 `(6,)` 的张量 `x`,将其重塑为 `(2, 3)` 的形状。
2. 创建一个形状为 `(1, 3, 3)` 的张量 `x`,去掉其第 0 维。
3. 创建两个形状为 `(3,)` 的张量 `x` 和 `y`,将它们沿第 0 维连接。
### **题目 6:梯度计算**
1. 创建一个张量 `x = [2.0, 3.0, 4.0]`,并启用梯度计算。定义 `y = x^2 + 2x + 1`,计算 `y` 对 `x` 的梯度。
2. 创建一个形状为 `(2, 2)` 的随机张量 `x`,并启用梯度计算。定义 `y = sum(x^2)`,计算 `y` 对 `x` 的梯度。
### **题目 7:常用函数**
1. 创建一个形状为 `(3, 3)` 的随机张量 `x`,计算它的总和、均值和最大值。
2. 创建两个形状为 `(2, 2)` 的随机张量 `x` 和 `y`,将它们沿第 0 维堆叠。
### **题目 8:GPU 加速**
1. 检查是否有 GPU 可用,如果有,创建一个形状为 `(1000, 1000)` 的随机张量 `x`,并将其移动到 GPU 上,计算 `x + 1`。
### **题目 9:综合练习**
1. 创建一个形状为 `(5, 5)` 的随机张量 `x`,计算它的转置,并将结果与原始张量相加。
2. 创建一个形状为 `(10,)` 的张量 `x`,将其重塑为 `(2, 5)`,然后计算每列的和。
3. 创建一个形状为 `(3, 3)` 的随机张量 `x`,并启用梯度计算。定义 `y = sum(x * x.T)`,计算 `y` 对 `x` 的梯度。
### **题目 10:挑战题**
1. 实现一个简单的线性回归模型:
- 创建输入数据 `x = [1.0, 2.0, 3.0, 4.0]` 和目标数据 `y = [2.0, 4.0, 6.0, 8.0]`。
- 定义模型参数 `w` 和 `b`(初始化为随机值),并启用梯度计算。
- 定义损失函数为均方误差(MSE),使用梯度下降法更新参数 `w` 和 `b`,训练 100 次并打印最终的 `w` 和 `b`。
### **提示**
- 使用 `torch.optim.SGD` 实现梯度下降。
- 使用 `torch.nn.functional.mse_loss` 计算均方误差。