深入理解 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 Image

class 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_dir
        self.transform = transform
        self.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 = samples
        self.transform = transform
        self.target_transform = target_transform

    def __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 Image

class 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_dir
        self.transform = transform
        self.target_transform = target_transform
        self.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_indices
        else:
            self.indices = val_indices

    def __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, label

    def _load_image(self, image_path):
        # 实现加载图片的方法
        image = Image.open(image_path).convert('RGB')
        return image

    def _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 Image

class 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_dir
        self.transform = transform
        self.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, label

    def _load_image(self, image_path):
        # 实现加载图片的方法
        image = Image.open(image_path).convert('RGB')
        return image

class 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_dir
        self.transform = transform
        self.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, label

    def _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 DataLoader

dataloader = 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 transforms

data_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 Dataset

class 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_dir
        self.transform = transform
        self.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))

    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个epoch
    model.train()
    running_loss = 0.0
    for 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 则通过批量加载、数据打乱和并行处理,大幅提升了数据加载的效率。在实际应用中,结合数据变换与增强技术,可以进一步提升模型的性能和泛化能力。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CSS2笔记

一、CSS基础 1.CSS简介 2.CSS的编写位置 2.1 行内样式 2.2 内部样式 2.3 外部样式 3.样式表的优先级 4.CSS语法规范 5.CSS代码风格 二、CSS选择器 1.CSS基本选择器 通配选择器元素选择器类选择器id选择器 1.1 通配选择器 1.2 元素选择器 1.3 类选择器 1.4 ID选择器 1.5 基…

【偏好对齐】通过ORM直接推导出PRM

论文地址:https://arxiv.org/pdf/2412.01981 相关博客 【自然语言处理】【大模型】 ΨPO:一个理解人类偏好学习的统一理论框架 【强化学习】PPO:近端策略优化算法 【偏好对齐】PRM应该奖励单个步骤的正确性吗? 【偏好对齐】通过OR…

springmvc--请求参数的绑定

目录 一、创建项目,pom文件 二、web.xml 三、spring-mvc.xml 四、index.jsp 五、实体类 Address类 User类 六、UserController类 七、请求参数解决中文乱码 八、配置tomcat,然后启动tomcat 1. 2. 3. 4. 九、接收Map类型 1.直接接收Map类型 &#x…

第五届电网系统与绿色能源国际学术会议(PGSGE 2025)

2025年第五届电网系统与绿色能源国际学术会议(PGSGE 2025) 定于2025年01月10-12日在吉隆坡召开。 第五届电网系统与绿色能源国际学术会议(PGSGE 2025) 基本信息 会议官网:www.pgsge.org【点击投稿/了解会议详情】 会议时间:202…

CSS——4. 行内样式和内部样式(即CSS引入方式)

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>方法1&#xff1a;行内样式</title></head><body><!--css引入方式&#xff1a;--><!--css的引入的第一种方法叫&#xff1a;行内样式将css代码写…

彩色图像分割—香蕉提取

实验任务 彩色图像分割—香蕉提取 利用香蕉和其它水果及其背景颜色在R,G,B分量上的差异进行识别,根据香 蕉和其它水果在R,G,B分量的二值化处理&#xff0c;获得特征提取的有效区域&#xff0c;然后提取 特征&#xff0c;达到提取香蕉的目的。附&#xff1a;统计各种水果及个数…

【算法】克里金(Kriging)插值原理及Python应用

文章目录 [toc] 前言一、克里金插值原理1.1 概述1.2 基本公式1.2 权重 w i w_i wi​的确定1.3 拟合函数的确定 二、Python建模与可视化2.1 Demo2.1.1 随机生成已知格网点2.1.2 拟合2.1.3 评估内符合精度2.1.3 内插未知格网点2.1.4 画图 2.2 结果图 参考文献 前言 最近学习了一下…

QML自定义滑动条Slider的样式

代码展示 import QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Controls 2.1Window {visible: truewidth: 640height: 480title: qsTr("Hello World")Slider {id: controlvalue: 0.5background: Rectangle {x: control.leftPaddingy: control.topPadding …

Android Studio学习笔记

01-课程前面的话 02-Android 发展历程 03-Android 开发机器配置要求 04-Android Studio与SDK下载安装 05-创建工程与创建模拟器 在 Android Studio 中显示 “Device Manager” 有以下几种方法&#xff1a; 通过菜单选项 打开 Android Studio&#xff0c;确保已经打开了一个…

Qt天气预报系统设计界面布局第四部分右边

Qt天气预报系统 1、第四部分右边的第一部分1.1添加控件 2、第四部分右边的第二部分2.1添加控件 3、第四部分右边的第三部分3.1添加控件3.2修改控件名字 1、第四部分右边的第一部分 1.1添加控件 拖入一个widget&#xff0c;改名为widget04r作为第四部分的右边 往widget04r再拖…

Spring boot + Hibernate + MySQL实现用户管理示例

安装MySQL Windows 11 Mysql 安装及常用命令_windows11 mysql-CSDN博客 整体目录 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLS…

Spring Boot 整合 Keycloak

1、概览 本文将带你了解如何设置 Keycloak 服务器&#xff0c;以及如何使用 Spring Security OAuth2.0 将Spring Boot应用连接到 Keycloak 服务器。 2、Keycloak 是什么&#xff1f; Keycloak是针对现代应用和服务的开源身份和访问管理解决方案。 Keycloak 提供了诸如单点登…

【Rust自学】10.2. 泛型

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 题外话&#xff1a;泛型的概念非常非常非常重要&#xff01;&#xff01;&#xff01;整个第10章全都是Rust的重难点&#xff01;&#xf…

51单片机——共阴数码管实验

数码管中有8位数字&#xff0c;从右往左分别为LED1、LED2、...、LED8&#xff0c;如下图所示 如何实现点亮单个数字&#xff0c;用下图中的ABC来实现 P2.2管脚控制A&#xff0c;P2.3管脚控制B&#xff0c;P2.4管脚控制C //定义数码管位选管脚 sbit LSAP2^2; sbit LSBP2^3; s…

SwiftUI 撸码常见错误 2 例漫谈

概述 在 SwiftUI 日常撸码过程中&#xff0c;头发尚且还算茂盛的小码农们经常会犯这样那样的错误。虽然犯这些错的原因都很简单&#xff0c;但有时想要快速准确的定位它们却并不容易。 况且这些错误还可能在模拟器和 Xcode 预览&#xff08;Preview&#xff09;表现的行为不甚…

米哈游可切换角色背景动态壁纸

米哈游可切换角色背景动态壁纸 0. 视频 B站演示: 米哈游可切换角色背景动态壁纸-wallpaper 1. 基本信息 作者: 啊是特嗷桃系列: 复刻系列 (衍生 wallpaper壁纸引擎 用)网站: 网页版在线预览 (没有搞大小适配, 建议横屏看; 这个不能切角色, 只能在wallpaper中切)仓库: GitHub…

OWASP ZAP之API 请求基础知识

ZAP API 提供对 ZAP 大部分核心功能的访问,例如主动扫描器和蜘蛛。ZAP API 在守护进程模式和桌面模式下默认启用。如果您使用 ZAP 桌面,则可以通过访问以下屏幕来配置 API: Tools -> Options -> API。 ZAP 需要 API 密钥才能通过 REST API 执行特定操作。必须在所有 …

Elasticsearch: 高级搜索

这里写目录标题 一、match_all匹配所有文档1、介绍&#xff1a; 二、精确匹配1、term单字段精确匹配查询2、terms多字段精确匹配3、range范围查询4、exists是否存在查询5、ids根据一组id查询6、prefix前缀匹配7、wildcard通配符匹配8、fuzzy支持编辑距离的模糊查询9、regexp正则…

齿轮缺陷检测数据集VOC+YOLO格式485张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;485 标注数量(xml文件个数)&#xff1a;485 标注数量(txt文件个数)&#xff1a;485 标注…

ArkTs之NAPI学习

1.Node-api组成架构 为了应对日常开发经的网络通信、串口访问、多媒体解码、传感器数据收集等模块&#xff0c;这些模块大多数是使用c接口实现的&#xff0c;arkts侧如果想使用这些能力&#xff0c;就需要使用node-api这样一套接口去桥接c代码。Node-api整体的架构图如下&…