Dans ByteDance, les applications basées sur l'apprentissage profond fleurissent partout. Alors que les ingénieurs se concentrent sur les effets de modèle, ils doivent également prêter attention à la cohérence et aux performances des services en ligne. Cela nécessite généralement une division du travail entre des experts en algorithmes et des experts en ingénierie. Ce mode entraîne des coûts relativement élevés, tels que le dépannage et la vérification des différences.
Avec la popularité du framework PyTorch/TensorFlow, la formation des modèles d'apprentissage en profondeur et le raisonnement en ligne ont été unifiés. Les développeurs n'ont qu'à prêter attention à la logique de l'algorithme spécifique et à appeler l'API Python du framework pour terminer le processus de vérification de la formation. , le modèle peut être facilement exporté et le travail de raisonnement est complété par un moteur C++ unifié hautes performances. Expérience développeur améliorée, de la formation au déploiement.
Cependant, un service complet comporte généralement de nombreuses logiques métier telles que le pré-traitement/post-traitement. Ce type de logique traite généralement diverses entrées dans des Tensors, puis les entre dans le modèle. traités au format Target, certains scénarios typiques sont les suivants :
Notre objectif est de fournir des solutions de formation et d'inférence automatisées et unifiées pour le processus de bout en bout ci-dessus, et atténuer le développement manuel du processus d'inférence, des différences d'alignement et d'autres problèmes pour obtenir une solution de déploiement unifiée à grande échelle.
PyTorch/TensorFlow et d'autres frameworks ont relativement résolu le problème de la formation/inférence de modèle unifié, de sorte que le calcul du modèle lui-même n'a pas le problème de l'intégration de la formation et de l'inférence (l'optimisation des performances de l'opérateur n'est pas dans le cadre de cette discussion).
Le problème principal à résoudre est le suivant : le pré-traitement et le post-traitement doivent fournir une formation performante et une solution intégrée push.
Pour ce type de logique, TensorFlow 2.x fournit tf.function (pas encore complet) et PyTorch fournit TorchScript, qui, sans exception, sélectionne un sous-ensemble de la syntaxe Python native. Mais même si elle est si puissante, il reste des problèmes qui ne peuvent être ignorés :
De plus, il existe de nombreuses tâches d'apprentissage non approfondies, comme il y en a encore beaucoup tâches d'apprentissage non approfondies dans le traitement du langage naturel Les applications ou sous-tâches d'apprentissage profond, telles que l'étiquetage de séquences, le décodage de modèles de langage, la construction de caractéristiques artificielles de modèles arborescents et d'autres tâches, ont généralement des paradigmes de fonctionnalités plus flexibles, mais en même temps, elles ont Une solution intégrée de formation et de push de bout en bout n'a pas été entièrement mise en œuvre. Il reste encore beaucoup de travail de développement et de vérification de l'exactitude.
Afin de résoudre les problèmes ci-dessus, nous avons développé une solution de prétraitement basée sur la compilation : MATXScript !
Dans le développement d'algorithmes d'apprentissage profond, les développeurs utilisent généralement Python pour des itérations et des expérimentations rapides, tout en utilisant C++ pour développer des services en ligne hautes performances, dans lesquels la vérification de l'exactitude et le développement de services deviendront un fardeau plus lourd !
MatxScript (https://github.com/bytedance/matxscript) est un compilateur AOT pour le sous-langage Python, qui peut traduire automatiquement Python en C++ et fournir des fonctions d'empaquetage et de publication en un clic. L'utilisation de MATXScript permet aux développeurs d'itérer rapidement sur les modèles tout en déployant des services hautes performances à moindre coût.
L'architecture de base est la suivante :
Parmi eux, le rôle du compilateur est très critique, et son processus principal est le suivant :
Grâce au processus ci-dessus, le code de prétraitement écrit par l'utilisateur peut être compilé dans un JitOp dans le Pipeline, afin de relier le pré- et post-traitement au modèle, nous avons également développé un système de traçage (le design de l'interface fait référence à PyTorch), avec l'architecture suivante :
Basé sur MATXScript, nous pouvons utiliser le même ensemble de code pour la formation et l'inférence, ce qui réduit considérablement le coût de déploiement du modèle. Dans le même temps, l'architecture et l'algorithme sont découplés et les étudiants en algorithme peuvent travailler entièrement en Python. Les étudiants en architecture se concentrent sur le développement du compilateur et l'optimisation du runtime. Dans ByteDance, cette solution a été vérifiée par un déploiement à grande échelle !
Ici, nous prenons le prétraitement de texte anglais le plus simple comme exemple pour montrer comment utiliser MATXScript.
Objectif : convertir un morceau de texte anglais en index
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; }
Terminez le le code peut être trouvé sur : https://github.com/bytedance/matxscript/tree/main/examples/text2ids
Résumé : Ce qui précède est une logique de prétraitement très simple implémentée en Python pur et peut être chargée par un C++ général. code Run, combinons le modèle pour montrer un véritable cas multimodal de bout en bout !
Ici, nous prenons comme exemple le multimodal graphique et textuel (Bert+Resnet). Le modèle est écrit à l'aide de PyTorch pour montrer le travail réel de formation et de déploiement.
a.
a. TextPipeline peut être utilisé comme une classe Python normale. Connectez-vous simplement à l'ensemble de donnéesb VisionPipeline implique un prétraitement GPU et est plus adapté au traitement par lots. Vous devez construire un DataLoader séparément (enterrez un point ici, nous ouvrirons la source. DataLoader multithread interne de ByteDance plus tard)
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
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()
Nous sommes l'équipe du système d'apprentissage automatique Bytedance-AML, engagée à fournir à l'entreprise un cadre intégré unifié de formation et de promotion de haute performance, et à servir également la coopération via la plateforme d'apprentissage automatique Volcano Engine Pour entreprises, la plate-forme d'apprentissage automatique Volcano Engine devrait fournir un support lié à MATX à partir de 2023, y compris des environnements miroir prédéfinis, des échantillons publics de scénarios courants, un support technique lors de l'accès et de l'utilisation en entreprise, etc., ce qui permet d'obtenir une formation et une inférence à faible coût. scénarios. Effets d’accélération et d’intégration. Bienvenue pour en savoir plus sur nos produits sur https://www.volcengine.com/product/ml-platform.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!