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

在 AMD GPU 上构建解码器 Transformer 模型

Building a decoder transformer model on AMD GPU(s) — ROCm Blogs

2024年3月12日 作者 Phillip Dang.

在这篇博客中,我们展示了如何使用 PyTorch 2.0 和 ROCm 在单个节点上的单个和多个 AMD GPU 上运行Andrej Karpathy’s beautiful PyTorch re-implementation of GPTGPT PyTorch 重新实现Andrej Karpathy’s beautiful PyTorch re-implementation of GPT。

GPT 模型的核心是仅解码器的 transformer 架构。这种架构以自回归的方式一次生成一个输出标记(在我们的情况下是字符),这意味着每个生成的标记都依赖于之前生成的标记。如需深入了解该模型的工作原理,我们强烈推荐查看以下内容:

  • Andrej Karpathy的 Let’s build GPT: 从头开始,用代码详细阐述 视频

  • Attention Is All You Need 论文。

我们首先使用 PyTorch 和 ROCm 在单个 GPU 上训练我们的模型,然后稍微修改代码以使用 to run on two GPUs using PyTorch 的分布式数据并行(Distributed Data Parallel, DDP)在两个 GPU 上运行。

在多 GPU 上进行分布式数据并行性的工作原理是:

  1. 将当前全局训练批次拆分为每个 GPU 上的小局部批次。例如,如果你有 8 个 GPU,且全局批次设置为 32 个样本,则每个 8 个 GPU 将具有 4 个样本的局部批次大小。

  2. 将模型复制到每个设备,以便每个设备可以独立处理其局部批次。

  3. 运行前向传播,然后是反向传播,并输出模型权重相对于局部批次损失的渐变。这会在多个设备上并发发生。

  4. 同步每个设备计算的局部梯度并将它们结合起来以更新模型权重。更新后的权重会重新分发到每个设备。

如需深入了解 PyTorch 中的分布式训练,请参阅 使用 DDP 进行多 GPU 训练。

先决条件

要跟随本博客的内容进行操作,您需要具备以下软件:

  • ROCm

  • PyTorch

  • Linux OS

接下来,通过运行以下代码确保您的系统能够识别两块 AMD GPU:

! rocm-smi --showproductname

输出结果应如下所示:

================= ROCm System Management Interface ================
========================= Product Info ============================
GPU[0] : Card series: Instinct MI210
GPU[0] : Card model: 0x0c34
GPU[0] : Card vendor: Advanced Micro Devices, Inc. [AMD/ATI]
GPU[0] : Card SKU: D67301
GPU[1] : Card series: Instinct MI210
GPU[1] : Card model: 0x0c34
GPU[1] : Card vendor: Advanced Micro Devices, Inc. [AMD/ATI]
GPU[1] : Card SKU: D67301
===================================================================
===================== End of ROCm SMI Log =========================

确保 PyTorch 也能识别这些 GPU:

import torch
import torch.nn as nn
from torch.nn import functional as F
print(f"number of GPUs: {torch.cuda.device_count()}")
print([torch.cuda.get_device_name(i) for i in range(torch.cuda.device_count())])

输出结果应如下所示:

number of GPUs: 2
['AMD Radeon Graphics', 'AMD Radeon Graphics']

加载数据

我们使用 tiny_shakespeare 数据集,该数据集包含来自莎士比亚各种剧作的40,000行文本。让我们加载它并查看前200个字符。

! wget https://raw.githubusercontent.com/karpathy/char-rnn/master/data/tinyshakespeare/input.txt
with open('input.txt', 'r', encoding='utf-8') as f:text = f.read()
print(text[:200])

输出:

First Citizen:
Before we proceed any further, hear me speak.All:
Speak, speak.First Citizen:
You are all resolved rather to die than to famish?All:
Resolved. resolved.First Citizen:
First, you

接下来,我们从文本中的唯一字符创建我们的词汇表,并建立字符与整数之间的映射。

chars = sorted(list(set(text)))
vocab_size = len(chars)
# create a mapping from characters to integers
stoi = { ch:i for i,ch in enumerate(chars) }
itos = { i:ch for i,ch in enumerate(chars) }
encode = lambda s: [stoi[c] for c in s] # encoder: take a string, output a list of integers
decode = lambda l: ''.join([itos[i] for i in l]) # decoder: take a list of integers, output a string

现在,我们将数据在编码字符之后分成训练集和测试集(即将每个字符转换为一个整数)。

data = torch.tensor(encode(text), dtype=torch.long)
n = int(0.9*len(data)) # first 90% will be train, rest val
train_data = data[:n]
val_data = data[n:]

让我们来看一个输入和目标的例子。

block_size = 8
x = train_data[:block_size]
y = train_data[1:block_size+1]
for t in range(block_size):context = x[:t+1]target = y[t]print(f"when input is {context} the target: {target}")

输出:

when input is tensor([18]) the target: 47
when input is tensor([18, 47]) the target: 56
when input is tensor([18, 47, 56]) the target: 57
when input is tensor([18, 47, 56, 57]) the target: 58
when input is tensor([18, 47, 56, 57, 58]) the target: 1
when input is tensor([18, 47, 56, 57, 58,  1]) the target: 15
when input is tensor([18, 47, 56, 57, 58,  1, 15]) the target: 47
when input is tensor([18, 47, 56, 57, 58,  1, 15, 47]) the target: 58

创建解码器transformer模型

让我们设置一些超参数,用于构建和训练模型。因为我们能够使用强大的AMD GPU,可以扩展我们的网络,并设置与Andrej在其视频教程中使用的相同的超参数。这包括增加我们的批量大小、块大小、层数和头数以及嵌入大小。我们希望这将使我们的损失值更低。

# 超参数
batch_size = 64 # 我们将并行处理多少个独立序列?
block_size = 256 # 预测的最大上下文长度是多少?
max_iters = 5000
eval_interval = 100
learning_rate = 3e-4
device = 'cuda' if torch.cuda.is_available() else 'cpu'
eval_iters = 200
n_embd = 384
n_head = 6
n_layer = 6
dropout = 0.2
# ------------torch.manual_seed(1337) # 设置手动种子以保证可重复性

解码器Transformer架构

以下是我们的主要模型类,它创建了一个解码器Transformer架构。其组件包括:

  • 自注意力机制:允许解码器在生成输出时权衡输入序列的不同部分。

  • 掩码自注意力:通过掩盖后续位置,防止解码器在训练期间看到未来的令牌。

  • 解码器层:由多层子层组成,如多头注意力和前馈神经网络,促进信息处理和生成。

Transformer decoder process

class Head(nn.Module):""" 一个自注意力头  """def __init__(self, head_size):super().__init__()self.key = nn.Linear(n_embd, head_size, bias=False)self.query = nn.Linear(n_embd, head_size, bias=False)self.value = nn.Linear(n_embd, head_size, bias=False)self.register_buffer('tril', torch.tril(torch.ones(block_size, block_size)))self.dropout = nn.Dropout(dropout)def forward(self, x):# 输入大小 (batch, time-step, channels)# 输出大小 (batch, time-step, head size)B,T,C = x.shapek = self.key(x)   # (B,T,hs)q = self.query(x) # (B,T,hs)# 计算注意力分数 ("affinities")wei = q @ k.transpose(-2,-1) * k.shape[-1]**-0.5 # (B, T, hs) @ (B, hs, T) -> (B, T, T)# 使用上三角矩阵技巧创建掩码用于自注意力机制# 该掩码确保在训练期间,解码器只能关注到当前生成的令牌之前的位置,防止看到未来的令牌,即仅从左到右注意wei = wei.masked_fill(self.tril[:T, :T] == 0, float('-inf')) # (B, T, T)wei = F.softmax(wei, dim=-1) # (B, T, T)wei = self.dropout(wei)#  执行值的加权聚合v = self.value(x) # (B,T,hs)out = wei @ v # (B, T, T) @ (B, T, hs) -> (B, T, hs)return outclass MultiHeadAttention(nn.Module):""" 并行的多头自注意力机制 """def __init__(self, num_heads, head_size):super().__init__()self.heads = nn.ModuleList([Head(head_size) for _ in range(num_heads)])self.proj = nn.Linear(head_size * num_heads, n_embd)self.dropout = nn.Dropout(dropout)def forward(self, x):out = torch.cat([h(x) for h in self.heads], dim=-1)out = self.dropout(self.proj(out))return outclass FeedFoward(nn.Module):""" 一个简单的线性层及其非线性激活 """def __init__(self, n_embd):super().__init__()self.net = nn.Sequential(nn.Linear(n_embd, 4 * n_embd),nn.ReLU(),nn.Linear(4 * n_embd, n_embd),nn.Dropout(dropout),)def forward(self, x):return self.net(x)class Block(nn.Module):""" Transformer块: 通信后是计算  """def __init__(self, n_embd, n_head):# n_embd: 嵌入维度,n_head: 多头数量super().__init__()head_size = n_embd // n_headself.sa = MultiHeadAttention(n_head, head_size)self.ffwd = FeedFoward(n_embd)self.ln1 = nn.LayerNorm(n_embd)self.ln2 = nn.LayerNorm(n_embd)def forward(self, x):x = x + self.sa(self.ln1(x))x = x + self.ffwd(self.ln2(x))return xclass GPTLanguageModel(nn.Module):def __init__(self):super().__init__()# 每个令牌直接从查找表中读取下一个令牌的logitsself.token_embedding_table = nn.Embedding(vocab_size, n_embd)self.position_embedding_table = nn.Embedding(block_size, n_embd)self.blocks = nn.Sequential(*[Block(n_embd, n_head=n_head) for _ in range(n_layer)])self.ln_f = nn.LayerNorm(n_embd) # final layer normself.lm_head = nn.Linear(n_embd, vocab_size)# 更好的权重初始化,原始GPT视频中未涵盖,但很重要,将在后续视频中介绍self.apply(self._init_weights)def _init_weights(self, module):if isinstance(module, nn.Linear):torch.nn.init.normal_(module.weight, mean=0.0, std=0.02)if module.bias is not None:torch.nn.init.zeros_(module.bias)elif isinstance(module, nn.Embedding):torch.nn.init.normal_(module.weight, mean=0.0, std=0.02)def forward(self, idx, targets=None):B, T = idx.shape# idx 和 targets 都是 (B, T) 的整数张量tok_emb = self.token_embedding_table(idx) # (B,T,C)pos_emb = self.position_embedding_table(torch.arange(T, device=device)) # (T,C)x = tok_emb + pos_emb # (B,T,C)x = self.blocks(x) # (B,T,C)x = self.ln_f(x) # (B,T,C)logits = self.lm_head(x) # (B,T,vocab_size)if targets is None:loss = Noneelse:B, T, C = logits.shapelogits = logits.view(B*T, C)targets = targets.view(B*T)loss = F.cross_entropy(logits, targets)return logits, lossdef generate(self, idx, max_new_tokens):# idx 是 (B, T) 当前上下文的索引数组for _ in range(max_new_tokens):# 将 idx 裁剪为最后 block_size 个令牌idx_cond = idx[:, -block_size:]# 获取预测结果logits, loss = self(idx_cond)# 只关注最后一个时间步logits = logits[:, -1, :] # becomes (B, C)# 应用 softmax 获得概率probs = F.softmax(logits, dim=-1) # (B, C)# 从概率分布中采样idx_next = torch.multinomial(probs, num_samples=1) # (B, 1)# 将采样得到的索引追加到运行的序列中idx = torch.cat((idx, idx_next), dim=1) # (B, T+1)return idx

实用函数

在训练我们的模型之前,我们需要两个实用函数:

  • 在训练我们的模型之前,我们需要两个实用函数:

  • 一个是获取随机批量数据的函数

为了估计损失:

@torch.no_grad()
def estimate_loss(model):out = {}model.eval()for split in ['train', 'val']:losses = torch.zeros(eval_iters)for k in range(eval_iters):X, Y = get_batch(split)logits, loss = model(X, Y)losses[k] = loss.item()out[split] = losses.mean()model.train()return out

为了获取一个小批量的数据:

# 数据加载
def get_batch(split):# 数据加载data = train_data if split == 'train' else val_dataix = torch.randint(len(data) - block_size, (batch_size,))x = torch.stack([data[i:i+block_size] for i in ix])y = torch.stack([data[i+1:i+block_size+1] for i in ix])x, y = x.to(device), y.to(device)return x, y

训练和推理 

现在我们已经准备好所有的部分,让我们实例化我们的模型,进行训练,并运行一些推理来生成我们(希望)类似莎士比亚风格的文本。

这是我们的主函数:

def main():model = GPTLanguageModel()model = model.to(device)# 输出模型的参数数量print(sum(p.numel() for p in model.parameters())/1e6, 'M parameters')# 创建一个 PyTorch 优化器optimizer = torch.optim.AdamW(model.parameters(), lr=learning_rate)for iter in range(max_iters):# 定期评估训练集和验证集的损失if iter % eval_interval == 0 or iter == max_iters - 1:losses = estimate_loss(model)print(f"step {iter}: train loss {losses['train']:.4f}, val loss {losses['val']:.4f}")# 抽取一个数据批次xb, yb = get_batch('train')# 计算损失logits, loss = model(xb, yb)optimizer.zero_grad(set_to_none=True)loss.backward()optimizer.step()# 使用模型进行推理以生成文本context = torch.zeros((1, 1), dtype=torch.long, device=device)print(decode(model.generate(context, max_new_tokens=2000)[0].tolist()))

我们创建了一个名为 gpt_single_gpu.py 的脚本,包含所有必要的命令。要运行它,请使用以下代码:

python3 gpt_single_gpu.py

以下是脚本的预期输出:

10.788929 M parameters
step 0: train loss 4.2221, val loss 4.2306
step 100: train loss 2.4966, val loss 2.5012
step 200: train loss 2.4029, val loss 2.4295
...
step 4900: train loss 0.8676, val loss 1.5644
step 4999: train loss 0.8598, val loss 1.5677

以下是我们生成的文本的前几行:

Thou fellow'dst idst the game of his names;
And yet since was Menenius, one would thrident again
That Anne. But where shall do become me injuries?JULIET:
O though often thee cortainted matter,--
A better with him he gone hath
A colder-balm equal-deniving,
Of what a peril the people, when he did make me
Disobedition, become him to see
That conceive on earth fitting his finger,

在验证损失为1.5677时,生成的文本看起来几乎像英语,并且模型能够学习莎士比亚输入的对话风格。

每次运行推理时,我们期望的结果会有所不同。这是因为模型从所有可能的标记分布中进行采样,其中每个标记的概率由 softmax 函数给出。

分布式训练在多 GPU 上

为了在 PyTorch 中使用多个 GPU 在单个节点上训练我们的模型,我们将使用 PyTorch 的分布式数据并行 (Distributed Data Parallel)。 为此,我们只需要对当前代码进行一点点修改。

首先,让我们从 PyTorch 导入一些所需的函数:

import torch.multiprocessing as mp
from torch.distributed import init_process_group, destroy_process_group
from torch.nn.parallel import DistributedDataParallel as DDP

接下来,让我们设置分布式数据并行组。 通常,每个 GPU 运行一个进程,因此我们需要设置一个组,以便所有进程和 GPU 之间可以相互通信。 让我们创建一个执行此操作的小函数。

def ddp_setup(rank, world_size):"""world_size: GPU 的数量rank: GPU 的 ID,从 0 到 world_size - 1"""os.environ['MASTER_ADDR'] = 'localhost'os.environ['MASTER_PORT'] = '12355'# 初始化进程组backend = "nccl"init_process_group(backend=backend, rank=rank, world_size=world_size)torch.cuda.set_device(rank)

在实例化模型之前,我们需要调用这个设置函数。 接下来,我们对主函数进行些许修改,使其能够在多个 GPU 上运行。 请注意,主函数现在接收两个参数:rank(GPU 的 ID)和 world_size(GPU 的数量)。

def main(rank:int, world_size:int):print(f"Training DDP model on rank/gpu {rank}.")ddp_setup(rank, world_size)# 每个 gpu/进程获得不同的种子torch.manual_seed(1337 + rank)model = GPTLanguageModel()model.to(rank)model = DDP(model, device_ids=[rank])... # 剩下的训练过程与单进程主函数的训练过程相同# 运行推理if rank == 0: # 仅在主进程上运行推理。没有这个 if 语句,每个进程都会运行自己的预测print('generating text')context = torch.zeros((1, 1), dtype=torch.long, device=device)# 因为模型现在是一个分布式模型,我们需要通过添加 "module" 来解包它print(decode(model.module.generate(context, max_new_tokens=500)[0].tolist()))#  一旦模型训练完成,销毁进程以干净退出destroy_process_group()

完整代码

我们创建了一个脚本 gpt_multiple_gpus.py ,其中包含所有必需的命令。要运行该脚本,请使用以下代码:

python3 gpt_multiple_gpus.py

以下是该脚本的预期输出。

We have 2 GPUs! Using 2 GPUs
Training DDP model on rank/gpu 1.
Training DDP model on rank/gpu 0.
10.788929 M parameters
10.788929 M parameters
GPU/rank 0 step 0: train loss 4.2221, val loss 4.2306
GPU/rank 1 step 0: train loss 4.2228, val loss 4.2304
GPU/rank 0 step 500: train loss 1.6010, val loss 1.7904
GPU/rank 1 step 500: train loss 1.5984, val loss 1.7871
...
GPU/rank 1 step 4999: train loss 0.5810, val loss 1.7733
GPU/rank 0 step 4999: train loss 0.5807, val loss 1.7723

以下是生成的文本:

HENRY BOLINGBROKE:
Warwick, It say; and he is safe, and whose
With unmorable slaves, they have stafd too:
So say the tidings you for Richmond, with ride?BUSHY:
Marry, my Lord Clarence to my noble lady.GLOUCESTER:
Go, to thee to thy daughter as I may break;
And what do now thy will I, I do me say
My name; it is the king.BUCKINGHAM:
'Twas every stranger:--
Nay, my good son.

输出来自两个不同的GPU(rank 0和1),每个训练/验证损失是不同的。这是因为每个进程有不同的种子,以确保它们不会在相同的数据批次上进行训练。 

相关文章:

在 AMD GPU 上构建解码器 Transformer 模型

Building a decoder transformer model on AMD GPU(s) — ROCm Blogs 2024年3月12日 作者 Phillip Dang. 在这篇博客中,我们展示了如何使用 PyTorch 2.0 和 ROCm 在单个节点上的单个和多个 AMD GPU 上运行Andrej Karpathy’s beautiful PyTorch re-implementation …...

Canvas简历编辑器-选中绘制与拖拽多选交互设计

Canvas简历编辑器-选中绘制与拖拽多选交互设计 在之前我们聊了聊如何基于Canvas与基本事件组合实现了轻量级DOM,并且在此基础上实现了如何进行管理事件以及多层级渲染的能力设计。那么此时我们就依然在轻量级DOM的基础上,关注于实现选中绘制与拖拽多选交…...

简单工厂(Simple Factory)

简单工厂(Simple Factory) 在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口。 说明: 简单工厂把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪…...

ffmpeg拉流分段存储到文件-笔记

通过ffmpeg可以从rtsp网络流拉取数据并存储到本地文件里,如下命令。做个笔记 ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.168:6880/live -c copy -f segment -segment_time 60 stream_piece_%d.mp4这条 ffmpeg 命令的作用是从一个 RTSP 流中捕获视频&#xff…...

Java 实习工资大概是多少?——解读影响薪资的因素

文章目录 1. 城市因素:一线、二线的差距2. 公司类型:互联网公司、外企和传统企业的差别3. 个人能力:经验、技术栈的重要性4. 其他影响因素:学历和实习时间总结推荐阅读文章 Java 开发作为广泛应用的职业方向,实习工资的…...

【Linux】万字详解:Linux文件系统与软硬链接

🌈 个人主页:Zfox_ 🔥 系列专栏:Linux 目录 🚀 前言 一: 🔥 磁盘的物理结构二: 🔥 磁盘的存储结构 三: 🔥 磁盘的逻辑结构 四: &#…...

spacenavd

介绍spacenavd开源项目,主要是因为在斯坦福大学的UMI项目中使用了该项目。在斯坦福大学的 UMI(Universal Manipulation Interface)项目中,Spacenavd 主要用于处理 3D Space Mouse(空间鼠标)的输入&#xf…...

C#WPF的XAML的语法详谈和特性

WPF的XAML(eXtensible Application Markup Language)是一种基于XML的标记语言,用于在.NET框架中定义和描述用户界面。XAML提供了一种声明性的方式来构建应用程序的UI元素,包括窗口、控件、布局、样式、动画和数据绑定等。 XAML的…...

一篇文章讲透数据结构之二叉搜索树

前言 在前面的学习过程中,我们已经学习了二叉树的相关知识。在这里我们再使用C来实现一些比较难的数据结构。 这篇文章用来实现二叉搜索树。 一.二叉搜索树 1.1二叉搜索树的定义 二叉搜索树(Binary Search Tree)是基于二叉树的一种升级版…...

新手入门c++(8)

到时候了,是时候给你们讲一下其他的定义形式与格式化输入输出了。 1.长整型变量 长整型变量分为两种: ①long类型 在计算机编程中,long 类型是一个整型数据类型,用于存储较大的整数。它的大小和范围取决于操作系统和编译器的实…...

新手铲屎官提问,有哪几款噪音低的宠物空气净化器推荐

相信很多铲屎官都明白的的痛就是猫咪掉毛太严重,所以每次看到满天飞的浮毛时只想赶紧逃离,一点都不想清理。但是家是自己的,猫是自己的,健康也是自己的,不清理也得清理。 为了更有效的清理浮毛,我朋友特意…...

解决RabbitMQ脑裂问题

文章目录 前言一、现象二、解决办法 前言 RabbitMQ脑裂 一、现象 RabbitMQ镜像群出现脑裂现象,各个节点的MQ实例都“各自为政”,数据并不同步。 二、解决办法 # 停止mq sh rabbitmq-server stop_app # 查看mq进程是否存在 ps -ef | grep rabbitmq # …...

经纬恒润AUTOSAR成功适配芯钛科技Alioth TTA8车规级芯片

在汽车电子领域,功能安全扮演着守护者的角色,它确保了车辆在复杂多变的情况下保持稳定可靠的运行。随着汽车电子的复杂性增加,市场对产品功能安全的要求也日益提高。基于此背景,经纬恒润AUTOSAR基础软件产品INTEWORK-EAS-CP成功适…...

4、java random随机数、一维数组、二维数组

目录 Random类与随机数生成数组的概述与使用数组的内存分配与访问数组的常见问题与解决方案一维数组的遍历与操作二维数组的概述与遍历1. Random类与随机数生成 引言 在编程中,我们经常需要生成随机数,比如在游戏、模拟实验或者数据处理中。Java提供了一个非常方便的类Rand…...

C++ 魔法三钥:解锁高效编程的封装、继承与多态

快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 目录 💯前言 💯封装 1.封装概念 2.封装格式 3.封装的原理 4.封装的作用 💯继承 1.继承的概念 2.继承格式 3.继承的…...

姿态传感器(学习笔记上)

上节我们学的是温湿传感器,这节我们学的是姿态传感器,虽然都是传感器,但是它们还是有很大的区别的,这节的传感器我们通过学习可知,开发板上的姿态传感器型号是QMI8658C,内部集成3轴加速度传感器和3轴陀螺仪…...

labelimg使用教程

快捷键 W:调出标注的十字架,开始标注 A:切换到上一张图片 D:切换到下一张图片 del:删除标注的矩形框 CtrlS:保存标注好的标签 Ctrl鼠标滚轮:按住Ctrl,然后滚动鼠标滚轮,…...

力扣21 : 合并两个有序链表

链表style 描述: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例: 节点大小相同时,l1的节点在前 何解? 1,遍历两个链表,挨个比较节点大小 同时遍…...

【Spring】Spring Boot 配置文件(7)

本系列共涉及4个框架:Sping,SpringBoot,Spring MVC,Mybatis。 博客涉及框架的重要知识点,根据序号学习即可。 有什么不懂的都可以问我,看到消息会回复的,可能会不及时,请见谅!! 1、配置文件作…...

《向量数据库指南》——解锁Wikipedia文章向量的跨语言搜索秘籍

嘿,各位向量数据库和AI应用的小伙伴们,我是你们的老朋友王帅旭,大禹智库的向量数据库高级研究员,也是《向量数据库指南》的作者。今天,咱们来聊聊一个超棒的数据集——百万条 Wikipedia 文章向量,这可是我在研究过程中发现的一个宝藏啊! 首先,咱们得说说这个数据集的来…...

【力扣 + 牛客 | SQL题 | 每日5题】牛客SQL热题204,201,215

1. 力扣1126:查询活跃业务 1.1 题目: 事件表:Events ------------------------ | Column Name | Type | ------------------------ | business_id | int | | event_type | varchar | | occurrences | int | --------…...

下载数据集用于图像分类并自动分为训练集和测试集方法

一、背景 最近需要用Vision Transformer(ViT)完成图像分类任务,因此查到了WZMIAOMIAO的GitHub,里面有各种图像处理的方法。而图像处理的前期工作就是获取大量的数据集,用于训练模型参数,以准确识别或分类我…...

Python xlrd库介绍

一、简介 xlrd是一个用于读取Excel文件(.xls和.xlsx格式)的Python库。它提供了一系列函数来访问Excel文件中的数据,如读取工作表、单元格的值等。 二、安装 可以使用以下命令安装xlrd库: pip install xlrd 三、使用方法 1. 导入库: 示例…...

Javascript立即执行函数

//立即执行函数 把函数的声明看作一个整体声明结束就立即调用 // (function(){console.log(hello) // })(); console.log((function (){ return 0; })()); // let afunction(){ console.log(hello) }; console.log(typeof a);//function,数组:objeck...

Linux相关概念和易错知识点(17)(文件、文件的系统调用接口、C语言标准流)

目录 1.文件 (1)文件组成和访问 (2)文件的管理 (3)C语言标准流 (4)struct file ①文件操作表 ②文件内核缓冲区 (5)Linux下一切皆文件 (…...

三防加固工业平板国产化的现状与展望

在当今全球科技竞争日益激烈的背景下,工业4.0和智能制造的浪潮推动了工业自动化设备的迅速发展,其中,三防加固工业平板电脑作为连接物理世界与数字世界的桥梁,其重要性不言而喻。所谓“三防”,即防水、防尘、防震&…...

3.1.3 看对于“肮脏”页面的处理

3.1.3 看对于“肮脏”页面的处理 文章目录 3.1.3 看对于“肮脏”页面的处理再看对于“肮脏”页面的处理MmPageOutVirtualMemory() 再看对于“肮脏”页面的处理 MmPageOutVirtualMemory() NTSTATUS NTAPI MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,PMEMORY_AREA Me…...

学 Python 还是学 Java?——来自程序员的世纪困惑!

文章目录 1. Python:我就是简单,so what?2. Java:严谨到让你头疼,但大佬都在用!3. 到底谁更香?——关于学哪门语言的百思不得姐结论——到底该选谁?推荐阅读文章 每个程序员都可能面…...

Spring Web MVC 入门

1. 什么是 Spring Web MVC Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从从⼀开始就包含在Spring框架中。它的 正式名称“SpringWebMVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为"Spring MVC". 什么是Servlet呢? Ser…...

吃牛羊肉的季节来了,快来看看怎么陈列与销售!

一、肉品陈列基本原则 (一)新鲜卫生 1、保证商品在正确的温度、正确的方式下陈列 (1)正确的温度:冷藏柜-2℃-2℃;冷冻柜库-20℃-18℃ (2)正确的方式: 商品不遮挡冷气出风口&…...

科技创新网站建设策划书/买卖链接网站

OWC介绍: Microsoft Office 2000中包含有一组称为OWC的新控件集合。利用这些组件,可以在WEB浏览器以及其他传统的编程环境下创建许多有用的数据分析解决方案与报表生成解决方案。 Office Web Component是一组COM(Component Object Model:组件对象模型)控…...

网站建设标准/免费信息推广平台

引用js和css很类似&#xff0c;大致有三种方式&#xff1a; 第一种&#xff1a; 在行内引用js&#xff0c; <div onclick"alert(111);"></div> 第二种&#xff1a; 在行外引用js&#xff0c; <script type"text/javascript">alert(2222)…...

天津网站设计/google付费推广

电脑公司GhostXPSP3快速装机海量驱动2012 文件名: DNGS_GHOSTXPSP3_V201206_NTFS.iso 大小: 870.54 MB MD5: 38972d1eed6c91214e3f3607a8806c0f SHA1: f02b9980941dde06dcfb9cda635f89f7dc554b64 ghost xp sp3 纯净版 http://siaina.cn 系统格式&#xff1a;NTFS光盘类型&…...

盐山网站建设/seo排名优化工具推荐

澄清P问题、NP问题、NPC问题的概念 作者:matrix67 日期:2006-08-28 字体大小: 小 中 大这或许是众多OIer最大的误区之一。你会经常看到网上出现“这怎么做&#xff0c;这不是NP问题吗”、“这个只有搜了&#xff0c;这已经被证明是NP问题了”之类的话。你要知道&#xff0c;大…...

买了虚拟主机怎么做网站/专业拓客公司联系方式

1 配置文件的先后顺序 properties 属性配置 &#xff01;&#xff01;&#xff01; settings 全局配置参数 typeAliases 类型别名 &#xff01;&#xff01;&#xff01; typeHandlers 类型处理器 objectFactory 对象工厂 plugins 插件 envioronments 环境 集合属性 对象 tr…...

烟台市住房和规划建设管理局网站/网上推广专员是什么意思

转载于:https://www.cnblogs.com/cicser/archive/2010/07/20/1781437.html...