PyTorch张量入门-从零搭建环境到Tensor操作
·
PyTorch 张量入门:从零搭建环境到 Tensor 操作
深度学习入门第一关:装好 PyTorch,玩转 Tensor。本文带你从 VSCode 配置开始,一路到 GPU 张量运算。
一、先搭环境,再谈学习
1.1 安装 PyTorch
# 创建虚拟环境(推荐 Python 3.9~3.11)
python -m venv dl_env
# 激活
# Windows:
dl_env\Scripts\activate
# macOS / Linux:
source dl_env/bin/activate
# 安装 PyTorch(CPU 版,先跑起来)
pip install torch torchvision torchaudio
# 如果有 NVIDIA 显卡,去 pytorch.org 复制 CUDA 版安装命令
1.2 VSCode 配置要点
// settings.json 关键配置
{
"python.defaultInterpreterPath": "${workspaceFolder}/dl_env/Scripts/python.exe",
"python.analysis.extraPaths": ["./src"],
"ruff.enable": true,
"editor.formatOnSave": true,
"editor.rulers": [88],
"files.autoSave": "afterDelay"
}
必装扩展:
- Python(微软官方,调试 + 智能提示)
- Pylance(类型检查,代码跳转)
- Ruff(极速 lint + format,替代 flake8/black/isort)
- Jupyter(数据科学必备,边写边跑)
装完别忘了:把 Python 解释器路径指向你刚建的 dl_env,否则 VSCode 还在用系统 Python。
1.3 验证环境
import torch
print(torch.__version__) # 2.x.x
print(torch.cuda.is_available()) # True 如果有 GPU
print(torch.cuda.device_count()) # GPU 数量
二、张量(Tensor)是什么
一句话:Tensor 就是 PyTorch 里的"数组",地位等于 NumPy 的 ndarray。但它比 ndarray 多一个关键能力——能在 GPU 上跑。
类比理解:
| 维度 | 数学概念 | PyTorch Tensor | NumPy |
|---|---|---|---|
| 0 维 | 标量(scalar) | torch.tensor(3) |
np.array(3) |
| 1 维 | 向量(vector) | torch.tensor([1,2,3]) |
np.array([1,2,3]) |
| 2 维 | 矩阵(matrix) | torch.rand(3,4) |
np.random.rand(3,4) |
| 3 维 | 立方体 | torch.rand(2,3,4) |
np.random.rand(2,3,4) |
| N 维 | 张量 | torch.rand(2,3,4,5) |
np.random.rand(2,3,4,5) |
深度学习里最常见的是 2D(全连接层权重矩阵)和 4D(卷积层的图像批次 NCHW)。
三、创建 Tensor 的 8 种方式
3.1 从 Python 数据创建
import torch
import numpy as np
# 从列表
a = torch.tensor([1, 2, 3])
print(a) # tensor([1, 2, 3])
# 从 NumPy 数组
b = torch.tensor(np.array([4, 5, 6]))
print(b) # tensor([4, 5, 6])
# 指定数据类型
c = torch.tensor([1, 2, 3], dtype=torch.float32)
print(c.dtype) # torch.float32
3.2 全零 / 全一 / 指定值
zeros = torch.zeros(3, 4) # 3×4 全零矩阵
ones = torch.ones(2, 3) # 2×3 全一矩阵
full = torch.full((2, 2), 7) # 2×2 全是 7
# 仿照已有张量的形状
x = torch.rand(3, 4)
zeros_like = torch.zeros_like(x) # 和 x 形状一样的全零
ones_like = torch.ones_like(x) # 和 x 形状一样的全一
3.3 随机张量
torch.manual_seed(42) # 设定随机种子,保证可复现
rand = torch.rand(3, 4) # 0~1 均匀分布
randn = torch.randn(3, 4) # 标准正态分布(均值 0,方差 1)
randint = torch.randint(0, 10, (3, 4)) # [0, 10) 随机整数
💡 训练模型前一定要
torch.manual_seed(42),否则每次跑结果不一样,debug 到怀疑人生。
3.4 线性 / 序列张量
arange = torch.arange(0, 10, 2) # tensor([0, 2, 4, 6, 8])
linspace = torch.linspace(0, 1, 5) # tensor([0.00, 0.25, 0.50, 0.75, 1.00])
四、Tensor 的属性:shape、dtype、device
拿到一个张量,先看三样东西:
x = torch.randn(2, 3, 4)
print(x.shape) # torch.Size([2, 3, 4]) — 形状
print(x.dtype) # torch.float32 — 数据类型
print(x.device) # cpu — 在哪个设备上
数据类型速查
| dtype | 说明 | 典型用途 |
|---|---|---|
torch.float32 |
32 位浮点(默认) | 模型权重、激活值 |
torch.float16 |
16 位浮点 | 混合精度训练 |
torch.int64 |
64 位整数(默认) | 标签、索引 |
torch.int32 |
32 位整数 | 部分旧代码 |
torch.bool |
布尔 | 掩码、条件筛选 |
类型转换
x = torch.tensor([1, 2, 3]) # 默认 int64
x = x.float() # 转 float32
x = x.int() # 转 int32
x = torch.tensor([1.0, 2.0], dtype=torch.float16) # 创建时指定
五、Tensor 基本操作
5.1 加减乘除
a = torch.tensor([1.0, 2.0, 3.0])
b = torch.tensor([4.0, 5.0, 6.0])
print(a + b) # tensor([5., 7., 9.])
print(a - b) # tensor([-3., -3., -3.])
print(a * b) # tensor([ 4., 10., 18.]) — 逐元素乘法
print(a / b) # tensor([0.2500, 0.4000, 0.5000])
print(a @ b) # 点积:1*4 + 2*5 + 3*6 = 32.0
5.2 矩阵乘法
A = torch.rand(3, 4) # 3×4
B = torch.rand(4, 5) # 4×5
# 三种写法,结果完全一样
C = A @ B
C = torch.matmul(A, B)
C = torch.mm(A, B) # 仅限 2D 矩阵
print(C.shape) # torch.Size([3, 5])
5.3 索引与切片
x = torch.arange(12).reshape(3, 4)
# tensor([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
print(x[0]) # 第 0 行:tensor([0, 1, 2, 3])
print(x[:, 0]) # 第 0 列:tensor([0, 4, 8])
print(x[1:, 2:]) # 第 1 行起、第 2 列起
# tensor([[ 6, 7],
# [10, 11]])
5.4 变形(reshape / view)
x = torch.arange(12)
a = x.reshape(3, 4) # 变成 3×4
b = x.view(3, 4) # 同上,但要求内存连续
c = x.reshape(3, -1) # -1 表示"自动算":12/3=4
# 展平
flat = x.reshape(-1) # 回到一维
reshape始终安全(会自动拷贝),view更快但要求内存连续。不确定时用reshape。
5.5 拼接与堆叠
a = torch.tensor([[1, 2], [3, 4]])
b = torch.tensor([[5, 6], [7, 8]])
cat_dim0 = torch.cat([a, b], dim=0) # 沿行拼接
# tensor([[1, 2],
# [3, 4],
# [5, 6],
# [7, 8]])
cat_dim1 = torch.cat([a, b], dim=1) # 沿列拼接
# tensor([[1, 2, 5, 6],
# [3, 4, 7, 8]])
stacked = torch.stack([a, b], dim=0) # 新增一维堆叠
# shape: torch.Size([2, 2, 2])
六、Tensor 与 NumPy 互转
import numpy as np
# Tensor → NumPy(共享内存,修改一个会影响另一个)
x = torch.rand(3, 3)
arr = x.numpy()
arr[0, 0] = 999
print(x[0, 0]) # 也变成 999!
# 不想共享?加 .copy()
arr_safe = x.numpy().copy()
# NumPy → Tensor
arr = np.array([[1, 2], [3, 4]])
t = torch.from_numpy(arr) # 共享内存
t2 = torch.tensor(arr) # 深拷贝,不共享
经验:训练时数据处理用 NumPy,进模型前转 Tensor,出来再转回 NumPy 画图。
七、GPU 加速
把计算搬到 GPU 上,核心就一个操作:
# 检查 GPU 是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")
# 创建时直接指定
x = torch.rand(1000, 1000, device=device)
# 或者创建后迁移
x = torch.rand(1000, 1000)
x = x.to(device) # 搬到 GPU
# 在 GPU 上做矩阵乘法,速度碾压 CPU
y = torch.rand(1000, 1000, device=device)
z = x @ y # 瞬间完成
一个简单的速度对比:
import time
size = 5000
x_cpu = torch.rand(size, size)
y_cpu = torch.rand(size, size)
# CPU 计时
t0 = time.time()
_ = x_cpu @ y_cpu
print(f"CPU: {time.time() - t0:.3f}s")
if torch.cuda.is_available():
x_gpu = x_cpu.to("cuda")
y_gpu = y_cpu.to("cuda")
torch.cuda.synchronize() # 预热
t0 = time.time()
_ = x_gpu @ y_gpu
torch.cuda.synchronize() # 等 GPU 算完
print(f"GPU: {time.time() - t0:.3f}s")
八、实战:用 Tensor 写一个线性回归
import torch
torch.manual_seed(42)
# 1. 造数据:y = 3x + 2 + 噪声
X = torch.rand(100, 1) * 10 # 100 个样本,0~10
y = 3 * X + 2 + torch.randn(100, 1) * 2
# 2. 初始化参数(用 Tensor,不是 nn.Module)
w = torch.randn(1, requires_grad=True) # 权重
b = torch.randn(1, requires_grad=True) # 偏置
# 3. 训练
lr = 0.01
for epoch in range(200):
# 前向
y_pred = X @ w + b
loss = ((y_pred - y) ** 2).mean() # MSE
# 反向传播
loss.backward()
# 梯度下降(手动更新,不用 optimizer)
with torch.no_grad():
w -= lr * w.grad
b -= lr * b.grad
w.grad.zero_()
b.grad.zero_()
if epoch % 40 == 0:
print(f"Epoch {epoch:3d} | Loss: {loss.item():.4f}")
print(f"\n真实参数: w=3.0, b=2.0")
print(f"拟合参数: w={w.item():.3f}, b={b.item():.3f}")
# 输出:
# Epoch 0 | Loss: 207.8994
# Epoch 40 | Loss: 19.0575
# Epoch 80 | Loss: 9.3985
# Epoch 120 | Loss: 6.1175
# Epoch 160 | Loss: 5.0025
# 真实参数: w=3.0, b=2.0
# 拟合参数: w=2.958, b=2.203
用纯 Tensor 写一个完整的训练循环,把"前向传播 → 计算损失 → 反向传播 → 更新参数"这四步走一遍,比直接调 nn.Linear 更能理解底层发生了什么。
九、总结
| 掌握点 | 核心 API |
|---|---|
| 创建 Tensor | torch.tensor(), torch.zeros(), torch.randn(), torch.arange() |
| 查属性 | .shape, .dtype, .device |
| 类型转换 | .float(), .int(), dtype= |
| 索引切片 | [row, col], [start:end], [:, col] |
| 变形 | .reshape(), .view(), -1 自动推导 |
| 拼接 | torch.cat(), torch.stack() |
| NumPy 互转 | .numpy(), torch.from_numpy() |
| GPU | .to("cuda"), torch.cuda.is_available() |
| 自动求导 | requires_grad=True, .backward(), .grad |
Tensor 就是深度学习的"基本粒子"。后面接触的全连接层、卷积层、RNN……本质上都是对 Tensor 的封装和运算。这一关过了,后面的路会顺畅很多。
更多推荐


所有评论(0)