6月8日day48打卡

随机函数与广播机制

知识点回顾

  1. 随机张量生成torch.randn函数
  2. 卷积池化计算公式(可以不掌握,会自动计算的)
  3. pytorch广播机制加法乘法广播机制

psnumpy运算也有类似广播机制基本一致

作业:自己借助ai举几个例子帮助自己理解即可

import torch
import torch.nn as nn# 生成输入张量 (批量大小, 通道数, 高度, 宽度)
input_tensor = torch.randn(1, 3, 32, 32)  # 例如CIFAR-10图像
print(f"输入尺寸: {input_tensor.shape}")  # 输出: [1, 3, 32, 32]# 定义卷积层
conv_layer = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1)  # 示例参数
print(f"卷积层参数: {conv_layer}")  # 输出: 卷积层的参数# 前向传播
output_tensor = conv_layer(input_tensor)    # 卷积操作
print(f"卷积后尺寸: {output_tensor.shape}")  # 输出: [1, 64, 32, 32]# 2. 池化层操作 (减小空间尺寸)
pool = nn.MaxPool2d(kernel_size=2, stride=2) # 创建一个最大池化层
pool_output = pool(output_tensor)
print(f"池化后尺寸: {pool_output.shape}")  # 输出: [1, 64, 16, 16]# 3. 将多维张量展平为向量
flattened = pool_output.view(pool_output.size(0), -1)
print(f"展平后尺寸: {flattened.shape}")  # 输出: [1, 64 * 16 * 16] = [1, 16384]# 4. 线性层操作
fc1 = nn.Linear(in_features=16384,     # 输入特征数out_features=128      # 输出特征数
)
fc_output = fc1(flattened)
print(f"线性层后尺寸: {fc_output.shape}")  # 输出: [1, 128]# 5. 再经过一个线性层(例如分类器)
fc2 = nn.Linear(128, 10)  # 假设是10分类问题
final_output = fc2(fc_output)
print(f"最终输出尺寸: {final_output.shape}")  # 输出: [1, 10]
print(final_output)# 使用Softmax替代Sigmoid
softmax = nn.Softmax(dim=1)  # 在类别维度上进行Softmax
class_probs = softmax(final_output)
print(f"Softmax输出: {class_probs}")  # 总和为1的概率分布
print(f"Softmax输出总和: {class_probs.sum():.4f}")
输入尺寸: torch.Size([1, 3, 32, 32])
卷积层参数: Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
卷积后尺寸: torch.Size([1, 64, 32, 32])
池化后尺寸: torch.Size([1, 64, 16, 16])
展平后尺寸: torch.Size([1, 16384])
线性层后尺寸: torch.Size([1, 128])
最终输出尺寸: torch.Size([1, 10])
tensor([[-0.1682, -0.2191,  0.4092,  0.1416,  0.2290,  0.1882,  0.2205, -0.0307,0.1588, -0.5265]], grad_fn=<AddmmBackward0>)
Softmax输出: tensor([[0.0786, 0.0747, 0.1401, 0.1072, 0.1170, 0.1123, 0.1160, 0.0902, 0.1090,0.0549]], grad_fn=<SoftmaxBackward0>)
Softmax输出总和: 1.0000

广播机制可以理解为:计算机帮你偷偷“复制粘贴”小数据,让不同形状的数组/张量能直接做运算

比如你有两个“表格”(张量)要做加法,但它们的形状不一样。这时候广播机制会自动把小表格的数据“复制”成和大表格一样的形状,然后再相加。整个过程不需要你手动写循环或复制代码,计算机自己搞定。

举个生活中的例子:

假设你要把一杯糖水(1勺糖 + 100ml水)和一桶水(1000ml水)混合。广播机制就像:

  • 发现糖水太少(形状小),自动把糖水“复制”10份(变成10勺糖 + 1000ml水),然后和一桶水混合。

技术上的条件(能广播的前提):

两个张量的维度要“从后往前对齐”,要么尺寸相同,要么其中一个尺寸是1。例如:

  • 形状 (3, 2) 和 (1, 2):可以广播(第二个维度都是2,第一个维度一个是3,一个是1 → 把1扩展成3)。
  • 形状 (3, 2) 和 (2, 3):不能广播(维度对不齐)。
# 张量A:形状(3, 2)(3行2列)
A = torch.tensor([[1, 2], [3, 4], [5, 6]])# 张量B:形状(1, 2)(1行2列)
B = torch.tensor([[10, 20]])# 广播后,B会被“复制”成(3, 2)(3行2列,每行都是[10,20])
# 然后A + B 等价于:
# [[1+10, 2+20],
#  [3+10, 4+20],
#  [5+10, 6+20]]
result = A + B
print(result)  # 输出: [[11, 22], [13, 24], [15, 26]]

好处:

不用手动写循环复制数据,代码更简洁。比如给一个大矩阵的每个元素加一个数(标量),广播机制会自动把标量“复制”到所有元素的位置,直接运算。

合法广播和非法广播是广播机制中的两种情况,核心区别是两个张量的形状是否满足广播规则

合法广播:

如果两个张量的形状“从最后一个维度开始向前对齐”时,每个对应的维度满足以下任一条件:

  • 两个维度尺寸相同(可以直接运算);
  • 其中一个维度尺寸为1(可以自动扩展成另一个维度的尺寸)。

此时计算机会自动帮你扩展小张量的形状,完成运算,这就是合法广播。

非法广播:

如果两个张量的形状在“从后往前对齐”时,存在某个对应的维度尺寸既不相同,也不为1,此时无法自动扩展,计算机会报错,这就是非法广播。

举个具体例子(用PyTorch张量):

合法广播:
# 张量A:形状(3, 2)(3行2列)
A = torch.tensor([[1, 2], [3, 4], [5, 6]])# 张量B:形状(1, 2)(1行2列)
B = torch.tensor([[10, 20]])  # 最后一个维度是2(和A的最后一个维度相同),前一个维度是1(可以扩展)# 广播后B会被扩展成(3, 2)(每行都是[10,20]),然后相加
result = A + B  # 合法!输出: [[11,22], [13,24], [15,26]]

 非法广播:

# 张量C:形状(3, 2)(3行2列)
C = torch.tensor([[1, 2], [3, 4], [5, 6]])# 张量D:形状(2, 3)(2行3列)
D = torch.tensor([[10, 20, 30], [40, 50, 60]])  # 最后一个维度是3(C的最后一个维度是2,不相等且不为1)result = C + D  # 非法!会报错:"shape mismatch"(形状不匹配)

总结:

合法广播是“规则允许的形状匹配”,计算机会偷偷帮你扩展;非法广播是“形状完全对不上”,必须手动调整形状(比如用reshape)才能运算。

2.1加法的广播机制:

二维张量与一维向量相加

import torch# 创建原始张量
a = torch.tensor([[10], [20], [30]])  # 形状: (3, 1)
b = torch.tensor([1, 2, 3])          # 形状: (3,)result = a + b
# 广播过程
# 1. b补全维度: (3,) → (1, 3)
# 2. a扩展列: (3, 1) → (3, 3)
# 3. b扩展行: (1, 3) → (3, 3)
# 最终形状: (3, 3)print("原始张量a:")
print(a)print("\n原始张量b:")
print(b)print("\n广播后a的值扩展:")
print(torch.tensor([[10, 10, 10],[20, 20, 20],[30, 30, 30]]))  # 实际内存中未复制,仅逻辑上扩展print("\n广播后b的值扩展:")
print(torch.tensor([[1, 2, 3],[1, 2, 3],[1, 2, 3]]))  # 实际内存中未复制,仅逻辑上扩展print("\n加法结果:")
print(result)

 

原始张量a:
tensor([[10],[20],[30]])原始张量b:
tensor([1, 2, 3])广播后a的值扩展:
tensor([[10, 10, 10],[20, 20, 20],[30, 30, 30]])广播后b的值扩展:
tensor([[1, 2, 3],[1, 2, 3],[1, 2, 3]])加法结果:
tensor([[11, 12, 13],[21, 22, 23],[31, 32, 33]])

三维张量与二维张量相加 

# 创建原始张量
a = torch.tensor([[[1], [2]], [[3], [4]]])  # 形状: (2, 2, 1)
b = torch.tensor([[10, 20]])               # 形状: (1, 2)# 广播过程
# 1. b补全维度: (1, 2) → (1, 1, 2)
# 2. a扩展第三维: (2, 2, 1) → (2, 2, 2)
# 3. b扩展第一维: (1, 1, 2) → (2, 1, 2)
# 4. b扩展第二维: (2, 1, 2) → (2, 2, 2)
# 最终形状: (2, 2, 2)result = a + b
print("原始张量a:")
print(a)print("\n原始张量b:")
print(b)print("\n广播后a的值扩展:")
print(torch.tensor([[[1, 1],[2, 2]],[[3, 3],[4, 4]]]))  # 实际内存中未复制,仅逻辑上扩展print("\n广播后b的值扩展:")
print(torch.tensor([[[10, 20],[10, 20]],[[10, 20],[10, 20]]]))  # 实际内存中未复制,仅逻辑上扩展print("\n加法结果:")
print(result)
原始张量a:
tensor([[[1],[2]],[[3],[4]]])原始张量b:
tensor([[10, 20]])广播后a的值扩展:
tensor([[[1, 1],[2, 2]],[[3, 3],[4, 4]]])广播后b的值扩展:
tensor([[[10, 20],[10, 20]],[[10, 20],[10, 20]]])加法结果:
tensor([[[11, 21],[12, 22]],[[13, 23],[14, 24]]])

 二维张量与标量相加

# 创建原始张量
a = torch.tensor([[1, 2], [3, 4]])  # 形状: (2, 2)
b = 10                              # 标量,形状视为 ()# 广播过程
# 1. b补全维度: () → (1, 1)
# 2. b扩展第一维: (1, 1) → (2, 1)
# 3. b扩展第二维: (2, 1) → (2, 2)
# 最终形状: (2, 2)result = a + b
print("原始张量a:")
print(a)
# 输出:
# tensor([[1, 2],
#         [3, 4]])print("\n标量b:")
print(b)
# 输出: 10print("\n广播后b的值扩展:")
print(torch.tensor([[10, 10],[10, 10]]))  # 实际内存中未复制,仅逻辑上扩展print("\n加法结果:")
print(result)
# 输出:
# tensor([[11, 12],
#         [13, 14]])
原始张量a:
tensor([[1, 2],[3, 4]])标量b:
10广播后b的值扩展:
tensor([[10, 10],[10, 10]])加法结果:
tensor([[11, 12],[13, 14]])

高维张量与低维张量相加 

# 创建原始张量
a = torch.tensor([[[1, 2], [3, 4]]])  # 形状: (1, 2, 2)
b = torch.tensor([[5, 6]])            # 形状: (1, 2)# 广播过程
# 1. b补全维度: (1, 2) → (1, 1, 2)
# 2. b扩展第二维: (1, 1, 2) → (1, 2, 2)
# 最终形状: (1, 2, 2)result = a + b
print("原始张量a:")
print(a)
# 输出:
# tensor([[[1, 2],
#          [3, 4]]])print("\n原始张量b:")
print(b)
# 输出:
# tensor([[5, 6]])print("\n广播后b的值扩展:")
print(torch.tensor([[[5, 6],[5, 6]]]))  # 实际内存中未复制,仅逻辑上扩展print("\n加法结果:")
print(result)
# 输出:
# tensor([[[6, 8],
#          [8, 10]]])
原始张量a:
tensor([[[1, 2],[3, 4]]])原始张量b:
tensor([[5, 6]])广播后b的值扩展:
tensor([[[5, 6],[5, 6]]])加法结果:
tensor([[[ 6,  8],[ 8, 10]]])

关键总结:

  1. 尺寸变化:广播后的形状由各维度的最大值决定(示例2中最终形状为(2,2,2))。
  2. 值扩展:维度为1的张量通过复制扩展值(示例1中b从[1,2,3]扩展为三行相同的值)。
  3. 内存效率:扩展是逻辑上的,实际未复制数据,避免了内存浪费。 

2.2乘法的广播机制: 

矩阵乘法(@)
的特殊规则
矩阵乘法除了遵循通用广播规则外,还需要满足矩阵乘法的维度约束:
最后两个维度必须满足:A.shape[-1]==B.shape[-2](即A的列数等于B的行数)
其他维度(批量维度):遵循通用广播规则

批量矩阵与单个矩阵相乘 

import torch# A: 批量大小为2,每个是3×4的矩阵
A = torch.randn(2, 3, 4)  # 形状: (2, 3, 4)# B: 单个4×5的矩阵
B = torch.randn(4, 5)     # 形状: (4, 5)# 广播过程:
# 1. B补全维度: (4, 5) → (1, 4, 5)
# 2. B扩展第一维: (1, 4, 5) → (2, 4, 5)
# 矩阵乘法: (2, 3, 4) @ (2, 4, 5) → (2, 3, 5)
result = A @ B            # 结果形状: (2, 3, 5)print("A形状:", A.shape)  # 输出: torch.Size([2, 3, 4])
print("B形状:", B.shape)  # 输出: torch.Size([4, 5])
print("结果形状:", result.shape)  # 输出: torch.Size([2, 3, 5])
A形状: torch.Size([2, 3, 4])
B形状: torch.Size([4, 5])
结果形状: torch.Size([2, 3, 5])

 批量矩阵与批量矩阵相乘(部分广播)

# A: 批量大小为3,每个是2×4的矩阵
A = torch.randn(3, 2, 4)  # 形状: (3, 2, 4)# B: 批量大小为1,每个是4×5的矩阵
B = torch.randn(1, 4, 5)  # 形状: (1, 4, 5)# 广播过程:
# B扩展第一维: (1, 4, 5) → (3, 4, 5)
# 矩阵乘法: (3, 2, 4) @ (3, 4, 5) → (3, 2, 5)
result = A @ B            # 结果形状: (3, 2, 5)print("A形状:", A.shape)  # 输出: torch.Size([3, 2, 4])
print("B形状:", B.shape)  # 输出: torch.Size([1, 4, 5])
print("结果形状:", result.shape)  # 输出: torch.Size([3, 2, 5])
A形状: torch.Size([3, 2, 4])
B形状: torch.Size([1, 4, 5])
结果形状: torch.Size([3, 2, 5])

 三维张量与二维张量相乘(高维广播)

# A: 批量大小为2,通道数为3,每个是4×5的矩阵
A = torch.randn(2, 3, 4, 5)  # 形状: (2, 3, 4, 5)# B: 单个5×6的矩阵
B = torch.randn(5, 6)        # 形状: (5, 6)# 广播过程:
# 1. B补全维度: (5, 6) → (1, 1, 5, 6)
# 2. B扩展第一维: (1, 1, 5, 6) → (2, 1, 5, 6)
# 3. B扩展第二维: (2, 1, 5, 6) → (2, 3, 5, 6)
# 矩阵乘法: (2, 3, 4, 5) @ (2, 3, 5, 6) → (2, 3, 4, 6)
result = A @ B               # 结果形状: (2, 3, 4, 6)print("A形状:", A.shape)     # 输出: torch.Size([2, 3, 4, 5])
print("B形状:", B.shape)     # 输出: torch.Size([5, 6])
print("结果形状:", result.shape)  # 输出: torch.Size([2, 3, 4, 6])
A形状: torch.Size([2, 3, 4, 5])
B形状: torch.Size([5, 6])
结果形状: torch.Size([2, 3, 4, 6])

@浙大疏锦行 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/84157.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机常用快捷键分类汇总,涵盖 Windows、macOS 以及通用软件场景

一、系统通用快捷键 功能Windows 快捷键macOS 快捷键复制Ctrl CCommand C粘贴Ctrl VCommand V剪切Ctrl XCommand X撤销Ctrl ZCommand Z全选Ctrl ACommand A保存Ctrl SCommand S打印Ctrl PCommand P新建窗口/标签页Ctrl NCommand N关闭当前窗口/标签页Ctrl WC…

ES6中的Map与Set数据结构的简单应用

一、Map定义和基本用法 Map是一种键值对集合&#xff0c;其中键和值都可以是任何类型&#xff08;对象、原始值等&#xff09;。与普通对象不同&#xff0c;Map保持键值对的插入顺序&#xff0c;并且允许使用任何类型的键。 1、创建Map const map new Map()2、添加键值对。…

25.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--用户服务接口

用户管理是任何系统的基础功能之一&#xff0c;本篇介绍了如何实现一个完整的用户管理模块&#xff0c;包括用户信息的增删改查、用户状态管理、分页查询、数据验证和权限控制。核心代码实现部分涵盖了控制器&#xff08;UserController&#xff09;、服务接口&#xff08;IUse…

基于深度学习的无人机轨迹预测

完整代码见文末 随着无人机技术的不断发展,无人机在农业、物流、监控等领域的应用日益广泛。精准的轨迹预测不仅能够提高无人机飞行的效率和安全性,还能在应对复杂环境下的突发状况时做出迅速反应。因此,基于深度学习的无人机轨迹预测已成为当前研究和应用的热门方向。 无…

AUTOSAR实战教程--DoIP_02_诊断链路建立流程

第一步&#xff1a;DoIP实体车辆声明/诊断仪车辆识别请求 打开激活线以后&#xff0c;DoIP实体发的三帧车辆声明报文。其中包含了DoIP实体的诊断逻辑地址&#xff08;可以类比DoCAN的物理请求/响应地址&#xff09;&#xff0c;对应车辆的VIN码&#xff08;若已配置&#xff0…

跟我学c++中级篇——多线程中的文件处理

一、文件处理 作为IO处理的一种重要场景&#xff0c;文件处理是几乎所有编程都无法绕过的一个情况。稍微复杂的一些的程序都可能需要文件处理&#xff0c;不管这种文件处理对开发者来说是显式的还是隐式的。相对于其它语言&#xff0c;C并未提供多么好的文件处理API接口&#…

Flutter知识点汇总

Flutter架构解析 1. Flutter 是什么?它与其他移动开发框架有什么不同? Flutter 是 Google 开发的开源移动应用开发框架,可用于快速构建高性能、高保真的移动应用(iOS 和 Android),也支持 Web、桌面和嵌入式设备。。它与其他移动开发框架(如 React Native、Xamarin、原…

【会员专享数据】1980—2022年中国逐日月年潜在蒸散发栅格数据

气象数据是我们在各项研究中都经常使用的数据&#xff0c;尤其是高精度的气象数据应用价值非常高。 之前我们分享过研究者张凌, 胡英屹等发布在国家冰川冻土沙漠科学数据中心平台上的nc格式的1980—2022年中国高分辨率逐日、逐月、逐年气象数据&#xff01;很多小伙伴拿到数据…

前端打包工具简单介绍

前端打包工具简单介绍 一、Webpack 架构与插件机制 1. Webpack 架构核心组成 Entry&#xff08;入口&#xff09; 指定应用的起点文件&#xff0c;比如 src/index.js。 Module&#xff08;模块&#xff09; Webpack 把项目当作模块图&#xff0c;模块可以是 JS、CSS、图片等…

工业控制核心引擎高性能MCU——MM32F5370

RAMSUN提供的MM32F5370搭载180MHz Arm China Star-MC1处理器&#xff0c;集成DSP、FPU与三角函数加速单元&#xff08;CORDIC&#xff09;&#xff0c;轻松应对复杂算法需求。其技术亮点包括&#xff1a; 超高精度PWM&#xff1a;8通道208ps级高精度PWM输出&#xff0c;满足储能…

AI架构师修炼之道

1 AI时代的架构革命 与传统软件开发和软件架构师相比&#xff0c;AI架构师面临着三重范式转换&#xff1a; 1.1 技术维度&#xff0c;需处理异构算力调度与模型生命周期管理的复杂性&#xff1b; 1.2 系统维度&#xff0c;需平衡实时性与资源约束的矛盾&#xff1b; 1.3 价…

数学建模期末速成 主成分分析的基本步骤

设有 n n n个研究对象&#xff0c; m m m个指标变量 x 1 , x 2 , ⋯ , x m x_1,x_2,\cdots,x_m x1​,x2​,⋯,xm​&#xff0c;第 i i i个对象关于第 j j j个指标取值为 a i j a_{ij} aij​,构造数据矩阵 A ( a i j ) n m A\left(\begin{array}{c}a_{ij}\end{array}\right)_{…

博图 SCL 编程技巧:灵活实现上升沿与下降沿检测案例分享(上)

博图 SCL 编程技巧&#xff1a;灵活实现上升沿与下降沿检测案例分享 在 PLC 编程中&#xff0c;检测信号从 0 变为 1 (上升沿) 或从 1 变为 0 (下降沿) 是最基础也是最关键的操作之一。它常用于启动单次动作、计数、状态切换等场景。在西门子 TIA Portal 环境中&#xff0c;虽…

深度学习入门Day3--鱼书学习(2)

这俩天刚忙完答辩的事情&#xff0c;终于有时间学习了 一、3层神经网络实现 1.本节中的符号使用说明。 w 12 ( 1 ) w_{12}^{(1)} w12(1)​表示前一层的第2个神经元 x 2 x_{2} x2​到后一层的第一个神经元 a 1 a_{1} a1​的权重。权重右下角按照“后一层的索引号、前一层的索引…

服务器 | Centos 9 系统中,如何部署SpringBoot后端项目?

系列文章目录 虚拟机 | Ubuntu 安装流程以及界面太小问题解决 虚拟机 | Ubuntu图形化系统&#xff1a; open-vm-tools安装失败以及实现文件拖放 虚拟机 | Ubuntu操作系统&#xff1a;su和sudo理解及如何处理忘记root密码 文章目录 系列文章目录前言一、环境介绍二、 使用syst…

CNN核心机制深度解析:卷积池化原理 PyTorch实现经典网络

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文系统讲解CNN核心原理、经典网络架构和图像分类实战&#xff0c;涵盖卷积层、池化层、LeNet/AlexNet/VGG/ResNet设计思想&#xff0c;并提供CIFAR-…

6个月Python学习计划 Day 17 - 继承、多态与魔术方法

第三周 Day 4 &#x1f3af; 今日目标 理解类的继承和方法重写掌握多态思想及其实际应用了解并使用常见的魔术方法&#xff08;如 str、len 等&#xff09; &#x1f9ec; 类的继承&#xff08;Inheritance&#xff09; Python 支持单继承与多继承&#xff0c;常用语法如下&…

抖音怎么下载视频

抖音作为一款短视频社交平台&#xff0c;凭借其独特的短视频形式和丰富的内容&#xff0c;吸引了大量用户。有些用户在欣赏完抖音视频后&#xff0c;想要将其保存下来&#xff0c;以便日后观看。如何在抖音下载视频呢&#xff1f;本文将为您详细介绍抖音视频下载的技巧和方法。…

使用MinIO搭建自己的分布式文件存储

目录 引言&#xff1a; 一.什么是 MinIO &#xff1f; 二.MinIO 的安装与部署&#xff1a; 三.Spring Cloud 集成 MinIO&#xff1a; 1.前提准备&#xff1a; &#xff08;1&#xff09;安装依赖&#xff1a; &#xff08;2&#xff09;配置MinIO连接&#xff1a; &…

uni-app 如何实现选择和上传非图像、视频文件?

在 uni-app 中实现选择和上传非图像、视频文件&#xff0c;可根据不同端&#xff08;App、H5、小程序&#xff09;的特点&#xff0c;采用以下方法&#xff1a; 一、通用思路&#xff08;多端适配优先推荐&#xff09; 借助 uni.chooseFile 选择文件&#xff0c;再用 uni.upl…