Python_day48随机函数与广播机制

在继续讲解模块消融前,先补充几个之前没提的基础概念

尤其需要搞懂张量的维度、以及计算后的维度,这对于你未来理解复杂的网络至关重要

一、 随机张量的生成

在深度学习中经常需要随机生成一些张量,比如权重的初始化,或者计算输入纬度经过模块后输出的维度,都可以用一个随机函数来实现需要的张量格式,而无需像之前一样必须加载一张真实的图片。

随机函数的种类很多,我们了解其中一种即可,毕竟目的主要就是生成,对分布要求不重要。

1.1 torch.randn函数

在 PyTorch 中,torch.randn()是一个常用的随机张量生成函数,它可以创建一个由标准正态分布(均值为 0,标准差为 1)随机数填充的张量。这种随机张量在深度学习中非常实用,常用于初始化模型参数、生成测试数据或模拟输入特征。

torch.randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

  • size:必选参数,表示输出张量的形状(如(3, 4)表示 3 行 4 列的矩阵)。
  • dtype:可选参数,指定张量的数据类型(如torch.float32、torch.int64等)。
  • device:可选参数,指定张量存储的设备(如'cpu'或'cuda')。
  • requires_grad:可选参数,是否需要计算梯度(常用于训练模型时)。
import torch
# 生成标量(0维张量)
scalar = torch.randn(())
print(f"标量: {scalar}, 形状: {scalar.shape}")  
标量: -1.6167410612106323, 形状: torch.Size([])
# 生成向量(1维张量)
vector = torch.randn(5)  # 长度为5的向量
print(f"向量: {vector}, 形状: {vector.shape}")  
向量: tensor([-1.9524,  0.5900,  0.7467, -1.8307,  0.4263]), 形状: torch.Size([5])
# 生成矩阵(2维张量)
matrix = torch.randn(3, 4)  # 3行4列的矩阵
print(f"矩阵:{matrix},矩阵形状: {matrix.shape}")  
矩阵:tensor([[ 0.0283,  0.7692,  0.2744, -1.6120],[ 0.3726,  1.5382, -1.0128,  0.4129],[ 0.4898,  1.4782,  0.2019,  0.0863]]),矩阵形状: torch.Size([3, 4])
# 生成3维张量(常用于图像数据的通道、高度、宽度)
tensor_3d = torch.randn(3, 224, 224)  # 3通道,高224,宽224
print(f"3维张量形状: {tensor_3d.shape}")  # 输出: torch.Size([3, 224, 224])
3维张量形状: torch.Size([3, 224, 224])
# 生成4维张量(常用于批量图像数据:[batch, channel, height, width])
tensor_4d = torch.randn(2, 3, 224, 224)  # 批量大小为2,3通道,高224,宽224
print(f"4维张量形状: {tensor_4d.shape}")  # 输出: torch.Size([2, 3, 224, 224])
4维张量形状: torch.Size([2, 3, 224, 224])

1.2 其他随机函数

除了这些随机函数还有很多,自行了解,主要是生成数据的分布不同。掌握一个即可,掌握多了参数也记不住。

torch.rand():生成在 [0, 1) 范围内均匀分布的随机数。

x = torch.rand(3, 2)  # 生成3x2的张量
print(f"均匀分布随机数: {x}, 形状: {x.shape}")
均匀分布随机数: tensor([[0.2089, 0.7786],[0.1043, 0.1573],[0.9637, 0.0397]]), 形状: torch.Size([3, 2])

torch.randint():生成指定范围内的随机整数

x = torch.randint(low=0, high=10, size=(3,))  # 生成3个0到9之间的整数
print(f"随机整数: {x}, 形状: {x.shape}")
随机整数: tensor([3, 5, 7]), 形状: torch.Size([3])

torch.normal():生成指定均值和标准差的正态分布随机数。

mean = torch.tensor([0.0, 0.0])
std = torch.tensor([1.0, 2.0])
x = torch.normal(mean, std)  # 生成两个正态分布随机数
print(f"正态分布随机数: {x}, 形状: {x.shape}")
正态分布随机数: tensor([ 0.1419, -1.5212]), 形状: torch.Size([2])
# 一维张量与二维张量相加
a = torch.tensor([[1, 2, 3], [4, 5, 6]])  # 形状: (2, 3)
b = torch.tensor([10, 20, 30])             # 形状: (3,)# 广播后:b被扩展为[[10, 20, 30], [10, 20, 30]]
result = a + b  
result
tensor([[11, 22, 33],[14, 25, 36]])

1.3 输出维度测试

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]
输入尺寸: torch.Size([1, 3, 32, 32])

二维的卷积和池化计算公式是一致的

# 1. 卷积层操作
conv1 = nn.Conv2d(in_channels=3,        # 输入通道数out_channels=16,      # 输出通道数(卷积核数量)kernel_size=3,        # 卷积核大小stride=1,             # 步长padding=1             # 填充
)
conv_output = conv1(input_tensor) # 由于 padding=1 且 stride=1,空间尺寸保持不变
print(f"卷积后尺寸: {conv_output.shape}")  # 输出: [1, 16, 32, 32]
卷积后尺寸: torch.Size([1, 16, 32, 32])
# 2. 池化层操作 (减小空间尺寸)
pool = nn.MaxPool2d(kernel_size=2, stride=2) # 创建一个最大池化层
pool_output = pool(conv_output)
print(f"池化后尺寸: {pool_output.shape}")  # 输出: [1, 16, 16, 16]
池化后尺寸: torch.Size([1, 16, 16, 16])
# 3. 将多维张量展平为向量
flattened = pool_output.view(pool_output.size(0), -1)
print(f"展平后尺寸: {flattened.shape}")  # 输出: [1, 4096] (16*16*16=4096)
展平后尺寸: torch.Size([1, 4096])
# 4. 线性层操作
fc1 = nn.Linear(in_features=4096,     # 输入特征数out_features=128      # 输出特征数
)
fc_output = fc1(flattened)
print(f"线性层后尺寸: {fc_output.shape}")  # 输出: [1, 128]
线性层后尺寸: torch.Size([1, 128])
# 5. 再经过一个线性层(例如分类器)
fc2 = nn.Linear(128, 10)  # 假设是10分类问题
final_output = fc2(fc_output)
print(f"最终输出尺寸: {final_output.shape}")  # 输出: [1, 10]
print(final_output)
最终输出尺寸: torch.Size([1, 10])
tensor([[-0.3018, -0.4308,  0.3248,  0.2808,  0.5109, -0.0881, -0.0787, -0.0700,-0.1004, -0.0580]], grad_fn=<AddmmBackward>)

多分类问题通常使用Softmax,二分类问题用Sigmoid

# 使用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}")
Softmax输出: tensor([[0.0712, 0.0626, 0.1332, 0.1275, 0.1605, 0.0882, 0.0890, 0.0898, 0.0871,0.0909]], grad_fn=<SoftmaxBackward>)
Softmax输出总和: 1.0000

通过这种方法,可以很自然的看到每一层输出的shape,实际上在pycharm等非交互式环境ipynb时,可以借助断点+调试控制台不断测试维度信息,避免报错。

二、广播机制

什么叫做广播机制

PyTorch 的广播机制(Broadcasting)是一种强大的张量运算特性,允许在不同形状的张量之间进行算术运算,而无需显式地扩展张量维度或复制数据。这种机制使得代码更简洁高效,尤其在处理多维数据时非常实用。

当对两个形状不同的张量进行运算时,PyTorch 会自动调整它们的形状,使它们在维度上兼容。具体规则如下:

从右向左比较维度:PyTorch 从张量的最后一个维度开始向前比较,检查每个维度的大小是否相同或其中一个为 1。 维度扩展规则: 如果两个张量的某个维度大小相同,则继续比较下一个维度。 如果其中一个张量的某个维度大小为 1,则该维度会被扩展为另一个张量对应维度的大小。 如果两个张量的某个维度大小既不相同也不为 1,则会报错。

2.1 PyTorch 广播机制

PyTorch 的广播机制(Broadcasting)是一种高效的张量运算特性,允许在不同形状的张量之间执行元素级操作(如加法、乘法),而无需显式扩展或复制数据。这种机制通过自动调整张量维度来实现形状兼容,使代码更简洁、计算更高效。

当对两个形状不同的张量进行运算时,PyTorch 会按以下规则自动处理维度兼容性:

  1. 从右向左比较维度:PyTorch 从张量的最后一个维度(最右侧)开始向前逐维比较。
  2. 维度扩展条件
    • 相等维度:若两个张量在某一维度上大小相同,则继续比较下一维度。
    • 一维扩展:若其中一个张量在某一维度上大小为 1,则该维度会被扩展为另一个张量对应维度的大小。
    • 不兼容错误:若某一维度大小既不相同也不为 1,则抛出 RuntimeError。-----维度必须满足广播规则,否则会报错。
  3. 维度补全规则:若一个张量的维度少于另一个,则在其左侧补 1 直至维度数匹配。

关注2个信息

  1. 广播后的尺寸变化
  2. 扩展后的值变化

2.1.1 加法的广播机制

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]])
2三维张量与二维张量相加
# 创建原始张量
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]]])
3二维张量与标量相加
# 创建原始张量
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]])
4高维张量与低维张量相加
# 创建原始张量
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.1.2 乘法的广播机制

矩阵乘法(@)的特殊规则

矩阵乘法除了遵循通用广播规则外,还需要满足矩阵乘法的维度约束:

最后两个维度必须满足:A.shape[-1] == B.shape[-2](即 A 的列数等于 B 的行数)

其他维度(批量维度):遵循通用广播规则

1批量矩阵与单个矩阵相乘
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])
2批量矩阵与批量矩阵相乘(部分广播)
# 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])
3三维张量与二维张量相乘(高维广播)
# 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])

知识点回顾:

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

ps:numpy运算也有类似的广播机制,基本一致

作业:

自己多借助ai举几个例子帮助自己理解即可

一、随机张量生成:torch.randn 函数

功能

生成服从 标准正态分布(均值为 0,方差为 1) 的随机张量。

常见用法与示例

python

运行

import torch# 示例1:生成形状为 (3, 4) 的随机张量(2维)
tensor1 = torch.randn(3, 4)
print("tensor1 shape:", tensor1.shape)
print("tensor1内容:\n", tensor1)# 示例2:生成形状为 (2, 3, 5) 的随机张量(3维,常用于图像批次)
tensor2 = torch.randn(2, 3, 5)  # 假设 batch_size=2,通道数=3,尺寸=5x5
print("\ntensor2 shape:", tensor2.shape)
print("tensor2内容:\n", tensor2)# 示例3:生成指定数据类型的张量(如 float64)
tensor3 = torch.randn(2, 2, dtype=torch.float64)
print("\ntensor3 dtype:", tensor3.dtype)

输出说明

plaintext

tensor1 shape: torch.Size([3, 4])

tensor1内容:

tensor([[ 0.123, -0.456, 0.789, -1.012],

[-2.345, 3.456, -4.567, 5.678],

[-6.789, 7.890, -8.901, 9.012]])

tensor2 shape: torch.Size([2, 3, 5])

tensor2内容:

tensor([[[-0.111, 0.222, -0.333, 0.444, -0.555],

[ 0.666, -0.777, 0.888, -0.999, 1.010],

[ 1.111, -1.222, 1.333, -1.444, 1.555]],

[[-1.666, 1.777, -1.888, 1.999, -2.010],

[ 2.111, -2.222, 2.333, -2.444, 2.555],

[-2.666, 2.777, -2.888, 2.999, -3.010]]])

tensor3 dtype: torch.float64

二、PyTorch 广播机制(加法和乘法)

核心规则

当两个张量形状不同时,PyTorch 会自动扩展维度较小的张量,使其形状与另一个张量兼容,前提是:

  1. 从后往前(右到左)对比维度,每个维度要么相等,要么其中一个为 1
  2. 扩展的维度会被 “复制”,以匹配另一个张量的形状。
示例 1:加法广播(维度互补)

python

运行

# 张量A:形状 (3, 1),张量B:形状 (1, 4)
A = torch.tensor([[1], [2], [3]])  # shape (3, 1)
B = torch.tensor([[1, 2, 3, 4]])     # shape (1, 4)
C = A + B  # 广播后形状变为 (3, 4)
print("A + B 的结果:\n", C)

广播过程分析
  • A 的形状(3, 1) → 从右到左维度为 [1, 3](注意 PyTorch 按 (dim0, dim1) 存储,这里从后往前是 dim1=1, dim0=3)。
  • B 的形状(1, 4) → 从右到左维度为 [4, 1]
  • 对比维度最后一维(列):A 的维度是 1,B 的维度是 4 → 兼容,A 的列会被复制为 4 列。
    • 第一维(行):A 的维度是 3,B 的维度是 1 → 兼容,B 的行会被复制为 3 行。
  • 结果形状(3, 4)
输出结果

plaintext

A + B 的结果:

tensor([[2, 3, 4, 5],

[3, 4, 5, 6],

[4, 5, 6, 7]])

示例 2:乘法广播(维度为 1 的扩展)

python

运行

# 张量X:形状 (2, 3, 4),张量Y:形状 (4,)
X = torch.randn(2, 3, 4)  # shape (2, 3, 4)
Y = torch.tensor([1, 2, 3, 4])  # shape (4,) → 等价于 (1, 1, 4)
Z = X * Y  # 广播后Y形状变为 (1, 1, 4),与X的 (2, 3, 4) 兼容
print("X * Y 的形状:", Z.shape)

广播过程分析
  • Y 的形状(4,) → 视为 (1, 1, 4)(补前两个维度为 1)。
  • 对比维度最后一维(4):相等,无需扩展。
    • 前两维(1 和 1):与 X 的 (2, 3) 兼容,Y 会被复制为 (2, 3, 4)
  • 结果形状(2, 3, 4)

三、Numpy 广播机制(与 PyTorch 基本一致)

示例:Numpy 加法广播

python

运行

import numpy as np# 数组A:形状 (3, 1),数组B:形状 (1, 4)
A = np.array([[1], [2], [3]])
B = np.array([[1, 2, 3, 4]])
C = A + B  # 结果与 PyTorch 示例1完全一致
print("Numpy A + B 的结果:\n", C)

输出结果

plaintext

Numpy A + B 的结果:

[[2 3 4 5]

[3 4 5 6]

[4 5 6 7]]

四、卷积和池化(自动计算,无需手动公式)

在 PyTorch 中,卷积和池化通过定义层(如 nn.Conv2d, nn.MaxPool2d)实现,框架会自动计算输出形状。以下是简单示例:

示例:2D 卷积层

python

运行

import torch.nn as nn# 输入:batch_size=1,通道数=1,尺寸=5x5
x = torch.randn(1, 1, 5, 5)  
# 卷积层:输入通道=1,输出通道=2,卷积核=3x3,步长=1,填充=0
conv_layer = nn.Conv2d(in_channels=1, out_channels=2, kernel_size=3)
output = conv_layer(x)  # 输出形状:(1, 2, 3, 3)(自动计算:(5-3+1)=3)
print("卷积输出形状:", output.shape)

示例:最大池化层

python

运行

# 池化层:核大小=2x2,步长=2
pool_layer = nn.MaxPool2d(kernel_size=2, stride=2)
pooled = pool_layer(output)  # 输出形状:(1, 2, 1, 1)(3//2=1)
print("池化输出形状:", pooled.shape)

@浙大疏锦行

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

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

相关文章

C++中的数组

在C中&#xff0c;数组是存储固定大小同类型元素的连续内存块。它是最基础的数据结构之一&#xff0c;广泛用于各种场景。以下是关于数组的详细介绍&#xff1a; 一、一维数组 1. 定义与初始化 语法&#xff1a;类型 数组名[元素个数];示例&#xff1a;int arr[5]; // 定义…

three.js 零基础到入门

three.js 零基础到入门 什么是 three.js为什么使用 three.js使用 Three.js1. 创建场景示例 2.创建相机3. 创建立方体并添加网格地面示例 5. 创建渲染器示例 6. 添加效果(移动/雾/相机跟随物体/背景)自动旋转示例效果 相机自动旋转示例 展示效果 实现由远到近的雾示例展示效果 T…

Elasticsearch的写入性能优化

优化Elasticsearch的写入性能需要从多维度入手,包括集群配置、索引设计、数据处理流程和硬件资源等。以下是一些关键优化策略和最佳实践: 一、索引配置优化 合理设置分片数与副本数分片数(Shards):过少会导致写入瓶颈(无法并行),过多会增加集群管理开销。公式参考:分…

FMC STM32H7 SDRAM

如何无痛使用片外SDRAM? stm32 已经成功初始化了 STM32H7 上的外部 SDRAM&#xff08;32MB&#xff09; 如何在开发中无痛使用SDRAM 使它像普通 RAM 一样“自然地”使用? [todo] 重要 MMT(Memory Management Tool) of STM32CubeMx The Memory Management Tool (MMT) disp…

【AIGC】RAGAS评估原理及实践

【AIGC】RAGAS评估原理及实践 &#xff08;1&#xff09;准备评估数据集&#xff08;2&#xff09;开始评估2.1 加载数据集2.2 评估忠实性2.3 评估答案相关性2.4 上下文精度2.5 上下文召回率2.6 计算上下文实体召回率 RAGas&#xff08;RAG Assessment)RAG 评估的缩写&#xff…

VuePress完美整合Toast消息提示

VuePress 整合 Vue-Toastification 插件笔记 记录如何在 VuePress 项目中整合使用 vue-toastification 插件&#xff0c;实现优雅的消息提示。 一、安装依赖 npm install vue-toastification或者使用 yarn&#xff1a; yarn add vue-toastification二、配置 VuePress 客户端增…

C#学习12——预处理

一、预处理指令&#xff1a; 解释&#xff1a;是在编译前由预处理器执行的命令&#xff0c;用于控制编译过程。这些命令以 # 开头&#xff0c;每行只能有一个预处理指令&#xff0c;且不能包含在方法或类中。 个人理解&#xff1a;就是游戏里面的备战阶段&#xff08;不同对局…

开疆智能Profinet转Profibus网关连接CMDF5-8ADe分布式IO配置案例

本案例是客户通过开疆智能研发的Profinet转Profibus网关将PLC的Profinet协议数据转换成IO使用的Profibus协议&#xff0c;操作步骤如下。 配置过程&#xff1a; Profinet一侧设置 1. 打开西门子组态软件进行组态&#xff0c;导入网关在Profinet一侧的GSD文件。 2. 新建项目并…

(三)Linux性能优化-CPU-CPU 使用率

CPU使用率 user&#xff08;通常缩写为 us&#xff09;&#xff0c;代表用户态 CPU 时间。注意&#xff0c;它不包括下面的 nice 时间&#xff0c;但包括了 guest 时间。nice&#xff08;通常缩写为 ni&#xff09;&#xff0c;代表低优先级用户态 CPU 时间&#xff0c;也就是进…

Digital IC Design Flow

Flow介绍 1.设计规格 架构师根据市场需求制作算法模型(Algorithm emulation)及芯片架构(Chip architecture),确定芯片设计规格书(Chip design specification) 原型验证 原型验证(Prototype Validation)通常位于产品开发流程的前期阶段,主要是在设计和开发的初步阶…

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…

LangChain工具集成实战:构建智能问答系统完整指南

导读&#xff1a;在人工智能快速发展的今天&#xff0c;如何构建一个既能理解自然语言又能调用外部工具的智能问答系统&#xff0c;成为许多开发者面临的核心挑战。本文将为您提供一套完整的解决方案&#xff0c;从LangChain内置工具包的基础架构到复杂系统的工程实践。 文章深…

P3156 【深基15.例1】询问学号

P3156 【深基15.例1】询问学号 - 洛谷 数据结构-线性表 #include<bits/stdc.h> using namespace std; int n,m,a[2000005]; int main(){cin>>n>>m;for(int i1;i<n;i)cin>>a[i];//使用数组模拟线性表while(m--){int k;cin>>k;cout<<a[…

衡量嵌入向量的相似性的方法

衡量嵌入向量的相似性的方法 一、常见相似性计算方法对比 方法核心原理公式优点缺点适用场景余弦相似度计算向量夹角的余弦值,衡量方向相似性,与向量长度无关。$\text{cos}\theta = \frac{\mathbf{a} \cdot \mathbf{b}}{\mathbf{a}\mathbf{b}欧氏距离计算向量空间中的直线距离…

小番茄C盘清理:专业高效的电脑磁盘清理工具

在使用电脑的过程中&#xff0c;我们常常会遇到系统盘空间不足、磁盘碎片过多、垃圾文件堆积等问题&#xff0c;这些问题不仅会导致电脑运行缓慢&#xff0c;还可能引发系统崩溃。为了解决这些问题&#xff0c;小番茄C盘清理应运而生。它是一款专业的C盘清理软件&#xff0c;能…

【版本控制】Git 和 GitHub 入门教程

目录 0 引言1 Git与GitHub的诞生1.1 Git&#xff1a;Linus的“两周奇迹”&#xff0c;拯救Linux内核1.2 GitHub&#xff1a;为Git插上协作的翅膀1.3 协同进化&#xff1a;从工具到生态的质变1.4 关键历程时间轴&#xff08;2005–2008&#xff09; 2 Git与GitHub入门指南2.1 Gi…

Dify源码教程:账户和密码传递分析

概述 Dify系统中账户创建过程中的密码处理是Web应用安全的重要环节。本教程详细分析了从前端表单到后端存储的完整流程&#xff0c;展示了Dify如何安全地处理用户凭据。 前端部分 在 dify/web/app/install/installForm.tsx 文件中&#xff0c;当用户填写完表单并点击安装按钮…

window查看SVN账号密码

背景 公司的SVN地址发生迁移&#xff0c;想迁移一下本地SVN地址&#xff0c;后来发现SVN账号密码忘记了。写此文章纯记录。 迁移SVN地址&#xff1a; 找到svn目录点击relocate&#xff0c;输入新的svn地址&#xff0c;如需输入账号密码&#xff0c;输入账号密码即完成svn地址…

Read View在MVCC里如何工作

Read View的结构 Read View中有四个重要的字段&#xff1a; m_ids&#xff1a;创建 Read View 时&#xff0c;数据库中启动但未提交的「活跃事务」的事务 id 列表 。min_trx_id&#xff1a;创建 Read View 时&#xff0c;「活跃事务」中事务 id 最小的值&#xff0c;即 m_ids …

如何在mac上安装podman

安装 Podman 在 macOS 上 在 macOS 上安装 Podman 需要使用 Podman 的桌面客户端工具 Podman Desktop 或通过 Homebrew 安装命令行工具。 使用 Homebrew 安装 Podman&#xff1a; (base) ninjamacninjamacdeMacBook-Air shell % brew install podman > Auto-updating Hom…