【Transformer-Hugging Face 06/10】 数据预处理实例

目录

  • 一、说明
  • 二、自然语言处理
    • 2.1 Pad
    • 2.2 截断
    • 2.3 构建张量
  • 三、TensorFlow
  • 四、处理语音
  • 五、计算机视觉
  • 六、填充
  • 七、Multimodal

一、说明

   在数据集上训练模型之前,需要将其预处理为预期的模型输入格式。无论您的数据是文本、图像还是音频,都需要将它们转换并组装成批量张量。🤗 Transformers 提供了一组预处理类来帮助为模型准备数据。在本教程中,您将了解以下内容:

  • 文本,使用Tokenizer将文本转换为标记序列,创建标记的数字表示,并将它们组装成张量。
  • 语音和音频,使用特征提取器从音频波形中提取顺序特征并将其转换为张量。
  • 图像输入使用ImageProcessor将图像转换为张量。
  • 多模态输入,使用处理器来组合分词器和特征提取器或图像处理器。

   AutoProcessor 无论您使用分词器、图像处理器、特征提取器还是处理器,它始终有效并自动为您正在使用的模型选择正确的类。

   在开始之前,请安装 🤗 数据集,以便您可以加载一些数据集进行实验:

pip install datasets

二、自然语言处理

   预处理文本数据的主要工具是分词器。分词器根据一组规则将文本分割成标记。标记被转换为数字,然后是张量,成为模型输入。模型所需的任何额外输入均由分词器添加。

   如果您计划使用预训练模型,那么使用关联的预训练分词器非常重要。这确保了文本以与预训练语料库相同的方式进行分割,并在预训练期间使用相同的相应标记到索引(通常称为词汇)。

   首先使用AutoTokenizer.from_pretrained()方法加载预训练的分词器。这将下载模型预训练的词汇:

from transformers import AutoTokenizer 
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")

   然后将您的文本传递给标记器:

encoded_input = tokenizer("Do not meddle in the affairs of wizards, for they are subtle and quick to anger.")
print(encoded_input)

{ ‘input_ids’ : [ 101 , 2079 , 2025 , 19960 , 10362 , 1999 , 1996 , 3821 , 1997 , 16657 , 1010 , 2005 , 2027 , 2024 , 11259 , 1998 , 4248 , 2000 , 4963 , 1012 , 102 ] ,
’ token_type_ids’ : [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
‘attention_mask’ : [ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ] }

   分词器返回一个包含三个重要项目的字典:

   input_ids是句子中每个标记对应的索引。

  •    Attention_mask指示是否应注意令牌。
  •    token_type_ids标识当存在多个序列时令牌属于哪一个序列。
  •    通过解码返回您的输入input_ids:
tokenizer.decode(encoded_input["input_ids"])

   '​​[CLS] 不要插手巫师的事务,因为他们很狡猾且容易生气。[九月]'正如您所看到的,分词器在句子中添加了两个特殊的标记 - CLSand SEP(分类器和分隔符)。并非所有模型都需要特殊标记,但如果需要,标记生成器会自动为您添加它们。

   如果您想要预处理多个句子,请将它们作为列表传递给分词器:

batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_inputs = tokenizer(batch_sentences)
print(encoded_inputs)

{ ‘input_ids’ : [[ 101 , 1252 , 1184 , 1164 , 1248 , 6462 , 136 , 102 ],
[ 101、1790、112、189、1341、1119、3520、1164、1248、6462、117、21902、1643、119、102 ] 、 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 101 , 1327 , 1164 , 5450 , 23434 , 136 , 102 ]],
‘token_type_ids’ : [[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 0 , 0 , 0 , 0 , 0 , 0 , 0 ]],
‘attention_mask’ : [[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ],
[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ],
[ 1 , 1 , 1 , 1 , 1 , 1 , 1 ]]}

2.1 Pad

   句子的长度并不总是相同,这可能是一个问题,因为张量(模型输入)需要具有统一的形状。填充是一种通过向较短句子添加特殊填充标记来确保张量为矩形的策略。

   将参数设置padding为True以填充批次中的较短序列以匹配最长序列:

batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_input = tokenizer(batch_sentences, padding=True)
print(encoded_input)

{ ‘input_ids’ : [[ 101 , 1252 , 1184 , 1164 , 1248 , 6462 , 136 , 102 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 101、1790、112、189、1341、1119、3520、1164、1248、6462、117、21902、1643、119、102 ] 、 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 101 , 1327 , 1164 , 5450 , 23434 , 136 , 102 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]],
‘token_type_ids’ : [[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]],
‘attention_mask’ : [[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ],
[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]]}

   第一个和第三个句子现在用0’ 填充,因为它们更短。

2.2 截断

另一方面,有时序列可能太长,模型无法处理。在这种情况下,您需要将序列截断为更短的长度。

将参数设置truncation为True将序列截断为模型接受的最大长度:

batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_input = tokenizer(batch_sentences, padding=True, truncation=True)
print(encoded_input)

{ ‘input_ids’ : [[ 101 , 1252 , 1184 , 1164 , 1248 , 6462 , 136 , 102 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 101、1790、112、189、1341、1119、3520、1164、1248、6462、117、21902、1643、119、102 ] 、 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 101 , 1327 , 1164 , 5450 , 23434 , 136 , 102 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]],
‘token_type_ids’ : [[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]],
‘attention_mask’ : [[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ],
[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]]}

   查看填充和截断概念指南以了解更多不同的填充和截断参数。

2.3 构建张量

最后,您希望分词器返回输入模型的实际张量。

将return_tensors参数设置pt为 PyTorch 或tfTensorFlow:

batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_input = tokenizer(batch_sentences, padding=True, truncation=True, return_tensors="pt")
print(encoded_input)

{ ‘input_ids’ : 张量([[ 101 , 1252 , 1184 , 1164 , 1248 , 6462 , 136 , 102 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 101、1790、112、189、1341、1119、3520、1164、1248、6462、117、21902、1643、119、102 ] 、 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 101 , 1327 , 1164 , 5450 , 23434 , 136 , 102 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]]),
‘token_type_ids’ : 张量([[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]]),
‘attention_mask’ : 张量([[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ],
[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]])}

三、TensorFlow

batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_input = tokenizer(batch_sentences, padding=True, truncation=True, return_tensors="tf")
print(encoded_input)

{ ‘input_ids’ : <tf.Tensor: shape=( 2 , 9 ), dtype=int32, numpy=
数组([[ 101 , 1252 , 1184 , 1164 , 1248 , 6462 , 136 , 102 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ,
[ 101、1790、112、189、1341、1119、3520、1164、1248、6462、117、21902、1643、119、102 ] 、 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 101 , 1327 , 1164 , 5450 , 23434 , 136 , 102 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]],
dtype=int32)>,
‘token_type_ids’ : <tf.Tensor: shape=( 2 , 9 ), dtype=int32, numpy=
数组([[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ,
[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]], dtype=int32)>,
‘attention_mask’ : <tf.Tensor: shape= ( 2 , 9 ), dtype=int32, numpy=
数组([[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ,
[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ],
[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]], dtype=int32)>}

   不同的管道在其“call()”中支持分词器参数的方式不同。“text-2-text- Generation”管道仅支持(即传递)“截断”。“文本生成”管道支持“max_length”、“truncation”、“padding”和“add_special_tokens”。在“fill-mask”管道中,分词器参数可以在“tokenizer_kwargs”参数(字典)中传递。

四、处理语音

   对于音频任务,您需要一个特征提取器来为模型准备数据集。特征提取器旨在从原始音频数据中提取特征,并将其转换为张量。

   加载MInDS-14数据集(有关如何加载数据集的更多详细信息,请参阅🤗数据集教程)以了解如何将特征提取器与音频数据集一起使用:

from datasets import load_dataset, Audio
dataset = load_dataset("PolyAI/minds14", name="en-US", split="train")

   访问该列的第一个元素audio以查看输入。调用该audio列会自动加载音频文件并重新采样:

 dataset[0]["audio"]

{ ‘数组’ : 数组([ 0. , 0.00024414 , - 0.00024414 , …, - 0.00024414 ,
0. , 0. ], dtype=float32),
‘路径’ : ‘/root/.cache/huggingface/datasets/下载/提取/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~JOINT_ACCOUNT/602ba55abb1e6d0fbce92065.wav’,‘sampling_rate’:8000 }
_

   这将返回三个项目:

  • array是作为一维数组加载并可能重新采样的语音信号。
  • path指向音频文件的位置。
  • sampling_rate指的是每秒测量语音信号中的多少个数据点。
       在本教程中,您将使用Wav2Vec2模型。查看模型卡,您将了解到 Wav2Vec2 是在 16kHz 采样语音音频上进行预训练的。音频数据的采样率与用于预训练模型的数据集的采样率相匹配非常重要。如果您的数据的采样率不相同,那么您需要对数据重新采样。
  1. 使用Datasets的cast_column方法将采样率上采样到16kHz:
dataset = dataset.cast_column("audio", Audio(sampling_rate=16_000))
  1. 其次调用该audio列以重新采样音频文件:
    dataset[0][“audio”]

{ ‘数组’ : 数组([ 2.3443763e-05 , 2.1729663e-04 , 2.2145823e-04 , …,
3.8356509e-05 , - 7.3497440e-06 , - 2.1754686e-05 ], dtype=float32),
‘路径’:‘/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~JOINT_ACCOUNT/602ba55abb1e6d0fbce92065.wav’ ,
‘采样率’ : 16000 }

   接下来,加载特征提取器以规范化并填充输入。填充文本数据时,0会添加 a 以表示较短的序列。同样的想法也适用于音频数据。特征提取器将0- 解释为静音 - 添加到array。

   使用AutoFeatureExtractor.from_pretrained()加载特征提取器:

from transformers import AutoFeatureExtractor
feature_extractor = AutoFeatureExtractor.from_pretrained("facebook/wav2vec2-base")

   将音频传递array到特征提取器。我们还建议sampling_rate在特征提取器中添加参数,以便更好地调试可能发生的任何静默错误。

audio_input = [dataset[0]["audio"]["array"]]
feature_extractor(audio_input, sampling_rate=16000)

{ ‘input_values’ : [array([ 3.8106556e-04 , 2.7506407e-03 , 2.8015103e-03 , …,
5.6335266e-04 , 4.6588284e-06 , - 1.7142107e-04 ], dtype=float32) ] }

   就像分词器一样,您可以应用填充或截断来处理批量中的变量序列。看一下这两个音频样本的序列长度:

dataset[0]["audio"]["array"].shape

dataset[1]["audio"]["array"].shape

   创建一个函数来预处理数据集,使音频样本具有相同的长度。指定最大样本长度,特征提取器将填充或截断序列以匹配它:

def preprocess_function(examples):
    audio_arrays = [x["array"] for x in examples["audio"]]
    inputs = feature_extractor(
        audio_arrays,
        sampling_rate=16000,
        padding=True,
        max_length=100000,
        truncation=True,
    )
    return inputs

   将 应用于preprocess_function数据集中的前几个示例:

processed_dataset = preprocess_function(dataset[:5])

   样本长度现在相同并且与指定的最大长度匹配。您现在可以将处理后的数据集传递给模型!

processed_dataset["input_values"][0].shape
processed_dataset["input_values"][1].shape

五、计算机视觉

   对于计算机视觉任务,您需要一个图像处理器来为模型准备数据集。图像预处理由几个步骤组成,将图像转换为模型期望的输入。这些步骤包括但不限于调整大小、标准化、颜色通道校正以及将图像转换为张量。

   图像预处理通常遵循某种形式的图像增强。图像预处理和图像增强都对图像数据进行变换,但它们的目的不同:
  图像增强以有助于防止过度拟合并提高模型稳健性的方式改变图像。您可以在增强数据的方式上发挥创意 - 调整亮度和颜色、裁剪、旋转、调整大小、缩放等。但是,请注意不要通过增强来改变图像的含义。
  图像预处理可确保图像与模型的预期输入格式匹配。在微调计算机视觉模型时,必须与模型最初训练时完全一样地对图像进行预处理。
  您可以使用任何您喜欢的库来进行图像增强。对于图像预处理,使用ImageProcessor与模型关联的。

   加载food101数据集(有关如何加载数据集的更多详细信息,请参阅 🤗数据集教程)以了解如何将图像处理器与计算机视觉数据集结合使用:

   使用 🤗 Datasetssplit参数仅从训练分割中加载小样本,因为数据集非常大!

from datasets import load_dataset
dataset = load_dataset("food101", split="train[:100]")

接下来,使用 🤗 数据集功能查看图像Image:

dataset[0]["image"]

在这里插入图片描述

使用AutoImageProcessor.from_pretrained()加载图像处理器:

from transformers import AutoImageProcessor
image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")

   首先,让我们添加一些图像增强。您可以使用您喜欢的任何库,但在本教程中,我们将使用 torchvision 的transforms模块。如果您有兴趣使用其他数据增强库,请在Albumentations或Kornia 笔记本中了解如何操作。

   1. 在这里,我们使用Compose将几个变换链接在一起 -RandomResizedCrop和ColorJitter。请注意,对于调整大小,我们可以从image_processor. 对于某些模型,需要精确的高度和宽度,而对于其他模型,仅shortest_edge定义了高度和宽度。

from torchvision.transforms import RandomResizedCrop, ColorJitter, Compose

size = (
    image_processor.size["shortest_edge"]
    if "shortest_edge" in image_processor.size
    else (image_processor.size["height"], image_processor.size["width"])
)

_transforms = Compose([RandomResizedCrop(size), ColorJitter(brightness=0.5, hue=0.5)])

   2. 该模型接受pixel_values 作为其输入。ImageProcessor可以负责标准化图像并生成适当的张量。创建一个函数,将一批图像的图像增强和图像预处理相结合并生成pixel_values:

def transforms(examples):
    images = [_transforms(img.convert("RGB")) for img in examples["image"]]
    examples["pixel_values"] = image_processor(images, do_resize=False, return_tensors="pt")["pixel_values"]
    return examples

   在上面的示例中,我们进行设置do_resize=False是因为我们已经在图像增强变换中调整了图像的大小,并利用了size适当的image_processor. 如果在图像增强期间不调整图像大小,请忽略此参数。默认情况下,ImageProcessor将处理调整大小。

   如果您希望将图像标准化作为增强变换的一部分,请使用image_processor.image_mean, 和image_processor.image_std值。

   3. 然后使用 🤗 数据集set_transform动态应用转换:

dataset.set_transform(transforms)

   4. 现在,当您访问图像时,您会注意到图像处理器已添加pixel_values. 您现在可以将处理后的数据集传递给模型!

dataset[0].keys()

   这是应用变换后图像的样子。该图像已被随机裁剪,并且其颜色属性有所不同。

import numpy as np
import matplotlib.pyplot as plt

img = dataset[0]["pixel_values"]
plt.imshow(img.permute(1, 2, 0))

在这里插入图片描述

   对于对象检测、语义分割、实例分割和全景分割等任务,ImageProcessor 提供后处理方法。这些方法将模型的原始输出转换为有意义的预测,例如边界框或分割图。

六、填充

   在某些情况下,例如,在微调DETR时,模型会在训练时应用尺度增强。这可能会导致一批图像的尺寸不同。您可以使用DetrImageProcessor.pad() DetrImageProcessor并定义一个自定义来将collate_fn图像一起批处理。

def collate_fn(batch):
    pixel_values = [item["pixel_values"] for item in batch]
    encoding = image_processor.pad(pixel_values, return_tensors="pt")
    labels = [item["labels"] for item in batch]
    batch = {}
    batch["pixel_values"] = encoding["pixel_values"]
    batch["pixel_mask"] = encoding["pixel_mask"]
    batch["labels"] = labels
    return batch

七、Multimodal

   对于涉及多模式输入的任务,您需要一个处理器来为模型准备数据集。处理器将两个处理对象耦合在一起,例如分词器和特征提取器。

   加载LJ 语音数据集(有关如何加载数据集的更多详细信息,请参阅 🤗数据集教程)以了解如何使用处理器进行自动语音识别 (ASR):

from datasets import load_dataset
lj_speech = load_dataset("lj_speech", split="train")

   对于 ASR,您主要关注的是audio,text因此您可以删除其他列:

lj_speech = lj_speech.map(remove_columns=["file", "id", "normalized_text"])

   现在看一下audio和text列:

lj_speech[0]["audio"]

{ ‘数组’ : 数组([- 7.3242188e-04 , - 7.6293945e-04 , - 6.4086914e-04 , …,
7.3242188e-04 , 2.1362305e-04 , 6.1035156e-05 ], dtype=float32) ,
‘路径’:‘/root/.cache/huggingface/datasets/downloads/extracted/917ece08c95cf0c4115e45294e3cd0dee724a1165b7fc11798369308a465bd26/LJSpeech-1.1/wavs/LJ001-0001.wav’,
‘放大率’:22050 }

lj_speech[0]["text"]

   ‘印刷,就我们目前所关心的唯一意义而言,与展览中展示的大多数艺术和手工艺不同,甚至是所有艺术和手工艺’
请记住,您应该始终对音频数据集的采样率进行重新采样,以匹配用于预训练模型的数据集的采样率!

lj_speech = lj_speech.cast_column("audio", Audio(sampling_rate=16_000))

   使用AutoProcessor.from_pretrained()加载处理器:

from transformers import AutoProcessor
processor = AutoProcessor.from_pretrained("facebook/wav2vec2-base-960h")

   1. 创建一个函数来将数组中包含的音频数据处理为 input_values,并将文本标记为标签。这些是模型的输入:

def prepare_dataset(example):
    audio = example["audio"]
    example.update(processor(audio=audio["array"], text=example["text"], sampling_rate=16000))
    return example

   2. 将prepare_dataset函数应用于样本:

prepare_dataset(lj_speech[0])

   处理器现已添加input_values和labels,并且采样率也已正确下采样至 16kHz。您现在可以将处理后的数据集传递给模型!

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

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

相关文章

Vulnhub靶机:hacksudoAliens

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;hacksudoAliens&#xff08;10.0.2.46&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://download.vulnhub.com…

Log360,引入全新安全与风险管理功能,助力企业积极抵御网络威胁

ManageEngine在其SIEM解决方案中推出了安全与风险管理新功能&#xff0c;企业现在能够更主动地减轻内部攻击和防范入侵。 SIEM 这项新功能为Log360引入了安全与风险管理仪表板&#xff0c;Log360是ManageEngine的统一安全信息与事件管理&#xff08;SIEM&#xff09;解决方案…

数字图像处理(实践篇)四十六 OpenCV-Python 目标定位(Features2D + Homography)

目录 一 单映射Homography 二 涉及的函数 三 实践 一 单映射Homography 在计算机视觉中,平面的单应性被定义为一个平面到另外一个平面的投影映射。 单映射Homography 就是将一张图像上的点映射到另一张图像上的对应点的3x3变换矩阵。从下图中可以看出&#x

深兰科技陈海波出席CTDC2024第五届首席技术官领袖峰会:“民主化AI”的到来势如破竹

1月26日&#xff0c;CTDC 2024 第五届首席技术官领袖峰会暨出海创新峰会在上海举行。深兰科技创始人、董事长陈海波受邀出席了本届会议&#xff0c;并作为首个演讲嘉宾做了题为“前AGI时代的生产力革命范式”的行业分享。 作为国内顶级前瞻性技术峰会&#xff0c;CTDC首席技术官…

国考省考行测:判断推理,论证逻辑

国考省考行测&#xff1a;判断推理&#xff0c;论证逻辑 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#xff0c;而常规国考省考最重要的还是申论和行测&#xff0c;所以大家认真准备吧&#xff0c;我讲一起屡屡申论和…

Linux进程信号处理:深入理解与应用(3)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;its 6pm but I miss u already.—bbbluelee 0:01━━━━━━️&#x1f49f;──────── 3:18 &#x1f504; ◀️…

SQL 表信息 | 统计 | 脚本

介绍 统计多个 SQL Server 实例上多个数据库的表大小、最后修改时间和行数&#xff0c;可以使用以下的 SQL 查询来获取这些信息。 脚本 示例脚本&#xff1a; DECLARE Query NVARCHAR(MAX)-- 创建一个临时表用于存储结果 CREATE TABLE #TableSizes (DatabaseName NVARCHAR…

游泳哪个牌子口碑最好?全球最好的游泳耳机排行榜

在水中畅游时&#xff0c;倾听悠扬的音乐或放松的声音是一种愉悦的体验&#xff0c;而蓝牙游泳耳机的出现更是为游泳者提供了更便利的选择。市场上涌现出多款不同品牌的蓝牙游泳耳机&#xff0c;为了满足游泳爱好者对音乐的需求&#xff0c;小编为大家精心整理了一些值得推荐的…

C++多线程学习[五]:RAII锁

一、什么是RAII 使用局部对象来控制资源的技术&#xff0c;即它的生命周期由操作系统来管理&#xff0c;无需人工的介入。 为什么要采用RAII技术呢&#xff1f; 主要是在开发过程中资源的销毁容易忘记&#xff0c;容易造成死锁或内存泄露。 {}为一个区域 &#xff0c;这里锁的…

JVM 性能调优 - 参数调优(3)

查看 JVM 内存的占用情况 编写代码 package com.test;public class PrintMemoryDemo {public static void main(String[] args) {// 堆内存总量long totalMemory Runtime.getRuntime().totalMemory();// jvm 试图使用的最大堆内存long maxMemory Runtime.getRuntime().maxM…

Matlab使用点云工具箱进行点云配准

一、代码 source_pc pcread(bun_zipper.ply); target_pc pcread(bun_zipper2.ply); % 下采样 gridStep 0.001; ptCloudA pcdownsample(source_pc,gridAverage,gridStep); ptCloudB pcdownsample(target_pc,gridAverage,gridStep); % 初始变换矩阵 tform_initial affine3…

AE2023 After Effects 2023

After Effects 2023是一款非常强大的视频编辑软件&#xff0c;提供了许多新功能和改进&#xff0c;使得视频编辑和合成更加高效和灵活。以下是一些After Effects 2023的特色功能&#xff1a; 新合成预设列表&#xff1a;After Effects 2023彻底修改了预设列表&#xff0c;使其…

Excel——有效性、二级菜单联动

一、录入规范数据 1.手动输入序列录入有效性信息 选择需要录入有效性的所有单元格 选择【数据】——【有效性】——【有效性】 在【允许】输入的值之间选择【序列】 在【序列】输入框中输入想要选择的值&#xff0c;中间用逗号&#xff08;必须是英文逗号&#xff09;隔开 。…

Java入门之JavaSe(韩顺平p1-p?)

学习背景&#xff1a; 本科搞过一段ACM、研究生搞了一篇B会后&#xff0c;本人在研二要学Java找工作啦~~&#xff08;宇宙尽头是Java&#xff1f;&#xff09;爪洼纯小白入门&#xff0c;C只会STL、python只会基础Pytorch、golang参与了一个Web后端项目&#xff0c;可以说项目小…

Linux 网络:PTP 简介

文章目录 1. 前言2. PTP(Precision Time Protocol​) IEEE 1588 协议简介2.1 PTP IEEE 1588 协议时间同步原理2.2 PTP IEEE 1588 协议时钟类型2.2.1 普通时钟(OC: Ordinary Clock)2.2.2 边界时钟(BC: Boundary Clock)2.2.3 透明时钟(TC: Transparent Clock)2.2.3.1 端对端透明时…

挂耳耳机哪个牌子好?推荐几款性价比超高的挂耳耳机

在寻求更轻便舒适的听音体验时&#xff0c;挂耳耳机逐渐成为众多用户的优先选择。市场上各式各样的耳挂耳机琳琅满目&#xff0c;种类繁多&#xff0c;挂耳耳机哪个牌子好&#xff1f;为了帮助大家更好地了解耳挂耳机的市场状况&#xff0c;我推荐几款性价比超高的挂耳耳机。 挂…

MongoDB的分片集群(二) :mongodb4.x分片集群离线搭建开启安全认证

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 相关文章&#xff1a; MongoDB的分片集群(一) : 基础知识 在《MongoDB的分片集群(一) : 基础知识》中梳理了分片集群的基础知识…

知名开发工具RubyMine全新发布v2023.3——支持AI Assistant

RubyMine 是一个为Ruby 和 Rails开发者准备的 IDE&#xff0c;其带有所有开发者必须的功能&#xff0c;并将之紧密集成于便捷的开发环境中。 RubyMine v2023.3正式版下载 新版本改进AI Assistant支持、Rails应用程序和引擎的自定义路径、对Rails 7.1严格locals的代码洞察、RB…

页面模块向上渐变显示效果实现

ps: 先祝各位朋友新春快乐 ^o^/ 想要首页不那么枯燥无味吗&#xff1f;还在未首页过于单调而苦恼吧&#xff0c;来试试这个吧&#xff08;大佬请忽略上述语句o&#xff09; 今天要实现一个页面线上渐变显示的效果&#xff0c;用来丰富首页等页面&#xff1a; 这里先随机建立几…

jsp商场会员卡管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 商场会员卡管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.…