中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

高效使用Pytorch的6個技巧分別是什么

發布時間:2021-12-04 19:10:23 來源:億速云 閱讀:115 作者:柒染 欄目:大數據

本篇文章給大家分享的是有關高效使用Pytorch的6個技巧分別是什么,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

導讀  

只報告模型的Top-1準確率往往是不夠的。

將train.py腳本轉換為具有一些附加特性的強大pipeline     

 

每一個深度學習項目的最終目標都是為產品帶來價值。當然,我們想要最好的模型。什么是“最好的” —— 取決于特定的用例,我將把這個討論放到這篇文章之外。我想談談如何從你的train.py腳本中得到最好的模型。

 

我們將介紹以下技巧:

建議1 — 利用PyTorch生態系統的高級訓練框架

PyTorch在從頭開始編寫訓練循環時提供了極佳的靈活性和自由度。理論上,這為編寫任何訓練邏輯提供了無限可能。在實踐中,你很少會為訓練CycleGAN、distilling BERT或3D物體檢測從頭開始實現編寫訓練循環。

從頭編寫一個完整的訓練循環是學習PyTorch基本原理的一個很好的方法。不過,我強烈建議你在掌握了一些知識之后,轉向高級框架。有很多選擇:Catalyst, PyTorch-Lightning, Fast.AI, Ignite,以及其他。高級框架通過以下方式節省你的時間:

  • 提供經過良好測試的訓練循環
  • 支持配置文件
  • 支持多gpu和分布式訓練
  • 管理檢查點/實驗
  • 自動記錄訓練進度

從這些高級庫中獲得最大效果需要一些時間。然而,這種一次性的投資從長期來看是有回報的。

優點

  • 訓練pipeline變得更小 —— 代碼越少 —— 出錯的機會就越少。
  • 易于進行實驗管理。
  • 簡化分布式和混合精度訓練。

缺點

  • 通常,當使用一個高級框架時,我們必須在框架特定的設計原則和范例中編寫代碼。
  • 時間投資,學習額外的框架需要時間。
 

給我看指標

高效使用Pytorch的6個技巧分別是什么

建議2 —— 在訓練期間查看其他指標

幾乎每一個用于在MNIST或CIFAR甚至ImageNet中對圖像進行分類的快速啟動示例項目都有一個共同點 —— 它們在訓練期間和訓練之后都報告了一組最精簡的度量標準。通常情況下,包括Top-1和Top-5準確度、錯誤率、訓練/驗證損失,僅此而已。雖然這些指標是必要的,但它只是冰山一角!

現代圖像分類模型有數千萬個參數。你想只使用一個標量值來計算它嗎?

Top-1準確率最好的CNN分類模型在泛化方面可能不是最好的。根據你的領域和需求,你可能希望保存具有最 false-positive/false-negative的模型,或者具有最高平均精度的模型。

讓我給你一些建議,在訓練過程中你可以記錄哪些數據:

  • Grad-CAM heat-map —— 看看圖像的哪個部分對某一特定類的貢獻最大。

高效使用Pytorch的6個技巧分別是什么

可視化Grad-CAM heat-maps有助于識別模型是否基于真實病理或圖像偽影做出預測  
 
  • Confusion Matrix — 顯示了對你的模型來說哪兩個類最具挑戰性。

高效使用Pytorch的6個技巧分別是什么

混淆矩陣揭示了一個模型對特定類型進行不正確分類的頻率  
 
  • Distribution of predictions — 讓你了解最優決策邊界。

高效使用Pytorch的6個技巧分別是什么

該模型的negative和positive 預測的分布表明,有很大一部分數據模型無法確定地分類  
 
  • Minimum/Average/Maximum 跨所有層的梯度值,允許識別是否在模型中存在消失/爆炸的梯度或初始化不好的層。
 

使用面板工具來監控訓練

建議3 — 使用TensorBoard或任何其他解決方案來監控訓練進度

在訓練模型時,你可能最不愿意做的事情就是查看控制臺輸出。通過一個功能強大的儀表板,你可以在其中一次看到所有的度量標準,這是檢查訓練結果的更有效的方法。

高效使用Pytorch的6個技巧分別是什么

Tensorboard可以快速的檢查和比較你運行的訓練  
 

對于少量實驗和非分布式環境,TensorBoard是一個黃金標準。自版本1.3以來,PyTorch就完全支持它,并提供了一組豐富的特性來管理試用版。還有一些更先進的基于云的解決方案,比如Weights&Biases、[Alchemy](https://github.com/catalyst team/alchemy)和TensorBoard.dev,這些解決方案使得在多臺機器上監控和比較訓練變得更容易。

當使用Tensorboard時,我通常記錄這樣一組指標:

  • 學習率和其他可能改變的優化參數(動量,重量衰減,等等)
  • 用于數據預處理和模型內部的時間
  • 貫穿訓練和驗證的損失(每個batch和每個epoch的平均值)
  • 跨訓練和驗證的度量
  • 訓練session的超參數最終值
  • 混淆矩陣,Precision-Recall曲線,AUC(如果適用)
  • 模型預測的可視化(如適用)
 

一圖勝千言

直觀地觀察模型的預測是非常重要的。有時訓練數據是有噪聲的;有時,模型會過擬合圖像的偽影。通過可視化最好的和最差的batch(基于損失或你感興趣的度量),你可以對模型執行良好和糟糕的情況進行有價值的洞察。

建議4 — 可視化每個epoch中最好和最壞的batch。它可能會給你寶貴的見解。

Catalyst用戶提示:這里是使用可視化回調的示例:https://github.com/BloodAxe/Catalyst-Inria-Segmentation-Example/blob/master/fit_predict.py#L258

例如,在全球小麥檢測挑戰中,我們需要在圖像上檢測小麥頭。通過可視化最佳batch的圖片(基于mAP度量),我們看到模型在尋找小物體方面做得近乎完美。

高效使用Pytorch的6個技巧分別是什么

最佳模型預測的可視化顯示了模型在小物體上的良好表現  
 

相反,當我們查看最差一批的第一個樣本時,我們看到模型很難對大物體做出準確的預測。可視化分析為任何數據科學家都提供了寶貴的見解。

高效使用Pytorch的6個技巧分別是什么

最差模型預測的可視化揭示了模型在大物體上的性能很差  
 

查看最差的batch也有助于發現數據標記中的錯誤。通常情況下,貼錯標簽的樣本損失更大,因此會成為最差的batch。通過在每個epoch對最糟糕的batch做一個視覺檢查,你可以消除這些錯誤:

高效使用Pytorch的6個技巧分別是什么

標記錯誤的例子。綠色像素表示true positives,紅色像素表示false negative。在這個示例中,ground-truth掩模標在了它實際上不存在的位置上。  
 
 

使用Dict作為Dataset和Model的返回值

建議5 — 如果你的模型返回一個以上的值,使用Dict來返回結果,不要使用tuple

在復雜的模型中,返回多個輸出并不少見。例如,目標檢測模型通常返回邊界框及其標簽,在圖像分割CNN-s中,我們經常返回中間層的mask進行深度監督,多任務學習最近也很常用。

在許多開源實現中,我經常看到這樣的東西:

# Bad practice, don't return tuple
class RetinaNet(nn.Module):
  ...

  def forward(self, image):
    x = self.encoder(image)
    x = self.decoder(x)
    bboxes, scores = self.head(x)
    return bboxes, scores

  ...
 

對于作者來說,我認為這是一種非常糟糕的從模型返回結果的方法。下面是我推薦的替代方法:

class RetinaNet(nn.Module):
  RETINA_NET_OUTPUT_BBOXES = "bboxes"
  RETINA_NET_OUTPUT_SCORES = "scores"

  ...

  def forward(self, image):
    x = self.encoder(image)
    x = self.decoder(x)
    bboxes, scores = self.head(x)
    return { RETINA_NET_OUTPUT_BBOXES: bboxes, 
             RETINA_NET_OUTPUT_SCORES: scores }

  ...
 

這個建議在某種程度上與“The Zen of Python”的設定產生了共鳴 —— “明確的比含蓄的更好”。遵循這一規則將使你的代碼更清晰、更容易維護。

那么為什么我認為第二種選擇更好呢?有幾個原因:

  • 返回值有一個顯式的名稱與它關聯。你不需要記住元組中元素的確切順序。
  • 如果你需要訪問返回的字典的一個特定元素,你可以通過它的名字來訪問。
  • 從模型中添加新的輸出不會破壞代碼。

使用Dict,你甚至可以更改模型的行為,以按需返回額外的輸出。例如,這里有一個簡短的片段,演示了如何返回多個“主”輸出和兩個“輔助”輸出來進行度量學習:

# https://github.com/BloodAxe/Kaggle-2020-Alaska2/blob/master/alaska2/models/timm.py#L104

def forward(self, **kwargs):
  x = kwargs[self.input_key]
  x = self.rgb_bn(x)
  x = self.encoder.forward_features(x)
  embedding = self.pool(x)
  result = {
    OUTPUT_PRED_MODIFICATION_FLAG: self.flag_classifier(self.drop(embedding)),
    OUTPUT_PRED_MODIFICATION_TYPE: self.type_classifier(self.drop(embedding)),
  }
  if self.need_embedding:
    result[OUTPUT_PRED_EMBEDDING] = embedding
  if self.arc_margin is not None:
    result[OUTPUT_PRED_EMBEDDING_ARC_MARGIN] = self.arc_margin(embedding)

  return result
 

同樣的建議也適用于Dataset類。對于Cifar-10玩具示例,可以將圖像及其對應的標簽作為元組返回。但當處理多任務或多輸入模型,你想從數據集返回Dict類型的樣本:

# https://github.com/BloodAxe/Kaggle-2020-Alaska2/blob/master/alaska2/dataset.py#L373
class TrainingValidationDataset(Dataset):
    def __init__(
        self,
        images: Union[List, np.ndarray],
        targets: Optional[Union[List, np.ndarray]],
        quality: Union[List, np.ndarray],
        bits: Optional[Union[List, np.ndarray]],
        transform: Union[A.Compose, A.BasicTransform],
        features: List[str],
    ):
        """
        :param obliterate - Augmentation that destroys embedding.
        """
        if targets is not None:
            if len(images) != len(targets):
                raise ValueError(f"Size of images and targets does not match: {len(images)} {len(targets)}")

        self.images = images
        self.targets = targets
        self.transform = transform
        self.features = features
        self.quality = quality
        self.bits = bits

    def __len__(self):
        return len(self.images)

    def __repr__(self):
        return f"TrainingValidationDataset(len={len(self)}, targets_hist={np.bincount(self.targets)}, qf={np.bincount(self.quality)}, features={self.features})"

    def __getitem__(self, index):
        image_fname = self.images[index]
        try:
            image = cv2.imread(image_fname)
            if image is None:
                raise FileNotFoundError(image_fname)
        except Exception as e:
            print("Cannot read image ", image_fname, "at index", index)
            print(e)

        qf = self.quality[index]
        data = {}
        data["image"] = image
        data.update(compute_features(image, image_fname, self.features))

        data = self.transform(**data)

        sample = {INPUT_IMAGE_ID_KEY: os.path.basename(self.images[index]), INPUT_IMAGE_QF_KEY: int(qf)}

        if self.bits is not None:
            # OK
            sample[INPUT_TRUE_PAYLOAD_BITS] = torch.tensor(self.bits[index], dtype=torch.float32)

        if self.targets is not None:
            target = int(self.targets[index])
            sample[INPUT_TRUE_MODIFICATION_TYPE] = target
            sample[INPUT_TRUE_MODIFICATION_FLAG] = torch.tensor([target > 0]).float()

        for key, value in data.items():
            if key in self.features:
                sample[key] = tensor_from_rgb_image(value)

        return sample
 

當你的代碼中有Dictionaries時,你可以在任何地方使用名稱常量引用輸入/輸出。遵循這條規則將使你的訓練管道非常清晰和容易遵循:

# https://github.com/BloodAxe/Kaggle-2020-Alaska2

callbacks += [
  CriterionCallback(
    input_key=INPUT_TRUE_MODIFICATION_FLAG,
    output_key=OUTPUT_PRED_MODIFICATION_FLAG,
    criterion_key="bce"
  ),
  CriterionCallback(
    input_key=INPUT_TRUE_MODIFICATION_TYPE,
    output_key=OUTPUT_PRED_MODIFICATION_TYPE,
    criterion_key="ce"
  ),
  CompetitionMetricCallback(
    input_key=INPUT_TRUE_MODIFICATION_FLAG,
    output_key=OUTPUT_PRED_MODIFICATION_FLAG,
    prefix="auc",
    output_activation=binary_logits_to_probas,
    class_names=class_names,
  ),
  OutputDistributionCallback(
      input_key=INPUT_TRUE_MODIFICATION_FLAG,
      output_key=OUTPUT_PRED_MODIFICATION_FLAG,
      output_activation=binary_logits_to_probas,
      prefix="distribution/binary",
  ),
  BestMetricCheckpointCallback(
    target_metric="auc", 
    target_metric_minimize=False, 
    save_n_best=3),
]
   

在訓練中檢測異常

就像人類可以閱讀含有許多錯誤的文本一樣,深度學習模型也可以在訓練過程中出現錯誤時學習“一些合理的東西”。作為一名開發人員,你要負責搜索異常并對其表現進行推理。  
 

建議6 — 在訓練期間使用 torch.autograd.detect_anomaly()查找算術異常

如果你在訓練過程中在損失/度量中看到NaNs或Inf,你的腦海中就會響起一個警報。它是你的管道中有問題的指示器。通常情況下,它可能由以下原因引起:

  • 模型或特定層的初始化不好(你可以通過觀察梯度大小來檢查哪些層)
  • 數學上不正確的運算(負數的     torch.sqrt()     ,非正數的     torch.log()     ,等等)
  • 不當使用     torch.mean()     和     torch.sum()      的reduction(zero-sized張量上的均值會得到nan,大張量上的sum容易導致溢出)
  • 在loss中使用     x.sigmoid()     (如果你需要在loss函數中使用概率,更好的方法是     x.sigmoid().clamp(eps,1-eps      )以防止梯度消失)
  • 在Adam-like的優化器中的低epsilon值
  • 在使用fp16的訓練的時候沒有使用動態損失縮放

為了找到你代碼中第一次出現Nan/Inf的確切位置,PyTorch提供了一個簡單易用的方法torch. autograde .detect_anomaly()

import torch

def main():
    torch.autograd.detect_anomaly()
    ...
    # Rest of the training code
   

# OR
class MyNumericallyUnstableLoss(nn.Module):
  def forward(self, input, target):
    with torch.autograd.set_detect_anomaly(True):
       loss = input * target
       return loss

將其用于調試目的,否則就禁用它,異常檢測會帶來計算開銷,并將訓練速度降低10-15% 。

以上就是高效使用Pytorch的6個技巧分別是什么,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

黄大仙区| 凉城县| 丰镇市| 剑河县| 宾川县| 高碑店市| 阿巴嘎旗| 武胜县| 德格县| 安福县| 中牟县| 遵化市| 东方市| 沭阳县| 隆德县| 巢湖市| 水城县| 岳普湖县| 江阴市| 桃源县| 巴塘县| 深州市| 长泰县| 广州市| 平果县| 泸溪县| 垫江县| 铜川市| 田东县| 隆回县| 周口市| 临清市| 庄河市| 高邑县| 北碚区| 理塘县| 沾化县| 丰宁| 五莲县| 怀安县| 西畴县|