PyTorch常用函数总结(持续更新)
本文主要记录自己在用 PyTorch复现经典模型 过程中遇到的一些函数及用法,以期对 常见PyTorch函数 更加熟练~
官方Docs:PyTorch documentation — PyTorch 2.6 documentation
目录
数据层面
torch.sign(tensor)
torch.tensor(np.eye(3)[y])
torch.ones() / torch.sum(dim=0)
torch.unsqueeze()升维 & torch.squeeze()降维
torch.mm() / torch.matmul() / torch.mul()
torch.clamp_()
torch.tensor().item()
torch.tensor().view()
torch.gather()
torch.pow()
torch.stack() / torch.cat()
torch.tensor().t()
torch.manual_seed()
torch.empty()
torch.einsum()
torch.randn() / torch.randint()
模型层面
TensorDataset() / Dataset() / DataLoader()
nn.MSELoss() / nn.BCELoss()
optim.Adam() 等优化器
torch.nn.Sigmoid() / torch.nn.Softmax()
nn.ModuleList() / nn.ParameterList()
数据层面
torch.sign(tensor)
sign函数就是符号函数,大于0的输入变为1输出,小于0的输入变为-1输出,0输出为0。如下:
>>> a = torch.tensor([0.7, -1.2, 0., 2.3])
>>> torch.sign(a)
tensor([ 1., -1., 0., 1.])
可以在该函数上做一些变种,如单位阶跃函数:
import torch
theta = lambda t: (torch.sign(t) + 1.) / 2.
torch.tensor(np.eye(3)[y])
import numpy as npa=np.eye(3) # 生成对角线全是1,其余全是0的3维矩阵
print(a)a=np.eye(4,k=1) # k=1表示全是1的那条对角线往右上走一格(只有3个1了)
print(a)a=np.eye(4,k=-1) # k=-1表示全是1的那条对角线往左下走一格(只有3个1了)
print(a)a=np.eye(4,k=-3) # k=-3表示全是1的那条对角线往左下走三格(只有1个1了)
print(a)
结果:
[[1. 0. 0.][0. 1. 0.][0. 0. 1.]][[0. 1. 0. 0.][0. 0. 1. 0.][0. 0. 0. 1.][0. 0. 0. 0.]][[0. 0. 0. 0.][1. 0. 0. 0.][0. 1. 0. 0.][0. 0. 1. 0.]][[0. 0. 0. 0.][0. 0. 0. 0.][0. 0. 0. 0.][1. 0. 0. 0.]]
torch.tensor(np.eye(3)[y]) 为 标签label 转 one-hot向量 的一种写法:
- np.eye(3)[y] 使用y,即label中的值作为索引,选择单位矩阵中对应的行
- y的三个元素依次为0、2、2,代表依次选择第0行、第2行、第2行
import torch
import numpy as npy = torch.tensor([0, 2, 2])
y_onehot = torch.tensor(np.eye(3)[y])
print(y_onehot)tensor([[1., 0., 0.],[0., 0., 1.],[0., 0., 1.]], dtype=torch.float64)
torch.ones() / torch.sum(dim=0)
a = torch.ones((2, 3)) # 两行三列、全为1的矩阵
print(a)tensor([[1., 1., 1.],[1., 1., 1.]])a1 = torch.sum(a)
a2 = torch.sum(a, dim=0) # 列优先
a3 = torch.sum(a, dim=1) # 行优先print(a1) tensor(6.)
print(a2) tensor([2., 2., 2.])
print(a3) tensor([3., 3.])
如果加上keepdim=True,则会保持dim的维度不被squeeze
a2 = torch.sum(a, dim=0, keepdim=True) # keepdim=True的结果也是二维,即两个[[
a3 = torch.sum(a, dim=1, keepdim=True)print(a2) tensor([[2., 2., 2.]])
print(a3) tensor([[3.],[3.]])
torch.unsqueeze()升维 & torch.squeeze()降维
torch.unsqueeze() 函数起升维的作用,参数dim 表示在哪个地方加一个维度
- 注意dim范围。比如输入input是一维,则dim=0时数据为行方向扩,dim=1时为列方向扩,再大错误
x = torch.tensor([1, 2, 3, 4]) # torch.Size([4])y = torch.unsqueeze(x, 0) # 在第0维扩展,第0维大小为1
y, y.shape # (tensor([[1, 2, 3, 4]]), torch.Size([1, 4]))y = torch.unsqueeze(x, 1) # 在第1维扩展,第1维大小为1
y, y.shape
'''
(tensor([[1],[2],[3],[4]]),torch.Size([4, 1]))
'''y = torch.unsqueeze(x, -1) # 在最后一维扩展,最后一维大小为1
# 结果同在第1维扩展
torch.squeeze() 函数的功能是维度压缩,返回一个tensor(张量),其中 input中维度大小为1的所有维都被删除。举个例子,如果 input 的形状为 (A×1×B×C×1×D),那么返回的tensor形状为 (A×B×C×D)
torch.squeeze(input, dim=None, out=None)
当给定dim 时,只在给定的维度上进行压缩操作,注意给定的维度大小必须是1,否则不能进行压缩。举个例子:如果 input 的形状为 (A×1×B),squeeze(input, dim=0)后,返回的tensor不变,因为第0维的大小为A,不是1;squeeze(input, dim=1)后,返回的tensor将被压缩为 (A×B)
torch.mm() / torch.matmul() / torch.mul()
torch.mm() 只适合二维张量的矩阵乘法,如 m*n 和 n*p 输出为 m*p
A = torch.tensor([[1, 2], [3, 4]])
B = torch.tensor([[5, 6], [7, 8]])
result = torch.mm(A, B) 或 result = torch.matmul(A, B) 二维时两者等价tensor([[19, 22],[43, 50]])
若三维或更高维度,可以用 torch.matmul();同时它也支持矩阵与向量的乘法、向量与向量的点积。如例:
# 矩阵与向量乘法
A = torch.tensor([[1, 2], [3, 4]])
v = torch.tensor([1, 1])
result = torch.matmul(A, v)tensor([3, 7])# 向量与向量乘法
v1 = torch.tensor([1, 2])
v2 = torch.tensor([3, 4])
result = torch.matmul(v1, v2) # 1*3 + 2*4 = 11tensor(11)
而 torch.mul() 是两个矩阵的元素对位相乘,即哈达玛积。故输入的两个矩阵维度必须一致,返回的仍是同维度的矩阵
# 两个张量乘法
A = torch.tensor([1, 2, 3])
B = torch.tensor([4, 5, 6])
result = torch.mul(A, B)tensor([4, 10, 18])# 张量与标量乘法
A = torch.tensor([1, 2, 3])
result = torch.mul(A, 2)tensor([2, 4, 6])
更多张量乘法见Pytorch常用乘法函数总结:torch.mul()、*、torch.mm()、torch.bmm()、torch.mv()、torch.dot()、@、torch.matmul()-CSDN博客
torch.clamp_()
torch.clamp_(input, min, max, out=None) → Tensor
将输入input张量每个元素的值压缩到区间 [min, max],并直接将结果返回给这个tensor(而不是返回新的tensor)
tensor = torch.tensor([[-1, 2], [3, 10], [15, -5]])
# 使用clamp_限制张量的值在0到5之间
tensor.clamp_(0, 5) 或 torch.clamp_(tensor, 0, 5)tensor([[0, 2],[3, 5],[5, 0]])
若为torch.clamp() ,即没有下划线,则返回一个新的tensor
clamped_tensor = torch.clamp(tensor, 0, 5)# tensor本身不会改变,clamped_tensor将包含限制后的值
pytorch中,一般来说,如果对tensor的一个函数后加了下划线,表明这是一个in-place类型(当在一个tensor上操作了之后,是直接修改了这个tensor,而不是返回一个新的tensor而并不修改旧的tensor)
torch.tensor().item()
.item() 返回的是一个浮点型数据。在求loss或者accuracy时,一般使用 .item()
import torch
x = torch.randn(2, 2) # 2行2列
print(x)
print(x[1,1])
print(x[1,1].item())tensor([[ 0.4702, 0.5145],[-0.0682, -1.4450]])
tensor(-1.4450)
-1.445029854774475
torch.tensor().view()
用于tensor维度的重构,即返回一个有相同数据、但不同维度的tensor
view函数的操作对象应该是tensor类型。如果不是tensor类型,可以通过 torch.tensor() 来转换
temp = [1,2,3,4,5,6] # temp的类型为list,非Tensor
temp = torch.tensor(temp) # 将temp由list类型转为Tensor类型。torch.Size([6])print(temp.view(2,3)) # 将temp的维度改为2*3
print(temp.view(2,3,1)) # 将temp的维度改为2*3*1
print(temp.view(2,3,1,1)) # 更多的维度也没有问题,只要保证维度改变前后的元素个数相同就行,即2*3*1*1=6
特殊用法:
- 如果某个参数为-1,表示该维度取决于其他维度,由Pytorch自己计算得到;
- 如果直接view(-1),表示将tensor转为一维tensor
temp = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(temp) # torch.Size([2, 3])
print(temp.view(-1)) # 多维张量转为一维张量tensor([1, 2, 3, 4, 5, 6])
torch.gather()
从原tensor中获取指定dim和指定index的数据。方便从批量tensor中获取指定索引下的数据,该索引是高度自定义且可乱序的
torch.gather(input, dim, index)
- dim:dim=1 表示按照行号进行索引;dim=0 表示按照列号进行索引
- index:索引张量,指定要从input的dim维度上提取哪些元素。index的大小应和返回结果相同
例1:在0维上gather(按照列号)
import torchx = torch.tensor([[10, 20, 30], [40, 50, 60], [70, 80, 90]])index = torch.tensor([[0, 2, 1], [1, 0, 2], [2, 1, 0]])result = torch.gather(x, dim=0, index=index)
print(result)tensor([[10, 80, 60],[40, 20, 90],[70, 50, 30]])
例2:在1维上gather(按照行号)
x = torch.tensor([[10, 20, 30], [40, 50, 60], [70, 80, 90]])index = torch.tensor([[2, 1, 0], [0, 2, 1], [1, 0, 2]])result = torch.gather(x, dim=1, index=index)
print(result)tensor([[30, 20, 10],[40, 60, 50],[80, 70, 90]])
例3:实际应用,获取分类任务中真实类别的预测概率
import torch
import torch.nn.functional as Flogits = torch.tensor([[2.0, 1.0, 0.1], [0.5, 2.1, 1.3]])labels = torch.tensor([[0], [1]]) # 真实类别索引# 计算 softmax 使其成为概率
probs = F.softmax(logits, dim=1) # dim=0 列优先,dim=1 行优先tensor([[0.6590, 0.2424, 0.0986],[0.1863, 0.5141, 0.2996]])# 使用 gather 提取 labels即真实标签 对应的概率
selected_probs = torch.gather(probs, dim=1, index=labels)tensor([[0.6590],[0.5141]])
PyTorch中torch.gather()函数-CSDN博客
torch.gather()函数-CSDN博客
torch.pow()
对输入tensor的分量求幂次运算
a = torch.tensor(3)
b = torch.pow(a,2) # tensor(9) 即3^2=9c = torch.randn(4) # tensor([0.0923, 0.7006, -0.2963, 0.6543])
# 对其中的每个分量求平方
d = torch.pow(c,2) # tensor([0.0085, 0.4909, 0.0878, 0.4282])
PyTorch 笔记(05)— Tensor 基本运算(torch.abs、torch.add、torch.clamp、torch.div、torch.mul、torch.pow等)-CSDN博客
torch.stack() / torch.cat()
torch.stack() 将多个形状相同的张量沿着一个新维度进行堆叠,即合并成一个更高维度的张量
torch.stack(tensors, dim=0)
- tensors:一个包含多个张量的序列(例如,列表或元组)。所有张量必须具有相同的形状
- dim:要插入新维度的位置,默认为0
- 返回值:在指定的维度dim上增加了一个新的维度,原始张量的形状在其他维度上保持不变
例1:沿第0维堆叠
import torch# 创建三个形状相同的张量
x1 = torch.tensor([1, 2])
x2 = torch.tensor([3, 4])
x3 = torch.tensor([5, 6])# 沿着第0维堆叠
result = torch.stack([x1, x2, x3], dim=0)print(result)
tensor([[1, 2],[3, 4],[5, 6]])print(result.shape) # 输出: torch.Size([3, 2])
例2:沿第1维堆叠
import torch# 创建三个形状相同的张量,形状为(2,)
x1 = torch.tensor([1, 2])
x2 = torch.tensor([3, 4])
x3 = torch.tensor([5, 6])result = torch.stack([x1, x2, x3], dim=1)print(result)
tensor([[1, 3, 5],[2, 4, 6]])print(result.shape) # 输出: torch.Size([2, 3])
torch.stack() 会在指定维度上增加一个新的维度,而 torch.cat() 是沿着现有维度连接多个张量,张量的形状不会增加新的维度
torch.cat(tensors, dim=0)
- tensors:一个包含多个张量的序列(例如,列表或元组)。这些张量的形状必须在除了指定维度dim之外相同
- dim:要沿着其连接的维度,默认为0,表示沿着行拼接
- 返回值:在指定的维度上将输入的多个张量拼接起来
例1:沿第0维拼接
import torch# 创建两个形状相同的张量
x1 = torch.tensor([[1, 2], [3, 4]])
x2 = torch.tensor([[5, 6], [7, 8]])# 沿着第0维度拼接
result = torch.cat([x1, x2], dim=0)print(result)
tensor([[1, 2],[3, 4],[5, 6],[7, 8]])print(result.shape) # 输出: torch.Size([4, 2])
例2:沿第1维拼接
import torch# 创建两个形状相同的张量
x1 = torch.tensor([[1, 2], [3, 4]])
x2 = torch.tensor([[5, 6], [7, 8]])result = torch.cat([x1, x2], dim=1)print(result)
tensor([[1, 2, 5, 6],[3, 4, 7, 8]])print(result.shape) # 输出: torch.Size([2, 4])
例3:拼接不同维度的张量(这些张量的形状必须在除了指定维度dim之外相同)
# 创建两个形状不同的张量
x1 = torch.tensor([[1, 2], [3, 4]]) # (2, 2)
x2 = torch.tensor([[5, 6]]) # (1, 2)# 沿着第0维度拼接
result = torch.cat([x1, x2], dim=0)print(result)
tensor([[1, 2],[3, 4],[5, 6]])print(result.shape) # 输出: torch.Size([3, 2])
例4:拼接张量和标量
# 创建张量和标量
x1 = torch.tensor([1, 2, 3])
scalar = torch.tensor([4])# 沿着第 0 维度拼接
result = torch.cat([x1, scalar], dim=0)print(result)
tensor([1, 2, 3, 4])
torch.tensor().t()
将tensor进行转置
import torch
a = torch.tensor([[1,2],[3,4]])a
tensor([[1, 2],[3, 4]])a.t()
tensor([[1, 3],[2, 4]])
Pytorch里.t()的作用-CSDN博客
torch.manual_seed()
用于设置随机数生成器种子,确保每次运行时生成相同的随机数序列。通常,用于确保实验的可复现性,特别是在训练深度学习模型时,需要确保每次训练模型的初始化权重和数据的随机划分一致
torch.manual_seed(seed) # seed为一个整数。一般设置为 42
torch.manual_seed() 只会影响在CPU上的随机数生成。如果使用了GPU,还需要设置GPU上的随机数种子
# 设置GPU上的随机数种子
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed) # 如果使用多个GPU
注:如果代码中还使用了numpy,也可以设置numpy的随机种子,使得整个实验过程是可复现的
np.random.seed(seed)
参考:pytorch如何确保 可重复性/每次训练结果相同(固定了随机种子,为什么还不行)? - Cheer-ego的回答 - 知乎
torch.empty()
创建一个具有指定形状、但内容未定义,即未经初始化(不会被初始化为零或者任何其他值)的张量。由于不进行任何初始化工作,它比 torch.zeros() 或 torch.randn() 等初始化函数更快
# *表示必选,其余参数都为可选
torch.empty(*size, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- size:张量的形状,可以是整数或元组。如 (2, 3) 表示一个2×3的张量
- dtype:张量的数据类型,默认为torch.float32
- layout:张量的布局,默认为torch.strided,通常不需要改
- device:张量存储的设备,默认CPU,通过 torch.device('cuda') 可以将张量创建在GPU上
# 创建一个2x2的未初始化张量,并放到GPU上
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
tensor_gpu = torch.empty(2, 2, device=device)
- requires_grad:默认为False。如果设置为True,则张量将追踪其所有操作,支持自动求导(用于神经网络训练)
应用场景:
- 模型权重初始化
tensor = torch.empty(3, 3) # 创建一个未初始化的张量
torch.nn.init.normal_(tensor, mean=0.0, std=1.0) # 使用正态分布初始化
- 高效内存分配:知道张量的形状,但暂时不关心其内容时,可以使用 torch.empty() 创建一个张量,并稍后填充或更新它的内容
# 多任务学习的一个例子
task1_dim, task2_dim = 3, 2
y_train_task1 = torch.empty(num_samples, task1_dim)
y_train_task1[:, 0] = torch.randint(0, 2, (num_samples,)).float() # 是否停留
y_train_task1[:, 1] = torch.randn(num_samples) # 停留时长
y_train_task1[:, 2] = torch.randint(0, 2, (num_samples,)).float() # 是否点击y_train_task2 = torch.empty(num_samples, task2_dim)
y_train_task2[:, 0] = torch.randn(num_samples) # 点击后播放时长
y_train_task2[:, 1] = torch.randint(0, 2, (num_samples,)).float() # 播放后是否点赞
torch.einsum()
爱因斯坦求和约定
- 提供了一种灵活且高效的方式来执行各种线性代数操作(如矩阵乘法、矩阵转置、向量点积、外积)、广播操作、求和或聚合操作(如矩阵迹)等
- 通过符号表示操作中的维度来描述操作,而不需要显式地使用循环或中间张量
torch.einsum(equation, *operands)
- equation:一个字符串,指定了操作的维度及求和的规则(通过字母表示张量的维度,维度之间用逗号分隔)
- operands:需要操作的张量,可以是多个张量
矩阵乘法:(m, n) 与 (n, p) -> (m, p)
torch.einsum('ij,jk->ik', A, B)
向量点积:对应元素相乘并求和,即dot product
torch.einsum('i,i->', a, b)
向量外积(outer product):假设向量a 和 向量b 的维度分别是 (m) 和 (n),通过将 向量a 中的每个元素和 向量b 中的每个元素相乘,生成一个 (m, n)维度 的矩阵
torch.einsum('i,j->ij', a, b)
矩阵转置:
torch.einsum('ij->ji', A)
广播:torch.einsum('ij,j->ij', A, B) 表示将A的每一列与B对应的元素相乘,从而实现广播
A = torch.tensor([[1, 2, 3, 4],[1, 1, 1, 1],[4, 3, 2, 1]]) # torch.Size([3, 4])
B = torch.tensor([2, 2, 2, 2]) # torch.Size([4])# 广播
result = torch.einsum('ij,j->ij', A, B)print(result)
tensor([[2, 4, 6, 8],[2, 2, 2, 2],[8, 6, 4, 2]]) # torch.Size([3, 4])
矩阵迹(trace):矩阵对角线元素的和
torch.einsum('ii->', A)
torch.randn() / torch.randint()
torch.randn() 用于生成服从标准正态分布(均值为0,标准差为1)的随机浮点数
# *表示必选,其余参数都为可选
torch.randn(*size, dtype=None, device=None, requires_grad=False)
- size:生成张量的形状,可以是一个整数或一个整数元组
- dtype:张量的数据类型,默认为torch.float32
- device:默认为CPU。如果需要创建GPU上的张量,可以使用 torch.device('cuda') 或指定 device='cuda'
- requires_grad:是否需要计算梯度,默认False
常见用途:初始化神经网络权重、生成噪声、随机生成生态分布数据
torch.randint() 用于生成指定范围内的整数随机数,并可以指定张量的形状。返回一个包含随机整数的张量,生成的整数值是离散的,形状由size指定,生成的数值位于 [low, high) 之间
# *表示必选,其余参数都为可选
torch.randint(*low, *high, *size, dtype=None, device=None, requires_grad=False)
- low:生成的随机数的下限(包含)
- high:生成的随机数的上限(不包含)
- dtype:默认为torch.int64
- 其它参数同上
常见用途:随机生成整数类型的标签(如分类标签)或索引、生成数据集的随机批次索引
两者对比:
模型层面
TensorDataset() / Dataset() / DataLoader()
from torch.utils.data import TensorDataset, Dataset, DataLoader
TensorDataset 通常用于将特征张量和标签张量组合在一起,封装成一个数据集对象,便于传递给模型训练
# *tensors可以是任意数量的张量,但必须保证第一个维度都相同
torch.utils.data.TensorDataset(*tensors)
- 每个张量的第一个维度(代表样本数量)应该是相同的,因为这些张量会按行组合起来,每一行代表一个样本
- 返回一个可迭代的数据集对象,可以通过DataLoader将其包装成一个数据加载器,以便按批次加载数据
应用:
dataset = TensorDataset(features, labels)# 如果数据集包含多个特征和多个标签
dataset = TensorDataset(features1, features2, labels1, labels2) # 将两个特征张量和两个标签张量组合在一起,每个批次中返回四个元素
Dataset 是用于表示数据集的基类,可以通过继承 torch.utils.data.Dataset 类来定义自己的数据集类(自定义如何加载数据、如何处理数据)。需要实现两个方法:
- __len__():返回数据集的大小,即数据集中样本的数量
- __getitem__(index):根据索引返回数据集中一个样本,通常是特征和标签。可以在这里进行数据的预处理,如数据增强、归一化、标准化等
import torch
from torch.utils.data import Dataset, DataLoaderclass MyDataset(Dataset):def __init__(self, features, labels):self.features = featuresself.labels = labelsdef __len__(self):return len(self.features) # 数据集的大小def __getitem__(self, idx):# 根据索引返回一个数据样本,包括特征和标签x = self.features[idx]y = self.labels[idx]return x, y# 创建自定义数据集实例
dataset = MyDataset(features, labels)
DataLoader 用于批量加载数据,通常与 TensorDataset 或自定义的数据集类一起使用。提供了批量加载(将数据按批次加载到内存中进行训练。batch_size)、数据打乱(帮助提高模型训练的泛化能力。shuffle)、并行加载(使用多线程并行加载数据,提高数据加载速度。num_workers)、自动迭代(类似于迭代一个list)等功能
torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,batch_sampler=None, num_workers=0, collate_fn=None,pin_memory=False, drop_last=False, timeout=0,worker_init_fn=None)
-
dataset
: 传入的数据集对象。它可以是TensorDataset
、Dataset
的子类或自定义的数据集类,必须实现__len__
和__getitem__
方法。 -
batch_size
(int, default=1): 每个批次包含的样本数量。 -
shuffle
(bool, default=False): 是否在每个epoch结束后打乱数据。设置为True
会对数据进行随机打乱,这在训练过程中通常是必需的。 -
sampler
(torch.utils.data.Sampler, optional): 通常用于定制数据抽取方式。可以选择不使用shuffle
,而使用自定义的sampler
。 -
batch_sampler
(torch.utils.data.BatchSampler, optional): 类似于sampler
,但返回批次样本。 -
num_workers
(int, default=0): 用于加载数据的子进程数量。设置为大于0时,DataLoader
将在多个进程中并行加载数据(通常会提升加载速度)。一般来说,num_workers
设置为系统 CPU 核心数的 1-2 倍比较合适。 -
collate_fn
(callable, optional): 用于将一个批次内的数据组合成一个小批量。可以根据需要自定义,如填充、拼接等。 -
pin_memory
(bool, default=False): 如果设置为True
,DataLoader
会将数据加载到内存中并进行内存页锁定,这在使用GPU加速时可能提高性能。 -
drop_last
(bool, default=False): 如果设置为True
,在数据集大小不能被batch_size
整除时,会丢弃最后一个不满批次的数据。 -
timeout
(int, default=0): 如果设置为正值,则表示加载数据时最大超时时间(秒)。一般不常用,除非遇到数据加载卡顿的情况。 -
worker_init_fn
(callable, optional): 如果使用多进程加载数据,可以传入一个函数,用于在每个子进程初始化时执行自定义操作(例如设置随机种子)。
例1:基本使用
import torch
from torch.utils.data import TensorDataset, DataLoader# 特征张量和标签张量
features = torch.randn(10, 5) # 10个样本,每个样本有 5个特征
labels = torch.randint(0, 2, (10,)) # 10个标签,0或1# 创建TensorDataset
dataset = TensorDataset(features, labels)# 使用 DataLoader创建批量加载器
dataloader = DataLoader(dataset, batch_size=3, shuffle=True)# 迭代 DataLoader,按批次加载数据
for data in dataloader:inputs, targets = dataprint(inputs.shape, targets.shape)torch.Size([3, 5]) torch.Size([3])
torch.Size([3, 5]) torch.Size([3])
torch.Size([3, 5]) torch.Size([3])
torch.Size([1, 5]) torch.Size([1])
例2:自定义collate_fn函数
- 用于定义如何将一个批次内的数据组合成一个小批量
- 如下例,collate_fn 将批次数据按最大长度进行填充,使得每个输入张量的长度相同。适用于处理变长序列数据(如文本、时间序列等)
# 自定义处理批次数据(例如填充到相同的长度)
def collate_fn(batch):# 将一个包含多个元组的列表(或可迭代对象)解包为两个独立的列表(或元组)inputs, targets = zip(*batch)max_len = max([len(x) for x in inputs])# 假设想要按最大长度填充数据padded_inputs = [torch.cat([x, torch.zeros(max_len - len(x))]) for x in inputs]return torch.stack(padded_inputs), torch.tensor(targets)# 创建 DataLoader,使用自定义的 collate_fn
dataloader = DataLoader(dataset, batch_size=3, collate_fn=collate_fn)# 迭代 DataLoader
for data in dataloader:inputs, targets = dataprint(inputs)print(targets)
参考 Pytorch的数据读取机制:Dataset类 & DataLoader类以及collate_fn参数
nn.MSELoss() / nn.BCELoss()
import torch.nn as nn
nn.MSELoss() 是用于计算均方误差(Mean Squared Error,MSE)的损失函数,常用于回归问题。相较于 nn.L1Loss(),MSELoss更加敏感于离群点(Outliers),因为它使用了平方项,离群点的影响被放大;而 L1Loss() 使用的是绝对值,对离群点的影响较小。
- 参数:reduction(可选,默认是 'mean' )
- mean:返回所有样本的损失均值
- sum:返回所有样本的损失总和
- none:返回一个张量,包含每个样本的损失值
- 训练神经网络时,如果使用MSELoss,输出层通常是线性激活,即没有激活函数,或使用ReLU / Tanh 等
import torch
import torch.nn as nn# 假设我们有一些预测值和真实值
y_true = torch.tensor([1.0, 2.0, 3.0])
y_pred = torch.tensor([1.5, 2.5, 3.5])# 定义 MSELoss
mse_loss = nn.MSELoss()# 计算 MSE损失
loss = mse_loss(y_pred, y_true)
print(f'MSE Loss: {loss.item()}') # MSE Loss: 0.25
nn.BCELoss() 是用于二分类问题的二进制交叉熵损失函数(Binary Cross Entropy Loss),要求预测值是一个概率值(介于0~1),通常需要使用Sigmoid函数;标签必须是二分类标签(0或1)
- 参数:reduction(可选,默认是 'mean' ),用法同上,可以选择返回均值、总和或每个样本的损失
- 如果模型输出的不是概率值(即通过Sigmoid进行归一化的值),而是原始的未归一化分数(logits),可以使用 nn.BCEWithLogitsLoss() 。该损失函数会自动对logits进行Sigmoid操作,而无需显式地在模型输出中应用Sigmoid
optim.Adam() 等优化器
import torch.optim as optim optimizer = optim.Adam(model.parameters(), lr=0.001)
Pytorch提供了多种优化器:
- optim.SGD:使用梯度下降的随机版本更新参数。缺点是易陷入局部最小值,且收敛速度较慢
- lr:学习率(需要手动调整)
- momentum:动量,用来加速收敛,减少震荡,避免陷入局部最小值
- weight_decay:L2正则化系数
- optim.Adagrad:根据每个参数的历史梯度自适应调整学习率
- 对于稀疏梯度有很好的表现
- 对于长期训练可能导致学习率下降太快(变为0,停止训练),从而无法收敛
- optim.RMSprop:是一种自适应学习率的优化器,在序列数据如RNN中表现优异
- lr:学习率
- alpha:衰减因子,控制过去梯度的影响
- weight_decay:L2正则化系数
- optim.Adam:是SGD的一个改进版本,结合了 Momentum 和 RMSprop 的优点,能自动调整每个参数的学习率,故通常不需要过多的超参数调整
- 对于稀疏梯度表现较好;比普通的SGD更稳定,不容易陷入局部最小值
- 某些情况下比SGD更容易过拟合,尤其是当训练集较小时
- optim.Adadelta:是Adagrad的改进版本,旨在解决Adagrad在训练时学习率下降过快的问题
- optim.NAdam:是Adam和Nesterov动量的结合。由于Nesterov加速的优势,可能加速收敛;但计算开销相对较大,训练时间较长
- optim.FTRL:适用于稀疏特征的优化,常用于大规模机器学习问题
- optim.LBFGS:是一种基于二阶优化方法的算法,适用于较小的数据集和模型,常用于精细调优阶段,收敛速度较快,能得到更精确的最优解
- optim.SparseAdam:是Adam的稀疏版本,通常用于处理具有稀疏梯度的模型(如嵌入层)
- optim.ASGD:基于SGD的变种,结合了平均化策略来减少震荡。比传统SGD更稳定,但适用于特定类型的任务,故不常用
不同优化器对比参考 七种反向传播优化器总结及Python实现(SGD、SGDM、Adagrad、RMSProp、Adam、NAG、AdaDelta)
torch.nn.Sigmoid() / torch.nn.Softmax()
torch.nn.Sigmoid() 将输入值映射到一个 0~1 之间的输出(会对张量的每个元素应用Sigmoid函数),常用于二分类问题中的输出层,尤其是需要输出概率值的情况
- 除了 nn.Sigmoid() 模块,还可以直接使用 torch.sigmoid() 函数
如二分类模型最后一层通常是一个Sigmoid激活函数,将模型输出映射到0~1之间,表示某一类的概率(如输出0.8表示模型认为该样本属于正类的概率为80%):
# 模型的输出层定义
output_layer = nn.Linear(in_features, 1) # 输出一个标量
output = nn.Sigmoid(output_layer(x))
问题:在输入值较大或较小时(即接近0或接近1),梯度会变得非常小,几乎为0,这可能导致训练时出现梯度消失。因此Sigmoid不适合用在隐藏层,而通常用于输出层
- vs ReLU:ReLU输出范围是 (0, +∞),常用于隐藏层的激活函数,相对于Sigmoid能更有效地避免梯度消失问题
- vs Tanh:Tanh输出范围是 (-1, 1),与Sigmoid相比,Tanh在训练时通常表现得更好,因为它的输出对称性使得模型的学习更加稳定
torch.nn.Softmax() 将输入的多个值转换为一个概率分布,输出的概率值和为1,通常用于多分类任务的输出层
- 参数dim:决定沿哪个维度应用softmax
- dim=0:通常是batch维度,适用于对每个样本的类别进行归一化
- dim=1:通常是样本维度,是大多数多分类任务的标准做法
- 参数dtype:指定返回张量的数据类型,通常是浮点数类型
- 等价写法:torch.softmax(x, dim=1) 函数
- 若输入得分非常大或非常小,可能导致数值上的不稳定。因此,通常会对输入进行缩放处理(例如减去每行的最大值)。上面两种softmax写法都已经自动进行了数值稳定性处理,不需要再手动处理
例1:以二维输入为例
import torch.nn as nninput = torch.tensor([[1., 2, 3],[4, 5, 6]]) # input必须为float类型m1 = nn.Softmax(dim=0)
output1 = m1(input)m2 = nn.Softmax(dim=1) # dim=1表示在每一行(即每个样本)上应用Softmax
output2 = m2(input)# dim=-1就是按最后一维,这个例子里等价于dim=1
- 二维tensor参考:【Pytorch】torch.nn. Softmax()_torch.softmax-CSDN博客
- 多维tensor可以参考:Pytorch nn.Softmax(dim=?) - 知乎
例2:在训练多分类模型时,常常使用 torch.nn.CrossEntropyLoss,它会自动应用softmax(不需要在模型的输出层显式使用softmax,而是可以直接输出未经softmax归一化的原始得分,即logits)
# 定义 CrossEntropyLoss
criterion = nn.CrossEntropyLoss()# y_pred是未经Softmax处理的logits,y_true是标签(整数索引)
y_pred = torch.tensor([[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]])
y_true = torch.tensor([2, 1])# 计算损失
loss = criterion(y_pred, y_true)
print(f'CrossEntropyLoss: {loss.item()}')
nn.ModuleList() / nn.ParameterList()
nn.ModuleList() 是一个用于保存 nn.Module对象的容器,是一个有序的容器,可以按顺序存储多个子模块(如多个卷积层、全连接层等)。在Pytorch中,它能够保证其中的每个模块都被正确地注册到模型中,且可以通过 .parameters() 自动获取模型中的所有参数
- 所有的子模块会被自动地添加到模型的参数列表中
- 在模型的forward函数中可以动态地通过索引调用各个子模块
import torch
import torch.nn as nnclass ExampleModel(nn.Module):def __init__(self):super(ExampleModel, self).__init__()self.layers = nn.ModuleList([nn.Conv2d(1, 32, 3), nn.Conv2d(32, 64, 3)])def forward(self, x):for layer in self.layers:x = layer(x)return x
nn.ParameterList() 是专门用于存储 nn.Parameter 对象(nn.Parameter是torch.Tensor的一个子类,用于存储模型中的参数,如权重和偏置)的容器。用于管理模型中手动创建的、通常需要进行梯度更新的参数
- 适用于存储多个独立的参数,如自定义的权重、偏置等
- 不会自动注册任何模块,仅仅用于管理参数,这些参数可以直接参与优化过程
import torch
import torch.nn as nnclass ExampleModel(nn.Module):def __init__(self):super(ExampleModel, self).__init__()self.weights = nn.ParameterList([nn.Parameter(torch.randn(3, 3)) for _ in range(5)])def forward(self, x):for weight in self.weights:x = torch.matmul(x, weight)return x
总结:
nn.ModuleList()
用于存储nn.Module
子模块,主要作用是组织网络层级,确保模块的自动注册nn.ParameterList()
用于存储nn.Parameter
,主要用于管理模型的参数(例如权重和偏置),而不是层或子模块
相关文章:
PyTorch常用函数总结(持续更新)
本文主要记录自己在用 PyTorch复现经典模型 过程中遇到的一些函数及用法,以期对 常见PyTorch函数 更加熟练~ 官方Docs:PyTorch documentation — PyTorch 2.6 documentation 目录 数据层面 torch.sign(tensor) torch.tensor(np.eye(3)[y]) torch.on…...
Docker 常用命令大全
一、启动类 1. 启动 docker systemctl start docker 2. 关闭 docker systemctl stop docker 3. 重新启动 docker systemctl restart docker 4. docker 设置自启动 systemctl enable docker 5. 查看 docker 运行状态 systemctl status docker 6. 查看 docker 版本号等信息 docke…...
单片机裸机编程:状态机与其他高效编程框架
在单片机裸机编程中,状态机是一种非常强大的工具,能够有效管理复杂的逻辑和任务切换。除了状态机,还有其他几种编程模式可以在不使用 RTOS 的情况下实现高效的程序设计。以下是一些常见的方法: 1. 状态机编程 状态机通过定义系统…...
TCP,http,WebSocket
TCP(Transmission Control Protocol,传输控制协议)和HTTP(HyperText Transfer Protocol,超文本传输协议)都是网络通信中的重要协议,但它们在网络协议栈的不同层次上工作,各自负责不同…...
gotool在线工具集
1. 包含各种 sql 处理 2. 包含 json 处理 3. 包含 图片处理 4. 跨平台传输 gotool...
HBuilder X中,uni-app、js的延时操作及定时器
完整源码下载 https://download.csdn.net/download/luckyext/90430165 在HBuilder X中,uni-app、js的延时操作及定时器可以用setTimeout和setInterval这两个函数来实现。 1.setTimeout函数用于在指定的毫秒数后执行一次函数。 例如, 2秒后弹出一个提…...
ow rank decomposition如何用于矩阵的分解
1. 什么是矩阵分解和低秩分解 矩阵分解是将一个矩阵表示为若干结构更简单或具有特定性质的矩阵的组合或乘积的过程。低秩分解(Low Rank Decomposition)是其中一种方法,旨在将原矩阵近似为两个或多个秩较低的矩阵的乘积,从而降低复…...
2.3做logstash实验
收集apache日志输出到es 在真实服务器安装logstash,httpd systemctl start httpd echo 666 > /var/www/html/index.html cat /usr/local/logstash/vendor/bundle/jruby/2.3.0/gems/logstash-patterns-core-4.1.2/patterns/httpd #系统内置变量 cd /usr/local/…...
JAVAweb之过滤器,监听器
文章目录 过滤器认识生命周期FilterConfigFilterChain过滤器执行顺序应用场景代码 监听器认识ServletContextListenerHttpSessionListenerServletRequestListener代码 过滤器 认识 Java web三大组件之一,与Servlet相似。过滤器是用来拦截请求的,而非处…...
IO进程 day05
IO进程 day05 9. 进程9. 9. 守护进程守护进程的特点守护进程创建步骤 10. 线程10.1. 线程的概念10.2. 进程和线程的区别10.2. 线程资源10.3. 线程的函数接口1. pthread_create-创建线程线程函数和普通函数的区别 2. pthread_exit3.线程资源回收函数join和detach的区别 获取线程…...
Mac 散热救星:Macs Fan Control,让你的苹果电脑“冷静”又安静!
各位果粉们,是不是经常遇到这样的烦恼:用着用着电脑,突然就发热卡顿,风扇狂转噪音大得跟拖拉机似的?别担心,今天给大家安利一款超实用的软件 —— Macs Fan Control,它可是让苹果电脑“冷静”又…...
警惕将“数据标注”岗位包装为“大数据工程师”充数
数据标注(Data Annotation)是人工智能和大数据产业链中的基础性工作,其核心任务是为原始数据添加标签或注释,使计算机能够识别和学习数据中的特征,从而训练出更精准的机器学习或深度学习模型。以下是具体解析及它与“大…...
C语言 —— 此去经年 应是良辰好景虚设 - 函数
目录 1. 函数的概念 1.1 库函数 1.2 自定义函数 2. 形参和实参 3. return 语句 4. 数组做函数参数 5. 嵌套调用和链式访问 5.1 嵌套调用 5.2 链式访问 6. 函数的声明和定义 6.1 单个文件 6.2 多个文件 7. static 和 extern 7.1 static 修饰局部变量 7.2 static 修…...
最新前端框架选型对比与建议(React/Vue/Svelte/Angular)
前端框架选型对比与建议(React/Vue/Svelte/Angular) 一、核心框架技术特性对比(基于最新版本) 维度React 19 25Vue 3.5 12Svelte 5 25Angular 19 5核心理念函数式编程、JSX语法、虚拟DOM渐进式框架、组合式API、模板语法编译时框…...
AOP基础-01.快速入门
一.AOP 对于统计每一个业务方法的耗时这一操作,如果再业务层的每一个方法前获取方法运行的开始时间,方法结束获取结束时间,然后计算执行耗时,那这样就太繁琐了。能不能定义一个模板方法,使得该方法能够在业务层的方法执…...
为什么MySQL选择使用B+树作为索引结构
B树是MySQL最常见的索引结构,大部分存储引擎都支持 B 树索引。 相对于其他竞争力强的数据结构,B树都有战胜它们成为大多时候MySQL选择使用索引结构的理由: 第一个强有力的竞争对手是B树: 1. B树每个节点都存储了完整的数据&…...
基于SSA-KELM-Adaboost(麻雀搜索优化的极限学习机自适应提升算法)的多输入单输出回归预测【MATLAB】
SSA-KELM-Adaboost 是一种结合了麻雀搜索算法(SSA)、核极限学习机(KELM)和Adaboost集成学习的复合回归预测模型。该模型通过参数优化与集成策略提升预测精度和鲁棒性,适用于复杂非线性回归问题。以下是其核心理论与…...
分享些常用的工具类
一、照片 1、Unsplash:https://unsplash.com/ 2、pixabay:https://pixabay.com/zh/ 二、壁纸 1、Wallpaper Engine 2、wallhaven:https://wallhaven.cc/ 3、极简壁纸:https://bz.zzzmh.cn/ 三、AI语音 1、微软Azure项目&…...
Apache SeaTunnel 构建实时数据同步管道(最新版)
文章作者 王海林 白鲸开源 数据集成引擎研发 Apache SeaTunnel Committer & PMC Member,Apache SkyWalking Committer,多年平台研发经验,目前专注于数据集成领域。 导读 在当今数字化快速发展的时代,数据已然成为企业决策…...
96.【C语言】解析预处理(4)
目录 5.条件编译 #ifdef 其他条件编译指令 #if 多个分支的条件编译 判断是否被定义 嵌套指令 6.头文件的包含方式 本地文件包含 库文件包含 嵌套文件包含 问题:头文件的重复包含 解决问题:避免头文件的重复包含 方法1:#pragma once 方法2:#ifndef、#define和#en…...
linux用户操作与权限
Linux的root用户 root用户(超级管理员) root用户拥有最大的系统操作权限。 普通用户的权限一般在其home目录内是不受限的,但是出来自己的home目录,仅有只读和执行权限。 su su命令切换到root账号 语法:su [-] [用户…...
Proof Beyond Boundaries: Hong Kong zkNight 活动精彩回顾
2 月 19 日,随着夜幕的降临,一场汇聚行业智慧与前瞻视野的高端主题活动 ——Proof Beyond Boundaries: Hong Kong zkNight,在香港铜锣湾 Vpoint 的 6/F 盛大启幕。本次活动由 ZEROBASE 主办,Techub News 承办,吸引了众…...
QT零基础学习之路(五)--自定义信号和槽
源码地址(优先更新):点击此处...
Pytorch实现之GIEGAN(生成器信息增强GAN)训练自己的数据集
简介 简介:在训练数据样本之前首先利用VAE来推断潜在空间中不同类的分布,用于后续的训练,并使用它来初始化GAN。与ACGAN和BAGAN不同的是,提出的GIEGAN有一个分类器结构,这个分类器主要判断生成的图像或者样本图像属于哪个类,而鉴别器仅判断图像是来自于生成器还是真实样…...
HTTP 动态报错码的原因和解决方法
目录 1xx(信息性状态码) 2xx(成功状态码) 3xx(重定向状态码) 4xx(客户端错误状态码) 5xx(服务器错误状态码) 参考文章 以下是 HTTP 动态报错码的常见原…...
单核处理器编程会简单很多的原因
乱序执行的本质:单核处理器的乱序执行(Out-of-Order Execution)允许指令动态调度以提升效率,但其核心原则是保持程序语义的单线程正确性。所有指令的最终提交(Retirement)必须严格按照程序顺序完成,以确保异常处理、中断和外部观察结果的正确性。 提交阶段的顺序性:尽管…...
C++之vector和list辨析
std::vector 和 std::list 是 C 标准库中两种常用的容器,它们都用于存储和管理元素集合,但在底层实现和性能特性上有显著的区别。 1. 底层实现 std::vector: 基于动态数组实现。元素在内存中是连续存储的。支持随机访问(通过下标访问元素&a…...
C++ 八股(整理记录)
1. 指针和引用的区别 定义与初始化: 指针:可以声明时不初始化,并且可以在之后指向任何同类型的变量。指针是一个变量,它存储的是另一个变量的地址。 int a 10; int* p; // 声明一个指向int的指针 p &a; // 将p指向变量a的…...
docker部署GPU环境
使用 Docker 部署 GPU 环境涉及到几个关键步骤,以下是详细步骤: 1. 安装 NVIDIA 驱动程序 确保你的系统已经安装了 NVIDIA GPU 驱动。这是使用 GPU 的前提条件。 2. 安装 Docker 和 nvidia-container-toolkit 首先,确保你已经安装了 Docker。然后,安装 NVIDIA Containe…...
单片机裸机编程-时机管理
对于 RTOS 实时操作系统,我们是通过 TASK(任务)进行底层操作的,这与裸机编程中的函数(fun)类似。不同的任务或函数实现不同的功能,在RTOS中,单片机有信号量、队列等不同任务之间的通…...
使用VScode开发STM32:基于CMake(包含标准库和HAL库工程)
使用VScode开发STM32:基于CMake(包含标准库和HAL库工程) 本教程使用VScode作为代码编辑工具、Cmake作为构建系统生成器、Make进行构建系统、使用arm-none-eabi-gcc进行交叉编译、使用OpenOCD作为代码下载与调试工具,最终搭建出适…...
Linux操作与权限2
查看权限控制信息 序号1,表示文件,文件夹权限控制信息 序号2,表示文件,文件夹所属用户 序号3,表示文件,文件夹所属用户组 12345678910d/l/-r/-w/-x/-r/-w/-x/-r/-w/-x/- 权限细节总共分为10个槽位 表格1&…...
解析第十一页
多选707、如图所示组网,SWA、SWB、SWC、SWD运行RSTP,则以下说法正确的是? A、可以在SWB的GE0/0/2端口开启边缘端口,让连接终端的接口快速进入转发状态 B、边缘端口收到BPDU之后会重新参与生成树的计算 C、可以在SWC的GEO/0/2端口开启边缘端口,让连接终端的接口快速进入转…...
SQL之order by盲注
目录 一.order by盲注的原理 二.注入方式 a.布尔盲注 b.时间盲注 三.防御 一.order by盲注的原理 order by子句是用于按指定列排序查询结果,列名或列序号皆可。 order by 后面接的字段或者数字不一样,那么这个数据表的排序就会不同。 order by 盲…...
阻止浏览器的默认缩放机制
在移动端浏览器中,当用户点击输入框(如密码输入框)时,页面可能会自动放大以提高可读性。这种行为通常是由于浏览器的默认缩放机制引起的。要阻止这种自动放大行为,可以采取以下几种方法: 使用 viewport 元…...
python 引用父目录:层级的模块
from pathlib import Path import sys 获取 project 目录 project_dir Path(file).resolve().parent.parent 将 project 目录添加到 sys.path 中 sys.path.append(str(project_dir)) 导入 support 模块 import support support.print_func(“Runoob”)...
实用:查找Linux进程调度统计信息的三个方法
实用:查找Linux进程调度统计信息的三个方法 在现代操作系统中,理解进程调度行为对于优化性能和解决瓶颈问题至关重要。本文将详细介绍如何在Linux系统中获取进程从调度队列中调入(enqueue)和调出(dequeue)…...
以下是自定义针对 Vite + TypeScript 项目的完整路径别名配置流程:
以下是针对 Vite TypeScript 项目的完整路径别名配置流程: 1. 安装必要依赖 bash npm install -D types/node 2. 配置 vite.config.ts typescript // vite.config.ts import { defineConfig } from vite import vue from vitejs/plugin-vue import path from pat…...
基于Matlab实现汽车远近光灯识别的详细步骤及代码示例
以下是一个基于Matlab实现汽车远近光灯识别的详细步骤及代码示例,主要通过图像处理技术来区分远光灯和近光灯。 整体思路 图像预处理:包括读取图像、灰度化、去噪等操作,以提高后续处理的准确性。边缘检测:找出图像中的边缘信息…...
Solidity 开发环境
Solidity 开发环境 Solidity编辑器:Solidity编辑器是⼀种专⻔⽤于编写和编辑Solidity代码的编辑器。常⽤的Solidity编辑器包括 Visual Studio Code、Atom和Sublime Text。以太坊开发环境:以太坊开发环境(Ethereum Development Environment&a…...
Ollama+Cherrystudio+beg-m3+Deepseek R1 32b部署本地私人知识库(2025年2月win11版)
之前综合网络各方面信息得到的配置表: 在信息爆炸的时代,数据安全和个性化需求愈发凸显。搭建本地私人知识库,不仅能确保数据的安全性,还能根据个人需求进行个性化定制,实现知识的高效管理和利用。随着技术的不断发展…...
vue3.0将后端返回的word文件流转换为pdf并导出+html2pdf.js将页面导出为pdf
实现思路 1.将Word文档转换为HTML:mammoth.js,它可以将.docx文件转换为HTML 2.将HTML转换为PDF:使用html2pdf.js将HTML转换为PDF 如果想要相同的效果,也可以把前端页面直接导出转换为pdf: 运用的插件:html2pdf.js 后端…...
【心得】缓存穿透与缓存击穿总是记混,一文从英语单词含义角度分析带你区分清楚!
一句话省流版:缓存穿透的英语为cache penetration,可以翻译为缓存渗透,“渗透”联想到网安的攻击渗透,故缓存穿透是绕过防护进行攻击; 缓存击穿的英语为"cache breakdown",可以翻译为缓存故障,“…...
day02
作业2 为 Activity 设置2种不同的启动模式并通过 adb 命令进行查看任务栈信息,并且打印生命周期方法执行日志 step1:生成第二个Activity和相应配置、 一个是singleTask模式,还一个是mainActivity的默认格式 step2:打印生命周期…...
JavaScript 简单类型与复杂类型-堆和栈
深入理解JavaScript中的简单类型(基本数据类型)与复杂类型(引用数据类型)如何在内存中存储对于编写高效、无误的代码至关重要。本文将探讨这两种类型的差异,以及它们在内存中的存储机制——栈(Stack&#x…...
五、AIGC大模型_04LLaMA-Factory基础知识与SFT实战
1、LLaMA-Factory 基本介绍 1.1 定义 LLaMA-Factory 是一个开源的大型语言模型(LLM)微调框架,旨在帮助开发者和研究人员轻松地对预训练语言模型进行定制化训练和优化 1.2 功能特点 支持多种预训练模型 LLaMA Factory 支持超过 100 种主流的…...
数字IC后端设计实现OCC(On-chip Clock Controller)电路介绍及时钟树综合案例
数字IC后端时钟树综合专题(OCC电路案例分享) 复杂时钟设计时钟树综合(clock tree synthesis)常见20个典型案例 1、什么是OCC? 片上时钟控制器(On-chip Clock Controllers ,OCC),也称为扫描时钟控制器(Scan Clock Con…...
LeetCodehot 力扣热题100 全排列
这段代码的目的是计算给定整数数组的所有全排列(permutations),并返回一个包含所有排列的二维数组。 思路解析 在这段代码中,采用了 深度优先搜索(DFS) 和 回溯 的方法来生成所有的排列。 关键步骤…...
深度学习c++资源库:vector容器,蓝桥杯常用算法sort,unique(排序+去重)
vector容器 1.基本概念 <vector> 是 STL 中的一个容器类,不同于普通数组的静态空间,vector可以动态扩展。 动态扩展:并不是在原空间连接新空间,而是找到更大的内存空间,将原数据拷贝到新空间,释放…...
Postgresql-重置统计信息(reset statistics)
文章目录 理解 PostgreSQL 中的 pg_stat_resetpg_stat_reset 的作用与使用时机pg_stat_reset 所需权限PostgreSQL 重置统计信息的方法重置整个database重置特定表的统计重置特定function的统计重置Statistics Collector:重置 WAL(Write-Ahead Logging)统…...