- GPT-4oは高解像度モードで使用される各512x512タイルの処理に170トークンを課している。約0.75トークン/単語の比率で見ると、これは画像1枚が約227語に相当するということ
- 「百聞は一見にしかず」という言い回しと比べると、約4倍の差がある
- 170という数字は、奇妙なくらいに特徴的な数字である。OpenAIは価格設定では「20ドル」や「0.50ドル」のような丸められた数字を使い、内部次元では2や3の累乗を使う
- なぜ170のような数字を選んだのだろうか? プログラミングでは、コードベースに説明もなく放り込まれた数字を「マジックナンバー」と呼ぶが、170はかなり目立つマジックナンバーである
- 画像コストをトークン数に変換するのはなぜだろうか? 単に課金目的なら、タイルあたりのコストを列挙するほうが混乱が少ないはずである
- OpenAIが170を選んだのが、単に文字どおりそれが事実だからだとしたらどうだろうか? 画像タイルが実際に170個の連続した埋め込みベクトルで表現されているとしたらどうだろうか?
埋め込み
- まずトランスフォーマーモデルについて思い出すべき点は、離散トークンではなくベクトル上で動作するということだ
- 入力はベクトルでなければならず、そうでなければトランスフォーマーの中核である内積類似度が意味をなさない
- トークンという概念全体は前処理段階にすぎない。テキストはトークンに変換され、そのトークンはトランスフォーマーモデルの最初のレイヤーに到達する前に、埋め込みモデルによって埋め込みベクトルへ変換される
- たとえば、Llama 3は内部的に4,096個の特徴次元を使用している
- 「My very educated mother just served us nine pizzas.」という文を見ると
- BPEによって10個の整数トークン(ピリオドを含む)に変換され、その後それぞれが埋め込みモデルによって4,096次元ベクトルに変換されて、10x4096行列になる
- これがトランスフォーマーモデルへの「本当の」入力である
- ただし、これらのベクトルが必ずしもテキスト埋め込みモデルから出てこなければならないという法則はない
- これはテキストデータにはうまく機能する戦略だが、トランスフォーマーに入力したい別形式のデータがあるなら、単に別の埋め込み戦略を使えばよい
- OpenAIは2021年にCLIP埋め込みモデルを発表しているため、この方向で考えていることはわかっている
- CLIPはテキストと画像を同じ意味ベクトル空間に埋め込み、コサイン類似度を使って、テキスト文字列に関連する画像や、別の画像と意味的に類似した画像を見つけられるようにする
- ただしCLIPは画像全体を単一ベクトルに埋め込むのであって、170個ではない。GPT-4oは画像(同様に動画、音声、その他の種類のデータ)を表現するために、内部で別の高度な戦略を使っているはずだ。だからこそ「omnimodal」なのである
- 特に画像データについて、その戦略が何なのか推論してみる
特徴次元数
- GPT-4oが埋め込みベクトルを表現するために内部的に使っている次元数を推定してみる。独自仕様なので実際の数値はわからないが、妥当な仮定はできる
- OpenAIは2の累乗を好み、ときには3を単独の因数として混ぜるように見える
- たとえばada-002の埋め込みでは1,536を、text-embedding-3-largeでは3,072を使っている
- GPT-3は全体で12,288次元を使うことが知られている
- GPT-4oはそのパラメータを維持したか、増やした可能性がある
- GPT-3からGPT-4oで埋め込み数が減ったとは考えにくいが、不可能ではない
- GPT-4 Turboのようなリリースは実際に以前のバージョンより速く安価であり、もし小さいサイズでも品質面で同等に良いというベンチマーク結果を開発者が持っていたなら、埋め込み次元の削減がその一部だった可能性はある
- GPT-4o内部で使われている特徴次元数は、次のいずれかである可能性が高い: 1536, 2048, 3072, 4096, 12228, 16384, 24576
- GPT-4oが埋め込みベクトルの次元に12,228を使っていると仮定する。2倍または4倍程度の差があっても、それほど重要ではない。同じ議論が成り立つ
画像埋め込み
- 画像タイルは正方形なので、正方形のトークングリッドとして表現される可能性が高い
- 170は13x13に非常に近い
- 追加トークンは、CLIPと同様に画像全体のゲシュタルト的な印象をエンコードする単一の埋め込みベクトルかもしれない
- だとすると、512x512x3から13x13x12228へはどうやって到達するのだろうか?
戦略1: 生ピクセル
- 画像をベクトル空間に入れる非常に単純な方法:
- 512x512画像を8x8の「ミニタイル」グリッドに分割する
- 各ミニタイルは64x64x3で、12,228次元ベクトルに展開される
- 各ミニタイルが単一の埋め込みベクトルになる
- 画像タイル全体は64個の連続した埋め込みベクトルで表現される
- このアプローチには2つの問題がある:
- 64 ≠ 170
- 非常に筋が悪い(生のRGB値を使って埋め込み、あとはtransformerが解決してくれると期待するのは理にかなっていない)
戦略2: CNN
- 幸い、このような特性を持つモデルはすでに存在し、10年以上にわたって画像データをうまく処理してきた実績がある。畳み込みニューラルネットワーク(Convolutional Neural Network)である
- CNNはtranslationやscale invarianceのような特性を持つ
- AlexNetやYOLOは代表的なCNNアーキテクチャの例である
- CNNはraw pixelをsemantic vectorへ圧縮する漏斗のようなものだ
- YOLOは画像を単一の平坦なベクトルに縮約せず、13x13で止まる
- YOLOv3の出力は13x13グリッドに配置された169個の異なるベクトルで、それぞれ1,024次元である
- GPT-4oの仮想的な画像埋め込みCNNは、こうしたCNNアーキテクチャの形に似ていると予想される
- 512x512x3から13x13x12228へ到達するために標準的なCNNレイヤーを使う方法を提示する
- AlexNetに似た設計なら、これをうまく実現できる(同一の反復ブロックを5個使用)
- YOLOにより近い別案もあるが、そこでは12x12に到達する(13x13ではなく)
- 証明はできないが、こうした推測的な設計は、画像をkxkの埋め込みベクトルグリッドとして表現できるもっともらしいCNNアーキテクチャが存在することを示している
実験的検証
- GPT-4oは本当に13x13グリッドの埋め込みベクトルを見ているのだろうか?
- それを試すために、Zenerカードに着想を得たタスクを考案した。画像の格子内にあるすべての記号の色と形を識別するというものだ
- 簡単なプログラムでテスト用の格子画像を生成し、各セルの形と色をJSON配列形式で説明するようGPT-4oにプロンプトを与えた
- もし13x13仮説が正しければ、GPT-4oは13x13サイズまではうまく性能を示し、その後は性能が低下すると予想される
- しかし実際には、5x5格子までは完璧な性能を示し、それ以降で急激に低下した
- 7x7格子では76%の正確度を示し、13x13格子では偶然レベルの性能になった
- これは、169個のトークンが13x13格子を表しているという仮説が誤っていることを意味する
- ただし5x5格子の結果は、GPT-4oが画像内で25個の区別可能なオブジェクトとその絶対位置を追跡できることを示唆している
- 基本的な考え方は正しいが、次元の見立てを誤っていた可能性があり、CNNにさらに層を追加して13x13ではなく5x5まで縮小できるかもしれない
- 5x5格子以下のみを使うと仮定した場合、170トークンに到達するために出力をどのように構造化できるかを考える必要がある
ピラミッド戦略
- 85や170に近い数を得る一つの方法は、画像を徐々に細分化されたレベルの一連のピラミッドのようにエンコードしていると仮定することだ
- 画像全体のゲシュタルト的な印象を捉えるために1つの埋め込みベクトルから始め、左・中央・右と上・中・下を捉えるために
3x3 を追加し、次に 5x5、7x7 などを追加する
- この戦略は
7x7 で止めると「マスターサムネイル」に対する85トークンに非常に近くなる
- 最後に
9x9 グリッドを追加すると170に非常に近くなる
- 12+32+52+72+92=1+9+25+49+81=165
512x512 タイルに対して暫定的な 2x2 グリッドを使い、それぞれに1つの特別な <|image start|> トークンを仮定すれば完全に一致させられる
- 1+12+32+52+72=1+1+9+25+49=85
- 1+12+22+32+52+72+92=1+1+4+9+25+49+81=170
- この方式には行の始まりや終わりを示す区切り記号はないが、テキストトークンの位置情報をエンコードするのにRoPEが使われるのと似た形で、2Dの位置エンコーディングで処理できるはずだ
- 上の内容は奇数サイズのグリッドだけを採用し、
5x5 を飛ばしているため、Zenerグリッドの性能が 5x5 以降で落ち始めるという証拠とは完全には一致しない
- 代案として、
5x5 までのすべてのグリッドサイズ(偶数と奇数)を取ることもできる
- このアプローチでは55個のトークンになる: 12+22+32+42+52=55
- 各ミニタイルあたり3トークン、さらに各タイル間に区切りトークン1つを仮定すれば170に到達できる
- 数値的な根拠としては完全に満足できるものではないが、経験的な結果とはよく一致する
- ピラミッド戦略は直感的に非常に魅力的で、異なるズームレベルで空間情報をエンコードするほとんど「自明」な方法のように感じられる
- これは
5x5 グリッド以下ではうまく機能し、6x6 以上では非常に低調になる理由を説明できるかもしれない
- どの仮説もすべてを説明できそうなほど魅力的に近づいている一方で、数字がどうしてもきれいに合わないように見えるのはもどかしい
- それでも、こうしたピラミッド戦略は私が思いつける中では最善のものだ
光学文字認識(OCR)
- 上のどの仮説も、GPT-4oがOCRをどのように行っているかは説明していない
- CLIPは基本的にOCRをそれほどうまくこなせず、少なくとも大きなテキストブロックについてはそうだ
- (それでも、GPT-4oがOCRを実行できるという事実自体はかなり驚くべきことで、創発的能力の明確な例だ)
- GPT-4oは明らかに高品質なOCRを実行できる
- 長いテキストブロックを転写でき、手書き文字や移動・回転・投影された文字、あるいは部分的に隠れた文字も読める
- 最新のOCRエンジンは、画像を整え、文字のバウンディングボックスや帯を見つけ、その帯に沿って1文字または1単語ずつ特殊な文字認識モデルを走らせるために多くの処理を行う
- 理論上は、OpenAIが本当にそれほど優れたモデルを構築した可能性もあるが、Zenerグリッド課題での比較的弱い性能とは一致しない
- 画像内のきれいな
6x6 グリッドの36個の記号を読めないなら、何百もの文字を完璧に読むことはできないはずだ
- この不一致を説明するための単純な理論:
- OpenAIはTesseractのような既製のOCRツール(あるいは独自の最先端ツール)を動かし、識別されたテキストを画像データと一緒にトランスフォーマーへ入力しているのではないかと考えている
- これは、初期バージョンが画像に隠されたテキストに簡単に混乱していた理由を説明できる(GPT-4oの観点では、そのテキストはプロンプトの一部だったためだ)
- これは現在では修正されており、GPT-4oは画像内に隠された悪意あるプロンプトを無視するのが得意になっている
- しかしこれは、画像から見つかったテキストに対してトークン単位の課金がない理由を説明しない
- 興味深いことに、テキストを画像として送るほうが実際にはより効率的だ
- 小さいが読めるフォントの
512x512 画像には400〜500個のテキストトークンが容易に入るが、課金されるのは「マスターサムネイル」向けの85個に加えた170個の入力トークンだけで、合計255トークンになる(画像内の語数よりはるかに少ない)
- この理論は、画像処理時に追加の遅延が発生する理由を説明する
- CNN自体は本質的に即時だが、サードパーティ製OCRには追加の時間がかかるはずだ
- ところで(これが何かを証明するとは言わないが)、OpenAIのコードインタープリタで使われているPython環境にはPyTesseractがインストールされている
- アップロードした画像に対してPyTesseractを実行して、セカンドオピニオンを得るよう依頼できる
結論
- 本質的には、OpenAIが魔法の数字170を使っていたという一つの確かな事実から多くを推測してきた
- しかし、YOLOのような他のCNNアーキテクチャと非常によく整合する、完全にもっともらしいアプローチ、つまり画像タイルを埋め込みベクトルへ写像する方法が存在するように思える
- したがって、170トークンが単に画像処理に必要なおおよその計算量に対して課金するための近似値として使われているだけだとは考えていない
- また、一部の他のマルチモーダルモデルのように、画像データとテキストデータを結合するためにレイヤーを連結しているとも思わない
- GPT-4oは、CLIPとYOLOを混ぜたようなCNNアーキテクチャを用い、画像を直接トランスフォーマーの意味ベクトル空間へ埋め込むことで、
512x512 画像を 文字どおり 170個の埋め込みベクトルで表現しているのだと思う
- この記事を書き始めたとき、170トークンは
13x13 グリッドと1つの追加の「ゲシュタルト的印象」トークンのためのものだと完全に解読したと確信していた
- しかし、Zener課題での性能が
5x5 以降で低下し始めたことで、その考えは崩れた。内部で何をしているにせよ、13x13 よりはるかに小さいようだ
- それでもYOLOとの類推には説得力があり、
5x5 のZener課題での性能は、何らかのグリッド処理を行っていることをほとんど裏づけている
- この理論は、他の領域でも多くの予測力を持っている
- GPT-4oが複数の画像を処理し、2枚の画像を比較するといった作業を行える理由を説明する
- 同じ画像の中で複数のオブジェクトを見ることはできる一方、複雑なシーンでオブジェクトが多すぎると圧倒される理由を説明する
- GPT-4oがシーン内の個々のオブジェクトの絶対位置や相対位置について非常に曖昧に見える理由、また画像内のオブジェクトを正確に数えられない理由を説明する(オブジェクトが隣接する2つのグリッドセルにまたがると、同じクラスが両方で活性化されるため、それが1つのオブジェクトなのか2つなのか確信できない)
- 皮肉なことに、この理論でうまく説明できない唯一の点こそ、そもそもこの記事を書く動機になった問いだ。なぜよりによって170トークンなのか?
- ピラミッド理論(
1x1 + 2x2 + 3x3 + 4x4 + 5x5)が私の思いつく中では最善だったが、特別きれいなものではない
- もう少ししっくりくる理論を持っている人(あるいはNDAに抵触しない範囲で実際の知識を持っている人)の意見を聞いてみたい
後記: アルファチャンネルのトリック
- このプロジェクトを進める中で、GPT-4o がアルファチャンネルを 無視 し、やや直感に反する挙動をすることが分かった
- 「無視する」とは、画像エディタが PNG を JPG に変換するときのように、既定の背景に合成して透明度を取り除く方式ではない
- GPT-4o は文字どおり RGB チャンネルだけを取り込み、アルファチャンネルは無視する
- これは慎重に用意した 4 枚の画像で説明できる
- 説明のために HTML と CSS を使ってチェック柄パターンの上に画像を表示しており、画像自体はフラットで透明な背景を持つ
- ただし半分は透明な 黒 の背景を持ち、残り半分は透明な 白 の背景を持つ
- 「透明な黒」または「透明な白」とは何か?
- RGBA 色を 4 バイトで表現するとき、アルファが 100% であっても RGB バイトは依然として存在する
- したがって
(0, 0, 0, 255) と (255, 255, 255, 255) はある意味では異なる色だが、どちらも 100% 透明なので、正しいレンダラーが異なって表示する場面はない
- GPT-4o にこの 4 枚の画像で何を「見ている」のか尋ねると:
- 透明な黒背景に黒いテキスト: GPT-4o は "" と読む
- 透明な白背景に黒いテキスト: GPT-4o は "ENORMOUS" と読む
- 透明な黒背景に白いテキスト: GPT-4o は "SCINTILLA" と読む
- 透明な白背景に白いテキスト: GPT-4o は "" と読む
- ここで何が起きているのだろうか?
- GPT-4o は、テキストの色が透明背景の「色」と異なるときにだけテキストを読める、というパターンが見られる
- これは、GPT-4o がアルファチャンネルを 無視 し、RGB チャンネルだけを見ていることを示している。GPT-4o にとって、透明な黒は黒であり、透明な白は白である
- RGB チャンネル 3 つを保持したままアルファチャンネルを 100% に設定して画像を操作すると、より明確に確認できる
- これには Pillow 関数を使った
- これを使って以下の 2 枚の画像を作成したが、RGB データは同じで、アルファチャンネルだけが異なる
- アルファチャンネル = 255: GPT-4o は隠されたカモノハシを簡単に見ることができる
- アルファチャンネル = 0: GPT-4o には完全に透明な画像として見える
hidden_platypus.png 画像をダウンロードして ChatGPT に直接挿入してみると、正確に説明してくれる
- 画像サイズが 39.3KB で
platypus.png と同じであることに気づくだろう。完全に空で透明な画像なら、PNG 圧縮によってはるかに小さくなっているはずだ
- あるいは上記の関数を使ってアルファチャンネルを再び 255 に設定し、元の画像を復元することもできる
- これがバグかどうかは定かではないが、確かに驚くべき挙動であり、悪意ある利用者が人間を介さず GPT-4o に直接情報を密輸するために使えるようにも思える
- しかし GPT-4o は、画像に隠された悪意あるプロンプトを検出して無視する点で、GPT-4v より はるかに 優れている
image_tagger ユーティリティで生成した GPT-4o テスト画像ギャラリーでは、GPT-4o が画像に隠された悪意あるプロンプトを正しく検出し、無視した別の例を確認できる
- したがって、たとえバグだとしても、悪用可能かどうかは明らかではない
- それでも、GPT-4o がブラウザ上で人間が見るものと同じものを「見ている」のであれば、ここまで驚かなかっただろう
2件のコメント
したがって、(0, 0, 0, 255) と (255, 255, 255, 255) はある意味では異なる色ですが、どちらも 100% 透明であるため、正しいレンダラーであれば異なって表示される状況はありません。
透明にするなら alpha が 0 の (0, 0, 0, 0) と (255, 255, 255, 0) のはずなので、本文に誤植があるようですね。
Hacker Newsの意見