Skip to content
Guides1 min read

ブラウザのタブで動くセグメンテーションを出荷する

クリックによるセグメンテーションとオープン語彙のテキストプロンプトは、どちらも GPU なしでクライアント側で動きます。そのために必要だったのは、検証されたエンコーダの契約、測定で選んだ量子化、そして手書きのトークナイザーでした。

Potato Team

pip install potato-annotation をすれば、GPU も新しい Python 依存も、アノテーション時の外向き通信もなしにセグメンテーションが動くべきです。

最後の制約は贅沢ではありません。いくつかの研究グループは Potato をエアギャップ環境に配備しており、そこではクリック時に取得されるモデルは遅い機能ではなく存在しない機能です。そのため Potato の画像支援モデルは二つとも、ONNX Runtime Web を通じてアノテーターのブラウザで動きます。クリックによるセグメンテーションには MobileSAM、テキストプロンプトには Grounding DINO です。

そこに入った三つのことは書き留めておく価値があります。このプロジェクトの外にも一般化するからです。

エンコーダの契約にはもっともらしい読み方が複数ある

SAM の画像エンコーダは前処理済みのテンソルを受け取り、その仕様には解釈の余地があります。正規化、リサイズの規約、パディング、チャンネル順です。

我々は一つの読み方を実装し、マスクを得ました。それは正しく見えました。正解に対する重心誤差は 70 から 148 ピクセル。壊れたパイプラインというより、少し雑なアノテーターと読める種類の誤差です。もっともらしい三つの別々の読み方が、いずれも自信ありげでもっともらしい、誤ったマスクを生みました。

正しい読み方は 0.1 px に着地します。

教訓は「仕様をもっと注意深く読め」ではありません。ここでの誤った読み方は正解データがなければ見えないということです。マスクは正しい形をしていて、おおよそ正しい位置にあり、下流の検査はすべて通ります。四つの候補を切り分けられるのは既知の正解に対する数値比較だけで、そのうち正しいのは一つです。

そこで契約は、コメントに書くのではなく実際の重みに対するテストで固定されています。コメントでも同じだけ真実を述べられたでしょうが、退行は捕まえられなかったはずです。

量子化は本物の選択だった

686 MB のモデルをブラウザで動かすために量子化するのは、選択肢ではなく必須です。しかしどの量子化にするかは、たいていエクスポートツールの既定に任されています。

完全精度の Grounding DINO エクスポートに対して測ったところ:

エクスポート完全精度に対するボックス IoUサイズ
q4f160.972151 MB
int80.874201 MB

q4f16 は元のジオメトリを目に見えて多く保ち、しかも 50 MB 小さいのです。int8 は慣習的な選択であり、それではより大きなファイルでより悪いモデルを出荷することになっていました。

これを測るのに要したのは半日で、そうしなければこの選択は恒久的になっていたでしょう。画面にボックスが出るようになった後で量子化の選択を検討し直す人はいないからです。

その後 COCO の猫二匹の写真で実際に確認しました。両方の猫が 0.724 と 0.688 で検出され、ボックスは Python の参照実装と小数点以下四桁まで一致しました。

トークナイザーを手で書く

Grounding DINO は、キャプションが BERT と同じやり方でトークン化されている必要があります。素直な手は transformers.js を持ち込むことです。

それは関数一つのために約 2 MB の JavaScript を、すでに 151 MB のモデルを読み込むページに載せることになるので、WordPiece を直接実装しました。おおよそ 200 行で、HuggingFace の tokenizers に対してトークン単位で照合してあります。

節約したバイト数が本題ではありません。本題は、モデルの学習時のトークナイザーと食い違うトークナイザーは、閾値の問題に見える微妙に誤った検出を生むということです。トークナイザーを疑うまでに box_threshold の調整で丸一日を使うことになるでしょう。トークン単位の等価性テストがあれば、その失敗の型は起こりにくいのではなく起こり得なくなります。

ブラウザが正解でなくなるところ

動画のマスク伝播はサーバー側で動きます。これは不整合ではなく意図した例外です。

経済性が違うのです。クリックによるセグメンテーションはクリックごとに安価なデコーダ一回分のコストがかかり、その相手であるエンコーディングは画像ごとに一度計算してキャッシュされます。伝播はフレームごとにモデル全体を一回通す必要があり、モデルは五つのグラフにわたって 181 MB あり、動画はすでにサーバー上にあります。ブラウザのタブで百フレームは、ページが数分固まることを意味します。

我々はフレームごとに再プロンプトする、より軽いブラウザ内のキャリーフォワード経路も維持しており、この二つを同じ機能として説明しないよう注意しています。「SAM 2 の伝播があなたのブラウザで動きます」はより良い一文であり、そして偽の一文です。

これを作る人に伝えたいこと

  1. 出力より先に正解データを用意すること。 失敗の型はもっともらしい誤出力であり、それはレビューを通り抜けます。
  2. 量子化を測ること。 既定値は、別の制約のもとで誰かが下した選択です。
  3. 前処理を参照実装に対して数値で検証すること。 目視では 0.1 px と 148 px の誤差を一目で区別できません。
  4. エンコーダとデコーダを分離し、高価な側をキャッシュすること。クリックが対話的に感じられるのは、まるごとその分離のおかげです。

参考文献