当前位置: 首页 > news >正文

【机器学习深度学习】张量基本操作

目录

一、张量基本操作

1.1 执行代码

 1.2 运行结果

1.3 代码解析

 ✅ 1. 创建张量(tensor、randn、zeros)

✅ 2. 索引与切片(类似 NumPy)

✅ 3. 形状变换(reshape、转置、压缩)

✅ 4. 数学运算(逐元素 + 矩阵乘 + 求和)

✅ 5. 广播机制(不同维度也能加)

✅ 6. 内存共享验证(view 是原数据的视图)

二、什么是张量(Tensor)

三、示例代码中有哪些“张量”

四、小结一句话:


一、张量基本操作

1.1 执行代码

#张量的基本操作import torch
# ==============================
# 1. 张量的基本操作
# ==============================
print("="*50)
print("1. 张量基本操作示例")
print("="*50)# 创建张量
x = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32)
y = torch.randn(2, 3)  # 正态分布随机张量
z = torch.zeros(3, 2)
print(f"创建张量:\n x={x}\n y={y}\n z={z}")# 索引和切片
print("\n索引和切片:")
print("x[1, 2] =", x[1, 2].item())  # 获取标量值
print("x[:, 1:] =\n", x[:, 1:])# 形状变换
reshaped = x.view(3, 2)  # 视图操作(不复制数据)
transposed = x.t()       # 转置
squeezed = torch.randn(1, 3, 1).squeeze()  # 压缩维度
print(f"\n形状变换:\n 重塑后: {reshaped.shape}\n 转置后: {transposed.shape}\n 压缩后: {squeezed.shape}")# 数学运算
add = x + y              # 逐元素加法
matmul = x @ transposed  # 矩阵乘法
sum_x = x.sum(dim=1)     # 沿维度求和
print(f"\n数学运算:\n 加法:\n{add}\n 矩阵乘法:\n{matmul}\n 行和: {sum_x}")# 广播机制
a = torch.tensor([1, 2, 3])
b = torch.tensor([[10], [20]])
print(a.shape)
print(b.shape)
print(f"\n广播加法:\n{a + b}")# 内存共享验证
view_tensor = x.view(6)
view_tensor[0] = 100
print("\n内存共享验证(修改视图影响原始张量):")
print(f"视图: {view_tensor}\n原始: {x}")

 1.2 运行结果

==================================================
1. 张量基本操作示例
==================================================
创建张量:
 x=tensor([[1., 2., 3.],
        [4., 5., 6.]])
 y=tensor([[ 0.1558, -1.4728,  0.0306],
        [ 0.8278,  1.3076,  0.5648]])
 z=tensor([[0., 0.],
        [0., 0.],
        [0., 0.]])

索引和切片:
x[1, 2] = 6.0
x[:, 1:] =
 tensor([[2., 3.],
        [5., 6.]])

形状变换:
 重塑后: torch.Size([3, 2])
 转置后: torch.Size([3, 2])
 压缩后: torch.Size([3])

数学运算:
 加法:
tensor([[1.1558, 0.5272, 3.0306],
        [4.8278, 6.3076, 6.5648]])
 矩阵乘法:
tensor([[14., 32.],
        [32., 77.]])

广播加法:
tensor([[11, 12, 13],
        [21, 22, 23]])

内存共享验证(修改视图影响原始张量):
视图: tensor([100.,   2.,   3.,   4.,   5.,   6.])
原始: tensor([[100.,   2.,   3.],
        [  4.,   5.,   6.]])


1.3 代码解析

 ✅ 1. 创建张量(tensorrandnzeros
x = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32)
y = torch.randn(2, 3)  # 标准正态分布随机数
z = torch.zeros(3, 2)
  • x 是一个 2行3列 的手动定义张量。

  • y 是一个 2x3 的 随机张量,服从 N(0,1)。

  • z 是一个 3x2 的 全零张量


✅ 2. 索引与切片(类似 NumPy)

x[1, 2].item()     # 取第1行第2列的数,结果是 6.0
x[:, 1:]           # 所有行,保留第1列以后(含1)
  • x[1, 2] = 6,就是第2行第3列的元素;

  • x[:, 1:] 等价于:

[[2, 3],[5, 6]]

✅ 3. 形状变换(reshape、转置、压缩)
x.view(3, 2)       # 重塑形状为 3行2列(原数据数量不变)
x.t()              # 转置(只支持二维):行变列、列变行
torch.randn(1, 3, 1).squeeze()  # 删除维度为1的维
  • .view() 是 PyTorch 的 reshape,不复制数据;

变形后变成:

[[1, 2],[3, 4],[5, 6]]

🔑 核心规则:总元素数量不变(2×3 = 3×2 = 6),只是重新安排形状。

  • .t() 是转置:原来 2x3 → 3x2;

.t() 进行转置,行变列、列变行,结果是:

[[1, 4],[2, 5],[3, 6]]

就像把矩阵绕主对角线翻了一下。

📌 注意:

  • .t() 只适用于二维张量;

  • 如果是三维或更高,需要用 .transpose(dim0, dim1)

  • .squeeze() 把 [1, 3, 1] 变成 [3],因为它删除所有 维度=1 的轴。

原始张量:

a = torch.randn(1, 3, 1)
print(a.shape)  # torch.Size([1, 3, 1])

这代表一个形状是 [1, 3, 1] 的张量:

它有 3 个元素,但加了两个维度为 1 的“壳”:

  • 第 1 个维度是 1(只有 1 个“通道”)

  • 第 3 个维度是 1(每个值外面包了一层)

【为啥会有维度为1的“壳”?】

很多场景(图像、批处理、模型输出)为了格式统一,会多包几层:

比如:

[Batch, Features, Channel]

即使某些维度大小为1,也会保留,以统一接口。


✅ 4. 数学运算(逐元素 + 矩阵乘 + 求和)
x + y              # 对应位置相加(维度一样)
x @ x.t()          # 矩阵乘法(2x3 与 3x2)
x.sum(dim=1)       # 每一行求和,返回 [6, 15]
  • x + y 是元素加(相同位置相加);

x =
[[1, 2, 3],[4, 5, 6]]y =
[[0.1, 0.2, 0.3],[0.4, 0.5, 0.6]]x + y =
[[1+0.1, 2+0.2, 3+0.3],[4+0.4, 5+0.5, 6+0.6]]
=
[[1.1, 2.2, 3.3],[4.4, 5.5, 6.6]]#最终结果
tensor([[1.1, 2.2, 3.3],[4.4, 5.5, 6.6]])
  • x @ x.T 是线性代数中的矩阵乘法;

这表示:

注意:@ 表示矩阵乘法,不是逐元素乘法!

x =
[[1, 2, 3],[4, 5, 6]]x.t() =
[[1, 4],[2, 5],[3, 6]]

计算过程

第一行 dot 第一列:
1×1 + 2×2 + 3×3 = 1 + 4 + 9 = 14第一行 dot 第二列:
1×4 + 2×5 + 3×6 = 4 + 10 + 18 = 32第二行 dot 第一列:
4×1 + 5×2 + 6×3 = 4 + 10 + 18 = 32第二行 dot 第二列:
4×4 + 5×5 + 6×6 = 16 + 25 + 36 = 77✅ 结果:
x @ x.t() =
[[14, 32],[32, 77]]

  • x.sum(dim=1) 结果是:

x.sum(dim=1):每一行求和x =
[[1, 2, 3],[4, 5, 6]]沿着“行的方向”(dim=1)求和:第一行:1 + 2 + 3 = 6第二行:4 + 5 + 6 = 15
[1+2+3, 4+5+6] → [6, 15]✅ 输出:
tensor([6, 15])

✅ 5. 广播机制(不同维度也能加)
a = torch.tensor([1, 2, 3])       # shape: [3]
b = torch.tensor([[10], [20]])   # shape: [2, 1]
a + b

a.shape = [3]
b.shape = [2, 1]

通过广播规则:

  • a 是一个长度为 3 的一维张量 [1, 2, 3],形状是 [3]

  • b 是一个二维张量:

[[10],[20]]

形状是 [2, 1]

🔁广播规则回顾(Broadcasting Rules)

从后往前比较维度(右对齐),满足以下任一即可广播:

  • 维度相等 ✅

  • 其中一个维度为 1 ✅

  • 缺失维度视为 1 ✅

记忆口诀:“广播先对齐,缺1来撑齐,横竖补成行列齐”

▲第一步:把 ab 的形状写完整!

即把它们“补齐维度”,方便对齐:

张量原始形状看作是二维矩阵
a[3][1, 3] → 横向一排
b[2, 1][2, 1] → 纵向两列

你可以这样想象:

a = [1, 2, 3]         →     [[1, 2, 3]]  ← 横排,1行3列  
b = [[10], [20]]      →     [[10],       ← 竖排,2行1列[20]]

▲第二步:广播机制让它们形状“变一样”

原则是:当两个张量维度不一致时,PyTorch 会尝试扩展它们

我们来手动画一下:

a 的形状 [1, 3]

[[1, 2, 3]]

想和 b 的 [2, 1] 相加,就会自动复制 2 行,变成:

[[1, 2, 3],[1, 2, 3]]   ← 广播成 [2, 3]

b 的形状 [2, 1]

[[10],[20]]

要和 [2, 3] 相加,就会复制每行的 1 个值成 3 列,变成:

[[10, 10, 10],[20, 20, 20]] ← 广播成 [2, 3]

▲第三步:相加

两个 [2, 3] 的矩阵对应位置相加:

[[1+10, 2+10, 3+10],     = [11, 12, 13][1+20, 2+20, 3+20]]     = [21, 22, 23]

最终结果是:

广播加法:
tensor([[11, 12, 13],[21, 22, 23]])

✅ 6. 内存共享验证(view 是原数据的视图)
view_tensor = x.view(6)
view_tensor[0] = 100
print(x)
  • x.view(6) 是将 x 展平成 1 维数组(6个元素);

  • 修改 view_tensor[0] = 100同时修改了原始 x 的第一个值

  • 因为 .view()共享内存的视图,不是拷贝副本。

原始张量 x 是:
x = torch.tensor([[1, 2, 3],[4, 5, 6]])
形状是 (2, 3),也就是:
行 0: [1, 2, 3]  
行 1: [4, 5, 6]

▲第一步:view_tensor = x.view(6)

这一步是把 x 重塑成一个一维向量,有 6 个元素:

view_tensor = [1, 2, 3, 4, 5, 6]  # shape: [6]

⚠️ 注意:不是复制数据!只是换了形状!它和 x 共用同一块内存。

▲第二步:view_tensor[0] = 100

修改了第一个元素,把原来的 1 改成了 100:

view_tensor = [100, 2, 3, 4, 5, 6]

因为它和 x 共享内存,所以 x 的第一个元素(也就是 x[0, 0])也被改了!

▲第三步:print(x)

现在 x 的原始矩阵变成了:

x =
[[100, 2, 3],[  4, 5, 6]]

最终结果:

x =
tensor([[100., 2., 3.],[4., 5., 6.]])

🔚 总结

操作功能易错点
.view()重塑形状会共享内存,修改影响原张量
.t()转置仅支持2D
.squeeze()去掉维度=1 的轴常用于数据降维
+元素加维度不一样时会广播
@矩阵乘法对应线性代数矩阵运算
🔚 内存共享与不共享对比图


    二、什么是张量(Tensor)

    张量(Tensor)就是“任意维度的数值容器”,一维、二维、三维、甚至 N 维都可以。

    在 PyTorch 中,所有通过 torch.tensor()torch.randn()torch.zeros()torch.view() 等操作得到的对象,都是张量

    张量就是一种 可以包含数字、并支持数学操作的多维数组。它是 PyTorch 的核心数据结构,类似于 NumPy 的 ndarray,但支持自动求导、GPU 运算等。

    🎯 更清晰地说:

    维度名称举例PyTorch 类型
    0 维标量3.14不是张量,float
    1 维向量[1, 2, 3]张量(shape=[3]
    2 维矩阵[[1, 2], [3, 4]]张量(shape=[2, 2]
    3 维张量RGB图像(3通道)张量(如 shape=[3, H, W]
    N 维高维张量NLP中词向量batch等张量

    ✅ 所以说:

    所有的矩阵、向量,乃至于多维数组,在 PyTorch 中都是张量。


    早期数学/物理中张量的严格定义:

    • 张量通常是二维或更高的数学对象

    • 标量是 0阶张量,向量是 1阶张量,矩阵是 2阶张量……

    • 所以有时人们说“张量是多维结构”,把标量另算

    但在 PyTorch / NumPy / 深度学习实际编程中

    所有数字类型(0维、1维、2维……)统一叫 张量


    角度标量是不是张量?解释
    数学传统❌ 不一定有时专门分开谈
    PyTorch 实际编程✅ 是torch.Size([]) 代表 0维张量
    NumPy 一致行为✅ 是np.array(3.14).ndim == 0

     ✅ 但注意:不是“多维才是张量”

    0维(只有一个数的情况)也是张量!

    例子:

    x = torch.tensor(7)
    print(x.shape)  # torch.Size([])
    

    这是一个0维张量,只是你看不到形状,它只有一个数字

    张量 = 标量(0维) + 向量(1维) + 矩阵(2维) + 多维数组(3维以上)

    可以理解为:

    • “张量 = 包括所有维度的数组”

    • “维度越高,数据结构越复杂,但都是张量”


    三、示例代码中有哪些“张量”

    变量名是不是张量来源注释说明
    x✅ 是torch.tensor(...)2x3 手动创建的浮点张量
    y✅ 是torch.randn(...)2x3 正态分布随机张量
    z✅ 是torch.zeros(...)3x2 全 0 张量
    x[1, 2]❌ 不是张量的元素是张量中的标量值(float),用 .item() 取出
    x[:, 1:]✅ 是x 的切片子张量,仍然是张量
    reshaped✅ 是x.view(...)同一块内存的不同形状张量
    transposed✅ 是x.t()转置后张量(2x3 → 3x2)
    squeezed✅ 是squeeze()压缩维度后的张量
    add✅ 是x + y张量加法结果(形状相同)
    matmul✅ 是x @ x.t()张量矩阵乘法结果
    sum_x✅ 是x.sum(dim=1)每行求和后的张量(形状为 [2]
    a✅ 是torch.tensor(...)一维张量,shape: [3]
    b✅ 是torch.tensor(...)二维张量,shape: [2, 1]
    a + b✅ 是广播相加后的结果shape: [2, 3]
    view_tensor✅ 是x.view(6)原张量的“扁平化视图”
    view_tensor[0]❌ 不是单个元素张量里的一个标量,不再是张量本体

     

    四、小结一句话:

    只要是 torch.xxx(...) 创建出来的、或张量切片、变换、计算出来的结果,都是张量;
    只有 .item()[i][j] 取出的是具体数字(标量),不是张量。

     

    相关文章:

  • 学做西点的网站seo编辑招聘
  • 网站搭建合同汽车网络营销策划方案
  • 新手练习做网站哪个网站比较合适在线一键免费生成网页网站
  • 做网站备案照片的要求策划网络营销方案
  • wordpress界面只有文字吉安seo招聘
  • 网站的布局结构广州新闻头条最新消息
  • 无人机灯光驱动模块技术解析
  • Netty对象池ObjectPool源码解析
  • arthas助力Java程序Full GC频率大降!
  • NVIDIA A100 GPU的计算与内存层级结构
  • day042-负载均衡与web集群搭建
  • AR/VR 显示画质失真?OAS 体全息光栅案例来解决
  • Vue Devtools “Open in Editor” 配置教程(适用于 VSCode 等主流编辑器)
  • Codex+ 自建中转 API 部署教程(Windows 版)
  • 3 大语言模型预训练数据-3.2 数据处理-3.2.2 冗余去除——1.SimHash算法处理冗余信息的核心原理
  • react中使用3D折线图跟3D曲面图
  • 分布式环境下 Spring Boot 项目基于雪花算法的唯一 ID 生成方案
  • 【LLaMA-Factory 实战系列】四、API 篇 - 部署推理服务与批量调用实战
  • 国道观察者手记
  • computed()、watch() 与 watchEffect()
  • Android14音频子系统-Audio HAL分析
  • H5录音、图文视频IndexDB储存最佳实践:用AI生成语音备忘录
  • 华为云Flexus+DeepSeek征文|基于Dify+ModelArts打造智能客服工单处理系统
  • 了解笔记本电脑制造:从品牌到代工厂的全产业链
  • Android14音频子系统-ASoC-ALSA之DAPM电源管理子系统
  • 鸿蒙与h5的交互