主頁 >  其他 > PyTorch多卡分布式訓練DistributedDataParallel 使用方法

PyTorch多卡分布式訓練DistributedDataParallel 使用方法

2022-02-08 07:26:39 其他

PyTorch多卡分布式訓練DistributedDataParallel 使用方法

目錄

PyTorch多卡分布式訓練DistributedDataParallel 使用方法

1.DP模式和DP模式

(1)單行程多GPU訓練模式:DP模式

(2)多行程多GPU訓練模式:DDP模式

2.Pytorch分布式訓練方法

3.Pytorch-Base-Trainer(PBT)分布式訓練工具

(1) 工具介紹

(2) 安裝

(3)使用方法

4.Example: 構建自己的分類Pipeline

5.可視化


【尊重原則,轉載請注明出處】:https://panjinquan.blog.csdn.net/article/details/122702287

1.DP模式和DP模式

Pytorch多卡訓練有兩種方式,一種是單行程多GPU訓練模式(single process multi-gpus),另一種的多行程多卡模式(multi-processes multi-gpus)

(1)單行程多GPU訓練模式:DP模式

Pytorch通過nn.DataParallel可實作多卡訓練模型(簡稱DP模式),這是single process multi-gpus 的多卡并行機制,這種并行模式下并行的多卡都是由一個行程進行控制,其缺點有:

  1. 盡管 DataLoader 可以指定 num_worker,增加負責加載資料的執行緒數量,但是執行緒的資源受限于父行程,且由于python的GIL機制,不能利用好多核的并行優勢
  2. 模型在 gpu 群組中進行初始化與廣播程序依賴單一行程的串行操作
  3. DP模式相當于將多個GPU卡合并為一個卡進行訓練

盡管DataParallel更易于使用(只需簡單包裝單GPU模型),但由于使用一個行程來計算模型權重,然后在每個批處理期間將分發到每個GPU,因此通信很快成為一個瓶頸,GPU利用率通常很低,而且,nn.DataParallel要求所有的GPU都在同一個節點上(不支持分布式),

(2)多行程多GPU訓練模式:DDP模式

Pytorch通過nn.parallel.DistributedDataParallel可實作多行程多卡訓練模型(也稱DDP模式),這種多卡并行機制的特點/優勢有:

  1. 一個行程一個GPU(當然可以讓每個行程控制多個GPU,但這顯然比每個行程有一個GPU要慢)
  2. 充分利用多核并行的優勢加載資料
  3. 模型在 gpu 群組中進行初始化的程序由各自的行程負責調度
  4. 代碼可以無縫切換單機多卡與多機多卡訓練,因為此時單機單卡成為了單機多卡/多機多卡并行下的一個特例
  5. GPU可以都在同一個節點上,也可以分布在多個節點上,每個行程都執行相同的任務,并且每個行程都與所有其他行程通信,行程或者說GPU之間只傳遞梯度,這樣網路通信就不再是瓶頸,

在訓練程序中,每個行程從磁盤加載batch資料,并將它們傳遞到其GPU,每一個GPU都有自己的前向程序,然后梯度在各個GPUs間進行All-Reduce,每一層的梯度不依賴于前一層,所以梯度的All-Reduce和后向程序同時計算,以進一步緩解網路瓶頸,在后向程序的最后,每個節點都得到了平均梯度,這樣模型引數保持同步,

這就要求多個行程,甚至多個節點上的多個行程實作同步并通信,Pytorch通過distributed.init_process_group函式來實作這一點,他需要知道行程0位置以便所有行程都可以同步,以及預期的行程總數,每個行程都需要知道行程總數及其在行程中的順序,以及使用哪個GPU,通常將行程總數稱為world_size,

Pytorch提供了nn.utils.data.DistributedSampler來為各個行程切分資料,以保證訓練資料不重疊,

nn.DataParallelnn.distributedataparallel的主要差異可以總結為以下幾點:

  1. DistributedDataParallel支持模型并行,而DataParallel并不支持,這意味如果模型太大單卡顯存不足時只能使用前者;
  2. DataParallel是單行程多執行緒的,只用于單機情況,而DistributedDataParallel是多行程的,適用于單機和多機情況,真正實作分布式訓練;
  3. DistributedDataParallel的訓練更高效,因為每個行程都是獨立的Python解釋器,避免GIL問題,而且通信成本低其訓練速度更快,基本上DataParallel已經被棄用;
  4. 必須要說明的是DistributedDataParallel中每個行程都有獨立的優化器,執行自己的更新程序,但是梯度通過通信傳遞到每個行程,所有執行的內容是相同的;

除了PyTorch官方實作的分布式訓練方案,還有horovod分布式訓練工具,不僅支持PyTorch還支持TensorFlow和MXNet框架,實作起來也是比較容易的,速度方面應該不相上下,

參考資料:PyTorch分布式訓練簡明教程 - 知乎


2.Pytorch分布式訓練方法

分布式訓練一般分為資料并行模型并行兩種,Pytorch分布式訓練的實作步驟可簡述如下:

  1. 首先在nn.DataParallel(即DP模式下)實作多卡加載資料,訓練模型并除錯成功;這一步是為了保證你的訓練流程正常無BUG,然后就可以開始魔改了
  2. 資料并行(分布式)DataLoader的樣本采樣器(sampler)修改為分布式采樣器torch_utils.distributed.DistributedSampler
  3. 模型并行(分布式):將torch.nn.parallel.DistributedDataParallel 代替torch.nn.DataParallel
  4. 為了能夠使用 DistributedDataParallel 需要先進行行程間通訊環境的初始化,torch.distributed.init_process_group()
  5. 為了解決并行訓練中加載到各個 worker/gpu 中的 sub-mini-batch 之間出現 example overlap 問題,還可以配合 torch.utils.data.distributed.DistributedSampler 進行使用
  6. 為了讓行程與 gpu 進行一一匹配,在程式的開頭通過 torch.cuda.set_device 設定目標設備
  7. (可選)為了讓各個 worker/gpu 能有一致的初始值,在程式開頭通過 torch.manual_seed 與 torch.cuda.manual_seed 來初始化亂數種子

所以代碼結構如下:

# filename: distributed_example.py
# import some module
...
...
 
parser = argparse.Argument()
parser.add_argument('--init_method', defalut='env://', type=str)
parser.add_argument('--local_rank', type=int, default=0)
args = parser.parse()
 
import os
# Set master information and NIC
# NIC for communication
os.environ['NCCL_SOCKET_IFNAME'] = 'xxxx'
# set master node address
# recommend setting to ib NIC to gain bigger communication bandwidth
os.environ['MASTER_ADDR'] = '192.168.xx.xx'
# set master node port
# **caution**: avoid port conflict
os.environ['MASTER_PORT'] = '1234'
 
def main():
    # step 1
    # set random seed
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
     
    # step 2
    # set target device
    torch.cuda.set_device(args.local_rank)
 
 
    # step 3
    # initialize process group
    # use nccl backend to speedup gpu communication
    torch.distributed.init_process_group(backend='nccl', init_method=args.init_method)
     
    ...
    ...
    # step 4
    # set distributed sampler
    # the same, you can set distributed sampler for validation set
    train_sampler = torch.utils.data.distributed.DistributedSampler(
        dataset_train)
    train_loader = torch.utils.data.DataLoader(
        dataset_train, batch_size=BATCH_SIZE, sampler=train_sampler, pin_memory=PIN_MEMORY,
        num_workers=NUM_WORKERS
    )
     
    ...
    ...
    # step 5
    # initialize model 
    model = resnet50()
    model.cuda()
     
    # step 6
    # wrap model with distributeddataparallel
    # map device with model process, and we bind process n with gpu n(n=0,1,2,3...) by default.
    model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.local_rank], output_device=args.local_rank)
     
    ...
    ...
    for epoch in range(epochs):
        # step 7
        # update sampler with epoch
        train_sampler.set_epoch(epoch)
         
        # then do whatever you want to do, just like a single device/gpu training program
        ...
        ...

注意:

由于程式開頭采用了 torch.cuda.set_device() 指定了目標的設備,所以后續的操作中如果有涉及要將資料、模型移動到 gpu 中的操作需要改為 model.cuda()、inputs.cuda(),該指令會將物件正確地復制到對應的 cuda 設備中,

如果你執意使用 to 操作,那么注意確保 xx.to('cuda:n') 中的 cuda:n 與目標設備是匹配的,

以多行程方式啟動訓練腳本

你當然可以以 python distributed_example.py 這樣的形式啟動訓練腳本,不過這樣無法觸發多行程,pytorch 為多行程啟動腳本提供了 launch 工具,所以正確的啟動方式是:

python -m torch.distributed.launch --nnodes=<nodes> --nproc_per_node=<process per node> --node_rank=<rank of current node>\
        distributed_example.py --arg1 --arg2 and all other arguments of your trainning script

引數說明:

  • nnodes:指定參與計算的節點數量,默認值為1,單機多卡的訓練中可以不用指定
  • nproc_per_node:指定每個節點中的所要啟動的行程數量,由于行程與 gpu 一一對應,所以這里的數值不能大于系統中所能使用的 gpu 數量
  • node_rank: 指定當前節點在整個系統中的序號,從 0 開始遞增,需要注意的是,在多機多卡訓練中 node_rank == 0 的節點表示 master,所以 node_rank == 0 的節點必須是 MASTER_ADDR 所在的節點,否則多卡間的通信無法正確建立連接,

老實說,【從DP模式升級到DDP的方法】看起來簡單,步驟也不多,但真正要跑起來還是很多地方需要優化的;

這種多行程訓練的方法,每個行程需要分配一個卡進行訓練,這就導致你保存模型,列印Log,測驗資料都變成復雜了,比如會出現多個行程都會列印相同的Log的問題;一般建議你,定義一個主行程,且在主行程中列印Log,保存模型,測驗資料等操作,這樣可以避免上述問題了

那有沒有一個簡單方法,可以快速實作Pytorch的分布式訓練

有的,我今天就介紹一個我自己整合的Pytorch的分布式訓練工具Pytorch-Base-Trainer,基于這套工具,你可以簡單配置,即可實作DP或者DDP模式的訓練,而無需關注各種行程間通訊,埠設定等這些復雜的程序,


3.Pytorch-Base-Trainer(PBT)分布式訓練工具

(1) 工具介紹

考慮到深度學習訓練程序都有一套約定成俗的流程,鄙人借鑒Keras開發了一套基礎訓練庫: Pytorch-Base-Trainer(PBT); 這是一個基于Pytorch開發的基礎訓練庫,支持以下特征:

  • 支持多卡訓練訓練(DP模式)和分布式多卡訓練(DDP模式),參考build_model_parallel
  • 支持argparse命令列指定引數,也支持config.yaml組態檔
  • 支持最優模型保存ModelCheckpoint
  • 支持自定義回呼函式Callback
  • 支持NNI模型剪枝(L1/L2-Pruner,FPGM-Pruner Slim-Pruner)nni_pruning
  • 非常輕便,安裝簡單

博客介紹:

Pytorch基礎訓練庫Pytorch-Base-Trainer(支持模型剪枝 分布式訓練)_pan_jinquan的博客-CSDN博客考慮到深度學習訓練程序都有一套約定成俗的流程,鄙人借鑒Keras開發了一套基礎訓練庫: Pytorch-Base-Trainer(PBT); 這是一個基于Pytorch開發的基礎訓練庫,支持以下特征:https://panjinquan.blog.csdn.net/article/details/122662902GitHub地址:

GitHub - PanJinquan/Pytorch-Base-Trainer: Pytorch分布式訓練框架https://github.com/PanJinquan/Pytorch-Base-Trainer

(2) 安裝

  • 原始碼安裝
git clone https://github.com/PanJinquan/Pytorch-Base-Trainer
cd Pytorch-Base-Trainer
bash setup.sh #pip install dist/basetrainer-*.*.*.tar.gz
  • pip安裝
pip install basetrainer
  • 使用NNI 模型剪枝工具,需要安裝NNI
# Linux or macOS
python3 -m pip install --upgrade nni
# Windows
python -m pip install --upgrade nni

(3)使用方法

basetrainer使用方法可以參考example.py,構建自己的訓練器,可通過如下步驟實作:

  • step1: 新建一個類ClassificationTrainer,繼承trainer.EngineTrainer
  • step2: 實作介面
def build_train_loader(self, cfg, **kwargs):
    """定義訓練資料"""
    raise NotImplementedError("build_train_loader not implemented!")


def build_test_loader(self, cfg, **kwargs):
    """定義測驗資料"""
    raise NotImplementedError("build_test_loader not implemented!")


def build_model(self, cfg, **kwargs):
    """定于訓練模型"""
    raise NotImplementedError("build_model not implemented!")


def build_optimizer(self, cfg, **kwargs):
    """定義優化器"""
    raise NotImplementedError("build_optimizer not implemented!")


def build_criterion(self, cfg, **kwargs):
    """定義損失函式"""
    raise NotImplementedError("build_criterion not implemented!")


def build_callbacks(self, cfg, **kwargs):
    """定義回呼函式"""
    raise NotImplementedError("build_callbacks not implemented!")
step3: 在初始化中呼叫build
def __init__(self, cfg):
    super(ClassificationTrainer, self).__init__(cfg)
    ...
    self.build(cfg)
    ...
step4: 實體化ClassificationTrainer,并使用launch啟動分布式訓練
def main(cfg):
    t = ClassificationTrainer(cfg)
    return t.run()


if __name__ == "__main__":
    parser = get_parser()
    args = parser.parse_args()
    cfg = setup_config.parser_config(args)
    launch(main,
           num_gpus_per_machine=len(cfg.gpu_id),
           dist_url="tcp://127.0.0.1:28661",
           num_machines=1,
           machine_rank=0,
           distributed=cfg.distributed,
           args=(cfg,))

4.Example: 構建自己的分類Pipeline

  • basetrainer使用方法可以參考example.py
# 單行程多卡訓練
python example.py --gpu_id 0 1 # 使用命令列引數
python example.py --config_file configs/config.yaml # 使用yaml組態檔
# 多行程多卡訓練(分布式訓練)
python example.py --config_file configs/config.yaml --distributed # 使用yaml組態檔
  • 目標支持的backbone有:resnet[18,34,50,101], ,mobilenet_v2等,詳見backbone等 ,其他backbone可以自定義添加
  • 訓練引數可以通過兩種方法指定: (1) 通過argparse命令列指定 (2)通過config.yaml組態檔,當存在同名引數時,以組態檔為默認值
引數型別參考值說明
train_datastr, list-訓練資料檔案,可支持多個檔案
test_datastr, list-測驗資料檔案,可支持多個檔案
work_dirstrwork_space訓練輸出作業空間
net_typestrresnet18backbone型別,{resnet,resnest,mobilenet_v2,...}
input_sizelist[128,128]模型輸入大小[W,H]
batch_sizeint32batch size
lrfloat0.1初始學習率大小
optim_typestrSGD優化器,{SGD,Adam}
loss_typestrCELoss損失函式
schedulerstrmulti-step學習率調整策略,{multi-step,cosine}
milestoneslist[30,80,100]降低學習率的節點,僅僅scheduler=multi-step有效
momentumfloat0.9SGD動量因子
num_epochsint120回圈訓練的次數
num_warn_upint3warn_up的次數
num_workersint12DataLoader開啟執行緒數
weight_decayfloat5e-4權重衰減系數
gpu_idlist[ 0 ]指定訓練的GPU卡號,可指定多個
log_freqin20顯示LOG資訊的頻率
finetunestrmodel.pthfinetune的模型
use_pruneboolTrue是否進行模型剪枝
progressboolTrue是否顯示進度條
distributedboolFalse是否使用分布式訓練

一個簡單分類例子如下:

# -*-coding: utf-8 -*-
"""
    @Author : panjq
    @E-mail : pan_jinquan@163.com
    @Date   : 2021-07-28 22:09:32
"""
import os
import sys

sys.path.append(os.getcwd())
import argparse
import basetrainer
from torchvision import transforms
from torchvision.datasets import ImageFolder
from basetrainer.engine import trainer
from basetrainer.engine.launch import launch
from basetrainer.criterion.criterion import get_criterion
from basetrainer.metric import accuracy_recorder
from basetrainer.callbacks import log_history, model_checkpoint, losses_recorder, multi_losses_recorder
from basetrainer.scheduler import build_scheduler
from basetrainer.optimizer.build_optimizer import get_optimizer
from basetrainer.utils import log, file_utils, setup_config, torch_tools
from basetrainer.models import build_models

print(basetrainer.__version__)


class ClassificationTrainer(trainer.EngineTrainer):
    """ Training Pipeline """

    def __init__(self, cfg):
        super(ClassificationTrainer, self).__init__(cfg)
        torch_tools.set_env_random_seed()
        cfg.model_root = os.path.join(cfg.work_dir, "model")
        cfg.log_root = os.path.join(cfg.work_dir, "log")
        if self.is_main_process:
            file_utils.create_dir(cfg.work_dir)
            file_utils.create_dir(cfg.model_root)
            file_utils.create_dir(cfg.log_root)
            file_utils.copy_file_to_dir(cfg.config_file, cfg.work_dir)
            setup_config.save_config(cfg, os.path.join(cfg.work_dir, "setup_config.yaml"))
        self.logger = log.set_logger(level="debug",
                                     logfile=os.path.join(cfg.log_root, "train.log"),
                                     is_main_process=self.is_main_process)
        # build project
        self.build(cfg)
        self.logger.info("=" * 60)
        self.logger.info("work_dir          :{}".format(cfg.work_dir))
        self.logger.info("config_file       :{}".format(cfg.config_file))
        self.logger.info("gpu_id            :{}".format(cfg.gpu_id))
        self.logger.info("main device       :{}".format(self.device))
        self.logger.info("num_samples(train):{}".format(self.num_samples))
        self.logger.info("num_classes       :{}".format(cfg.num_classes))
        self.logger.info("mean_num          :{}".format(self.num_samples / cfg.num_classes))
        self.logger.info("=" * 60)

    def build_optimizer(self, cfg, **kwargs):
        """build_optimizer"""
        self.logger.info("build_optimizer")
        self.logger.info("optim_type:{},init_lr:{},weight_decay:{}".format(cfg.optim_type, cfg.lr, cfg.weight_decay))
        optimizer = get_optimizer(self.model,
                                  optim_type=cfg.optim_type,
                                  lr=cfg.lr,
                                  momentum=cfg.momentum,
                                  weight_decay=cfg.weight_decay)
        return optimizer

    def build_criterion(self, cfg, **kwargs):
        """build_criterion"""
        self.logger.info("build_criterion,loss_type:{},num_classes:{}".format(cfg.loss_type, cfg.num_classes))
        criterion = get_criterion(cfg.loss_type, cfg.num_classes, device=self.device)
        return criterion

    def build_train_loader(self, cfg, **kwargs):
        """build_train_loader"""
        self.logger.info("build_train_loader,input_size:{}".format(cfg.input_size))
        transform = transforms.Compose([
            transforms.Resize([int(128 * cfg.input_size[1] / 112), int(128 * cfg.input_size[0] / 112)]),
            transforms.RandomHorizontalFlip(),
            transforms.RandomCrop([cfg.input_size[1], cfg.input_size[0]]),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
        ])
        dataset = ImageFolder(root=cfg.train_data, transform=transform)
        cfg.num_classes = len(dataset.classes)
        cfg.classes = dataset.classes
        loader = self.build_dataloader(dataset, cfg.batch_size, cfg.num_workers, phase="train",
                                       shuffle=True, pin_memory=False, drop_last=True, distributed=cfg.distributed)
        return loader

    def build_test_loader(self, cfg, **kwargs):
        """build_test_loader"""
        self.logger.info("build_test_loader,input_size:{}".format(cfg.input_size))
        transform = transforms.Compose([
            transforms.Resize([int(128 * cfg.input_size[1] / 112), int(128 * cfg.input_size[0] / 112)]),
            transforms.CenterCrop([cfg.input_size[1], cfg.input_size[0]]),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
        ])
        dataset = ImageFolder(root=cfg.train_data, transform=transform)
        loader = self.build_dataloader(dataset, cfg.batch_size, cfg.num_workers, phase="test",
                                       shuffle=False, pin_memory=False, drop_last=False, distributed=False)
        return loader

    def build_model(self, cfg, **kwargs):
        """build_model"""
        self.logger.info("build_model,net_type:{}".format(cfg.net_type))
        model = build_models.get_models(net_type=cfg.net_type, input_size=cfg.input_size,
                                        num_classes=cfg.num_classes, pretrained=True)
        if cfg.finetune:
            self.logger.info("finetune:{}".format(cfg.finetune))
            state_dict = torch_tools.load_state_dict(cfg.finetune)
            model.load_state_dict(state_dict)
        if cfg.use_prune:
            from basetrainer.pruning import nni_pruning
            sparsity = 0.2
            self.logger.info("use_prune:{},sparsity:{}".format(cfg.use_prune, sparsity))
            model = nni_pruning.model_pruning(model,
                                              input_size=[1, 3, cfg.input_size[1], cfg.input_size[0]],
                                              sparsity=sparsity,
                                              reuse=False,
                                              output_prune=os.path.join(cfg.work_dir, "prune"))
        model = self.build_model_parallel(model, cfg.gpu_id, distributed=cfg.distributed)
        return model

    def build_callbacks(self, cfg, **kwargs):
        """定義回呼函式"""
        self.logger.info("build_callbacks")
        # 準確率記錄回呼函式
        acc_record = accuracy_recorder.AccuracyRecorder(target_names=cfg.classes,
                                                        indicator="Accuracy")
        # loss記錄回呼函式
        loss_record = losses_recorder.LossesRecorder(indicator="loss")
        # Tensorboard Log等歷史記錄回呼函式
        history = log_history.LogHistory(log_dir=cfg.log_root,
                                         log_freq=cfg.log_freq,
                                         logger=self.logger,
                                         indicators=["loss", "Accuracy"],
                                         is_main_process=self.is_main_process)
        # 模型保存回呼函式
        checkpointer = model_checkpoint.ModelCheckpoint(model=self.model,
                                                        optimizer=self.optimizer,
                                                        moder_dir=cfg.model_root,
                                                        epochs=cfg.num_epochs,
                                                        start_save=-1,
                                                        indicator="Accuracy",
                                                        logger=self.logger)
        # 學習率調整策略回呼函式
        lr_scheduler = build_scheduler.get_scheduler(cfg.scheduler,
                                                     optimizer=self.optimizer,
                                                     lr_init=cfg.lr,
                                                     num_epochs=cfg.num_epochs,
                                                     num_steps=self.num_steps,
                                                     milestones=cfg.milestones,
                                                     num_warn_up=cfg.num_warn_up)
        callbacks = [acc_record,
                     loss_record,
                     lr_scheduler,
                     history,
                     checkpointer]
        return callbacks

    def run(self, logs: dict = {}):
        self.logger.info("start train")
        super().run(logs)


def main(cfg):
    t = ClassificationTrainer(cfg)
    return t.run()


def get_parser():
    parser = argparse.ArgumentParser(description="Training Pipeline")
    parser.add_argument("-c", "--config_file", help="configs file", default="configs/config.yaml", type=str)
    # parser.add_argument("-c", "--config_file", help="configs file", default=None, type=str)
    parser.add_argument("--train_data", help="train data", default="./data/dataset/train", type=str)
    parser.add_argument("--test_data", help="test data", default="./data/dataset/val", type=str)
    parser.add_argument("--work_dir", help="work_dir", default="output", type=str)
    parser.add_argument("--input_size", help="input size", nargs="+", default=[224, 224], type=int)
    parser.add_argument("--batch_size", help="batch_size", default=32, type=int)
    parser.add_argument("--gpu_id", help="specify your GPU ids", nargs="+", default=[0], type=int)
    parser.add_argument("--num_workers", help="num_workers", default=0, type=int)
    parser.add_argument("--num_epochs", help="total epoch number", default=50, type=int)
    parser.add_argument("--scheduler", help=" learning scheduler: multi-step,cosine", default="multi-step", type=str)
    parser.add_argument("--milestones", help="epoch stages to decay learning rate", nargs="+",
                        default=[10, 20, 40], type=int)
    parser.add_argument("--num_warn_up", help="num_warn_up", default=3, type=int)
    parser.add_argument("--net_type", help="net_type", default="mobilenet_v2", type=str)
    parser.add_argument("--finetune", help="finetune model file", default=None, type=str)
    parser.add_argument("--loss_type", help="loss_type", default="CELoss", type=str)
    parser.add_argument("--optim_type", help="optim_type", default="SGD", type=str)
    parser.add_argument("--lr", help="learning rate", default=0.1, type=float)
    parser.add_argument("--weight_decay", help="weight_decay", default=0.0005, type=float)
    parser.add_argument("--momentum", help="momentum", default=0.9, type=float)
    parser.add_argument("--log_freq", help="log_freq", default=10, type=int)
    parser.add_argument('--use_prune', action='store_true', help='use prune', default=False)
    parser.add_argument('--progress', action='store_true', help='display progress bar', default=True)
    parser.add_argument('--distributed', action='store_true', help='use distributed training', default=False)
    parser.add_argument('--polyaxon', action='store_true', help='polyaxon', default=False)
    return parser


if __name__ == "__main__":
    parser = get_parser()
    cfg = setup_config.parser_config(parser.parse_args(), cfg_updata=True)
    launch(main,
           num_gpus_per_machine=len(cfg.gpu_id),
           dist_url="tcp://127.0.0.1:28661",
           num_machines=1,
           machine_rank=0,
           distributed=cfg.distributed,
           args=(cfg,))

5.可視化

目前訓練程序可視化工具是使用Tensorboard,使用方法:

tensorboard --logdir=path/to/log/
??
??
??

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/423486.html

標籤:AI

上一篇:Github上10個資料科學和機器學習知識庫

下一篇:智能車淺談——抗干擾技術軟體篇

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more