YouDoでの機械孊習がどのように実皌働に移行するか。 Yandexでの講矩

倧芏暡なサヌビスでは、機械孊習を䜿甚しお問題を解決するこずは、䜜業の䞀郚のみを実行するこずを意味したす。 MLモデルの埋め蟌みはそれほど簡単ではなく、それらの呚りにCI / CDプロセスを構築するこずはさらに困難です。 Yandexカンファレンス「DataSciencethe application program」で、 YouDoのデヌタサむ゚ンス責任者であるAdam Eldarovは、モデルのラむフサむクルの管理、再トレヌニングず再トレヌニングプロセスのセットアップ、スケヌラブルなマむクロサヌビスの開発などに぀いお話したした。





-はじめに始めたしょう。 デヌタサむ゚ンティストがいたす。圌はJupyter Notebookにいく぀かのコヌドを曞いおおり、機胜゚ンゞニアリング、盞互怜蚌、モデルモデルのトレヌニングを行っおいたす。 速床は向䞊しおいたす。







しかし、ある時点で圌は理解しおいたす。䌚瀟のビゞネス䟡倀をもたらすために、圌は゜リュヌションを生産のどこかで、神話の生産に結び付けなければなりたせん。 ほずんどの堎合、本番環境で芋たラップトップは送信できたせん。 そしお、問題が発生したす。ラップトップ内でこのコヌドを特定のサヌビスに出荷する方法です。 ほずんどの堎合、APIを持぀サヌビスを䜜成する必芁がありたす。 たたは、PubSub、キュヌを介しお通信したす。







掚奚事項を䜜成するずき、モデルをトレヌニングしお再トレヌニングする必芁がありたす。 このプロセスを監芖する必芁がありたす。 この堎合、コヌド自䜓ずモデルの䞡方を垞にテストで確認する必芁がありたす。そのため、ある時点でモデルが狂わず、぀た先を予枬し始めるこずはありたせん。 たた、ABテストを通じお実際のナヌザヌで確認する必芁がありたす。



どのようにコヌドにアプロヌチしたすか GitLabがありたす。 すべおのコヌドは、特定のドメむンの問題を解決する倚くの小さなラむブラリに分割されおいたす。 同時に、これは別個のGitLabプロゞェクト、Gitバヌゞョン管理、およびGitFlow分岐モデルです。 事前テストフックなどを䜿甚しお、統蚈テストチェックを満たさないコヌドをコミットできないようにしたす。 そしお、テスト自䜓、ナニットテスト。 私たちは、プロパティベヌスのテストアプロヌチを䜿甚したす。







通垞、テストを蚘述するずき、テスト関数ず、手で䜜成する匕数、いく぀かの䟋、およびテスト関数が返す倀を持っおいるこずを意味したす。 これは䞍䟿です。 コヌドは膚らんでいお、原則ずしお倚くの人はそれを曞くのが面倒です。 その結果、テストによっお明らかになったコヌドの束がありたす。 プロパティベヌスのテストは、すべおの匕数に特定の分垃があるこずを意味したす。 フェヌゞングを行い、これらの分垃からすべおの匕数をサンプリングし、これらの匕数を䜿甚しおテスト察象の関数を呌び出し、特定のプロパティに぀いおこの関数の結果を確認したす。 その結果、コヌドがはるかに少なくなり、同時に倚くのテストがありたす。







GitFlowずは䜕ですか これは分岐モデルであり、2぀の䞻芁なブランチがあるこずを意味したす-開発ずマスタヌ、補品の準備ができおいるコヌドがあり、すべおの開発は開発ブランチで実行され、すべおの新機胜は機胜ブランチから取埗されたす。 ぀たり、各機胜は新しい機胜ブランチであり、機胜ブランチは短呜でなければならず、機胜トグルでもカバヌされたす。 その埌、リリヌスを䜜成し、devからmasterに倉曎をスロヌし、ラむブラリたたはサヌビスのバヌゞョンタグをその䞊に配眮したす。







私たちは開発を行っおおり、いく぀かの機胜を芋぀けおGitLabにプッシュし、機胜ブランチからバヌゞンぞのマヌゞリク゚ストを䜜成しおいたす。 トリガヌが動䜜し、テストを実行したす。すべおが正垞であれば、フリヌズできたす。 しかし、それを保持しおいるのは私たちではなく、チヌムの誰かです。 コヌドを修正し、それによりバス係数を増加させたす。 このコヌドセクションは既に2人に知られおいたす。 その結果、誰かがバスにぶ぀かった堎合、誰かはすでに自分が䜕をしおいるかを知っおいたす。







ラむブラリの継続的な統合は、通垞、倉曎のテストのように芋えたす。 たた、リリヌスするず、パッケヌゞのプラむベヌトPyPIサヌバヌにも公開されたす。







さらに、パむプラむンで収集できたす。 これには、Luigiラむブラリを䜿甚したす。 タスクなどの゚ンティティで動䜜したす。タスクには出力があり、タスクの実行䞭に䜜成されたアヌティファクトが保存されたす。 実行するビゞネスロゞックをパラメヌタヌ化し、タスクずその出力を識別するタスクパラメヌタヌがありたす。 さらに、タスクには垞に他のタスクが蚭定する芁件がありたす。 ある皮のタスクを実行するず、その出力をチェックするこずですべおの䟝存関係がチェックされたす。 出力が存圚する堎合、䟝存関係は開始されたせん。 䞀郚のストレヌゞからアヌティファクトが欠萜しおいる堎合、開始されたす。 これにより、パむプラむン、有向巡回グラフが圢成されたす。







すべおのパラメヌタヌはビゞネスロゞックを識別したす。 そうするこずで、圌らはアヌティファクトを特定したす。 これは垞に、ある皮の粒床、感床、たたは週、日、時間、3時間の日付です。 モデルをトレヌニングするず、Luigi taskaには垞にこのタスクのハむパヌパラメヌタヌがあり、それらが生成するアヌティファクトに挏れ、ハむパヌパラメヌタヌがアヌティファクトの名前に反映されたす。 したがっお、基本的にすべおの䞭間デヌタセットず最終成果物をバヌゞョン管理し、それらは䞊曞きされるこずはなく、垞にストレヌゞにのみ曎新され、ストレヌゞは䜕らかの皮類のピクニック、モデルなどの最終成果物を芋るHDFSずS3プラむベヌトを実行したす。 そしお、すべおのパむプラむンコヌドは、関連するリポゞトリのサヌビスプロゞェクトにありたす。







なんずか修正する必芁がありたす。 HashiCorpスタックが圹に立ちたす。Terraformを䜿甚しおコヌドの圢でむンフラストラクチャを宣蚀し、Vaultで秘密を管理したす。すべおのパスワヌド、デヌタベヌスぞの倖芳がありたす。 Consulは、構成に䜿甚できるキヌ倀ストレヌゞによっお配垃される怜出サヌビスです。 たた、Consulはノヌドずサヌビスのヘルスチェックを行い、可甚性をチェックしたす。



そしお-遊牧民。 それはオヌケストレヌションのシステムであり、サヌビスずある皮のバッチゞョブを排陀したす。







どのように䜿甚したすか Luigiパむプラむンがありたす。Dockerコンテナヌにパックし、バットたたは定期的なバッチゞョブをNomadにドロップしたす。 バッチゞョブ-これは完了したものであり、すべおが成功した堎合-すべおがOKであれば、手動で再開できたす。 しかし、䜕か問題が発生した堎合、Nomadは詊行を䜿い果たすか、正垞に終了しないたで再詊行したす。



定期的なバッチゞョブ-これはたったく同じで、スケゞュヌルに埓っおのみ機胜したす。



問題がありたす。 䜕らかのオヌケストレヌションシステムにコンテナを展開する堎合、このコンテナ、CPU、たたはメモリが必芁ずするメモリ量を瀺す必芁がありたす。 3時間実行するパむプラむンがある堎合、2時間で10 GBのRAM、1時間-70 GBが消費されたす。 圌に䞎えた制限を超えるず、Dockerデヌモンが来おDockersを殺したす。[02:26:13]絶えずメモリを远い出したくないので、70 GBすべおのピヌクメモリ負荷を指定する必芁がありたす。 しかし、ここに問題がありたす。3時間の70 GBがすべお割り圓おられ、他のゞョブにはアクセスできなくなりたす。



したがっお、私たちは他の方法で行った。 私たちのLuigiパむプラむン党䜓は、それ自䜓ではビゞネスロゞックの皮類を開始せず、Nomad、いわゆるパラメヌタヌ化されたゞョブでサむコロのセットを起動するだけです。 実際、これはサヌバヌnrzb[02:26:39]機胜の類䌌物であり、AVS Lambdaは知っおいたす。 ラむブラリを䜜成するずき、パラメヌタ化されたゞョブ、぀たりいく぀かのパラメヌタを持぀コンテナの圢匏ですべおのコヌドをCIを介しお展開したす。 たずえば、Lite JBM Classifierには、トレヌニング甚の入力デヌタぞのパスぞのパラメヌタヌ、モデルのハむパヌパラメヌタヌ、および出力アヌティファクトぞのパスがありたす。 これらはすべおNomadに登録されおおり、LuigiパむプラむンからAPIを介しおこれらすべおのNomadゞョブをプルできたすが、Luigiは同じタスクを䜕床も実行しないようにしたす。



垞に同じテキスト凊理を行っおいるずしたしょう。 10個の条件付きモデルがあり、毎回テキスト凊理を再開したくありたせん。 これは䞀床だけ開始され、同時に再利甚されるたびに完成した結果になりたす。 同時に、これらはすべお分散的に機胜したす。倧きなクラスタヌで巚倧なグリッド怜玢を実行でき、鉄を捚おる時間しかありたせん。







アヌティファクトがありたす。䜕らかの圢でこれをサヌビスの圢に敎える必芁がありたす。 サヌビスは、HTTP APIを公開するか、キュヌを介しお通信したす。 この䟋では、これはHTTP APIであり、最も単玔な䟋です。 同時に、サヌビスずの通信、たたはHTTP JSON APIを介しお他のサヌビスず通信するサヌビスは、JSONスキヌムを怜蚌したす。 サヌビス自䜓は、APIおよびこのオブゞェクトのスキヌムのドキュメントで垞にJSONオブゞェクトを蚘述したす。 ただし、すべおのJSONオブゞェクトフィヌルドが垞に必芁なわけではないため、消費者䞻導のコントラクトが怜蚌され、このスキヌムが怜蚌され、カスケヌド型障害による分散システムの障害を防ぐために、パタヌンサヌキットブレヌカヌを介しお通信が行われたす。



同時に、Consulがこのサヌビスの可甚性を確認できるように、サヌビスはHTTPヘルスチェックを蚭定する必芁がありたす。 同時に、Nomadは、3぀のhelloチェックのサヌビスが連続しお存圚するようにするこずができ、サヌビスを再起動しお支揎するこずができたす。 サヌビスはすべおのログをJSON圢匏で曞き蟌みたす。 JSONロギングドラむバヌずElasticsスタックを䜿甚したす。FileBitはすべおの時点ですべおのJSONログを取埗しおログキャッシュに入れ、そこからElasticに到達するず、KBanを分析できたす。 同時に、メトリックを収集しおダッシュボヌドを構築するためにログを䜿甚したせん。それは非効率的です。これにはPrometheusを䜿甚するシステムを䜿甚したす。各ダッシュボヌドサヌビスのテンプレヌトを䜜成するプロセスがあり、サヌビスによっお生成される技術メトリックを分析できたす



さらに、䜕か問題が発生した堎合、アラヌトが入りたすが、ほずんどの堎合、これでは十分ではありたせん。 セントリヌは私たちの助けになりたす。これはむンシデント分析のためのものです。 実際、すべおの゚ラヌレベルログをSentryハンドラヌでキャプチャし、Sentryにプッシュしたす。 そしお、詳现なトレヌスバックがありたす。サヌビスがどの環境にあったか、どのバヌゞョン、どの関数がどのスコヌプで呌び出されたか、このスコヌプ内のどの倉数がどの倀であったかに関するすべおの情報がありたす。 すべおの蚭定、これはすべお衚瀺され、䜕が起こったのかを玠早く理解しお゚ラヌを修正するのに圹立ちたす。







その結果、サヌビスは次のようになりたす。 別のGitLabプロゞェクト、パむプラむンコヌド、テストコヌド、サヌビスコヌド自䜓、さたざたな構成、Nomad、CI構成、APIドキュメント、コミットフックなど。







リリヌスを行うずき、次のようにCIを実行したすコンテナヌを構築し、テストを実行し、ステヌゞングにクラスタヌをドロップし、そこでサヌビスのテストコントラクトを実行し、負荷テストを実斜しお、予枬が遅すぎないこずを確認し、考えおいる負荷を維持したす。 すべおが問題なければ、このサヌビスを実皌働環境に展開したす。 そしお、2぀の方法がありたす定期的なバッチゞョブがバックグラりンドで動䜜しおアヌティファクトを生成する堎合、たたはパむプを䜿甚しお䜕らかのパむプラむンをトリガヌする堎合、パむプラむンを展開するこずができたす。サヌビスを展開したす。







この堎合、他に䜕が起こりたすか 機胜ブランチの開発には、機胜トグルのようなパラダむムがあるず蚀いたした。 良い方法では、䜕かがうたくいかなかった堎合に戊闘で機胜をノックアりトするために、いく぀かのトグルで機胜をカバヌする必芁がありたす。 その埌、リリヌストレむンですべおの機胜を収集し、機胜が未完成であっおも展開できたす。 機胜の切り替えだけがオフになりたす。 私たちは党員デヌタサむ゚ンティストなので、AVテストも行いたいず考えおいたす。 LightGBMをCatBoostに眮き換えたずしたしょう。 これを確認したいのですが、同時に、AVテストはナヌザヌIDを参照しお管理されたす。 機胜トグルはuserIDにバむンドされおいるため、AVテストに合栌したす。 ここでこれらのメトリックを確認する必芁がありたす。



すべおのサヌビスはNomadに展開されたす。 2぀のNomadプロダクションクラスタヌがありたす。1぀はバッチゞョブ甚で、もう1぀はサヌビス甚です。







すべおのビゞネスむベントをKafkaにプッシュしたす。 そこから拟うこずができたす。 本質的に、それは子矊のアヌキテクチャです。 いく぀かのサヌビスでHDFSにサブスクラむブし、リアルタむム分析を行い、同時にClickHouseですべおをすくい取り、ダッシュボヌドを構築しおサヌビスのすべおのビゞネスむベントを分析できたす。 AVテストを分析できたす。







たた、コヌドを倉曎しなかった堎合は、機胜の切り替えを䜿甚しないでください。 ペンでパむプラむンを突っ蟌んだだけで、圌は新しいモデルを教えおくれたした。 それぞの新しい道がありたす。 構成内のモデルぞのNomadパスを倉曎し、新しいサヌビスをリリヌスするだけです。ここでCanary Deploymentパラダむムが助けになりたす。Nomadでボックスから利甚できたす。



珟圚のバヌゞョンのサヌビスは3぀のむンスタンスにありたす。 3぀のカナリアが必芁だず蚀いたす-叀いバヌゞョンを削枛するこずなく、新しいバヌゞョンのレプリカをさらに3぀展開したす。 その結果、トラフィックは2぀の郚分に分割され始めたす。 トラフィックの䞀郚は、サヌビスの新しいバヌゞョンに分類されたす。 すべおのサヌビスは、すべおのビゞネスむベントをKafkaにプッシュしたす。 その結果、メトリックをリアルタむムで分析できたす。



すべおが正垞であれば、すべおが正垞であるず蚀えたす。 デプロむするず、Nomadはすべおの叀いバヌゞョンを静かにオフにし、新しいバヌゞョンをスケヌリングしたす。



このモデルは、ナヌザヌアむテムずいう゚ンティティによっおバヌゞョンルヌティングをバむンドする必芁がある堎合に問題がありたす。 トラフィックはラりンドロビンでバランスが取られるため、このようなスキヌムは機胜したせん。 そのため、次の方法でサヌビスを2぀の郚分に分けたした。







これは、ゲヌトりェむ局ずワヌカヌ局です。 クラむアントは、HTTPを介しおゲヌトりェむレむダヌず通信したす。バヌゞョンを遞択し、トラフィックを分散するためのすべおのロゞックはゲヌトりェむにありたす。 同時に、述郚を完了するために必芁なすべおのI / Oバりンドタスクもゲヌトりェむに配眮されたす。 リク゚ストの述語でuserIDを取埗し、䜕らかの情報を远加する必芁があるずしたす。 他のマむクロサヌビスをプルしお、すべおの情報、機胜、たたはベヌスを取埗する必芁がありたす。 その結果、これらはすべおゲヌトりェむで発生したす。 圌はモデルにのみいる劎働者ず通信し、1぀のこずを行いたす-予枬したす。 入力および出力。



しかし、サヌビスを2぀の郚分に分割したため、リモヌトネットワヌク呌び出しのためにオヌバヌヘッドが発生したした。 それをレベル化する方法は HTTP2の䞊で実行されるGoogleのJRPCフレヌムワヌク、GoogleのRPCが助けになりたす。 倚重化ず圧瞮を䜿甚できたす。 JPRCはプロトバフを䜿甚したす。 これは、高速シリアル化ず逆シリアル化を行う、匷く型付けされたバむナリプロトコルです。



その結果、ゲヌトりェむずワヌカヌを個別にスケヌリングするこずもできたす。 䞀定量のオヌプンHTTP接続を維持できないずしたしょう。 さお、ゲヌトりェむをスケヌリングしたす。 予枬が遅すぎお、負荷を維持する時間がありたせん。 このアプロヌチは、倚腕バンディットに非垞に適しおいたす。 ゲヌトりェむでは、すべおのトラフィックバランシングロゞックが実装されおいるため、倖郚マむクロサヌビスにアクセスし、そこから各バヌゞョンのすべおの統蚈を取埗し、トラフィックのバランスをずる方法を決定できたす。 トンプ゜ンサンプリングを䜿甚するずしたしょう。







すべお問題ありたせん。モデルは䜕らかの圢で蚓緎されたので、Nomad configに登録したした。 しかし、トレヌニング䞭に陳腐化する時間がすでにある掚奚のモデルがあり、それらを絶えず再トレヌニングする必芁がある堎合はどうでしょうか すべおが同じ方法で行われたす。定期的なバッチゞョブによっお、たずえば3時間ごずに䜕らかのアヌティファクトが生成されたす。 同時に、圌の仕事の終わりに、パむプラむンはConsulの新しいモデルのパスを蚭定したす。 これはキヌ倀ストレヌゞであり、構成に䜿甚されたす。 Nomadは構成を構成できたす。 キヌ倀ストレヌゞConsulの倀に基づいた環境倉数があるずしたす。 圌は倉曎を監芖し、新しいパスが衚瀺されるずすぐに、2぀のパスを取るこずができるず刀断したす。 圌は、新しいリンクを介しおアヌティファクト自䜓をダりンロヌドし、ボリュヌムずリブヌトを䜿甚しおサヌビスコンテナヌをDockerに配眮したす。これをすべお実行しお、ダりンタむムが発生しないようにしたす。 たたは、圌は新しい蚭定をレンダリングし、サヌビスを圌に報告したす。 たたは、サヌビス自䜓がそれを怜出したす-そしお、それ自䜓は独立しお、そのモデカをラむブ曎新できたす。 それだけです、ありがずう。



All Articles