范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

如何使PyTorch模型训练加快

  Feb 23, 2023
  by Sebastian Raschka
  这篇文章介绍了在不影响其准确性的情况下提高 PyTorch 模型训练性能的技术。我们将在 LightningModule 中包装一个 PyTorch 模型,并使用 Trainer 类来启用各种训练优化。 通过动动小手指改几行代码,便可在单个 GPU 上的训练时间从 22.53 分钟压榨到 2.75 分钟,关键是保持模型精度不垮。
  这是 8 倍的性能提升!真香!
  这篇博文于 03/17/2023 更新,现在使用 PyTorch 2.0 和 Lightning 2.0!
  介绍 在本教程中,我们将微调 DistilBERT 模型,它是 BERT 的精炼版本,在几乎相同的预测性能下缩小了 40%。 我们可以通过多种方式微调预训练语言模型。 下图描述了三种最常见的方法。
  上述所有三种方法 (a-c) 都假设我们已经使用自监督学习在未标记的数据集上对模型进行了预训练。 然后,在第 2步中,当我们将模型转移到目标任务时,我们要么
  a) 提取嵌入并在其上训练分类器(例如,这可以是来自 scikit-learn 的支持向量机); b) 替换/添加输出层并微调transformer的最后一层; c) 替换/添加输出层并微调所有层。 方法 a-c 按计算效率排序,其中 a) 通常是最快的。 根据经验,这种排序顺序也反映了模型的预测性能,其中 c) 通常会产生最高的预测精度。
  在本文中,我们将使用 c) 训练一个模型来预测 IMDB 电影评论数据集中的电影评论情绪,该数据集总共包含 50,000 条电影评论。 1)普通 PyTorch 基线
  我们先从简单的 PyTorch 基线开始,在 IMDB 电影评论数据集上训练 DistilBERT 模型。 如果你想自己运行代码,你可以conda一个虚拟环境,如下所示: conda create -n faster-blog python=3.9 conda activate faster-blog  pip install watermark transformers datasets torchmetrics lightning
  相关软件版本如下: Python version: 3.9.15 torch         : 2.0.0+cu118 lightning     : 2.0.0 transformers  : 4.26.1
  载数据集代码的 local_dataset_utilities.py 文件。 import os import sys import tarfile import time  import numpy as np import pandas as pd from packaging import version from torch.utils.data import Dataset from tqdm import tqdm import urllib   def reporthook(count, block_size, total_size):     global start_time     if count == 0:         start_time = time.time()         return     duration = time.time() - start_time     progress_size = int(count * block_size)     speed = progress_size / (1024.0**2 * duration)     percent = count * block_size * 100.0 / total_size      sys.stdout.write(         f"r{int(percent)}% | {progress_size / (1024.**2):.2f} MB "         f"| {speed:.2f} MB/s | {duration:.2f} sec elapsed"     )     sys.stdout.flush()   def download_dataset():     source = "http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz"     target = "aclImdb_v1.tar.gz"      if os.path.exists(target):         os.remove(target)      if not os.path.isdir("aclImdb") and not os.path.isfile("aclImdb_v1.tar.gz"):         urllib.request.urlretrieve(source, target, reporthook)      if not os.path.isdir("aclImdb"):          with tarfile.open(target, "r:gz") as tar:             tar.extractall()   def load_dataset_into_to_dataframe():     basepath = "aclImdb"      labels = {"pos": 1, "neg": 0}      df = pd.DataFrame()      with tqdm(total=50000) as pbar:         for s in ("test", "train"):             for l in ("pos", "neg"):                 path = os.path.join(basepath, s, l)                 for file in sorted(os.listdir(path)):                     with open(os.path.join(path, file), "r", encoding="utf-8") as infile:                         txt = infile.read()                      if version.parse(pd.__version__) >= version.parse("1.3.2"):                         x = pd.DataFrame(                             [[txt, labels[l]]], columns=["review", "sentiment"]                         )                         df = pd.concat([df, x], ignore_index=False)                      else:                         df = df.append([[txt, labels[l]]], ignore_index=True)                     pbar.update()     df.columns = ["text", "label"]      np.random.seed(0)     df = df.reindex(np.random.permutation(df.index))      print("Class distribution:")     np.bincount(df["label"].values)      return df   def partition_dataset(df):     df_shuffled = df.sample(frac=1, random_state=1).reset_index()      df_train = df_shuffled.iloc[:35_000]     df_val = df_shuffled.iloc[35_000:40_000]     df_test = df_shuffled.iloc[40_000:]      df_train.to_csv("train.csv", index=False, encoding="utf-8")     df_val.to_csv("val.csv", index=False, encoding="utf-8")     df_test.to_csv("test.csv", index=False, encoding="utf-8")   class IMDBDataset(Dataset):     def __init__(self, dataset_dict, partition_key="train"):         self.partition = dataset_dict[partition_key]      def __getitem__(self, index):         return self.partition[index]      def __len__(self):         return self.partition.
  在我们下面讨论之前先看看 主要的 PyTorch 代码: import os import os.path as op import time  from datasets import load_dataset import torch from torch.utils.data import DataLoader import torchmetrics from transformers import AutoTokenizer from transformers import AutoModelForSequenceClassification from watermark import watermark  from local_dataset_utilities import (    download_dataset,    load_dataset_into_to_dataframe,    partition_dataset, ) from local_dataset_utilities import IMDBDataset   def tokenize_text(batch):    return tokenizer(batch["text"], truncation=True, padding=True)   def train(num_epochs, model, optimizer, train_loader, val_loader, device):    for epoch in range(num_epochs):        train_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2).to(device)         for batch_idx, batch in enumerate(train_loader):            model.train()            for s in ["input_ids", "attention_mask", "label"]:                batch[s] = batch[s].to(device)             ### FORWARD AND BACK PROP            outputs = model(                batch["input_ids"],                attention_mask=batch["attention_mask"],                labels=batch["label"],            )            optimizer.zero_grad()            outputs["loss"].backward()             ### UPDATE MODEL PARAMETERS            optimizer.step()             ### LOGGING            if not batch_idx % 300:                print(                    f"Epoch: {epoch+1:04d}/{num_epochs:04d} | Batch {batch_idx:04d}/{len(train_loader):04d} | Loss: {outputs["loss"]:.4f}"                )             model.eval()            with torch.no_grad():                predicted_labels = torch.argmax(outputs["logits"], 1)                train_acc.update(predicted_labels, batch["label"])         ### MORE LOGGING        with torch.no_grad():            model.eval()            val_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2).to(device)            for batch in val_loader:                for s in ["input_ids", "attention_mask", "label"]:                    batch[s] = batch[s].to(device)                outputs = model(                    batch["input_ids"],                    attention_mask=batch["attention_mask"],                    labels=batch["label"],                )                predicted_labels = torch.argmax(outputs["logits"], 1)                val_acc.update(predicted_labels, batch["label"])             print(                f"Epoch: {epoch+1:04d}/{num_epochs:04d} | Train acc.: {train_acc.compute()*100:.2f}% | Val acc.: {val_acc.compute()*100:.2f}%"            )      print(watermark(packages="torch,lightning,transformers", python=True))    print("Torch CUDA available?", torch.cuda.is_available())    device = "cuda:0" if torch.cuda.is_available() else "cpu"     torch.manual_seed(123)     ##########################    ### 1 Loading the Dataset    ##########################    download_dataset()    df = load_dataset_into_to_dataframe()    if not (op.exists("train.csv") and op.exists("val.csv") and op.exists("test.csv")):        partition_dataset(df)     imdb_dataset = load_dataset(        "csv",        data_files={            "train": "train.csv",            "validation": "val.csv",            "test": "test.csv",        },    )     #########################################    ### 2 Tokenization and Numericalization    #########################################     tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")    print("Tokenizer input max length:", tokenizer.model_max_length, flush=True)    print("Tokenizer vocabulary size:", tokenizer.vocab_size, flush=True)     print("Tokenizing ...", flush=True)    imdb_tokenized = imdb_dataset.map(tokenize_text, batched=True, batch_size=None)    del imdb_dataset    imdb_tokenized.set_format("torch", columns=["input_ids", "attention_mask", "label"])    os.environ["TOKENIZERS_PARALLELISM"] = "false"     #########################################    ### 3 Set Up DataLoaders    #########################################     train_dataset = IMDBDataset(imdb_tokenized, partition_key="train")    val_dataset = IMDBDataset(imdb_tokenized, partition_key="validation")    test_dataset = IMDBDataset(imdb_tokenized, partition_key="test")     train_loader = DataLoader(        dataset=train_dataset,        batch_size=12,        shuffle=True,        num_workers=1,        drop_last=True,    )     val_loader = DataLoader(        dataset=val_dataset,        batch_size=12,        num_workers=1,        drop_last=True,    )     test_loader = DataLoader(        dataset=test_dataset,        batch_size=12,        num_workers=1,        drop_last=True,    )     #########################################    ### 4 Initializing the Model    #########################################     model = AutoModelForSequenceClassification.from_pretrained(        "distilbert-base-uncased", num_labels=2    )     model.to(device)    optimizer = torch.optim.Adam(model.parameters(), lr=5e-5)     #########################################    ### 5 Finetuning    #########################################     start = time.time()    train(        num_epochs=3,        model=model,        optimizer=optimizer,        train_loader=train_loader,        val_loader=val_loader,        device=device,    )     end = time.time()    elapsed = end - start    print(f"Time elapsed {elapsed/60:.2f} min")     with torch.no_grad():        model.eval()        test_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2).to(device)        for batch in test_loader:            for s in ["input_ids", "attention_mask", "label"]:                batch[s] = batch[s].to(device)            outputs = model(                batch["input_ids"],                attention_mask=batch["attention_mask"],                labels=batch["label"],            )            predicted_labels = torch.argmax(outputs["logits"], 1)            test_acc.update(predicted_labels, batch["label"])     print(f"Test accuracy {test_acc.compute()*100:.2f}%")
  上面的代码结构分为两部分,函数定义和在 if  name  == " main " 下执行的代码。 这个结构对于避免以后使用多个 GPU 时 Python 的多处理问题是必要的。
  if  name  == " main " 中的的前三部分包含设置数据集加载器的代码。 第四部分是初始化模型的地方。 第五部分运行训练函数并在测试集上评估微调模型。
  在 A100 GPU 上运行代码后,我得到了以下结果: Epoch: 0001/0003 | Batch 0000/2916 | Loss: 0.6867 Epoch: 0001/0003 | Batch 0300/2916 | Loss: 0.3633 Epoch: 0001/0003 | Batch 0600/2916 | Loss: 0.4122 Epoch: 0001/0003 | Batch 0900/2916 | Loss: 0.3046 Epoch: 0001/0003 | Batch 1200/2916 | Loss: 0.3859 Epoch: 0001/0003 | Batch 1500/2916 | Loss: 0.4489 Epoch: 0001/0003 | Batch 1800/2916 | Loss: 0.5721 Epoch: 0001/0003 | Batch 2100/2916 | Loss: 0.6470 Epoch: 0001/0003 | Batch 2400/2916 | Loss: 0.3116 Epoch: 0001/0003 | Batch 2700/2916 | Loss: 0.2002 Epoch: 0001/0003 | Train acc.: 89.81% | Val acc.: 92.17% Epoch: 0002/0003 | Batch 0000/2916 | Loss: 0.0935 Epoch: 0002/0003 | Batch 0300/2916 | Loss: 0.0674 Epoch: 0002/0003 | Batch 0600/2916 | Loss: 0.1279 Epoch: 0002/0003 | Batch 0900/2916 | Loss: 0.0686 Epoch: 0002/0003 | Batch 1200/2916 | Loss: 0.0104 Epoch: 0002/0003 | Batch 1500/2916 | Loss: 0.0888 Epoch: 0002/0003 | Batch 1800/2916 | Loss: 0.1151 Epoch: 0002/0003 | Batch 2100/2916 | Loss: 0.0648 Epoch: 0002/0003 | Batch 2400/2916 | Loss: 0.0656 Epoch: 0002/0003 | Batch 2700/2916 | Loss: 0.0354 Epoch: 0002/0003 | Train acc.: 95.02% | Val acc.: 92.09% Epoch: 0003/0003 | Batch 0000/2916 | Loss: 0.0143 Epoch: 0003/0003 | Batch 0300/2916 | Loss: 0.0108 Epoch: 0003/0003 | Batch 0600/2916 | Loss: 0.0228 Epoch: 0003/0003 | Batch 0900/2916 | Loss: 0.0140 Epoch: 0003/0003 | Batch 1200/2916 | Loss: 0.0220 Epoch: 0003/0003 | Batch 1500/2916 | Loss: 0.0123 Epoch: 0003/0003 | Batch 1800/2916 | Loss: 0.0495 Epoch: 0003/0003 | Batch 2100/2916 | Loss: 0.0039 Epoch: 0003/0003 | Batch 2400/2916 | Loss: 0.0168 Epoch: 0003/0003 | Batch 2700/2916 | Loss: 0.1293 Epoch: 0003/0003 | Train acc.: 97.28% | Val acc.: 89.88% Time elapsed 21.33 min Test accuracy 89.92%
  正如所见,模型从第 2 轮到第 3 轮开始略微过度拟合,验证准确率从 92.09% 下降到 89.88%。 最终测试准确率为 89.92%,这是对模型进行 21.33 分钟微调后达到的。 2) 使用Trainer Class
  现在,让我们将 PyTorch 模型包装在 LightningModule 中,以便我们可以使用来自 Lightning 的 Trainer 类: import os import os.path as op import time  from datasets import load_dataset import lightning as L from lightning.pytorch.callbacks import ModelCheckpoint from lightning.pytorch.loggers import CSVLogger import matplotlib.pyplot as plt import pandas as pd import torch from torch.utils.data import DataLoader import torchmetrics from transformers import AutoTokenizer from transformers import AutoModelForSequenceClassification from watermark import watermark  from local_dataset_utilities import (     download_dataset,     load_dataset_into_to_dataframe,     partition_dataset, ) from local_dataset_utilities import IMDBDataset   def tokenize_text(batch):     return tokenizer(batch["text"], truncation=True, padding=True)  class LightningModel(L.LightningModule):     def __init__(self, model, learning_rate=5e-5):         super().__init__()          self.learning_rate = learning_rate         self.model = model          self.train_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2)         self.val_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2)         self.test_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2)      def forward(self, input_ids, attention_mask, labels):         return self.model(input_ids, attention_mask=attention_mask, labels=labels)      def training_step(self, batch, batch_idx):         outputs = self(             batch["input_ids"],             attention_mask=batch["attention_mask"],             labels=batch["label"],         )         self.log("train_loss", outputs["loss"])         with torch.no_grad():             logits = outputs["logits"]             predicted_labels = torch.argmax(logits, 1)             self.train_acc(predicted_labels, batch["label"])             self.log("train_acc", self.train_acc, on_epoch=True, on_step=False)         return outputs["loss"]  # this is passed to the optimizer for training      def validation_step(self, batch, batch_idx):         outputs = self(             batch["input_ids"],             attention_mask=batch["attention_mask"],             labels=batch["label"],         )         self.log("val_loss", outputs["loss"], prog_bar=True)          logits = outputs["logits"]         predicted_labels = torch.argmax(logits, 1)         self.val_acc(predicted_labels, batch["label"])         self.log("val_acc", self.val_acc, prog_bar=True)      def test_step(self, batch, batch_idx):         outputs = self(             batch["input_ids"],             attention_mask=batch["attention_mask"],             labels=batch["label"],         )          logits = outputs["logits"]         predicted_labels = torch.argmax(logits, 1)         self.test_acc(predicted_labels, batch["label"])         self.log("accuracy", self.test_acc, prog_bar=True)      def configure_optimizers(self):         optimizer = torch.optim.Adam(             self.trainer.model.parameters(), lr=self.learning_rate         )         return optimizer   if __name__ == "__main__":     print(watermark(packages="torch,lightning,transformers", python=True), flush=True)     print("Torch CUDA available?", torch.cuda.is_available(), flush=True)      torch.manual_seed(123)      ##########################     ### 1 Loading the Dataset     ##########################     download_dataset()     df = load_dataset_into_to_dataframe()     if not (op.exists("train.csv") and op.exists("val.csv") and op.exists("test.csv")):         partition_dataset(df)      imdb_dataset = load_dataset(         "csv",         data_files={             "train": "train.csv",             "validation": "val.csv",             "test": "test.csv",         },     )      #########################################     ### 2 Tokenization and Numericalization     ########################################      tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")     print("Tokenizer input max length:", tokenizer.model_max_length, flush=True)     print("Tokenizer vocabulary size:", tokenizer.vocab_size, flush=True)      print("Tokenizing ...", flush=True)     imdb_tokenized = imdb_dataset.map(tokenize_text, batched=True, batch_size=None)     del imdb_dataset     imdb_tokenized.set_format("torch", columns=["input_ids", "attention_mask", "label"])     os.environ["TOKENIZERS_PARALLELISM"] = "false"      #########################################     ### 3 Set Up DataLoaders     #########################################      train_dataset = IMDBDataset(imdb_tokenized, partition_key="train")     val_dataset = IMDBDataset(imdb_tokenized, partition_key="validation")     test_dataset = IMDBDataset(imdb_tokenized, partition_key="test")      train_loader = DataLoader(         dataset=train_dataset,         batch_size=12,         shuffle=True,         num_workers=1,         drop_last=True,     )      val_loader = DataLoader(         dataset=val_dataset,         batch_size=12,         num_workers=1,         drop_last=True,     )      test_loader = DataLoader(         dataset=test_dataset,         batch_size=12,         num_workers=1,         drop_last=True,     )      #########################################     ### 4 Initializing the Model     #########################################      model = AutoModelForSequenceClassification.from_pretrained(         "distilbert-base-uncased", num_labels=2     )      #########################################     ### 5 Finetuning     #########################################      lightning_model = LightningModel(model)      callbacks = [         ModelCheckpoint(save_top_k=1, mode="max", monitor="val_acc")  # save top 1 model     ]     logger = CSVLogger(save_dir="logs/", name="my-model")      trainer = L.Trainer(         max_epochs=3,         callbacks=callbacks,         accelerator="gpu",         devices=[1],         logger=logger,         log_every_n_steps=10,         deterministic=True,     )      start = time.time()     trainer.fit(         model=lightning_model,         train_dataloaders=train_loader,         val_dataloaders=val_loader,     )      end = time.time()     elapsed = end - start     print(f"Time elapsed {elapsed/60:.2f} min")      test_acc = trainer.test(lightning_model, dataloaders=test_loader, ckpt_path="best")     print(test_acc)      with open(op.join(trainer.logger.log_dir, "outputs.txt"), "w") as f:         f.write((f"Time elapsed {elapsed/60:.2f} min "))         f.write(f"Test acc: {test_acc}")
  本文关注性能方面 跳过 LightningModule 的细节。
  简而言之,设置了一个 LightningModule,它定义了如何执行训练、验证和测试步骤。 然后,主要变化在代码第5部分,我们在其中微调模型。 将 PyTorch 模型包装在 LightningModel 类中,并使用 Trainer 类来拟合模型:  #########################################     ### 5 Finetuning     #########################################      lightning_model = LightningModel(model)      callbacks = [         ModelCheckpoint(save_top_k=1, mode="max", monitor="val_acc")  # save top 1 model     ]     logger = CSVLogger(save_dir="logs/", name="my-model")      trainer = L.Trainer(         max_epochs=3,         callbacks=callbacks,         accelerator="gpu",         devices=1,         logger=logger,         log_every_n_steps=10,         deterministic=True,     )      trainer.fit(         model=lightning_model,         train_dataloaders=train_loader,         val_dataloaders=val_loader,     )
  之前注意到验证准确率从第 2 轮下降到第 3 轮,因此使用 ModelCheckpoint 回调加载最佳模型(基于最高验证准确率)以在测试集上进行模型评估。 此外,将性能记录到 CSV 文件并将 PyTorch 行为设置为确定性。
  在同一台机器上,这个模型在 21.79 分钟内达到了 92.6% 的测试准确率:
  注意,如果禁用检查点并允许 PyTorch 在非确定性模式下运行,将获得与普通 PyTorch 相同的运行时间。
  3)自动混合精度训练
  如果我们的 GPU 支持混合精度训练,启用它通常是提高计算效率的主要方法之一。 特别是在训练期间在 32 位和 16 位浮点表示之间切换,而不会牺牲准确性。
  使用 Trainer 类,可以通过一行代码启用自动混合精度训练:  trainer = L.Trainer(         max_epochs=3,         callbacks=callbacks,         accelerator="gpu",         precision="16",  # <-- NEW         devices=[1],         logger=logger,         log_every_n_steps=10,         deterministic=True,     )
  如下图所示,使用混合精度训练可将训练时间从 21.79 分钟提高到 8.25 分钟! 这几乎快了3倍!
  测试集准确率为 93.2%——与之前的 92.6% 相比甚至略有提高(可能是由于在不同精度模式之间切换时舍入引起的差异。)
  4) 使用 Torch.Compile 的静态图
  在最近发布的 PyTorch 2.0 中,PyTorch 团队引入了新的 toch.compile 函数,该函数可以通过生成优化的静态图来加速 PyTorch 代码执行。 这是一个 3 步过程,包括图形获取、图形结构降低和图形编译。
  实现这一目标的背后很复杂,在PyTorch 2.0相关介绍中有更详细的解释。 作为用户,我们可以通过一个简单的命令 torch.compile 使用这一新功能。
  要利用 torch.compile,可以通过添加以下一行代码来修改我们的代码: # ... model = AutoModelForSequenceClassification.from_pretrained(         "distilbert-base-uncased", num_labels=2     )  model = torch.compile(model) # NEW lightning_model = LightningModel(model) # ...
  不幸的是,在这种混合精度上下文中,使用默认参数时,torch.compile 似乎不会提升 DistilBERT 模型的性能。 训练时间为 8.44 分钟,而之前为 8.25 分钟。 因此,本文中的后续基准测试不会使用 torch.compile。
  备注:两个技巧:
  1.将编译放在计时开始之前; 2。使用示例批次启动模型,如下所示 model.to(torch.device("cuda:0"))   model = torch.compile(model)    for batch_idx, batch in enumerate(train_loader):       model.train()       for s in ["input_ids", "attention_mask", "label"]:           batch[s] = batch[s].to(torch.device("cuda:0"))       break    outputs = model(       batch["input_ids"],       attention_mask=batch["attention_mask"],       labels=batch["label"],   )    lightning_model = LightningModel(model)   # start timing and training below
  运行时间提高到 5.6 分钟。 这表明初始优化编译步骤需要几分钟,但最终会加速模型训练。 在这种情况下,由于我们只训练三个时期的模型,因此由于额外的开销,编译的好处不明显。 但是,如果训练模型的时间更长或训练的模型更大,那么编译是值得的。
  (注意:目前为分布式设置准备模型有难搞,因为每个单独的 GPU 设备都需要模型的副本。这将需要重新设计一些代码,所以下面不会使用 torch.compile。) 5) 在4个GPU上并行训练分布式数据
  上面添加混合精度训练(并尝试添加图形编译)已在单个 GPU 上加速我们的代码,现在让尝试多 GPU 策略。 现在将在四个而不是一个 GPU 上运行相同的代码。
  请注意,下图中总结了几种不同的多 GPU 训练技术。
  从最简单的技术开始,通过 DistributedDataParallel 实现数据并行。 使用Trainer,只需要修改一行代码:   trainer = L.Trainer(         max_epochs=3,         callbacks=callbacks,         accelerator="gpu",         devices=4,  # <-- NEW         strategy="ddp",  # <-- NEW         precision="16",         logger=logger,         log_every_n_steps=10,         deterministic=True,     )
  在有四个 A100 GPU机器上,这段代码运行了 3.07 分钟,达到了 93.1% 的测试准确率。 同样,测试集的改进可能是由于使用数据并行时的梯度平均。
  6)DeepSpeed
  最后,尝试在 Trainer 中使用的 DeepSpeed 多 GPU 策略。
  但在实际尝试之前,分享下多 GPU 使用建议。 使用哪种策略在很大程度上取决于模型、GPU 的数量和 GPU 的内存大小。 例如,当预训练模型不适合单个 GPU 的大型模型时,最好从简单的"ddp_sharded"策略开始,该策略将张量并行性添加到"ddp"。使用前面的代码,"ddp_sharded"采用 跑完 2.58 分钟。
  或者也可以考虑更复杂的"deepspeed_stage_2"策略,它将优化器状态和梯度分片。 如果这不足以使模型适合 GPU 内存,请尝试"deepspeed_stage_2_offload"变体,它将优化器和梯度状态卸载到 CPU 内存(以性能为代价)。 如果你想微调一个模型,计算吞吐量通常比能够将模型放入较少数量的 GPU 的内存中更不重要。 在这种情况下,您可以探索 deepspeed 的"stage_3"变体,它对所有内容、优化器、梯度和参数进行分片,等等. strategy="deepspeed_stage_3" strategy="deepspeed_stage_3_offload" 由于 GPU 内存不是像 DistilBERT 这样小模型的问题,让我们试试"deepspeed_stage_2":
  首先,我们必须安装 DeepSpeed Python 库: pip install -U deepspeed
  接下来,我们只需更改一行代码即可启用"deepspeed_stage_2":  trainer = L.Trainer(         max_epochs=3,         callbacks=callbacks,         accelerator="gpu",         devices=4,         strategy="deepspeed_stage_2",  # <-- NEW         precision="16",         logger=logger,         log_every_n_steps=10,         deterministic=True,     )
  在机器上运行了 2.75 分钟,并达到了 92.6% 的测试准确率。
  请注意,PyTorch 现在也有自己的 DeepSpeed 替代方案,称为完全分片 DataParallel,我们可以通过 strategy="fsdp" 使用它。
  7) Fabric
  随着最近的 Lightning 2.0 发布,Lightning AI 发布了用于 PyTorch 的新 Fabric 开源库。 Fabric 本质上是一种扩展 PyTorch 代码的替代方法,无需使用我在上面第 2 节)使用 Trainer 类中介绍的 LightningModule 和 Trainer。
  Fabric只需要改几行代码,如下代码所示。 - 表示已删除的行,+ 是为将 Python 代码转换为使用 Fabric 而添加的行。 import os import os.path as op import time  + from lightning import Fabric  from datasets import load_dataset import matplotlib.pyplot as plt import pandas as pd import torch from torch.utils.data import DataLoader import torchmetrics from transformers import AutoTokenizer from transformers import AutoModelForSequenceClassification from watermark import watermark  from local_dataset_utilities import download_dataset, load_dataset_into_to_dataframe, partition_dataset from local_dataset_utilities import IMDBDataset   def tokenize_text(batch):     return tokenizer(batch["text"], truncation=True, padding=True)   def plot_logs(log_dir):     metrics = pd.read_csv(op.join(log_dir, "metrics.csv"))      aggreg_metrics = []     agg_col = "epoch"     for i, dfg in metrics.groupby(agg_col):         agg = dict(dfg.mean())         agg[agg_col] = i         aggreg_metrics.append(agg)      df_metrics = pd.DataFrame(aggreg_metrics)     df_metrics[["train_loss", "val_loss"]].plot(         grid=True, legend=True, xlabel="Epoch", ylabel="Loss"     )     plt.savefig(op.join(log_dir, "loss.pdf"))      df_metrics[["train_acc", "val_acc"]].plot(         grid=True, legend=True, xlabel="Epoch", ylabel="Accuracy"     )     plt.savefig(op.join(log_dir, "acc.pdf"))   - def train(num_epochs, model, optimizer, train_loader, val_loader, device): + def train(num_epochs, model, optimizer, train_loader, val_loader, fabric):        for epoch in range(num_epochs): -         train_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2).to(device) +         train_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2).to(fabric.device)          model.train()         for batch_idx, batch in enumerate(train_loader):  -             for s in ["input_ids", "attention_mask", "label"]: -                 batch[s] = batch[s].to(device)              outputs = model(batch["input_ids"], attention_mask=batch["attention_mask"], labels=batch["label"])              optimizer.zero_grad() -            outputs["loss"].backward() +            fabric.backward(outputs["loss"])              ### UPDATE MODEL PARAMETERS             optimizer.step()              ### LOGGING             if not batch_idx % 300:                 print(f"Epoch: {epoch+1:04d}/{num_epochs:04d} | Batch {batch_idx:04d}/{len(train_loader):04d} | Loss: {outputs["loss"]:.4f}")              model.eval()             with torch.no_grad():                 predicted_labels = torch.argmax(outputs["logits"], 1)                 train_acc.update(predicted_labels, batch["label"])          ### MORE LOGGING         model.eval()         with torch.no_grad(): -            val_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2).to(device) +            val_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2).to(fabric.device)             for batch in val_loader: -                for s in ["input_ids", "attention_mask", "label"]: -                    batch[s] = batch[s].to(device)                 outputs = model(batch["input_ids"], attention_mask=batch["attention_mask"], labels=batch["label"])                 predicted_labels = torch.argmax(outputs["logits"], 1)                 val_acc.update(predicted_labels, batch["label"])              print(f"Epoch: {epoch+1:04d}/{num_epochs:04d} | Train acc.: {train_acc.compute()*100:.2f}% | Val acc.: {val_acc.compute()*100:.2f}%")             train_acc.reset(), val_acc.reset()   if __name__ == "__main__":      print(watermark(packages="torch,lightning,transformers", python=True))     print("Torch CUDA available?", torch.cuda.is_available())     -   device = "cuda" if torch.cuda.is_available() else "cpu"     torch.manual_seed(123)      ##########################     ### 1 Loading the Dataset     ##########################     download_dataset()     df = load_dataset_into_to_dataframe()     if not (op.exists("train.csv") and op.exists("val.csv") and op.exists("test.csv")):         partition_dataset(df)      imdb_dataset = load_dataset(         "csv",         data_files={             "train": "train.csv",             "validation": "val.csv",             "test": "test.csv",         },     )      #########################################     ### 2 Tokenization and Numericalization     #########################################      tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")     print("Tokenizer input max length:", tokenizer.model_max_length, flush=True)     print("Tokenizer vocabulary size:", tokenizer.vocab_size, flush=True)      print("Tokenizing ...", flush=True)     imdb_tokenized = imdb_dataset.map(tokenize_text, batched=True, batch_size=None)     del imdb_dataset     imdb_tokenized.set_format("torch", columns=["input_ids", "attention_mask", "label"])     os.environ["TOKENIZERS_PARALLELISM"] = "false"      #########################################     ### 3 Set Up DataLoaders     #########################################      train_dataset = IMDBDataset(imdb_tokenized, partition_key="train")     val_dataset = IMDBDataset(imdb_tokenized, partition_key="validation")     test_dataset = IMDBDataset(imdb_tokenized, partition_key="test")      train_loader = DataLoader(         dataset=train_dataset,         batch_size=12,         shuffle=True,          num_workers=2,         drop_last=True,     )      val_loader = DataLoader(         dataset=val_dataset,         batch_size=12,         num_workers=2,         drop_last=True,     )      test_loader = DataLoader(         dataset=test_dataset,         batch_size=12,         num_workers=2,         drop_last=True,     )       #########################################     ### 4 Initializing the Model     #########################################  +    fabric = Fabric(accelerator="cuda", devices=4,  +                    strategy="deepspeed_stage_2", precision="16-mixed") +    fabric.launch()      model = AutoModelForSequenceClassification.from_pretrained(         "distilbert-base-uncased", num_labels=2)  -   model.to(device)     optimizer = torch.optim.Adam(model.parameters(), lr=5e-5)  +    model, optimizer = fabric.setup(model, optimizer) +    train_loader, val_loader, test_loader = fabric.setup_dataloaders( +        train_loader, val_loader, test_loader)      #########################################     ### 5 Finetuning     #########################################      start = time.time()     train(         num_epochs=3,         model=model,         optimizer=optimizer,         train_loader=train_loader,         val_loader=val_loader, -       device=device +       fabric=fabric     )      end = time.time()     elapsed = end-start     print(f"Time elapsed {elapsed/60:.2f} min")      with torch.no_grad():         model.eval() -       test_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2).to(device) +       test_acc = torchmetrics.Accuracy(task="multiclass", num_classes=2).to(fabric.device)         for batch in test_loader: -           for s in ["input_ids", "attention_mask", "label"]: -               batch[s] = batch[s].to(device)             outputs = model(batch["input_ids"], attention_mask=batch["attention_mask"], labels=batch["label"])             predicted_labels = torch.argmax(outputs["logits"], 1)             test_acc.update(predicted_labels, batch["label"])      print(f"Test accuracy {test_acc.compute()*100:.2f}%")
  正如所看到的,修改真的很轻量级! 它运行得如何呢? Fabric 仅用了 1.8 分钟就完成了微调! Fabric 比 Trainer 更轻量级——虽然它也能够使用回调和日志记录,但我们没有在这里启用这些功能来用一个极简示例来演示 Fabric。 太快了.
  何时使用 Lightning Trainer 或 Fabric 取决于个人喜好。 根据经验,如果您更喜欢对 PyTorch 代码进行轻量包装,请查看 Fabric。 另一方面,如果你转向更大的项目并且更喜欢 Lightning 提供的代码组织,推荐 Trainer。 结论
  在本文中,探索了各种提高 PyTorch 模型训练速度的技术。 如果使用 Lightning Trainer,可以用一行代码在这些选项之间切换,非常方便—,尤其是当您在调试代码时在 CPU 和 GPU 机器之间切换时。
  尚未探索的另一个方面是最大化批量大小,这可以进一步提高我们模型的吞吐量。 未完待续。

如果让AI来预测,中国什么时候可以超越美国,会是什么结果呢?中国在过去几十年中实现了惊人的经济增长和发展,成为了一个世界上最具影响力的国家之一。随着中国不断提升自己的各项实力,未来可能有望在某些领域超越美国。下面,我们将对中国在各个领域超越联想向美公司赔偿1。3亿美元专利费韩日同意解除半导体出口限制1微软官宣将把聊天机器人技术植入Office办公软件当地时间周四(3月16日),科技巨头微软在其官网宣布,公司正在将其人工智能(AI)技术植入到办公软件中,该功能名为MicrosoAM华科高义华教授团队钠离子电池最新综述近年来,由于地球上钠资源丰富分布广泛,钠离子电池引起了极大的关注。然而,目前SIBs仍面临能量密度低循环稳定性不理想的关键问题。SIBs电化学性能的增强取决于对潜在钠储存机制的全面NUMBERSTRING函数数字转汉字NUMBERSTRING(数值,序号)函数,序号有三个1231。NUMBERSTRING(数值,1)序号为1,转为小写汉字形式如果不想要一十的样式,使用SUBSTITUTE函数替换科技报国三十余载北京石油化工学院这支团队致力特种机器人中国造在北京石油化工学院,有这样一支团队,他们瞄准国家重大基础设施建设涉核涉水领域和重大装备制造领域的国家重大需求,针对这些领域存在的自动化焊接设备短板和卡脖子技术难题,深耕复杂环境下特5000万自拍7nm芯片,支持OIS防抖,2000价位优质拍照手机推荐之前星哥推荐了很多性价比出色的高性能手机给大家,许多消费者表示意犹未尽,不过也有些网友感到疑惑,2000价位左右的性价比手机,怎么尽是一些拍照鸡肋的产品,说实话,在手机行业内卷严重aigc领域好玩吗?AI配音操作教程AIGC领域是近年来备受关注的技术领域,它指的是人工智能和图形计算的结合,可以用于实现各种有趣的应用,如游戏虚拟现实视频处理等。在AIGC领域中,AI配音操作是一个非常有趣的应用,广州蓝景面对互联网大环境的就业难,我们该何去何从?首先不可否认,口罩的原因和经济大环境等原因,让互联网这几年真的挺难受的。所以,在这样恶劣的环境下,把一些问题推上了风口浪尖,问题暴露无遗。那核心的矛盾是什么呢,为什么会出现前端就业Kubernetes命令行工具(kubectl)1概述kubectl是Kubernetes集群的命令行工具,通过kubectl能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。2语法使用以下语法从终端窗口运行kub三月份换新机?高端等MateX3,2K预算选一加Ace2V3月份,手机行业迎来了一波新机潮,除了一些刚发布中端明星机型一加Ace2V,接下来会有多款重磅旗舰新机亮相,其中包括华为P60系列MateX3折叠屏OPPOFindX6系列魅族20新突破OmniArk芯神鼎在芯片的研发中,风险主要来自芯片的正确性代价成本。如何在流片前及时彻底地发现设计中潜藏的逻辑错误,保证芯片的可用性高效性始终是业内着力解决的问题。因此验证在芯片设计与实现中是非常重
十一黄金假期,推荐几条自驾旅行路线每个人都有一个关于自驾旅行的梦想!都说最美的风景永远都在路上!而大千世界之美,只有你前往才能看见!而去哪儿自驾总是最为苦恼!十一黄金假期快到了,于是整理了几条最美自驾路线,自驾一路9月FIP0036重磅支持大会,线上线下齐发力FIP0036提案支持大会是三峡星联合发起的中国首个以机构方为参与主体的支持大会,于9月23日在湖北宜昌圆满举办。各方均表达了对FIP0036提案的肯定与支持。会议由三峡星总部线下耻辱!英格兰01意大利,一场未胜提前降级在世界足坛流传着四大假象的梗英格兰很强意大利很弱,阿根廷能夺冠和国足能进世界杯。北京时间9月24日凌晨02时45分,20222023赛季欧国联A级别第三小组第五轮焦点战打响,意大利已有用户提前上手小米civi2居中药丸轻薄有颜影像堪称一绝随着小米civi2定档的消息确认以后,关于小米civi2的真机曝光就从未停止过,今天新机报告也是收集了一下小米civi2的真机图。图源网络图源网络图源网络随着新机发布日期的临近众多东契奇如果我可以当选MVP,那会是很大的成就独行侠球员卢卡东契奇参加NBAToday节目。期间,他接受了MalikaAndrews的采访。记者表示上赛季你进入了MVP的讨论范畴中。那么新赛季你是否寻求不仅仅要打进总决赛,同时周鹏接班人!宏远20岁前锋如今练成肌肉猛男,和年轻的周鹏太像新赛季的CBA距离开赛已经越来越近了,现在各支球队都已经陆续进入了备战状态,新加盟的球员以及一些从青年队提拔上来的球员都希望能够在训练中有好的表现,为自己在球队立足打下基础,获得更湖人关于威斯布鲁克的交易,3队交易方案出炉拉塞尔韦斯特布鲁克(RussellWestbrook)已将洛杉矶的房子出售,这对湖人球迷和整个球队来说可能是个好消息。毫无疑问,在经历了一个令人失望和表现不佳的赛季后,与韦斯特布鲁降了!国际油价跌至8个月来新低当地时间周五,市场对全球央行纷纷加息引发经济衰退的忧虑不断加剧,投资者抛售股票债券,加速买入美元避险,美国纽约股市三大股指全线下跌。截至收盘,道指跌1。62,标普500指数跌1。7库兹马上赛季的进步使我自信在湖人没这种机会北京时间9月24日,奇才球员凯尔库兹马在媒体日接受了采访。采访中库兹马谈到了奇才新赛季的核心三人组,他表示我们的阵容很有灵活性,我们每个人都能得分,也都愿意传球,我们都知道如何打球英甲直播谢周三VS韦康比流浪者预测后者处于下风英甲直播谢周三VS韦康比流浪者预测后者处于下风队伍谢周三VS韦康比流浪者时间09月24日2200比赛类型英甲联赛北京时间09月24日2200,周六凌晨,LDSPORTS分析英甲第1女篮输美国,锋线大核打出身价!入WNBA无难度,美国都拿她没办法今天女篮和美国的比赛,这场比赛确实精彩。而对于女篮来说,最大的惊喜还是李梦。要知道李梦在这场比赛已经成为了球队的核心。全场比赛李梦32分钟砍下了21分,这样的得分已经非常夸张了。特