Transformers 中使用 TorchScript


注意:這是我們使用TorchScript進行實驗的開始,我們仍在探索可變輸入大小模型的功能。它是我們關注的焦點,我們將在即將發佈的版本中加深我們的分析,提供更多代碼示例,更靈活的實現以及將基於python的代碼與已編譯的TorchScript進行基準測試的比較。

根據Pytorch的文檔:"TorchScript是一種從PyTorch代碼創建可序列化和可優化模型的方法"。Pytorch的兩個模塊JIT和TRACE允許開發人員導出他們的模型,這些模型可以在其他程序中重用,例如面向效率的C++程序。

我們提供了一個接口,該接口允許將transformers模型導出到TorchScript,以便他們可在與基於Pytorch的python程序不同的環境中重用。在這裡,我們解釋如何使用我們的模型,以便可以導出它們,以及將這些模型與TorchScript一起使用時要注意的事項。

導出模型需要兩件事:

  • 虛擬化輸入以執行模型正向傳播。
  • 需要使用torchscript標誌實例化該模型。

這些必要性意味著開發人員應注意幾件事。這些在下面詳細說明。

含義

TorchScript標誌和解綁權重

該標誌是必需的,因為該存儲庫中的大多數語言模型都在它們的Embedding層及其Decoding層具有綁定權重關係。TorchScript不允許導出綁定權重的模型,因此,有必要事先解綁權重。

這意味著以torchscript標誌實例化的模型使得Embedding層和Decoding層分開,這意味著不應該對他們進行同時訓練,導致意外的結果。

對於沒有語言模型頭(Language Model head)的模型,情況並非如此,因為那些模型沒有綁定權重。這些型號可以在沒有torchscript標誌的情況下安全地導出。

虛擬(dummy)輸入和標準長度

虛擬輸入用於進行模型前向傳播。當輸入值在各層中傳播時,Pytorch跟蹤在每個張量上執行的不同操作。然後使用這些記錄的操作創建模型的“跡"。

跡是相對於輸入的尺寸創建的。因此,它受到虛擬輸入尺寸的限制,並且不適用於任何其他序列長度或批次大小。嘗試使用其他尺寸時,會出現如下錯誤,如:

The expanded size of the tensor (3) must match the existing size (7) at non-singleton dimension 2

因此,建議使用至少與最大輸入大小相同的虛擬輸入大小來跟蹤模型。在推理期間對於模型的輸入,可以執行填充來填充缺少的值。作為模型 將以較大的輸入大小來進行跟蹤,但是,不同矩陣的尺寸也將很大,從而導致更多的計算。

建議注意每個輸入上完成的操作總數,並密切關注各種序列長度對應性能的變化。

在Python中使用TorchScript

以下是使用Python保存,加載模型以及如何使用"跡"進行推理的示例。

保存模型

該代碼段顯示瞭如何使用TorchScript導出BertModel。在這裡實例化BertModel,根據BertConfig類,然後以文件名traced_bert.pt保存到磁盤

<code>from transformers import BertModel, BertTokenizer, BertConfig
import torch

enc = BertTokenizer.from_pretrained("bert-base-uncased")

# 標記輸入文本
text = "[CLS] Who was Jim Henson ? [SEP] Jim Henson was a puppeteer [SEP]"
tokenized_text = enc.tokenize(text)

# 輸入標記之一進行掩碼
masked_index = 8
tokenized_text[masked_index] = '[MASK]'
indexed_tokens = enc.convert_tokens_to_ids(tokenized_text)
segments_ids = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1]

# 創建虛擬輸入
tokens_tensor = torch.tensor([indexed_tokens])
segments_tensors = torch.tensor([segments_ids])
dummy_input = [tokens_tensor, segments_tensors]

# 使用torchscript標誌初始化模型
# 標誌被設置為True,即使沒有必要,因為該型號沒有LM Head。
config = BertConfig(vocab_size_or_config_json_file=32000, hidden_size=768,
num_hidden_layers=12, num_attention_heads=12, intermediate_size=3072, torchscript=True)

# 實例化模型
model = BertModel(config)

# 模型設置為評估模式

model.eval()

# 如果您要​​使用from_pretrained實例化模型,則還可以設置TorchScript標誌
model = BertModel.from_pretrained("bert-base-uncased", torchscript=True)

# 創建跡
traced_model = torch.jit.trace(model, [tokens_tensor, segments_tensors])
torch.jit.save(traced_model, "traced_bert.pt")/<code>

載入模型

該代碼段顯示瞭如何加載以前以名稱traced_bert.pt保存到磁盤的BertModel。 我們重新使用之前初始化的dummy_input。

<code>loaded_model = torch.jit.load("traced_model.pt")
loaded_model.eval()

all_encoder_layers, pooled_output = loaded_model(dummy_input)/<code>

使用跟蹤模型進行推理

使用跟蹤模型進行推理就像使用其__call__ 方法一樣簡單:

<code>traced_model(tokens_tensor, segments_tensors)/<code>


分享到:


相關文章: