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

深入理解 PyTorch 的 Dataset 和 DataLoader:构建高效数据管道

文章目录

    • 简介
    • PyTorch 的 Dataset
      • Dataset 的基本概念
      • 自定义 Dataset
        • 实现 `__init__` 方法
          • 示例:从 CSV 文件加载数据
        • 实现 `__len__` 方法
        • 实现 `__getitem__` 方法
        • 另一种示例:直接传递列表
        • 训练集和验证集的定义
      • 1. 单个 `Dataset` 类 + 数据分割
      • 2. 分别定义两个 `Dataset` 类
      • 总结
    • PyTorch 的 DataLoader
      • DataLoader 的基本概念
      • DataLoader 的常用参数
    • 数据变换与增强
      • 常用的图像变换
      • 数据增强的应用
    • 完整示例:手写数字识别
      • 数据集准备
      • 定义自定义 Dataset
      • 构建 DataLoader
      • 训练循环
    • 优化数据加载
      • 内存优化
      • 并行数据加载
    • 常见问题与调试方法
      • 常见问题
      • 调试方法
    • 总结


简介

在深度学习项目中,数据的高效加载和预处理是提升模型训练速度和性能的关键。PyTorch 的 DatasetDataLoader 提供了一种简洁而强大的方式来管理和加载数据。通过自定义 Dataset,开发者可以灵活地处理各种数据格式和存储方式;而 DataLoader 则负责批量加载数据、打乱顺序以及多线程并行处理,大大提升了数据处理的效率。

本文将详细介绍 DatasetDataLoader 的使用方法,涵盖其基本概念、最佳实践、自定义方法、数据变换与增强,以及在实际项目中的应用示例。


PyTorch 的 Dataset

Dataset 的基本概念

Dataset 是 PyTorch 中用于表示数据集的抽象类。它的主要职责是提供数据的访问接口,使得数据可以被 DataLoader 方便地加载和处理。PyTorch 提供了多个内置的 Dataset 类,如 torchvision.datasets 中的 ImageFolder,但在实际项目中,常常需要根据具体需求自定义 Dataset

自定义 Dataset

自定义 Dataset 允许开发者根据特定的数据格式和存储方式,实现灵活的数据加载逻辑。一个自定义的 Dataset 类需要继承自 torch.utils.data.Dataset 并实现以下三个方法:

  1. __init__: 初始化数据集,加载数据文件路径和标签等信息。
  2. __len__: 返回数据集的样本数量。
  3. __getitem__: 根据索引获取单个样本的数据和标签。
实现 __init__ 方法

__init__ 方法用于初始化数据集,通常包括读取数据文件、解析标签、应用初步的数据变换等。关键在于构建一个可以根据索引高效访问样本的信息结构,通常是一个列表或其他集合类型。

示例:从 CSV 文件加载数据

假设我们有一个包含图像文件名和对应标签的 CSV 文件 annotations_file.csv,格式如下:

filename,label
img1.png,0
img2.png,1
img3.png,0
...

我们可以在 __init__ 方法中读取这个 CSV 文件,并构建一个包含所有样本信息的列表。

import os
import pandas as pd
from torch.utils.data import Dataset
from PIL import Imageclass CustomImageDataset(Dataset):def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):"""初始化数据集。参数:annotations_file (string): 包含图像路径与标签对应关系的CSV文件路径。img_dir (string): 图像所在的目录。transform (callable, optional): 可选的变换函数,应用于图像。target_transform (callable, optional): 可选的变换函数,应用于标签。"""self.img_labels = pd.read_csv(annotations_file)self.img_dir = img_dirself.transform = transformself.target_transform = target_transform# 构建一个包含所有样本信息的列表self.samples = []for idx in range(len(self.img_labels)):img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])label = self.img_labels.iloc[idx, 1]self.samples.append((img_path, label))

关键点说明:

  • 读取 CSV 文件:使用 pandas 读取 CSV 文件,将其存储为 DataFrame 以便后续处理。
  • 构建样本列表:遍历 DataFrame,将每个样本的图像路径和标签作为元组添加到 self.samples 列表中。这样,__getitem__ 方法可以通过索引高效访问数据。
实现 __len__ 方法

__len__ 方法返回数据集中的样本数量,通常为样本列表的长度。

    def __len__(self):"""返回数据集中的样本数量。"""return len(self.samples)
实现 __getitem__ 方法

__getitem__ 方法根据给定的索引返回对应的样本数据和标签。它是数据加载的核心部分,需要确保高效地读取和处理数据。

    def __getitem__(self, idx):"""根据索引获取单个样本。参数:idx (int): 样本索引。返回:tuple: (image, label) 其中 image 是一个 PIL Image 或者 Tensor,label 是一个整数或 Tensor。"""img_path, label = self.samples[idx]image = Image.open(img_path).convert('RGB')if self.transform:image = self.transform(image)  # 在这里应用转换if self.target_transform:label = self.target_transform(label)return image, label

关键点说明:

  • 读取图像:使用 PIL.Image 打开图像文件,并转换为 RGB 格式。
  • 应用变换:如果定义了图像变换函数 transform,则在此处应用于图像。
  • 处理标签:如果定义了标签变换函数 target_transform,则在此处应用于标签。
  • 返回数据:返回处理后的图像和标签,供 DataLoader 使用。
另一种示例:直接传递列表

如果数据集的信息已经以列表的形式存在,或者不需要从文件中读取,__init__ 方法可以直接接受一个包含样本信息的列表。

class CustomImageDataset(Dataset):def __init__(self, samples, transform=None, target_transform=None):"""初始化数据集。参数:samples (list of tuples): 每个元组包含 (image_path, label)。transform (callable, optional): 可选的变换函数,应用于图像。target_transform (callable, optional): 可选的变换函数,应用于标签。"""self.samples = samplesself.transform = transformself.target_transform = target_transformdef __len__(self):return len(self.samples)def __getitem__(self, idx):img_path, label = self.samples[idx]image = Image.open(img_path).convert('RGB')if self.transform:image = self.transform(image)if self.target_transform:label = self.target_transform(label)return image, label

使用示例:

samples = [('path/to/img1.png', 0),('path/to/img2.png', 1),# 更多样本...
]dataset = CustomImageDataset(samples, transform=data_transform)
训练集和验证集的定义

在实际项目中,通常需要将数据集划分为训练集和验证集,以评估模型的性能。定义训练集和验证集的方法可以根据具体的项目需求和数据集的性质来决定,通常有以下两种主要的方法:

1. 单个 Dataset 类 + 数据分割

在这种方法中,你创建一个单一的 Dataset 类来封装整个数据集(包括训练数据和验证数据),然后在初始化时根据需要对数据进行分割。你可以使用索引或布尔掩码来区分训练样本和验证样本。这种方法的好处是代码更简洁,且如果你的数据集非常大,可以避免重复加载相同的数据。

实现方式:

  • 使用 train_test_split 函数(例如来自 sklearn.model_selection)或其他逻辑来随机划分数据。
  • __init__ 方法中根据参数决定加载训练集还是验证集。

示例代码:

from torch.utils.data import Dataset, SubsetRandomSampler
import numpy as np
from sklearn.model_selection import train_test_split
from PIL import Imageclass CombinedDataset(Dataset):def __init__(self, data_dir, annotations_file, transform=None, target_transform=None, train=True, split_ratio=0.2):"""初始化数据集。参数:data_dir (string): 数据所在的目录。annotations_file (string): 包含图像路径与标签对应关系的CSV文件路径。transform (callable, optional): 可选的变换函数,应用于图像。target_transform (callable, optional): 可选的变换函数,应用于标签。train (bool): 是否加载训练集。如果为 False,则加载验证集。split_ratio (float): 验证集所占比例。"""self.data_dir = data_dirself.transform = transformself.target_transform = target_transformself.train = train# 加载所有图片文件路径和标签self.img_labels = pd.read_csv(annotations_file)self.image_files = [os.path.join(data_dir, fname) for fname in self.img_labels['filename']]self.labels = self.img_labels['label'].tolist()# 分割数据集为训练集和验证集indices = list(range(len(self.image_files)))train_indices, val_indices = train_test_split(indices, test_size=split_ratio, random_state=42)if self.train:self.indices = train_indiceselse:self.indices = val_indicesdef __len__(self):return len(self.indices)def __getitem__(self, idx):actual_idx = self.indices[idx]image_path = self.image_files[actual_idx]label = self.labels[actual_idx]image = self._load_image(image_path)if self.transform:image = self.transform(image)if self.target_transform:label = self.target_transform(label)return image, labeldef _load_image(self, image_path):# 实现加载图片的方法image = Image.open(image_path).convert('RGB')return imagedef _load_labels(self):# 实现加载标签的方法return self.labels# 创建训练集和验证集的实例
train_dataset = CombinedDataset(data_dir='path/to/data',annotations_file='annotations_file.csv',train=True,transform=data_transform
)
val_dataset = CombinedDataset(data_dir='path/to/data',annotations_file='annotations_file.csv',train=False,transform=data_transform
)

2. 分别定义两个 Dataset

另一种常见做法是为训练集和验证集分别创建独立的 Dataset 类。这样做可以让你针对每个数据集应用不同的预处理步骤或转换规则,从而增加灵活性。此外,如果训练集和验证集存储在不同的位置或格式不同,这也是一种自然的选择。

实现方式:

  • 为训练集和验证集各自创建单独的 Dataset 子类。
  • 每个子类负责自己数据的加载和预处理。

示例代码:

from torch.utils.data import Dataset
import os
from PIL import Imageclass TrainDataset(Dataset):def __init__(self, data_dir, annotations_file, transform=None, target_transform=None):"""初始化训练数据集。参数:data_dir (string): 训练数据所在的目录。annotations_file (string): 包含训练图像路径与标签对应关系的CSV文件路径。transform (callable, optional): 可选的变换函数,应用于图像。target_transform (callable, optional): 可选的变换函数,应用于标签。"""self.data_dir = data_dirself.transform = transformself.target_transform = target_transform# 加载所有训练图片文件路径和标签self.img_labels = pd.read_csv(annotations_file)self.image_files = [os.path.join(data_dir, fname) for fname in self.img_labels['filename']]self.labels = self.img_labels['label'].tolist()def __len__(self):return len(self.image_files)def __getitem__(self, idx):image_path = self.image_files[idx]label = self.labels[idx]image = self._load_image(image_path)if self.transform:image = self.transform(image)if self.target_transform:label = self.target_transform(label)return image, labeldef _load_image(self, image_path):# 实现加载图片的方法image = Image.open(image_path).convert('RGB')return imageclass ValDataset(Dataset):def __init__(self, data_dir, annotations_file, transform=None, target_transform=None):"""初始化验证数据集。参数:data_dir (string): 验证数据所在的目录。annotations_file (string): 包含验证图像路径与标签对应关系的CSV文件路径。transform (callable, optional): 可选的变换函数,应用于图像。target_transform (callable, optional): 可选的变换函数,应用于标签。"""self.data_dir = data_dirself.transform = transformself.target_transform = target_transform# 加载所有验证图片文件路径和标签self.img_labels = pd.read_csv(annotations_file)self.image_files = [os.path.join(data_dir, fname) for fname in self.img_labels['filename']]self.labels = self.img_labels['label'].tolist()def __len__(self):return len(self.image_files)def __getitem__(self, idx):image_path = self.image_files[idx]label = self.labels[idx]image = self._load_image(image_path)if self.transform:image = self.transform(image)if self.target_transform:label = self.target_transform(label)return image, labeldef _load_image(self, image_path):# 实现加载图片的方法image = Image.open(image_path).convert('RGB')return image# 创建训练集和验证集的实例
train_dataset = TrainDataset(data_dir='path/to/train_data',annotations_file='path/to/train_annotations.csv',transform=train_transform
)
val_dataset = ValDataset(data_dir='path/to/val_data',annotations_file='path/to/val_annotations.csv',transform=val_transform
)

总结

选择哪种方法取决于你的具体需求和偏好。如果你的数据集足够小并且训练集和验证集的处理方式相似,那么使用单个 Dataset 类并内部分割数据可能更为简便。然而,如果你希望对训练集和验证集应用不同的预处理策略,或者它们存储在不同的地方,那么分别为它们定义独立的 Dataset 类可能是更好的选择。


PyTorch 的 DataLoader

DataLoader 的基本概念

DataLoader 是 PyTorch 中用于批量加载数据的工具。它封装了数据集(Dataset)并提供了批量采样、打乱数据、并行加载等功能。通过 DataLoader,开发者可以轻松地将数据集与模型训练流程集成。

DataLoader 的常用参数

  • dataset: 要加载的数据集对象。
  • batch_size: 每个批次加载的样本数量。
  • shuffle: 是否在每个 epoch 开始时打乱数据。
  • num_workers: 使用的子进程数量,用于数据加载的并行处理。
  • collate_fn: 自定义的批量数据合并函数。
  • drop_last: 如果样本数量不能被批量大小整除,是否丢弃最后一个不完整的批次。

示例:

from torch.utils.data import DataLoaderdataloader = DataLoader(dataset,batch_size=32,shuffle=True,num_workers=4,drop_last=True
)

关键点说明:

  • 批量大小 (batch_size):决定每次训练迭代中使用的样本数量,影响训练速度和显存占用。
  • 数据打乱 (shuffle):在训练过程中打乱数据顺序,有助于模型泛化能力的提升。
  • 并行数据加载 (num_workers):增加 num_workers 的数量可以提高数据加载的效率,尤其在 I/O 密集型任务中效果显著。
  • 丢弃不完整批次 (drop_last):在某些情况下,尤其是批量归一化等操作中,保持每个批次大小一致是必要的。

数据变换与增强

常用的图像变换

在训练深度学习模型时,图像数据通常需要进行一系列的预处理和变换,以提高模型的性能和泛化能力。PyTorch 提供了丰富的图像变换工具,通过 torchvision.transforms 模块可以方便地实现这些操作。

常见的图像变换包括:

  • 缩放和裁剪:调整图像大小或裁剪为固定尺寸。
  • 旋转和翻转:随机旋转或翻转图像,增加数据多样性。
  • 归一化:将图像像素值标准化到特定范围,提高训练稳定性。
  • 颜色变换:调整图像的亮度、对比度、饱和度等。

示例:

from torchvision import transformsdata_transform = transforms.Compose([transforms.Resize((224, 224)),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
])

数据增强的应用

数据增强是通过对训练数据进行随机变换,生成更多样化的数据样本,从而提升模型的泛化能力。常见的数据增强技术包括随机裁剪、旋转、缩放、颜色抖动等。

示例:

data_augmentation = transforms.Compose([transforms.RandomResizedCrop(224),transforms.RandomRotation(15),transforms.RandomHorizontalFlip(),transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
])

在自定义 Dataset 中应用数据增强:

train_dataset = CustomImageDataset(annotations_file='annotations_file.csv',img_dir='path/to/images',transform=data_augmentation
)

完整示例:手写数字识别

以下将通过一个完整的手写数字识别示例,展示如何使用 DatasetDataLoader 构建高效的数据管道。

数据集准备

假设我们使用的是经典的 MNIST 数据集,包含手写数字的灰度图像及其对应标签。数据集已下载并解压至指定目录。

定义自定义 Dataset

尽管 PyTorch 已经提供了 torchvision.datasets.MNIST,我们仍通过自定义 Dataset 来深入理解其工作原理。

import os
from PIL import Image
import pandas as pd
from torch.utils.data import Datasetclass MNISTDataset(Dataset):def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):self.img_labels = pd.read_csv(annotations_file)self.img_dir = img_dirself.transform = transformself.target_transform = target_transformself.samples = []for idx in range(len(self.img_labels)):img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])label = self.img_labels.iloc[idx, 1]self.samples.append((img_path, label))def __len__(self):return len(self.samples)def __getitem__(self, idx):img_path, label = self.samples[idx]image = Image.open(img_path).convert('L')  # MNIST 为灰度图像if self.transform:image = self.transform(image)if self.target_transform:label = self.target_transform(label)return image, label

构建 DataLoader

from torch.utils.data import DataLoader
from torchvision import transforms# 定义数据变换
data_transform = transforms.Compose([transforms.Resize((28, 28)),transforms.ToTensor(),transforms.Normalize((0.1307,), (0.3081,))  # MNIST 的均值和标准差
])# 初始化数据集
train_dataset = MNISTDataset(annotations_file='path/to/train_annotations.csv',img_dir='path/to/train_images',transform=data_transform
)val_dataset = MNISTDataset(annotations_file='path/to/val_annotations.csv',img_dir='path/to/val_images',transform=data_transform
)# 构建 DataLoader
train_loader = DataLoader(train_dataset,batch_size=64,shuffle=True,num_workers=2,drop_last=True
)val_loader = DataLoader(val_dataset,batch_size=64,shuffle=False,num_workers=2,drop_last=False
)

训练循环

import torch
import torch.nn as nn
import torch.optim as optim# 定义简单的神经网络
class SimpleNN(nn.Module):def __init__(self):super(SimpleNN, self).__init__()self.flatten = nn.Flatten()self.fc1 = nn.Linear(28*28, 128)self.relu = nn.ReLU()self.fc2 = nn.Linear(128, 10)def forward(self, x):x = self.flatten(x)x = self.relu(self.fc1(x))x = self.fc2(x)return x# 初始化模型、损失函数和优化器
model = SimpleNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练过程
for epoch in range(5):  # 训练5个epochmodel.train()running_loss = 0.0for images, labels in train_loader:optimizer.zero_grad()outputs = model(images)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()avg_loss = running_loss / len(train_loader)print(f'Epoch [{epoch+1}/5], Loss: {avg_loss:.4f}')

输出示例:

Epoch [1/5], Loss: 0.3521
Epoch [2/5], Loss: 0.1234
Epoch [3/5], Loss: 0.0678
Epoch [4/5], Loss: 0.0456
Epoch [5/5], Loss: 0.0321

优化数据加载

内存优化

对于大型数据集,内存管理至关重要。以下是一些优化建议:

  • 懒加载:仅在 __getitem__ 方法中加载需要的样本,避免一次性加载全部数据到内存。
  • 使用内存映射:对于大规模数据,可以使用内存映射文件(如 HDF5)提高数据访问速度。
  • 减少数据冗余:确保样本列表中仅包含必要的信息,避免不必要的内存占用。

并行数据加载

利用多线程或多进程并行加载数据,可以显著提升数据加载速度,减少训练过程中的等待时间。

示例:

train_loader = DataLoader(train_dataset,batch_size=64,shuffle=True,num_workers=4,  # 增加工作进程数pin_memory=True  # 如果使用 GPU,可以设置为 True
)

关键点说明:

  • num_workers:增加 num_workers 的数量可以提高数据加载的并行度,但过高的值可能导致系统资源紧张。建议根据系统的 CPU 核心数和内存容量进行调整。
  • pin_memory:当使用 GPU 时,设置 pin_memory=True 可以加快数据从主内存到 GPU 的传输速度。

常见问题与调试方法

常见问题

  1. 数据加载缓慢:可能由于 num_workers 设置过低、数据存储在慢速磁盘或数据预处理过于复杂。
  2. 内存不足:大批量数据加载时,可能会耗尽系统内存。可以尝试减少 batch_size 或优化数据存储方式。
  3. 数据打乱不一致:确保在 DataLoader 中设置了 shuffle=True,并在不同的 epoch 中打乱数据顺序。

调试方法

  • 检查数据路径:确保所有数据文件路径正确,避免因路径错误导致的数据加载失败。
  • 验证数据格式:确保数据文件格式与 Dataset 类中的读取方式一致,例如图像格式、标签类型等。
  • 监控资源使用:使用系统监控工具(如 tophtop)查看 CPU、内存和磁盘 I/O 的使用情况,识别瓶颈。
  • 逐步调试:在 __getitem__ 方法中添加打印语句,逐步检查数据加载和处理流程。

总结

PyTorch 的 DatasetDataLoader 提供了构建高效数据管道的强大工具。通过自定义 Dataset,开发者可以灵活地处理各种数据格式和存储方式;而 DataLoader 则通过批量加载、数据打乱和并行处理,大幅提升了数据加载的效率。在实际应用中,结合数据变换与增强技术,可以进一步提升模型的性能和泛化能力。

相关文章:

深入理解 PyTorch 的 Dataset 和 DataLoader:构建高效数据管道

文章目录 简介PyTorch 的 DatasetDataset 的基本概念自定义 Dataset实现 __init__ 方法示例:从 CSV 文件加载数据 实现 __len__ 方法实现 __getitem__ 方法另一种示例:直接传递列表训练集和验证集的定义 1. 单个 Dataset 类 数据分割2. 分别定义两个 Da…...

VSCode设置ctrl或alt+mouse(left)跳转

总结: (1)VSCode初次远程连接服务器时,需要在服务器上下载 python 拓展,然后选择对应的环境 (2)VSCode设置ctrl或altmouse(left)跳转到定义...

在Ubuntu 18.04.6 LTS安装OpenFace流程

一、修改配置:将gcc8,g8作为默认选项 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 100 sudo update-alternatives --config gcc 选择版本,再查看gcc --version sudo update-alternatives --install /usr/bin/g g /usr/bin/g-…...

微服务拆分的艺术:构建高效、灵活的系统架构

目录 一、微服务拆分的重要性 二、微服务拆分的策略 1. 按照业务领域拆分 2. 按照团队结构拆分 3. 按照业务边界拆分 4. 按照数据和数据库拆分 5. 按照用户界面或外部接口拆分 6. 按照功能模块或领域驱动设计拆分 7. 按照性能和可伸缩性需求拆分 三、微服务拆分的实践…...

PHP框架+gatewayworker实现在线1对1聊天--发送消息(6)

文章目录 发送消息原理说明发送功能实现html部分javascript代码PHP代码 发送消息原理说明 接下来我们发送聊天的文本信息。点击发送按钮的时候,会自动将文本框里的内容发送出去。过程是我们将信息发送到服务器,服务器再转发给对方。文本框的id为msgcont…...

java项目之读书笔记共享平台(源码+文档)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的闲一品交易平台。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 读书笔记共享平台的主要使…...

RabbitMq的Java项目实践

在现代软件开发中,消息队列(Message Queue,简称MQ)作为一种重要的组件,承担着上下游消息传递和通信的重任。RabbitMQ作为一款流行的开源消息队列中间件,凭借其高可用性、可扩展性和易用性等特点&#xff0c…...

气膜球幕:引领元宇宙时代的科技与艺术光影盛宴—轻空间

在科技与艺术交织的时代,未来的观影体验将不再受限于传统屏幕的束缚。随着气膜球幕的崭新亮相,突破性的光影效果和沉浸式体验让我们走进了一个全新的视听世界。这不仅仅是一个简单的球形影院,它是连接现实与虚拟、科技与艺术、光与影的桥梁&a…...

行为模式2.命令模式------灯的开关

行为型模式 模板方法模式(Template Method Pattern)命令模式(Command Pattern)迭代器模式(Iterator Pattern)观察者模式(Observer Pattern)中介者模式(Mediator Pattern…...

Linux环境下静态库和动态库的实现

Linux 环境下静态库和动态库的实现 在软件开发中,库是非常重要的组成部分。它们包含了一组可复用的函数和代码片段,用于提高开发效率和代码质量。在Linux系统中,库分为静态库和动态库两种。本文将介绍它们的实现方式,结合C语言代…...

如何很快将文件转换成另外一种编码格式?编码?按指定编码格式编译?如何检测文件编码格式?Java .class文件编码和JVM运行期内存编码?

如何很快将文件转换成另外一种编码格式? 利用VS Code右下角的"选择编码"功能,选择"通过编码保存"可以很方便将文件转换成另外一种编码格式。尤其,在测试w/ BOM或w/o BOM, 或者ANSI编码和UTF编码转换,特别方便。VS文件另…...

Tortoisegit 安装之后没有Add、ignore解决

在本地的仓库文件夹中点击右键,找到Settings, 从General 找到Contex Menu,我的系统是Win11,所以用Win11 Contex Menu 将所需要的操作打勾即可。...

线性代数考研笔记

行列式 背景 分子行列式:求哪个未知数,就把b1,b2放在对应的位置 分母行列式:系数对应写即可 全排列与逆序数 1 3 2:逆序数为1 奇排列 1 2 3:逆序数为0 偶排列 将 1 3 2 只需将3 2交换1次就可以还原原…...

C语言带参数的宏定义的相关知识汇总(最常用的形式、带标记分隔符##的形式...)

阅读大型C工程代码时,绕不开带参数的宏定义的阅读,所以有必要强化一下这一块的知识。 01-带参数的宏定义最常用的形式 # define S(a,b) a*b ... ... ... area S(3,2);则在编译预处理时area S(3,2);被展开为: area 3 * 2;02-带标记分隔符…...

cpp编译链接等

一、编译预处理 C程序编译的过程:预处理 -> 编译(优化、汇编)-> 链接 预处理指令主要有以下三种: 包含头文件:#include 宏定义:#define(定义宏)、#undef(删除宏…...

openbmc sdk09.03 适配(一)

1.说明 本节是根据最新的sdk09.03适配ast2600平台。 sdk下载路径为: https://github.com/AspeedTech-BMC/openbmc可参阅文档: https://blog.csdn.net/wit_yuan/article/details/144613247nfs挂载方法: # mount -o nolock -t nfs serverip:/xx...

JavaScript HTML DOM 实例

JavaScript HTML DOM 实例 JavaScript 的 HTML DOM(文档对象模型)允许您通过脚本来控制 HTML 页面。DOM 是 HTML 文档的编程接口,它将 Web 页面与编程语言连接起来,使得开发者可以改变页面中的内容、结构和样式。在这篇文章中,我们将通过一系列实例来探讨如何使用 JavaSc…...

【Vue】:解决动态更新 <video> 标签 src 属性后视频未刷新的问题

问题描述 在 Vue.js 项目&#xff0c;当尝试动态更新 <video> 标签的 <source> 元素 src 属性来切换视频时&#xff0c;遇到了一个问题&#xff1a;即使 src 属性已更改&#xff0c;浏览器仍显示旧视频。具体表现为用户选择新视频后&#xff0c;视频区域继续显示之…...

C语言| 二维数字的定义

【二维数组】 二维数组的本质就是一维数组&#xff0c;表现形式上是二维的。 定义一般形式为 类型说明符 数组名[常量表达式][常量表达式]; 举例 int a[2][3]; 定义了一个2行3列的二维数组a&#xff0c;共有6个元素。 元素名字依次是&#xff1a;a[0][0],a[0][1],a[0][…...

全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之循环结构(for循环语句)—(十)(求解数学中特殊的数)

实战训练1—完全数 问题描述&#xff1a; 数学上的“完全数”是指真因子&#xff08;除了自身以外的约数&#xff09;之和等于它本身的自然数。例如&#xff0c;6的因子是1,2,3&#xff0c;而1236&#xff0c;所以6是完全数。如果一个正整数小于它的所有真因数之和&#xff0…...

【大模型】ChatGPT 数据分析与处理使用详解

目录 一、前言 二、AI 大模型数据分析介绍 2.1 什么是AI数据分析 2.2 AI数据分析与传统数据分析对比 2.2.1 差异分析 2.2.2 优劣势对比 2.3 AI大模型工具数据分析应用场景 三、AI大模型工具数据分析操作实践 3.1 ChatGPT 常用数据分析技巧操作演示 3.1.1 快速生成数据…...

[gcc]常见编译开关

GCC 提供了许多编译开关&#xff08;编译选项&#xff09;&#xff0c;这些开关可以用于控制编译过程的各种方面&#xff0c;如优化级别、调试信息、警告和错误处理等。 以下是一些常见的 GCC 编译开关&#xff1a; -o&#xff1a;指定输出文件名。例如&#xff0c;gcc -o myp…...

iOS实现在collectionView顶部插入数据效果

有时候&#xff0c;我们会遇到这种需求&#xff0c;就是下拉刷新的时候&#xff0c;在 collectionView顶部插入数据&#xff0c;这个时候&#xff0c;需要我们注意 主要有两点 1 关闭隐式动画 由于我们使用insert在collectionView顶部插入数据是有从头部插入的隐式动画的&#…...

GPIO、RCC库函数

void GPIO_DeInit(GPIO_TypeDef* GPIOx); void GPIO_AFIODeInit(void); void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct); //输出 读 uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx,…...

PostgreSQL学习笔记(一):PostgreSQL介绍和安装

目录 概念 PostgreSQL简介 PostgreSQL的关键特性 1. 标准兼容性 2. 扩展性 3. 数据完整性和可靠性 4. 丰富的数据类型 5. 查询能力 6. 事务和并发控制 7. 扩展和插件 8. 跨平台和多语言支持 9. 高可用性和扩展性 常用场景 安装 Linux apt安装 下载安装包安装 客…...

从摩托罗拉手机打印短信的简单方法

昨天我试图从摩托罗拉智能手机上打印短信&#xff0c;但当我通过USB将手机连接到电脑时&#xff0c;我在电脑上找不到它们。由于我的手机内存已达到限制&#xff0c;并且我想保留短信的纸质版本&#xff0c;您能帮我将短信从摩托罗拉手机导出到计算机吗&#xff1f; 如您所知&…...

矩阵运算提速——玩转opencv::Mat

介绍:用Eigen或opencv::Mat进行矩阵的运算&#xff0c;比用cpp的vector或vector进行矩阵运算要快吗? 使用 Eigen 或 OpenCV 的 cv::Mat 进行矩阵运算通常比使用 std::vector<int> 或 std::vector<double> 更快。这主要有以下几个原因&#xff1a; 优化的底层实现…...

vue请求后端需要哪些问题

在使用 Vue 前端框架请求后端服务时&#xff0c;需要考虑和解决的问题有很多。以下是一个详细的讲解&#xff1a; 1. **API 设计与文档** - **明确 API 端点**&#xff1a;了解后端提供的 API 端点&#xff08;URL&#xff09;&#xff0c;包括资源的路径和操作方法&#xff08…...

QML Image详解

1. 概述 Image 是 QML 中用于显示图片的基本组件。它允许开发者加载和显示各种格式的图像文件&#xff08;如 PNG, JPEG, GIF 等&#xff09;&#xff0c;并提供了多种配置选项来控制图片的显示方式和行为。Image 元素支持各种图像处理功能&#xff0c;比如缩放、裁剪、模糊等…...

Chapter4.1 Coding an LLM architecture

文章目录 4 Implementing a GPT model from Scratch To Generate Text4.1 Coding an LLM architecture 4 Implementing a GPT model from Scratch To Generate Text 本章节包含 编写一个类似于GPT的大型语言模型&#xff08;LLM&#xff09;&#xff0c;这个模型可以被训练来生…...

Linux 端口知识全解析

Linux 端口知识全解析 在 Linux 系统的网络世界里&#xff0c;端口如同一个个小小的“窗口”&#xff0c;数据的进出都依赖它们有条不紊地运作。理解 Linux 端口知识&#xff0c;无论是对于系统管理员排查网络故障&#xff0c;还是开发者进行网络编程&#xff0c;都至关重要。…...

《Armv8-A virtualization》学习笔记

1.MAIR 的全称是 Memory Attribute Indirection Register。它是ARM架构中的一种寄存器&#xff0c;用于定义内存的属性&#xff0c;并提供一种间接访问内存属性的机制。MAIR寄存器包含多个字段&#xff0c;这些字段指示不同类型内存的属性&#xff0c;例如是否可以缓存、是否为…...

23. 【.NET 8 实战--孢子记账--从单体到微服务】--记账模块--预算

在每个月发工资后很多人会对未来一个月的花销进行大致的计划&#xff0c;这个行为叫做预算。那么在这篇文章中我们将一起开发预算服务。 一、需求 预算需求就是简单的增删改查&#xff0c;虽然比较简单&#xff0c;但是也有几点需要注意。 编号需求说明1新增预算1. 针对每种…...

DOS攻击的原理和实现 (网络安全)hping3和Slowloris的运用

DoS攻击的原理和实现 DoS攻击&#xff08;Denial of Service Attack&#xff0c;拒绝服务攻击&#xff09;是指通过恶意手段使目标服务器、服务或网络资源无法正常提供服务&#xff0c;从而影响正常用户的访问。DoS攻击通常通过消耗目标系统的资源&#xff08;如带宽、内存、处…...

十三、Vue 过渡和动画

文章目录 一、Vue过渡和动画概述1. 过渡的基本原理2. 动画的基本原理二、使用 CSS 过渡1. 单元素过渡2. 过渡模式in - out 模式out - in 模式三、使用 CSS 动画1. 单元素动画2. 动画结合过渡四、JavaScript 钩子函数实现过渡和动画1. 基本概念2. 示例五、列表过渡1. 基本原理2.…...

Dubbo 关键知识点解析:负载均衡、容错、代理及相关框架对比

1.Dubbo 负载均衡策略&#xff1f; Dubbo 是一个分布式服务框架&#xff0c;它提供了多种负载均衡策略来分发服务调用。在 Dubbo 中&#xff0c;负载均衡的实现是基于客户端的&#xff0c;即由服务消费者&#xff08;Consumer&#xff09;端决定如何选择服务提供者&#xff08…...

仿生的群体智能算法总结之三(十种)

群体智能算法是一类通过模拟自然界中的群体行为来解决复杂优化问题的方法。以下是30种常见的群体智能算法,本文汇总第21-30种。接上文 : 编号 算法名称(英文) 算法名称(中文) 年份 作者 1 Ant Colony Optimization (ACO) 蚁群优化算法 1991 Marco Dorigo 2 Particle Swar…...

《量子比特大阅兵:不同类型量子比特在人工智能领域的优劣势剖析》

在科技的前沿&#xff0c;量子比特与人工智能的融合正开启一扇全新的大门。不同类型的量子比特&#xff0c;如超导、离子阱、光量子等&#xff0c;在与人工智能结合时展现出独特的优势与劣势。 超导量子比特 超导量子比特是目前应用较为广泛且研究相对成熟的量子比特类型。它…...

el-input输入框需要支持多输入,最后传输给后台的字段值以逗号分割

需求&#xff1a;一个输入框字段需要支持多次输入&#xff0c;最后传输给后台的字段值以逗号分割 解决方案&#xff1a;结合了el-tag组件的动态编辑标签 那块的代码 //子组件 <template><div class"input-multiple-box" idinputMultipleBox><div>…...

机器人领域的一些仿真器

模拟工具和环境对于开发、测试和验证可变形物体操作策略至关重要。这些工具提供了一个受控的虚拟环境&#xff0c;用于评估各种算法和模型的性能&#xff0c;并生成用于训练和测试数据驱动模型的合成数据。 Bullet Physics Library 用于可变形物体模拟的一个流行的物理引擎是 B…...

前端-动画库Lottie 3分钟学会使用

目录 1. Lottie地址 2. 使用html实操 3. 也可以选择其他的语言 1. Lottie地址 LottieFiles: Download Free lightweight animations for website & apps.Effortlessly bring the smallest, free, ready-to-use motion graphics for the web, app, social, and designs.…...

腾讯云智能结构化 OCR:驱动多行业数字化转型的核心引擎

在当今数字化时代的汹涌浪潮中&#xff0c;数据已跃升为企业发展的关键要素&#xff0c;其高效、精准的处理成为企业在激烈市场竞争中脱颖而出的核心竞争力。腾讯云智能结构化 OCR 技术凭借其前沿的科技架构与卓越的功能特性&#xff0c;宛如一颗璀璨的明星&#xff0c;在交通、…...

【开源免费】基于SpringBoot+Vue.JS精品在线试题库系统(JAVA毕业设计)

本文项目编号 T 115 &#xff0c;文末自助获取源码 \color{red}{T115&#xff0c;文末自助获取源码} T115&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...

c# CodeFirst生成表字段加注释

前置&#xff1a;ORM框架工具使用的FreeSql 背景&#xff1a;开发环境中运行接口&#xff0c;所有的表字段以及备注会自动加上&#xff0c;但是在测试环境时运行就只生成了表&#xff0c;没有把每个字段的注释加上 问题检查&#xff1a; FreeSql CodeFirst 支持将 c# 代码内的注…...

MySQL8.0复制原理和部署配置步骤

1. mysql 主从复制原理 在从库上执行change master to&#xff1b;会将主库的信息保存到从库中的master.info文件中在从库执行start slave;开启io_thread, sql_thread线程;io_thread工作&#xff1b;io_thread通过master.info文件中主库的连接信息去连接主库&#xff1b;连接成…...

Unity热更新文件修改后缀并拷贝到指定路径的工具类

最近在学习Hybrid热更新。每次编译完&#xff0c;需要修改后缀名和拷贝到特定路径覆盖旧文件&#xff0c;就叫AI写了个工具类。现在记录一下&#xff0c;毕竟ai写完还需要修改。 代码如下&#xff0c;放到Assets/Editor/路径下即可。 可根据需求自行改变路径和文件名。 using…...

前端vue+el-input实现输入框中文字高亮标红效果(学习自掘金博主文章)

学习自掘金文章https://juejin.cn/post/7295169886177918985 该博主的代码基于原生textarea控件和js实现&#xff0c;基于该博主的代码和思路&#xff0c;在vue下实现了相应功能 思路 生成html字符串来实现文字高亮标红效果&#xff0c;但是input输入控件不能渲染html字符串…...

SAP系统中的标准价、移动平均价是什么?有何区别?物料分类账的优点

文章目录 前言一、SAP系统中的价格控制二、移动平均价、标准价是什么&#xff1f;三、S价&#xff08;标准价&#xff09;的优势四、S价&#xff08;标准价&#xff09;的劣势五、V价&#xff08;移动平均价&#xff09;的优势六、V价&#xff08;移动平均价&#xff09;的劣势…...

通往O1开源之路

“Scaling of Search and Learning: A Roadmap to Reproduce o1 from Reinforcement Learning Perspective”由复旦大学和上海人工智能实验室的研究者撰写。该论文从强化学习视角出发&#xff0c;深入分析了实现类似OpenAI o1模型性能的路线图&#xff0c;聚焦于策略初始化、奖…...

【QT】实现RestFul接口

在这个教程中&#xff0c;我们将介绍如何在 Qt 中使用 QHttpServer 类来创建一个简单的 HTTP 服务器。QHttpServer 是 Qt 6 引入的新类&#xff0c;用于提供 HTTP 服务。这个类非常适合快速开发restful接口。 准备工作 确保你的 Qt 版本是 Qt 6 或更高版本&#xff0c;因为 Q…...