Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AIを活用した柔軟かつ効率的な社内リソース検索への取り組み

Cygames
September 09, 2024

 AIを活用した柔軟かつ効率的な社内リソース検索への取り組み

Cygames

September 09, 2024
Tweet

More Decks by Cygames

Other Decks in Technology

Transcript

  1. 7/63 リソース管理ツールにAI検索を実装 ◼ テキストで画像を検索 ◼ 画像で画像を検索 ◼ 色で画像を検索 AIを使えば テキストで直接画像検索できる

    ◼ 画像のアップロード時に検索用情報を登録 ◼ 検索時には登録された情報を使って検索 登録と検索
  2. 13/63 AI画像検索の原理(その4) 1. あらかじめ「検索対象の全画像」をベクトルに変換 2. 検索テキストをベクトルに変換 3. 2のベクトルに近い順に画像のベクトルをソート テキストで画像を検索 1.

    あらかじめ「検索対象の全画像」をベクトルに変換 2. 検索画像をベクトルに変換 3. 2のベクトルに近い順に画像のベクトルをソート 画像で画像を検索
  3. 23/63 実装 : デプロイ環境、ベクトル検索エンジン ◼ サーバレスで扱いやすい ◼ コストが低い ◼ リソース管理ツールとは別に実装(後で役に立った)

    ◼ Lambdaの詳しい話は次のデプロイのところで AWSのLambda上にデプロイ ◼ ベクトル間の距離を高速に求める ◼ Meta社のfaissを利用 https://github.com/facebookresearch/faiss ◼ 今回は検索件数が数万の単位なので必須ではない ベクトル検索エンジンを利用
  4. 24/63 実装 : ベクトル検索エンジン faiss ◼ C++実装なので高速 ◼ 多様な検索方法、GPUサポート(今回はCPU版を利用) 特徴

    ◼ コサイン類似度:2つのベクトルのなす角のコサイン値(同じベクトルの場合1) ◼ faiss.IndexFlatIPがコサイン類似度で検索 ◼ 削除時:検索インデックスを再作成(削除機能がないため) 今回はコサイン類似度が近いものを検索 ◼ 検索前:ベクトルを追加して「検索インデックス」を構築 ◼ 検索時:「検索したいベクトル」と「検索インデックス」から検索 ◼ 検索結果は距離が近い順のインデックス値 [2,3,1,…] 検索インデックスを構築 > 検索
  5. 25/63 実装 : faissはベクトルしか格納できない ◼ 同じ順番でfaissのインデックスを作成 ◼ faissの検索結果を使って、リソースIDを取得 ◼ 「ベクトル間の距離が近い順」の「リソースIDのリスト」を返す

    ◼ Pythonのpickle形式で保存 (リソースID:ベクトル)の配列を別に持つ 検索結果 リソースリスト リソースID1, 画像のベクトル1 リソースID2, 画像のベクトル2 リソースID3, 画像のベクトル3 faissの検索インデックス 画像のベクトル1 画像のベクトル2 画像のベクトル3 検索
  6. 26/63 実装 : APIごとの処理 ◼ 画像の登録時 > 検索インデックスの登録処理 ◼ 画像の検索時

    > 検索してソートされたリソースIDのリストを返す リソース管理ツールからAPIを呼び出す
  7. 27/63 実装 : 登録時の処理 1. 登録する画像をCLIPでベクトルに変換 2. リソースリストを読み込む 3. リソース名とベクトルのペアをリソースリストに追加

    4. リソースリストを使ってfaissのインデックスを再作成 インデックスの追加 faissの検索 インデックス インデックス 再作成 • ベクトル • リソースID リストに 追加 リソースリスト 画像 CLIPで ベクトル変換
  8. 28/63 実装 : 検索時の処理 1. テキストor画像をCLIPでベクトルに変換 2. faissのsearch関数で検索 3. コサイン距離が近い順に配列のインデックスのリストが返る

    4. リソースリストからリソースIDのリストを取得して返す faissの検索+リソースIDのリストを返す faissの検索 インデックス リンゴ テキスト ベクトル Search関数で 近いベクトルを検索 リソースIDの リストを取得 CLIPで ベクトル変換 リソースリスト
  9. 30/63 デプロイ上の問題点と解決策 ◼ 合計15万枚を登録 ◼ 1回のAPI呼び出しで20枚登録 ◼ 1分間に1回実行 ◼ 5日以上

    アップロード済みの画像を登録 ◼ 同時アクセスで検索インデックスが壊れる ◼ AIのモデルがインフラの帯域制限に引っかかってしまう ◼ 制限時間内に処理が終わらない 実行すると問題が多数発生
  10. 38/63 検索インデックスが同時アクセスで壊れる ◼ Faissの検索インデックスのファイルをEFSに保存 ◼ 登録時、検索時にロード&セーブ ◼ 同時アクセスするとファイルが破損! 当初の実装 ◼

    ネットワークファイルシステムなのでアクセス制御してくると思っていた EFSは同時アクセスの制御はしてくれない ◼ fcntl.LOCK_EXで排他ロック ◼ ロックファイルはサービスごとに作成(EFSに作成) ◼ サービス単位での同時アクセス数が少ないので問題なかった シンプルにファイルロックで回避
  11. 42/63 faissのファイルも帯域制限に引っかかる ◼ faissの検索インデックスをEFSに保存 ◼ 画像登録・検索ごとにEFSからロード 当初の実装 ◼ faissの検索インデックスは数十MB ◼

    数千回EFSから読み込むと制限がかかって遅くなる こちらも最初は問題なく動くが……! ◼ 関数呼び出しごとにS3から/tmpへ検索インデックスをコピー ◼ 更新後はS3へ戻す ◼ 最終的にEFSはロックファイル置き場としてのみ利用 同じ方法で解決
  12. 43/63 画像の登録処理が制限時間内に終わらない ◼ 画像の登録処理は20件まとめて行う ◼ Lambda内部では1件の登録処理を20回呼ぶ実装 ◼ モデルを20回S3から転送するので遅い! ◼ API

    Gatewayの制限のため30秒以内に終わらせたい 当初の実装 1. S3からモデルをコピー 2. 20件まとめて画像をベクトルに変換 3. faissにベクトルを登録 4. faissの検索インデックスをS3へコピー まとめて処理する実装に変更
  13. 44/63 開発期間 ◼ Japanese CLIPとfaissを使った実装 1週間 ◼ Lambdaでの初期実装 2週間 ◼

    リソース管理ツールへの組み込み 1ヶ月(別の担当者) ◼ デプロイ時のトラブル対応 1ヶ月 初期実装からリソース管理ツールへの組込みまで ◼ 基本構成は過去のAI機能と同じ ◼ AWSのインフラ構成も同じ ◼ AWS CDKのコードを流用 過去のAI機能の実装を使い回す
  14. 48/63 別のアプリケーションでも使いたい ◼ シナリオライターがゲーム中の背景画像を指定 ◼ 数百枚以上ある背景画像を検索したい ◼ タグやファイル名を知らないと探せない ◼ 埋もれている背景がある

    社内のシナリオ執筆ツールに導入してほしい ◼ リソース管理ツールとは独立している ◼ 別のサービスからでもAPIを呼び出せる 独立した実装になっているので導入が簡単
  15. 50/63 検索システムの改善 ◼ 「赤いリボンを付けたキャラクターA」で検索できるとさらに便利 ◼ Japanese CLIPのファインチューニングが必要 ◼ ファインチューニングの実装コードがない キャラクター名でも検索したい

    ◼ とあるカンファレンスで開発者の講演があった ◼ 講演後に話をして教えてもらった ◼ OpenAIのCLIPと同じ方法でファインチューニング可能 開発者に直接質問できた
  16. 51/63 ファインチューニングを行ってみた(その1) ◼ リソース管理ツールにはキャラクター名がタグで付いている ◼ 画像とキャラクター名の対応は取れるのでこれを学習 ◼ キャラクター名は学習できるが、学習済みの情報が失われてしまう キャラクター名を学習 ◼

    ファインチューニングで学習した知識は増えるが、他の知識を忘れる現象 ◼ 両者のバランスを維持するファインチューニング手法 ◼ PAINT ◼ Patching open-vocabulary models by interpolating weights ◼ 参考文献:深層学習による画像認識の基礎 オーム社 菅沼 雅徳 破滅的忘却
  17. 52/63 ファインチューニングを行ってみた(その2) ◼ LLaVA1.5は画像に対してテキストで問い合わせを行えるモデル ◼ キャラクターの名前+画像の説明テキストを学習 ◼ 「(キャラクター名)の画像です。ギターを持った女性がいます」 ◼ 出力は英語なので日本語に翻訳して適用

    ◼ 学習してみたが精度が上がっていかなかった ◼ 生成テキストが学習に向いていなかった可能性 LLaVA1.5モデルで画像からテキストを生成 画像 テキスト 「画像を説明して」 プロンプト LLaVAモデル 「ギターを持った 女性がいます」
  18. 55/63 音声版のCLIP : CLAP ◼ 画像以外を扱うCLIPモデルが多数公開済み ◼ 今回はLAION-AI/CLAPモデルを利用 音声版のCLIPを使えば可能! ◼

    CLAP : Contrastive Language-Audio Pretraining ◼ 楽曲、効果音を扱えるCLIP(英語のみ) ◼ 商用利用可能なライセンス ◼ 精度が高い ◼ 先頭の10秒のみ利用(10秒以下の場合はリピート) ◼ 楽曲用の事前学習モデルを利用 LAION-AI/CLAP
  19. 56/63 楽曲の自動タグ付け ◼ CLAPをクラス分類に適用 ◼ ジャンル : クラシック、カントリー、ジャズ、…… ◼ テンポ:速い、普通、ゆっくり

    ◼ ムード:クール、楽しい、ロマンティック、悲しい、…… ジャンル、テンポ、ムードを自動タグ付け ◼ ジャンル分類の場合 ◼ 例:this audio is {ジャンル名} sound ◼ ジャンル名 : 'classical', 'country', 'jazz’ , … ◼ 「テキスト」と「楽曲」の距離が近いものへ分類 テキストのテンプレートを利用してクラス分類 ◼ 途中でテンポやムードが変わる曲は扱えない 実際の運用に使える精度
  20. 58/63 Lambdaでの実装 ◼ モデルファイルがrinna社のCLIPより大きい ◼ 初期化に時間がかかる 同様にAWS Lambdaで実装 ◼ LAION-AI/CLAPはモデルのファイルサイズが2.2GB

    ◼ これをS3から毎回転送するのは時間がかかる ◼ モデルを16bitに変換すると383MB(精度変わらず) モデルファイルが大きい ◼ 特定のクラスのインスタンス化に数秒かかる ◼ インスタンスをPythonのpickle形式で保存 ◼ 毎回S3から転送して読み込むことで高速化 初期化に時間がかかる
  21. 62/63 まとめ : AIを使ったリソース検索を開発 ◼ 「いままで発掘できなかった画像が見つかった」など ◼ タグは使わずに、テキストで直接検索 ◼ 担当者ごとの感覚の違いに影響されない

    AI画像検索は評判がよかった ◼ 同様の仕組みで楽曲・効果音も検索できる ◼ 工夫すればクラス分類も実装可能 楽曲・効果音の検索にも利用可能 ◼ 原理は極めてシンプル ◼ サーバレスでの実装には工夫が必要 ◼ 独立したシステムにすると他でも使える サーバレスでの実装は少し大変
  22. 参考文献 ◼ MERT: Acoustic Music Understanding Model with Large- Scale

    Self-supervised Training ◼ https://github.com/yizhilll/MERT MERT ◼ Patching open-vocabulary models by interpolating weights ◼ https://arxiv.org/abs/2208.05592 PAINT
  23. クラス分類の精度を向上できないか? ◼ テキストor楽曲による検索がメイン ◼ 開発者がクラス分類は得意でないとコメント LAION-AI/CLAPはクラス分類は得意ではない ◼ タスクごとのモデルの精度を見れるサイト ◼ Music

    Auto-Tagging ◼ Music Genre Recognition ◼ Music Question Answering ◼ Music Classification Papers with Codeで探す ◼ 楽曲生成はかなり盛り上がっているのに…… 楽曲分類は人気がない