ByteDance では、ディープラーニングをベースにしたアプリケーションが随所で開花しており、エンジニアはモデルの効果に注目する一方で、オンライン サービスにも注意を払う必要があります一貫性とパフォーマンス。初期の頃、これには通常、アルゴリズムの専門家とエンジニアリングの専門家の間の分業と密接な協力が必要でした。このモデルには、差分トラブルシューティングや検証などの比較的高いコストがかかります。
PyTorch/TensorFlow フレームワークの人気により、深層学習モデルのトレーニングとオンライン推論が統合されました。開発者は、特定のアルゴリズム ロジックに注意を払い、フレームワークの Python API を呼び出すだけでトレーニングを完了できます。その後、モデルをシリアル化してエクスポートするのが非常に便利で、推論作業は統合された高性能 C エンジンによって完了します。トレーニングから展開までの開発者のエクスペリエンスが向上します。
ただし、完成したサービスには通常、前処理/後処理などの多くのビジネス ロジックが含まれており、このタイプのロジックでは通常、さまざまな入力を処理して Tensor に変換し、モデルに入力します。 、モデル出力 Tensor はターゲット形式に処理されます。いくつかの典型的なシナリオは次のとおりです。
PyTorch/TensorFlow などのフレームワークは、統合されたモデルのトレーニング/推論の問題を比較的解決しているため、モデルの計算自体にはトレーニングと推論の統合という問題はありません (オペレータのパフォーマンスの最適化については、この説明の範囲外です)。
解決すべき中心的な問題は、前処理と後処理で高パフォーマンスのトレーニングを提供し、統合ソリューションを推進する必要があるということです。このタイプのロジックの場合、TensorFlow 2.x は tf.function (まだ完成していません) を提供し、PyTorch は例外なくネイティブ Python 構文のサブセットを選択する TorchScript を提供します。しかし、たとえ非常に強力であっても、依然として無視できない問題があります:
パフォーマンス: このソリューションのほとんどは仮想マシンの実装に基づいています。仮想マシン ソリューションは柔軟性があり、非常に制御可能ですが、深層学習フレームワークのほとんどの仮想マシンは通常、パフォーマンスが十分ではありません。補足すると、このフレームワークは初期の Tensor コンピューティング向けに設計されたものであり、配列コンピューティングにおける各オペレーターのコストは非常に高く、仮想マシンのディスパッチやスケジューリングのコストは無視できます。ただし、プログラミング言語プログラミングへの移植のオーバーヘッドは無視するのが難しく、コードを書きすぎるとパフォーマンスのボトルネックになります。テストによると、TorchScript インタプリタのパフォーマンスは Python のパフォーマンスの約 1/5 にすぎず、tf.function のパフォーマンスはさらに悪くなります。 不完全な関数: 実際、実際のシナリオに適用すると、tf.function/TorchScript がサポートしていない多くの重要な関数が依然として見つかります。たとえば、カスタム リソースはパッケージ化できず、組み込みのシリアル化のみが可能です。タイプ; 文字列はバイト単位でのみ処理でき、中国語などの Unicode では diff が発生します; コンテナは同形である必要があり、カスタム タイプなどをサポートしていません...さらに、非対応のタイプも多数あります。 - 深層学習タスク。たとえば、シーケンス アノテーション、言語モデルのデコード、ツリー モデルの人工特徴構築など、自然言語処理には依然として多くの非深層学習アプリケーションやサブタスクが存在します。これらは通常、より柔軟な特徴パラダイムを備えています。エンドツーエンドの統合されたトレーニングとプロモーションのソリューションには、依然として多くの開発と正確性の検証作業が必要です。
上記の問題を解決するために、コンパイルに基づいた前処理ソリューション MATXScript を開発しました。
コア アーキテクチャは次のとおりです:
その中でもコンパイラの役割は非常に重要であり、その中心的なプロセスは次のとおりです。
上記のプロセスを通じて、ユーザーが作成した前処理コードはパイプラインで JitOp にコンパイルされます。前処理と後処理をモデルとリンクするために、トレース システムも開発しました (インターフェイスの設計は PyTorch を参照しています)。アーキテクチャは次のとおりです。
MATXScript に基づいて、トレーニングと推論に同じコード セットを使用できるため、モデル展開のコストが大幅に削減されます。同時に, アーキテクチャとアルゴリズムは分離されており, アルゴリズムの学生は完全に Python で作業できます. アーキテクチャの学生はコンパイラ開発とランタイムの最適化に焦点を当てます. ByteDance では, このソリューションは大規模な導入によって検証されています!
MATXScript の使用方法を示す例として、最も単純な英語テキストの前処理を示します。
目標: 英語テキストの一部をインデックスに変換する
class Text2Ids: def __init__(self) -> None: self.table: Dict[str, int] = { "hello": 0, "world": 1, "[UNK]": 2, } def lookup(self, word: str) return self.table.get(word, 2) def__call__ (self, words: List[str]) return [self.lookup(w) for w in words]
import matx class WorkFlow: def __init__(self): # 此处会进行代码编译,Python 代码自动编译封装为 Callable 对象 self.text2ids = matx.script(Text2Ids)() def process(self, texts): ids = self.text2ids(texts) return ids # test handler = WorkFlow() print(handler.process("hello world unknown")) # output: [0, 1, 2]
# dump mod = matx.trace(handler.process, "hello world") print(mod.run({"texts": "hello world"})) mod.save('./my_dir') # load mod = matx.load('./my_dir', -1) print(mod.run({"texts": "hello world"}))
#include <string> #include <vector> #include <map> #include <iostream> #include <matxscript/pipeline/tx_session.h> using namespace ::matxscript::runtime; int main() { // test case std::unordered_map<std::string, RTValue> feed_dict; feed_dict.emplace("texts", Unicode(U"hello world")); std::vector<std::pair<std::string, RTValue>> result; const char* module_path = "./my_dir"; const char* module_name = "model.spec.json"; { // -1 mean cpu auto sess = TXSession::Load(module_path, module_name, -1); auto result = sess->Run(feed_dict); for (auto& r : result) { std::cout << "key: " << r.first << ", value: " << r.second << std::endl; } } return 0; }
完全なコードについては、https://github を参照してください。 .com/bytedance/matxscript/tree/main/examples/text2ids
要約: 上記は純粋な Python で実装された非常に単純な前処理ロジックであり、一般的な C コードでロードして実行できます。モデル 実際のマルチモーダルなエンドツーエンドのケースを示します。
ここでは、グラフィック マルチモーダル (Bert Resnet) を例として取り上げます。モデルは、トレーニングとデプロイにおける実際の作業を示すために、PyTorch を使用して作成されています。
a . text
from typing import List, Dict, Tuple import libcut import matx class Vocabulary: ... def utf8_decoder(s: List[bytes]): return [x.decode() for x in s] class TextNDArrayBuilder: ... class TextPipeline: def __init__(self, mode: str = "eval"): self.mode = mode self.cut_engine = libcut.Cutter('/path/to/cut_models', ...) self.vocab = matx.script(Vocabulary)('/path/to/vocab.txt') self.decoder = matx.script(utf8_decoder) self.input_builder = matx.script(TextNDArrayBuilder)(self.vocab) def process(self, text: List[bytes]): # List[bytes] 是对齐 C++ 的 vector<string> text: List[str] = self.decoder(text) words: List[List[str]] = self.cut_engine(text) batch_ids: List[List[int]] = self.vocab(words) input_ids, segment_ids, mask_ids = self.input_builder(batch_ids, 32) if self.mode == "train": return input_ids.torch(), segment_ids.torch(), mask_ids.torch() return input_ids, segment_ids, mask_ids
b.vision
from typing import List, Dict, Tuple import matx from matx import vision class VisionPipeline: def __init__(self, device_id: int = 0, mode: str = "eval", image_size: int = 224,): self.is_training = mode == 'train' self.mode = mode ... def process(self, image,): if self.is_training: decode_nds = self.random_crop_decode(image) flip_nds = self.random_flip(decode_nds) resize_nds = self.resize(flip_nds) transpose_nd = self.transpose_norm(resize_nds, vision.SYNC) else: decode_nds = self.decode(image) resize_nds = self.resize(decode_nds) crop_nds = self.center_crop(resize_nds) transpose_nd = self.transpose_norm(crop_nds, vision.SYNC) if self.mode == "trace": return transpose_nd return transpose_nd.torch()
class MultimodalEvalPipeline: def __init__(self): self.text_pipe = TextPipeline(mode="eval", ...) self.vision_pipe = VisionPipeline(mode="eval", ...) self.torch_model = torch.jit.load('/path/to/multimodal.jit', map_locatinotallow='cuda:0') self.tx_model_op = matx.script(self.torch_model, device=0) def eval(self, texts: List[bytes], images: List[bytes]) input_ids, segment_ids, mask_ids = self.text_pipe.process(texts) images = self.vision_pipe.process(images) scores = self.tx_model_op(input_ids, segment_ids, mask_ids, images) return scores # examples example_batch_size = 8 text_examples = ['hello, world'.encode()] * example_batch_size with open('/path/image.jpg', 'rb') as f: image_example = f.read() image_examples = [image_example] * example_batch_size # pipeline instance pipe = MultimodalEvalPipeline(...) mod = matx.trace(pipe.eval, text_examples, image_examples) # test print(mod.run({"texts": text_examples, "images": image_examples})) # save mod.save('/path/to/my_multimodal')
概要: 上記の手順を完了すると、エンドツーエンドのトレーニングとトレーニングを完了できます。リリース作業、およびプロセス全体は純粋な Python コードで完了し、アルゴリズムを学生自身が完全に制御できます。もちろん、モデル計算自体にパフォーマンスの問題がある場合は、画像の自動変更と最適化によってバックグラウンドで完了することもできます。
注: 完全なコード例については、https://github.com/bytedance/matxscript/tree/main/examples/e2e_multi_modal
完全なサーバーには次のものが含まれます: IDL プロトコル、バッチ処理戦略、スレッド/スレッドのスケジューリングと配置、モデル推論...
ここではモデル推論についてのみ説明します。その他は開発可能です。合意に従って。 main 関数を使用して、モデルのロードと実行のプロセスを示します。
#include <string> #include <vector> #include <map> #include <iostream> #include <matxscript/pipeline/tx_session.h> using namespace ::matxscript::runtime; int main() { // test case std::unordered_map<std::string, RTValue> feed_dict; feed_dict.emplace("texts", List({String("hello world")})); feed_dict.emplace("images", List({String("......")})); std::vector<std::pair<std::string, RTValue>> result; const char* module_path = "/path/to/my_multimodal"; const char* module_name = "model.spec.json"; { // cuda:0 auto sess = TXSession::Load(module_path, module_name, 0); auto result = sess->Run(feed_dict); for (auto& r : result) { std::cout << "key: " << r.first << ", value: " << r.second << std::endl; } } return 0; }
上記のコードは、C でマルチモーダル モデルをロードする最も単純なケースです。サーバーを開発する学生の場合、次のことを実行するだけで済みます。単純な抽象化と規約を通じて、上記のコードは統一された C モデル サービス フレームワークに変換できます。
私たちは Bytedance-AML-機械学習システム チームであり、統一された高パフォーマンスのトレーニングとプロモーションの統合フレームワークを企業に提供することに尽力しています。 Volcano Engine Machine Learning Platform を通じてパートナー企業にサービスを提供する予定で、Volcano Engine Machine Learning Platform は 2023 年から、プリセットのミラー環境、共通シナリオの公開サンプル、企業のアクセスおよび使用時の技術サポートなどの MATX 関連サポートを提供する予定です。など、トレーニングと推論のシナリオの高速化と統合を低コストで実現できます。弊社製品の詳細については、https://www.volcengine.com/product/ml-platform をご覧ください。
以上がバイトダンスモデル大規模展開実戦の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。