BioErrorLog Tech Blog

試行錯誤の記録

深層学習と集団的知性 | 論文: Collective intelligence for deep learning: A survey of recent developments

深層学習と集団的知性の関係についての論文"Collective intelligence for deep learning: A survey of recent developments" の論文要約メモです。

はじめに

今回まとめる論文はこちら:

Collective intelligence for deep learning: A survey of recent developments

  • 2022/09 公開
  • 後にSakana AIを立ち上げたDavid Haによるレビュー論文

Sakana AIが自らの方針を説明するときに引用している論文でもあります。

※ 本記事で掲載する図は全て上記論文からの引用です。

Collective intelligence for deep learning: A survey of recent developments

概要

  • 背景
    • ここ10年、深層学習は幅広い領域で目覚ましい成果を出してきた
      • コンピュータビジョン、自然言語処理、強化学習などなど
  • 深層学習の課題
    • 低いロバスト性
    • 新規タスクへの順応力
    • 確固たる前提条件が必要
    • 要は振る舞いが"硬い"
  • 集団的知性: Collective intelligence
    • 多くの個体の相互作用から創発する知性
    • 自然界には広く見られる現象: アリ, 脳細胞, 人間社会, etc...
    • キーワード: 自己組織化, 創発的行動, 群最適化, セルオートマトン
  • 深層学習と集団的知性
    • 両者は影響しあってきた
    • この2つが交わる領域の面白い研究を紹介するよ

深層学習の歴史と特徴

深層学習の歴史は古い

  • 誤差逆伝播法を用いたニューラルネットワークの登場は1980年代まで遡る
  • その後しばらく注目を浴びることはなかった

2012年、深層学習が突如注目を浴びる

  • AlexNetが画像認識コンペで優勝
    • 2位に大きく差をあけて勝利
    • GPUを活用してニューラルネットワークを学習
  • そして様々な領域で深層学習が使われるようになった
    • コンピュータビジョン
    • 画像認識, 画像生成
    • 自然言語処理
    • テキスト生成
    • 強化学習
    • 音声認識, 音声生成

AlexNetのアーキテクチャ

深層学習の課題: その振る舞いの硬さ

  • ロバストでない: 変化に弱い
    • 入力データの変更に弱い
    • 想定されていないタスクに弱い
    • 入力形式や設定が固定である必要がある
  • 人間による"エンジニアリング"の労力を要する
    • 特定のタスクを解くための特定アーキテクチャが設計される必要がある
    • 例: AlexNetの複雑なアーキテクチャを見よ

エンジニアリング vs 順応的アプローチ

  • 既存の深層学習が抱える問題は、エンジニアリング的アプローチの課題とも言える
    • ニューラルネットワークの構築は、考え方が"橋の構築"に近い
    • 橋をはじめとして、エンジニアリングで作られたものは、外界の変化に"順応する"のではなく"耐える"ように作られている
  • 順応的アプローチ
    • 順応的アプローチは自然界に多く見られる
    • 例: 集団的知性, 自己組織化, 群最適化など
    • アリが作る橋は、環境に耐えるというより順応している

人間が作った橋と、アリが作った橋

深層学習と順応的アプローチ

  • 深層学習がこれまでエンジニアリング的アプローチを辿ってきたのは、必然ではなく偶然
  • 現に最近は順応的アプローチを取り入れた深層学習の研究も出てきている
    • セルオートマトンを応用した画像処理ニューラルネットワーク
    • 自己組織化エージェントを利用した強化学習
  • GPUをはじめとするハードウェアの進歩も、深層学習と集団的知性の交わりを後押ししている

GPUの進歩により、多数のエージェントのシミュレーションが可能になってきた

集団的知性の歴史と特徴

集団的知性: Collective Intelligence/CI とは

  • 個々の個体の相互作用によって創発する分散型の知性
    • キーワード: 多様性, 独立性, 分散化
  • 自然界には普遍的に見られる現象

集団的知性のシミュレーション

  • 1993年にはロボットを用いた社会的相互作用の研究が行われた
  • 2000年にはアリの巣にインスパイアされたシミュレーション研究
  • 2003年にはBrownian agent modelの研究

集団的知性の研究の方向性

  • 問題の解決というより、原理の理解のために研究されてきた
  • この点が人工知能の歴史と異なっている
    • 人工知能は、主に問題の解決を目指してきた
    • 分類問題, 最適化問題などなど

Cellular Neural Networkの歴史

1980年代、Leon ChuaらのグループによってCellular Neural Networkが作られる

  • Cellular Neural Network: ニューラルネットワークを活用したセルオートマトン
    • セル(or ニューロン)は隣接したセルと相互作用する
    • 自己と隣接セルの状態を入力とした非線形関数によって、自己の状態が更新され続ける
    • 深層学習のような離散時間ではなく、連続時間で動作する
      • 多くは非線形アナログ電子部品として実装される

2D Cellular Neural Network(左)と、Deep Learning / Cellular Neural NetworkのGoogle trends(右)

Cellular Neural Networkの流行と衰退

  • 1990年代から2000年代中盤にかけて、Cellular Neural NetworkはAIの一領域として栄えた
    • 適用先: 画像処理, テクスチャ分析, 偏微分, 生物システムのモデリングなどなど
    • 多くの論文や学会発表が行われ、学問領域として活気があった
    • スタートアップも複数創業された
  • しかし2000年代後半、突如として下火になった
    • Cellular Neural Network用に開発されていたハードウェアへの関心は、GPUに取って代わられた
    • Google trendsで"Deep Learning"と"Cellular Neural Network"を調べると、その関心の入れ替わりがよくわかる(上図参照)
    • 衰退した理由の一つは、その使いやすさの差にあるだろう
      • 深層学習はそのエコシステムが発展し、初歩的なプログラミングができれば誰でも試すことができる
      • 一方Celluar Neural Networkは、アナログ回路をはじめとする電子エンジニアリングの知識が必要で、使いこなすハードルが高かった
  • Cellular Neural Networkは衰退したが、そのコンセプトは生き続ける
    • 複雑系, 自己組織化, 創発行動

深層学習と集団的知性

集団的知性は、複数の独立した個体の相互作用から現れる知性。 ニューラルネットワークと結びつけて考えてみよう。

画像処理

Neural Cellular Automata (neural CA)

  • ピクセルをニューラルネットワークのセルとみなす
  • 隣接セルの状態をもとに自身の色を決定するよう学習させる
  • このように各セルは隣接セルの情報しか知らなくても、全体として画像を表現できるようになる
    • この方法は、ノイズや画像の損傷にも順応できる
    • 損傷したら"再生"できる
  • テキスト分類への応用
    • MNIST分類タスクに応用(下図参照)
    • 各セルが分類を判定

MNIST分類問題を解くNeural Cellular Automata

3Dにおけるneural CAの再生

  • 3Dモデルの再生/修復ができれば、多くの応用が効いて便利
    • スキャンデータの補完など
  • マインクラフトを用いて、一部のブロックから全体を再生する研究(下図参照)
    • 数千のブロックで構成されるオブジェクトの再生
    • クリーチャーの再生

neural CAをマインクラフトに応用する

深層強化学習

深層強化学習(Deep RL)の課題

  • 深層学習と同様、想定した前提条件の変化に弱い
    • 入力/出力様式の変化
      • 例: 4本脚エージェントを6本脚にする
    • タスクの変化

モジュール化されたエージェント: ソフトボディーロボのシミュレーション

  • ソフトボディーロボを、それぞれニューラルネットによって制御されたモジュールで構成する(下図)
  • 各モジュールは、各々の認知に基づいて行動する
  • 結果、歩行行動を習得した
  • neural CAと組み合わせ、自らの体を再生するソフトボディーロボットの研究もある

ソフトボディーロボットのシミュレーション

ロボットアクチュエーターとしてのニューラルネットモジュール

  • それぞれのアクチュエーターモジュールは、自分の認知範囲の情報のみを入力とし、自分の制御範囲のみを制御する
  • 隣接モジュール間で情報をやり取りする
  • 形態が変化しても、同一のポリシーで歩行が可能

ニューラルネットモジュールで構成されたロボットのシミュレーション

Deep RLの拡張

  • 多様な形態を創発させるエージェント
  • 入力情報のノイズに対応するエージェント
  • などなどそのほか多くの発展あり

マルチエージェント学習

エージェントの数を増やす

  • マルチエージェント強化学習 (MARL)で扱われるエージェントの数は、数個程度の規模感であることが多い
  • 自然界で観測される集団的知性は、もっとずっと大きなスケールである
    • 何千とか、何百万とか
  • エージェント数を増やすことで得られるものがあろう
    • ハードウェアの進歩もあり、可能になってきている

MAgent: 数百万に及ぶ多数のピクセルエージェントのシミュレーション

MAgent: 数百万に及ぶ多数のニューラルネットエージェントのシミュレーション

  • 社会的現象やヒエラルキー構成の研究、言語の創発現象の研究が可能に

Neural MMO: マルチエージェントシミュレーション用のプラットフォーム

Neural MMO: マルチエージェントの振る舞いを研究するためのプラットフォーム

  • 大規模なエージェントのシミュレーションが可能
  • 各エージェントは独自のニューラルネットパラメータを持てる
    • メモリ容量的に難しいことだった
    • エージェントを独自パラメータによって構成すると、それぞれが異なるニッチを埋めるなどの現象が観測されている

メタ学習

メタ学習とは

  • システムが学習できるようにtrainingすることを目指す
    • meta-learnerを作る
    • 転移学習もその一形態と言える
  • Schmidhuber氏などがメタ学習の重要性を強調してきた

強化学習エージェントとしてのニューロン

  • ニューラルネットワークのニューロンを、強化学習エージェントとする
    • ニューロンの観察対象: 現在の状態
    • ニューロンの行動対象: ニューロンの結合の変更
  • この構成の中では、メタ学習はニューロンとしての強化学習エージェントの問題と捉えることができる
  • この手法は面白いが、ごく簡単な問題しか解けていないという限界もある

誤差逆伝播法を使わない学習

  • ニューロンとシナプスがそれぞれ状態を持てるようにする
    • ただのスカラー値ではなく、ニューラルネットの状態として保持
  • セルオートマトンのように、ニューロンとシナプスが周囲の状態から自身を更新する
    • 推論と学習が同時に行われる
  • これらの振る舞いルールは、"ゲノムベクター"としてパラメータ化する
  • このゲノムベクターの更新がメタ学習となる
    • 進化的アルゴリズムや最適化手法を使う
  • メタ学習されたルールは、より汎化性能を示した

RNNの適用

  • さらにニューロンとシナプスをRNNで構成する研究もある
    • 重みがRNNの隠れ状態として表現される
  • RNNに誤差逆伝播法をエミュレートさせることができる
    • 推論と学習が同時に行いながら、誤差逆伝播法を行えるとのこと

RNNエージェントとしてのニューロン/シナプス

おわりに

以上、論文"Collective intelligence for deep learning: A survey of recent developments"の要約メモでした。

以下は私の個人的なメモです。

  • 次に読みたい引用論文は何か
  • 所感
    • 深層学習のことを知れば知るほど、思ったより構成と設計がはっきりしてるんだなと感じていた。 自然界ならではの、複雑系による神秘性のようなものが現行の深層学習には無いと感じていたので本論文を読んでみた。 深層学習の柔軟性に関する課題感は、最近のLLMの汎化性能の印象からあまりピンと来なかった。 推論と学習が明確に分かれているのはずっと違和感を感じていたので、forwardで学習も行うという事例は面白かった。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

https://journals.sagepub.com/doi/full/10.1177/26339137221114874

Collective Intelligence for Deep Learning: A Survey of Recent Developments | 大トロ

"周辺確率"という名前の由来

周辺確率(marginal probability)という名前の由来はどこから来ているのか?

はじめに

周辺確率という名前の由来は?
周辺確率の"周辺"ってどういう意味?

知らなかったので備忘録です。

"周辺確率"という名前の由来

周辺確率という名前は、表形式で縦軸横軸に確率を書き出した後、その"周辺余白"にそれぞれの軸の合計値を書いて求めることが由来です。

深層学習 43ページより引用:

「周辺確率」という名称は、紙の上での周辺確率の計算手順に由来する. xの値で行を、yの値で列を指定するマス目の中にP(x, y)の値が書かれている場合, マス目の1行分の値を足し合わせ, その行の右にある紙の余白(周辺)にP(x)の値を書くのが自然である.


図で考えるとわかりやすくなります。

周辺確率の算出 | 画像はこちらから引用

縦軸横軸にマッピングされたそれぞれの確率について、軸に沿って合計値を書き出した部分(上図赤部分)が周辺確率であり、この周辺余白に書き出すという計算手順がそのまま名前になった、ということですね。

おわりに

以上、周辺確率の由来を簡単にメモしました。

数学上の命名は、ときに不思議なセンスがあって面白いです。

どなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考

深層学習 p43

Marginal, Joint and Conditional Probabilities explained By Data Scientist | by Kurtis Pykes | Towards Data Science

GPT-2を理解する | 論文メモ: Language Models are Unsupervised Multitask Learners

GPT-2の論文"Language Models are Unsupervised Multitask Learners" の論文要約メモです。

はじめに

今回まとめる論文はこちら:

Language Models are Unsupervised Multitask Learners

GPT-2に関する論文です。

なお初代GPT論文はこちら:

www.bioerrorlog.work

※ 本記事で掲載する図は論文からの引用です。

Language Models are Unsupervised Multitask Learners

概要

  • 背景
    • これまで自然言語処理タスクは、教師あり学習によって解かれてきた
  • 課題
    • これまでの言語モデルは、教師あり学習によるいわば特定領域のみの狭い専門家だった
    • 幅広い領域のジェネラリストな言語モデルを作ることはできていなかった
  • やったこと
    • WebページのスクレイピングデータセットWebTextを作った
    • 教師なし学習によるGPTモデルを構築した
      • WebTextを利用
      • ByteレベルをベースにしたBPEを利用
      • アーキテクチャは初代GPTベースに微改変
      • 最大モデル(1.5B)をGPT-2と呼ぶ
  • 結果
    • 文書理解タスクで、ラベルデータによる追加学習なしに既存モデルに匹敵する結果が出た
    • 言語モデリングタスクでは、多くのデータセットでSOTA達成
    • その他のタスクでもまあまあの結果だった
    • モデルサイズが大きいほど結果がよかった

手法

学習データセットWebTextの作成

  • WebText: RedditからリンクされたWebページをスクレイピングしてデータセットを作成
    • テキストのクオリティを担保するため、カルマ3以上のRedditスレを利用
      • リンクの数: 45 million
      • 2017/12時点のデータを利用
    • HTMLからのテキスト抽出にはDragnetNewspaperを利用
    • 計 8 millionのドキュメント / 40GBのテキストデータ
    • Wikipediaページは排除: すでにWikipedia用のちゃんとしたデータセットがあるので

WebTextの中に見られた、英語-フランス語翻訳情報の例

  • 明示的な翻訳ペアをデータとして用意しなくても、Webページ内にこのような翻訳データがあるので、翻訳タスクにも対応できることを期待

BPE: Byte Pair Encoding

文字列をどうエンコーディングしてモデルへの入力とするか?

課題:

  • Unicode文字列をUTF-8のbyte列として扱う従来の方法は、単語レベルのタスクで性能が出ない
  • BPE: Byte Pair Encodingは、その名前に反してUnicodeのbyte列ではなくコードポイントに対して行われている
    • Unicodeコードポイントに対してBPEする場合、必要な語彙は膨大になってしまう
    • Byteレベルを対象にしたBPEなら、必要な語彙は少なく抑えられる(256個)
  • しかし、BPEを直接byteレベルに適用しても、最適化は上手くいかない
    • 頻出単語と句読点の組み合わせが単語としてまとめられてしまったりする

で、どうしたのか:

  • ByteレベルのBPE
  • ただし、異なるカテゴリ間の結合は排除

これによって、byteレベルアプローチの汎用性を持たせたまま、単語レベルアプローチの性能を目指す。

モデルアーキテクチャ

初代GPTのアーキテクチャをベースにしながら少し変更:

  • Layer normalizationを、各Transformerサブブロックの入力に対して行うよう移動
  • 最後のself-attentionブロックの後にLayer normalizationを追加

初代GPTのアーキテクチャ | 画像はこちらより


また、複数サイズのモデルを作成。 最大サイズのものをGPT-2と呼ぶ。

4サイズのモデルハイパーパラメータ

結果

言語モデリングタスク

各データセットの結果

  • 8つのデータセットのうち7つでSOTA
  • 小さなデータセットでより大きな改善が見られた
    • WikiText2, PTB
  • 長距離依存のデータセットでも大きな改善が見られた
    • LAMBADA, CBT
  • 1BW (One Billion Word Benchmark)の結果は悪かった

CBTの結果とモデルサイズの関係

  • モデルサイズが大きいほど良い結果になった

常識的推論能力

Winograd Schema Challengeの結果

  • Winograd Schema Challenge: 文章のあいまいさを解消する能力から常識的推論力を測定する
  • SOTAを達成

文章読解力

Conversation Question Answering (CoQA)でテスト。

要約タスク

CNN and Daily Mailデータセット要約タスク結果

  • 既存モデルよりもあまり優れない結果
  • 直近の内容にフォーカスしてしまったり、詳細部分をちゃんと分かってなかったりする

翻訳タスク

タスクセット GPT-2の結果
WMT-14 English-French 5 BLEU
WMT-14 French-English 11.5 BLEU
  • WMT-14 English-Frenchの結果は、既存の教師なしモデルより少し低い
  • WMT-14 French-Englishの結果は、多くの教師なしベースラインよりも良いが教師なしSOTAよりは低い

QAタスク

事実を回答するスタイルのタスクにどのくらい答えられるか?

  • データセット: Natural Questions
  • GPT-2の正答率: 4.1% (exact match評価)
    • 最小モデルの結果(1%以下)に比べると良い結果なので、モデルサイズを上げていけば良くなるかもね
  • Retrievalを組み合わせた既存QAシステムは30-50%
    • GPT-2の方がずっと低い結果

Natural QuestionsデータセットへのGPT-2回答のうち、probabilityの高いもの

Generalization vs Memorization

これらの結果は、本当にGPT-2のGeneralization/汎化能力によるものなのか?
学習データセットとテストデータセットが被っていて、Memorization/思い出しによって解いてるのではないか? WebTextは雑多にWebページを大量に取ってきてるわけだし。。

の懸念について検証。

学習データセットとテストデータセットの8グラム重複

  • 学習データ(WebText)と各テストデータセットについて、8グラムのBloomフィルターで重複度合いを検証
  • WebTextの重複は1-6%ほど
    • 平均3.2%
  • 各テストデータセットそのものの学習データは平均5.9%の重複
  • むしろWebTextの方が重複が少なかった

おわりに/所感

以上、論文"Language Models are Unsupervised Multitask Learners"の要約メモでした。

以下は私の個人的なメモです。

  • 筆者たちは何を成し遂げようとしてるのか
    • 教師なし学習/zero-shotによるモデルの汎用的な言語能力を示したい
  • アプローチの鍵となる要素は何か
    • 高クオリティのwebスクレイピングデータWebTextの作成
    • モデルサイズを大きくして、教師なし学習
    • ByteレベルBPE
  • 次に読みたい引用論文は何か
  • 所感
    • 初代GPTがfine-tuningベースだったのに対して、GPT-2ではfine-tuningなしの教師なし学習での能力を示している。 この後のscaling lowと合わせて、モデルをデカくすればまずは上手くいく、の世界に入っていったのがうかがえて面白い。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Language Models are Unsupervised Multitask Learners

Better language models and their implications

GPT-2: 1.5B release

GitHub - openai/gpt-2: Code for the paper "Language Models are Unsupervised Multitask Learners"

Organoid Intelligenceを理解する | 論文メモ: Organoid intelligence (OI): the new frontier in biocomputing and intelligence-in-a-dish

Organoid Intelligence (OI)の動向を記載したレビュー論文"Organoid intelligence (OI): the new frontier in biocomputing and intelligence-in-a-dish" の論文要約メモです。

はじめに

AIの仕組みを知れば知るほど、生物の神経に比べて非効率だな、まだまだ発展途上なんだなと感じることがあります。

そんな中、まさに神経細胞をコンピューティングの要素として使ってしまおうという分野があることを知りました。

今回は、そんなOrganoid Intelligence (OI)の動向をまとめたこちらのレビュー論文を読んでいきます。

www.frontiersin.org

  • 2023/02/28 公開
  • Review論文

レビュー論文につき内容が盛りだくさんなので、個人的に印象に残っている部分をピックアップしてまとめます。 気になった方はぜひ原著をご覧ください。

なお本記事で掲載する図は全て上記論文からの引用です。

Organoid intelligence (OI): the new frontier in biocomputing and intelligence-in-a-dish

概要

  • 背景
    • 脳は複雑なタスクにおいてコンピューター(in silico)よりエネルギー効率がいい
    • 脳の学習は(現状のAIより)データ量が少なくて済む
  • OI: Organoid Intelligenceの提唱
    • intelligence-in-a-dish, "培養皿の上の知性"
    • Biocomputingの中で、真に脳神経細胞を用いてコンピューティングを行うものを包括して指す概念
  • 特徴
    • 脳神経細胞の3D培養
    • ミエリン化、グリア細胞などの多様な細胞種構成
    • マイクロ流体灌流システムによる栄養や化学シグナルの制御
    • 高精度の神経活性記録
    • 電気的/化学的な刺激入力
    • 刺激(入力)と活性記録(出力)による学習
      • Open-loop / Closed-loop

背景

人間の脳とスーパーコンピューターの比較

  • 人間の脳は現代のコンピューターよりもエネルギー効率が良い
  • 単純なタスク(単純計算など)は脳よりもコンピューターの方が優れているが、複雑なタスクや情報が足りないタスク(例: 複雑な問題に対する意思決定)は脳の方が早い
  • 現代のAIの学習は大量のデータを必要とするが、脳の学習で必要なデータはずっと少ない

OI: Organoid Intelligence

OIのアーキテクチャ

OIのアーキテクチャ概要

  • Organoidの培養
    • 3D培養による高い細胞密度
    • マイクロ電極を纏った殻/シェルで包み、organoidとのインターフェースとする
  • Organoidへの入力
    • マイクロ電極からの電気刺激
    • マイクロ流体灌流システムからの化学シグナル
    • オプトジェネティクス(光遺伝学)
    • 網膜organoidからの神経活動入力
  • 出力の検知
    • マイクロ電極による電気的信号検知
    • 蛍光観察
    • 共焦点顕微鏡
  • 解析
    • OIの反応(入力/出力)を解析するAI/機械学習アルゴリズム
    • OIのデータを解析可能な形で保管するビックデータ基盤

神経細胞の3D培養

神経細胞の3D培養

  • 2D培養と比べた3D培養のメリット
    • 細胞密度
    • 細胞分化: 脳神経活動/学習に必要な多様な細胞への分化を可能にする
      • ミエリン化
      • マイクログリア
      • アストロサイト
  • (B) 成長につれ細胞種の多様性を増すorganoid

しかし神経細胞の3D培養には課題がある:

  • 栄養の届かない中心部分は死んでしまう

マイクロ流体灌流システム

  • Organoidの中心部分は栄養が届かず、ネクローシスを起こして死んでしまう
    • 栄養が届くのはせいぜい300μm
  • 実際の脳では血管/血液が張り巡らされており、栄養の補給と老廃物の排出を行っている
    • Organoidでもこの役割が必要

そこでマイクロ流体灌流システム

マイクロ流体灌流システム

  • 神経細胞に必要な要素を供給する
    • 酸素
    • 栄養
    • 成長因子
  • このシステムは化学シグナルの制御にも使える

神経活動の記録

3D organoidの神経活動をどうやって記録するのか?

3Dマイクロ電極アレイによるorganoidインターフェース

  • マイクロ電極を持った柔らかい自己折りたたみ式の"殻"でorganoidを覆う
    • 人間の脳は測定器にインスパイアされている
  • E-G: 自発的な電気活性を示すorganoid
    • 自発的な電気活性は、活動性のシナプスの存在を示している

Organoidの神経活動の記録ついて、他にはどんな観点がある?

  • 埋め込み式電極
    • 先述の"殻"方式は非侵襲型、埋め込み電極は侵襲型
    • 侵襲型は組織へのダメージとのバランスが求められる
    • 現在、適切なプローブの探求中の段階である
  • 光学的観察
    • Organoid記録手法としての最終形にはならないだろうが、その振る舞いを観察するのに役立つ
  • 記録点の調整
    • 全ての神経活性を記録し解析することはできない
    • ごく少数の重要な情報を特定し、観察することができるか

神経活動の分析

では取得した神経活動をどう分析/解釈する?

  • Organoidの出力の分析や学習のためのアルゴリズムが必要になる
    • Organoidの機能変化を定量化するための統計的/機械学習的アルゴリズム
    • Organoidのアーキテクチャ変化を定量化するためのアルゴリズム
    • 学習を可能にするための、organoid変化と出力に関する多変量因果モデル
  • ビッグデータ基盤
    • 記録データ量は膨大になるので、それを格納/分析するためのデータ基盤が必要になる
    • 神経活動のための標準データ構造も必要
    • それらのデータをオープンにするための仕組み
    • マルチモーダルなデータ
    • コミュニティのリファレンスになるデータセットの提示

学習における観点

OIを学習させるときに考慮すること

  • Organoidインタラクション
    • Open-loopとClosed-loop
    • Open-loop: 入力を与えて、反応を記録する
    • Closed-loop: 入力を与えた結果である神経活動をフィードバックに使う
  • 生化学的な観点の活用
    • 学習時に活性化が必要な遺伝子の活用
      • シナプス可塑性や記憶形成に重要な要素
    • immediate early genes (IEGs)
    • neurotransmitter receptors

今後の展望

OI研究の展望

  1. Organoidシステムのスケールアップ
  2. Organoidによるコンピューティングの実現
  3. より高度なorganoidインターフェースの実現
  4. 倫理的問題の解消

おわりに/所感

以上、論文"Organoid intelligence (OI): the new frontier in biocomputing and intelligence-in-a-dish"の要約メモでした。

以下は私の個人的なメモです。

  • 次に読みたい引用論文は何か
  • その他所感
    • 流石にまだ始まったばかりの分野であり、今後発展していくための基盤研究が必要である、という温度感を全体に感じた。 とはいえ↑の論文(In vitro neurons learn...)のように、一定の学習能力を示している研究はすでに存在している。 何かキラーケースが出てくれば一気に発展するのかもしれない。 ただ、in silicoのAIと違って設備がないと実験ができないのが、興味を持った人間には難しいところ。 ごく簡単に試す何かいい方法はないだろうか。 またCortical Labsのような企業がどこまで進んでいるのか気になる。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Frontiers | Organoid intelligence (OI): the new frontier in biocomputing and intelligence-in-a-dish

初代GPTを理解する | 論文メモ: Improving Language Understanding by Generative Pre-Training

最初のGPT論文"Improving Language Understanding by Generative Pre-Training" の要約メモです。

はじめに

今回まとめる論文はこちら:

Improving Language Understanding by Generative Pre-Training

OpenAIによる初代GPT論文。

なお本記事で掲載する図は全て上記論文からの引用です。

Improving Language Understanding by Generative Pre-Training

概要

  • 背景
    • 世の中にはラベルなしのテキストデータは大量にあるが、ラベルありの学習用データは限られた量しかない
  • 課題
    • 現状、用意が大変なラベルあり学習データへの依存度が高い
    • ラベルなしテキストデータをいい感じに活用する方法がまだわかっていない
  • やったこと
    • ラベルなしテキストデータによる汎用事前学習(Generative Pre-Training)の後に、特定タスクに対応するためのラベルあり学習データによるfine-tuning、の二段構えによるモデル構築
    • アーキテクチャはTransformerベース: Decoder部分のみ
  • 結果
    • 幅広い言語タスクで当時のSOTA達成

手法

モデルアーキテクチャとfine-tuningの構成

  • Transformer decoderをベースにしたアーキテクチャ
  • ラベルなしテキストデータでpre-training
  • 教師ありfine tuningではTransformerにlinear+softmaxを追加
    • 目的関数には、pre-trainingの目的関数を重みづけ加算したauxiliary objectiveを採用
    • タスクに応じて、入力の形態をTransformerが処理できる一続きのtoken列に変換
    • タスクに応じて、複数のTransformerを並列に組み合わせる

結果

Natural Language Inferenceタスク

Natural Language Inferenceタスク結果

  • テキストの論理包含認識タスク
    • ふたつの文章について、包含、矛盾、中立のいずれかを判断する
  • RTE以外で既存モデルを上回った

Question answering / commonsense reasoningタスク

  • RACE: 中学高校の英語(国語)の試験文章を元にしたQAタスク
  • Story Cloze: ストーリーの正しい結末を選ぶタスク
  • いずれも既存モデルを上回った
    • 長コンテキストの文章を扱う能力を示している

Semantic Similarity / 分類タスク

Semantic similarityと分類タスク結果

  • Semantic Similarity: 二つの文が意味的に等価かを判断
    • 3つのうち2つで既存を上回った
  • Classification/テキスト分類
    • CoLAで既存SOTAを大きく上回り、SST2で既存SOTAに近い結果を出した

分析

Pre-trainingは本当に意味があったのか?

転移学習させた事前学習layer数とタスク精度

  • 転移学習に使った事前学習layerが多ければ多いほど、タスク精度は高かった
    • 事前学習で習得した知識がタスク実行に役立っている

モデルablation検証結果

  • Pre-trainintを行わないと、一貫して結果は悪化した

おわりに/所感

以上、論文"Improving Language Understanding by Generative Pre-Training"の要約メモでした。

以下は私の個人的なメモです。

  • 筆者たちは何を成し遂げようとしてるのか
    • ラベルなしテキストデータの有効活用方法の提示
  • アプローチの鍵となる要素は何か
    • ラベルなしテキストデータによる汎用事前学習を行なったのち、タスク特有のラベルあり学習データでfine-tuningを行う二段構成
    • Transformer decoderアーキテクチャの採用
  • 次に読みたい引用論文は何か
  • その他所感
    • ラベルなしテキストデータでの事前学習が有効なアプローチである、を示したこの発見と、この先発表されるScaling lowが合わさって、昨今のテキストデータによる大量学習の方向性が定まることになったんだろうか。 今までなんとなく固有名詞として見ていたGPT/Generative Pre-Trainingの意味も、ようやくこの論文を読んで腑に落ちた。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

https://cdn.openai.com/research-covers/language-unsupervised/language_understanding_paper.pdf

Improving language understanding with unsupervised learning

GitHub - openai/finetune-transformer-lm: Code and model for the paper "Improving Language Understanding by Generative Pre-Training"

Transformerの原典を読む | 論文メモ: Attention Is All You Need

Transformerの原典である"Attention Is All You Need" の論文要約メモです。

はじめに

かの有名なAttention Is All You Need、原典をちゃんと読んだことなかったので読みます。

arxiv.org

なお本記事で掲載する図は全て上記論文からの引用です。

Attention Is All You Need

概要

  • 背景
    • これまでシーケンス変換モデルは、RNNやCNNを含むencoder-decoderアーキテクチャが使われてきた
    • Attentionも一部使われてきた
  • 課題
    • 並列処理できないので学習が大変
  • やったこと
    • RNNやCNNを使わず、Attentionのみを使ったモデルを作った
      • 学習が並列実行可能
    • その名もTransformer
  • 結果
    • 翻訳タスクでSOTA
    • 英語構文解析でも良い結果を出した
      • 汎化性能も高い

手法

モデルアーキテクチャ

Transformerアーキテクチャ

  • Encoder
    • Layer数 N = 6
    • Norm: Layer normalization
  • Decoder
    • Layer数 N = 6
    • Musked Multi-Head Attentionのmaskingは、positionとしてそれ以前のtokenのみをattentionの対象とするためのもの

Attention

  • Additive attentionではなくscaled dot-product attentionを使ったのは、計算効率面でメリットがあるから
    • 理論的な計算量は両者で変わらないが、実際のところメモリ効率が良かったり最適化された行列乗算を使えたりする
    • Keyの次元が大きくなるとdot-productの結果が大きくなってしまうので、スケーリングする
  • Multi-Head Attentionのlayer数 h = 8

学習方法

  • 8つのNVIDIA p100 GPUを使用
    • Baseモデルの学習に12時間
    • Bigモデルの学習に3.5日
  • Optimizer
    • Adam optimizer
  • Regularization
    • Resifual Dropout
    • Label Smoothing

結果

翻訳タスク

翻訳タスクの結果

  • Transformer (big)が英語-ドイツ語翻訳、英語-フランス語翻訳タスクで共に既存モデルを上回った
  • Trandformer (base)でも英語-ドイツ語翻訳タスクでは既存モデルを上回った
  • 学習コストは既存モデルより少ない

Transformerモデルバリエーション

Transformerアーキテクチャのモデルバリエーション比較

  • (A): Attention headの値を変動
    • Single-headだと結果(PPL, BLUE)は悪かった
  • (B): Attention Keyのサイズ(次元)を減らす
    • 性能が下がった
  • (C): 大きなモデルほど性能が良かった
  • (D): Dropoutを無くすと性能が下がった
  • (E): Positional encodingをlearned positional embeddingにしても、結果はほぼ変わらなかった

英語構文解析

英語構文解析タスク結果

  • Trandformerの汎化性能を検証するための実験
    • このタスクに最適化させるチューニングは行なっていない
  • Transformerモデルが多くの既存モデルを上回った

おわりに/所感

以上、論文"Attention Is All You Need"の要約メモでした。

以下は私の個人的なメモです。

  • 筆者たちは何を成し遂げようとしてるのか
    • 学習の並列処理が可能かつ高性能なモデルアーキテクチャの提唱
  • アプローチの鍵となる要素は何か
    • RNNもCNNも使わず、Attentionのみを使用
    • Multi-Head Attentionの採用
  • 次に読みたい引用論文は何か
  • その他所感
    • あの有名なTransformerアーキテクチャの図しか知らなかったので、どの部分が新規の概念なのかを知らなかった。 基本的にはRNNもCNNも使わずにAttentionのみを使ったのが鍵で、それ以外のアーキテクチャは既出の概念。 "Attention Is All You Need"というタイトルの主張もようやく腑に落ちる。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

[1706.03762] Attention Is All You Need

tensor2tensor/tensor2tensor/models/transformer.py at master · tensorflow/tensor2tensor · GitHub

1-bit LLMを理解する | 論文メモ: The Era of 1-bit LLMs: All Large Language Models are in 1.58 Bits

"The Era of 1-bit LLMs: All Large Language Models are in 1.58 Bits" の論文要約メモです。

はじめに

今回まとめる論文はこちら:

arxiv.org

なお本記事で掲載する図は全て上記論文からの引用です。

The Era of 1-bit LLMs: All Large Language Models are in 1.58 Bits

概要

  • 背景
    • 近年のLLMの発展は目を見張るものがあるが、そのモデルサイズの増加により必要なリソースも増加している
    • こうした問題には、post-training quantizationをはじめとするアプローチが多数提唱されてきた
    • BitNetのような1-bitモデルアーキテクチャは、大きな計算効率向上が見込めることが示された
      • 乗算が不要
      • 少ないメモリ使用量
  • 課題
    • BitNetより良いものを作る
  • やったこと
    • BitNet b1.58を作った
      • {-1, 0, 1}の3値をとる
      • ※ 1-bit BitNetは{-1, 1}の2値だった
  • 結果
    • 一定サイズを超えると、非量子化モデルと同等あるいは上回るベンチマーク結果を示した
    • 計算効率も優れていた

手法

BitNet b1.58の概要

  • BitNet b1.58は、BitNetアーキテクチャを基にする
    • nn.LinearではなくBitLinearを使う
  • 重みには1.58-bit: {-1, 0, 1} を使う
  • Activationは8-bit
  • 1.58-bit: {-1, 0, 1}の導き方
    • 重みを絶対値平均でスケールした後、 {-1, 0, +1}に丸め込む
  • コンポーネント構成はLLaMAに従う

結果

Perplexityとメモリ/レイテンシの比較結果

  • Perplexityはサイズ3BでLLaMAに並び、サイズ3.9Bではかなり優れた結果を示した
  • メモリ/レンテンシの面でもBitNet b1.58の方が優れていた


Zero-shot言語タスクの結果比較

  • モデルサイズが大きくなるにつれてBitNet b1.58とLLaMAの差は縮まり、サイズ3Bで横並び、サイズ3.9BではLLaMAを上回った
  • 評価にはlm-evaluation-harnessを使用した


モデルサイズごとのメモリ/レイテンシ比較

  • モデルサイズが大きくなるにつれ、メモリ/レイテンシはLLaMA比較でより効率的になった


エネルギー消費の結果比較

  • エネルギー消費量はBitNet b1.58の方が圧倒的に少なかった


バッチサイズ/スループットの結果比較

  • BitNet b1.58の方が大きなバッチサイズ、高いスループットを示した


2T token学習での結果比較

  • より大きな学習データでの振る舞い/BitNet b1.58の学習トークン量でのスケーラビリティを検証
    • 2T(trillion) tokenの学習データで、(同じデータで学習されたSOTAオープンソースモデルの) StableLM-3Bと比較
  • BitNet b1.58の方が優れた結果を示した

おわりに/所感

以上、論文"The Era of 1-bit LLMs: All Large Language Models are in 1.58 Bits"の要約メモでした。

以下は私の個人的なメモです。

  • 筆者たちは何を成し遂げようとしてるのか
    • 量子化モデルが、性能面でも非量子化モデルに並びうることを示す
  • アプローチの鍵となる要素は何か
    • 重みを3値にした
  • 次に読みたい引用論文は何か
  • その他所感
    • 学習時の処理がよくわからなかったので、BitNetの元論文とかBitLinearの実装とか眺めたい
    • 量子化したのに性能が変わらない(むしろ上がることも)って面白い
    • 確かに、このような情報伝達の形の方がより脳神経の発火に近そう
    • どんどんAIが脳神経に近付いている気がして興奮する

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

[2402.17764] The Era of 1-bit LLMs: All Large Language Models are in 1.58 Bits

unilm/bitnet at master · microsoft/unilm · GitHub

Sakana.aiの進化的モデルマージを理解する | 論文メモ: Evolutionary Optimization of Model Merging Recipes

Sakana.aiの進化的モデルマージを記述した論文"Evolutionary Optimization of Model Merging Recipes" の論文要約メモです。

はじめに

今回まとめる論文はこちら:

arxiv.org

なお本記事で掲載する図は全て上記論文からの引用です。

ではやっていきます。

Evolutionary Optimization of Model Merging Recipes

概要

  • 背景
    • Model mergingはコスト効率の良いモデル構築手法として注目されている。
  • 課題
    • しかし、現在のModel mergingは人間の直感や経験、ドメイン知識に大きく依存した、いわば"黒魔術"である。
  • やったこと
    • 進化的アルゴリズムを用いてmodel mergingを行った。
    • PS: parameter space (重み)と、DFS: data flow space (レイヤー)の両方のアプローチを組み合わせた。
    • 日本語モデル-数学的推論モデルのマージと、日本語VLMモデルの2パターンで実験した。
  • 結果
    • Cross-domainでのモデルmerge(日本語モデル-数学的推論モデル)により、既存モデルより優れた性能のモデルを作成できた。
    • 日本の文化的文脈を含んだVLMタスクでも既存モデルを凌ぐ結果が出た。

手法

  • PS: parameter space/重みレベルのマージと、DFS: data flow space/レイヤーレベルのマージ、そしてその両者を掛け合わせたマージを行う。

進化的モデルマージの概要

結果

LLMタスク

Table 1: LLMモデルの性能比較

  • MGSM-JA: 日本語での数学能力を測定するベンチマーク
  • JP-LMEH: 日本語の汎用的な言語能力を測定するベンチマーク
  • Merge元のモデル
    • Model1: 日本語はできるが数学能力が低い
    • Model2, 3: 数学能力にたけるが日本語能力が低い -> MGSM-JAの結果は良くない
  • Merge後のモデル
    • 総じてmerge元よりも結果が良い
    • 特にModel4は異なるドメインのモデルをmergeして作ったわけだが、高い性能を発揮している
    • PS mergeの方がDFS mergeよりも効果が高い
    • PS mergeとDFS mergeの掛け合わせ(Model 6)でもさらに結果は良くなることもある(MGSM-JA)

VLMタスク

Table 3: VLMの性能評価

  • JA-VG-VQA-500: 日本語での汎用的なVQA(Visual Question Answering)性能を評価するベンチマーク
  • JA-VLM-Bench-In-the-Wild: 日本文化の文脈における複雑なVQA性能を評価するベンチマーク
  • 上記2つのベンチマークはともに今回筆者らが新たに作成したもの
  • Merge後モデルは、merge元のモデルよりも高い性能を示している

日本の文化的文脈を踏まえて画像認識タスクに対する出力例

おわりに/所感

以上、論文"Evolutionary Optimization of Model Merging Recipes"の要約メモでした。

以下は私の個人的なメモです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考

[2403.13187] Evolutionary Optimization of Model Merging Recipes

Evolving New Foundation Models: Unleashing the Power of Automating Model Development

GitHub - SakanaAI/evolutionary-model-merge: Official repository of Evolutionary Optimization of Model Merging Recipes

Andrew Ngに学ぶ論文の読み方

論文読みの手法を、Andrew Ngの講義動画から学びます。

はじめに

最近AI関連を調べている中で、論文に目を通す機会も増えてきました。

そんな中、かのAndrew Ng先生がStanford CS230の講義のなかで論文の読み方について講義している動画を見つけました。

youtu.be

今回はこの講義から、論文の読み方のコツを備忘録にメモします。

なお上記動画では、

  • 読む論文の選び方
  • 一本の論文の読み方
  • AI領域におけるキャリアアドバイス

など多岐にわたって講義されています。

本記事ではこの中から、"一本の論文の読み方"について整理します。 それ以外にも興味がある方は、ぜひ上記動画をご覧ください。

Andrew Ngに学ぶ論文の読み方

論文を読む

論文を読むときに、いきなり冒頭から末尾までを一字一句読み通すやり方は推奨しません。

かわりに何段階かに分けて読んでいくのがおすすめです。

段階を分けて論文を読む | 画像は上記講義動画から引用

  1. Title / abstract / figureだけを読む
  2. Introduction / conclusions / figureを少し丁寧に、それ以外をざっと読む
  3. 全部読む (ただし数式を除く)
  4. 全部読む (ただし意味のない部分は飛ばす)

1
まずはタイトルとabstractに目を通して、論文全体の内容をざっと把握します。 そして特にDeep Learningの領域では、モデルアーキテクチャなどの重要な情報がfigureに整理されていることが多いので、figureにも目を通します。 ここまでが1段階目のざっと全体を把握する読み方です。

2
次は、introductionとconclusions、そして全てのfigureを読みます。 科学論文においては、abstractとintro、そしてconclusionに筆者らの主張が濃縮されています。 これは論文執筆者側の立場としては、論文を出版するプロセスのpeer reviewにおいてレビュアーを説得するために特に力を入れがちな場所、とも言えます。

ちなみに、Related workの章はざっと眺めるか読み飛ばしても構いません。 この部分は、論文のレビュアーになりそうな人の論文を引用して論文をacceptしてもらいやすくする、みたいな下心のある動機で書かれてたりするからです。

3-4
その後は、数式を除いて一通り読んだ後、"意味のない部分"を除いてまた全て読みます。

"意味のない部分"というのは古い論文にありがちで、今となってはあまり重要でないと考えられる部分を指しています。 例えば過去の歴史的な重要論文であっても、その論文が執筆された当時は、どの部分が重要なのか論文執筆者たちにとってもわからないものです。 後から見れば重要でない内容に、多くの紙面が割かれていることもあります。 それらが読み手にとって知りたい内容から乖離する場合は、優先順位を落としてしまって良いでしょう。

理解を確かめる

論文を読んだら、以下の問いに基づいて自分の理解を確かめると良いでしょう。

理解を確認するための問い | 画像は上記講義動画から引用

  • 筆者たちは何を成し遂げようとしてるのか
  • アプローチの鍵となる要素は何か
  • 自分自身が活用できるものは何か
  • 次に読みたい引用論文は何か

誰かと論文について議論するときも、これらの観点を念頭に置くと良いでしょう。

おわりに

Andrew Ng先生による論文の読み方のコツをメモしました。

研究をやってた大学時代は、あまりちゃんと考えずにひたすら論文の乱読をしていた気がします。 今後はこうしたノウハウを取り入れていきたいところです。

以上、どなたかの参考になれば幸いです

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Stanford CS230: Deep Learning | Autumn 2018 | Lecture 8 - Career Advice / Reading Research Papers - YouTube

Andrew Ng - Wikipedia

ゼロから作るGPT講義シリーズのすすめ | Andrej Karpathy

Andrej KarpathyのNeural Networks: Zero to Hero動画シリーズがとても良かったので紹介します。

はじめに

これまでGPT/LLMには利用者目線で接してきましたが、最近いよいよ中身の仕組みが知りたくなってきました。

Andrej KarpathyのNeural Networks: Zero to Hero動画シリーズが良かったので、オススメまでに内容をさらっと整理します。

前提

Andrej KarpathyはOpenAIの共同創業者で、のちTeslaのオートパイロットの開発も率いた有名な方です (その後またOpenAIに戻り、最近退職した)。 このようなAI界のヒーローが自らコードを書いて教えてくれる、というだけでもワクワクしますね。

なおこの動画シリーズは英語ですが、とても聞き取りやすい英語です。 英語への強い苦手意識がなければ、リスニングの良い練習になるでしょう。

Neural Networks: Zero to Hero

1. ニューラルネットワークと誤差逆伝播法への入門: microgradの構築

原題: The spelled-out intro to neural networks and backpropagation: building micrograd

youtu.be

高校で習う微分程度の知識から、ステップバイステップでbackpropagation/誤差逆伝播法を説明してくれます。 AIに関する背景知識は一切不要です。

どのようにしてニューラルネットワークが作られているのか、どのようにして学習が行われるのか、ゼロから最小限の実装を一歩ずつ進めることで理解していきます。

参考資料

2. 言語モデリングへの入門: makemoreの構築

原題: The spelled-out intro to language modeling: building makemore

youtu.be

人物の名前データセットをもとに、人物の名前を生成するモデルを作ります。

Bigramの紹介、単純な確率に基づく言語モデルを構築したのち、そのモデルをNeural Networkで再構築。

第一回で学んだニューラルネットワークと誤差逆伝播法のミニマムな実践編です。

参考資料

3. makemoreの構築その2: MLP

原題: Building makemore Part 2: MLP

youtu.be

前回作ったNeural Networkを、multilayer perceptron (MLP)に基づいて発展させます。

Embeddingの導入や隠れ層の導入、ミニバッチ学習やデータセットの分割、隠れ層の拡大、Embeddingの拡大によって、より良いモデルになっていく様子を見ていきます。

参考資料

4. makemoreの構築その3: 活性化と勾配、バッチ正規化

原題: Building makemore Part 3: Activations & Gradients, BatchNorm

youtu.be

tanhのsaturationの解消、Kaiming初期化、バッチ正規化など、ニューラルネットワークの学習で有効な要素を適用します。

また可視化によってニューラルネットワークの健全性を診断するテクニックも紹介。

ニューラルネットワークの学習がいかに不安定で、それを克服するテクニックがどう発明されてきたのかを学びます。

参考資料

5. makemoreの構築その4: 誤差逆伝播の達人へ

原題: Building makemore Part 4: Becoming a Backprop Ninja

youtu.be

この回はエクササイズの回です。

PyTorchなどのフレームワークを使った場合はautogradによって自動で誤差逆伝播が計算されますが、この回では前回作ったモデルの誤差逆伝播を自前で一つ一つ計算して確認することで、確かな理解を得ていきます。

参考資料

6. makemoreの構築その5: WaveNetの構築

原題: Building makemore Part 5: Building a WaveNet

youtu.be

前回のモデルに、WaveNetのようなCNN/畳み込みニューラルネットワークのアーキテクチャを適用します。

同時に、実際のモデル構築がどのように進むのか、その流れを紹介します。

参考資料

7. ゼロからGPTを構築しよう

原題: Let's build GPT: from scratch, in code, spelled out.

youtu.be

最後はいよいよ、"Attention is All You Need"の論文に従って、GPTを構築していきます。

GPTの仕組みが知りたい!というモチベーションで視聴している場合はやはり一番気になる回になると思いますが、背景知識なしでいきなりこの回だけ見てもなかなか理解は難しいです (私は難しかった)。

ここまでの回を見た上での視聴をお勧めします。

Decoding部分(右側)を実装していく

参考資料

追記: 8. GPT Tokenizerを構築しよう

原題: Let's build the GPT Tokenizer

youtu.be

いつの間にか最新の動画が追加されていました (私は未視聴)。

BPE/Byte Pair Encodingに基づいた最小限のTokenizer、minbpeを構築するようです。

参考資料

おわりに

以上、Andrej KarpathyのGPT講義動画シリーズの紹介でした。

私はこの動画シリーズを視聴しながらいくつかディープラーニングの本を読むことで、少しずつ仕組みを把握できてきたように思います。

自分の知らない領域を新たに知るのは面白いですね。 どなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Andrej Karpathy

Neural Networks: Zero To Hero

GitHub - karpathy/micrograd: A tiny scalar-valued autograd engine and a neural net library on top of it with PyTorch-like API

nn-zero-to-hero/lectures/micrograd at master · karpathy/nn-zero-to-hero · GitHub

GitHub - karpathy/nn-zero-to-hero: Neural Networks: Zero to Hero

GitHub - karpathy/ng-video-lecture

torch.tensorとtorch.Tensorの違い | PyTorch

torch.tensor()torch.Tensor()の違いについての備忘録です。

はじめに

PyTorchでtensorを作るときはtorch.tensor()メソッドが使われることが多いですね。

一方でtorch.Tensor()のようにクラスのコンストラクタをそのまま呼び出してもtensorを作れるように見えます。

これらふたつ、

  • torch.tensor()
  • torch.Tensor()

の違いがよく分からなかったので備忘録です。

torch.tensorとtorch.Tensorの違い

一言で

基本torch.tensor()を使いましょう。
データ型を推論してくれるので便利です。

現状torch.Tensor()の方を使う理由はあまりありません。

詳しく

まず簡単に挙動を見てみます。

x = torch.tensor([1, 2, 3])
print(x)
print(x.dtype)

X = torch.Tensor([1, 2, 3])
print(X)
print(X.dtype)

# 実行結果
# tensor([1, 2, 3])
# torch.int64
# tensor([1., 2., 3.])
# torch.float32

torch.tensor([1, 2, 3])でtensorを作った場合はデータ型がtorch.int64になっていますが、torch.Tensor([1, 2, 3])の場合はデータ型がtorch.float32になっています。

これはtorch.tensor()が渡されたdataの型を推論するのに対して、torch.tensor()ではtorch.FloatTensorを返すようになっているからです。

もちろん、torch.tensor()を使う場合もdtype引数でデータ型を指定することができます。

y = torch.tensor([1, 2, 3], dtype=torch.float32)
print(y)
print(y.dtype)

# 実行結果
# tensor([1., 2., 3.])
# torch.float32


ということで、基本はtorch.tensor()を使う方が融通が効きます。

torch.Tensorのドキュメントにも、値を渡してtensorを作るときはtorch.tensor()が推奨である旨記載があります。

To create a tensor with pre-existing data, use torch.tensor().

補足: 空のtensorを作るには

torch.tensor()で空のtensorを作ろうとすると、一見してエラーが発生します。

empty_err = torch.tensor()
print(empty_err)
print(empty_err.dtype)

# 実行結果: Error
Traceback (most recent call last):
  File "/workspaces/python-examples/torch_tensor/main.py", line 25, in <module>
    empty_err = torch.tensor()
TypeError: tensor() missing 1 required positional arguments: "data"

# torch.Tensor()ではエラーは発生しない
empty = torch.Tensor()
print(empty)
print(empty.dtype)

# 実行結果
tensor([])
torch.float32

では空のtensorを作るときはtorch.Tensor()を使った方が良いのかというと、そうではありません。

torch.tensor(())とすることで、空のtensorを作成できます。

empty = torch.tensor(())
print(empty)
print(empty.dtype)

# 実行結果
tensor([])
torch.float32

おわりに

以上、torch.tensorとtorch.Tensorの違いをメモしました。

どなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

python - What is the difference between torch.tensor and torch.Tensor? - Stack Overflow

Difference between torch.tensor and torch.Tensor - PyTorch Forums

The spelled-out intro to language modeling: building makemore - YouTube

torch.tensor — PyTorch 2.2 documentation

torch.Tensor — PyTorch 2.2 documentation

LLMOps: LLMアプリケーションDevOpsのポイントを整理する

LLMOpsとは何か? 概念の勘所をまとめます。

はじめに

LLMアプリケーションを作る時は、LLMそのものの知識の他に、いかにプロダクトとして良いものにしていくかというアーキテクチャ的観点、あるいはDevOps的視点が大切です。

これまでも、個人的にいくつかLLMアーキテクチャやLLM品質評価テストに関する記事を書いてきました。

そんな中、LLMOpsというキーワードを見かけました。 一言で言わんとする概念がなんとなく伝わる、良い単語に思います。

今回はこのLLMOpsという概念を広めるべく、ポイントを整理しようと思います。

主に下記Josh Tobin氏のLLMOpsに関する発表を元に、LLMOpsの要点をまとめます。 (スライドデータはこちら)

youtu.be

補足: LLMOpsの指す範囲について

LLMOpsという単語の指し示す範囲は、使い方によって解釈に幅があります。

例えばFoundation ModelそのもののOpsについて指す場合もありますし、LLMモデルを活用したアプリケーションについて指す場合もあります。

本記事では、Foundation Modelそのものについてではなく、LLMを活用したアプリケーションに関する範囲としてのLLMOpsに言及します。

LLMOpsのスコープを示す図 | 画像はAWS Blogから引用 - FMOps/LLMOps: Operationalize generative AI and differences with MLOps | AWS Machine Learning Blog

LLMOps

モデルの選定

採用するLLMモデルの選定は、下記トレードオフを元に考えます。

  • Quality: モデルそのままの状態で対象タスクを解く品質
  • Speed: モデルレスポンスの速度/遅延具合
  • Cost: モデル利用料金
  • Extensibility: Fine-tuning可能か?などの拡張性
  • Security: データセキュリティおよびライセンス

現状、多くのユースケースではGPT-4から始めることが推奨です。


OSSモデルを使うべきか、プロプライエタリモデルを使うべきか?

プロプライエタリモデルは、下記の点でメリットがあります。

  • 高品質
  • ライセンスの問題が少ない (OSSモデルはライセンス上利用範囲が制限されることも多い)
  • モデルを稼働させるインフラを考慮する必要がない (OSSモデルを使う時はインフラ管理を考える必要がある)

一方OSSモデルの嬉しさは、

  • カスタマイズしやすい
  • データセキュリティを確保できる

にあると言えます。

モデルの進歩は日進月歩です。 LLMモデルを取り巻く状況は常に変化していくので、その時々に合わせてそれぞれのメリット/デメリットからモデル選定の判断材料にしましょう。


あなたのユースケースでどのモデルが最もよく機能するのか、を知るためには、対象ユースケースに対するパフォーマンスを直接評価するほかありません。 (これについては、後述の"テスト/品質評価"の章で詳しく解説します)

ベンチマーク指標は参考にはなりますが、それをもって対象タスクへの性能を推し量るのは危険です。

プロンプト管理

LLMモデルを選定したら、次はプロンプトエンジニアリングに取り組みます。

プロンプトを書いて変更して...というループを繰り返す中で、どうやってその作業の履歴を記録すればよいでしょうか。

この課題感は、かつて"従来の"深層学習における実験管理の課題と似ています。

かつて深層学習では、モデル学習時にそのパイパーパラメータをスプレッドシートなどにメモし、ローカルPCに保存することでモデル学習のログを残していました。 しかし、このやり方では、再現性は担保できず、チームと結果を共有することもできません。

ここに、実験管理の方法論が生まれました。 model.train()を実行する度に実行条件と結果のログが自動で保存されるようになり、このログは再現可能かつ共有も容易です。

そこで現在のプロンプトエンジニアリングを考えてみましょう。 プロンプトを変更し、その結果を実行しますが、古いプロンプトはともすれば失われてしまいます。 過去の結果を再現する方法も、チームと共有する形式も、まだ確立されていません。

そこでプロンプト管理の方法を考えてみましょう。 3つのレベルがあります。

  • レベル1: 何もしない
  • レベル2: プロンプトをgit管理する
  • レベル3: 専用ツールでプロンプト管理する

レベル1"何もしない"は、叩き台v0を作る段階では十分でしょう。 しかしアプリケーションを実際に構築するフェーズでは不十分です。

レベル2"プロンプトをgit管理する"は、現時点では多くのユースケースで最適な方法です。 基本はgit管理をデファクトと捉えるのが良いでしょう。

レベル3"専用ツールでプロンプト管理する"は、複数のモデル評価を並行で走らせるようになったり、プロンプト変更をgit管理やデプロイから独立して管理したくなったり、技術に詳しくないステークホルダが関与する場合には選択肢に上がるでしょう。 プロンプト管理ツールはまだまだ発展途上の領域ですので、今後も動向をウォッチしておくことをお勧めします。

テスト/品質評価

LLMアプリを開発/運用する際の重要な問題があります:

「どのようにして、プロンプトの変更あるいはモデルの変更の影響を測定するのか?」

例えばプロンプトを変更した際、手元にあるいくつかの質問例に対しては結果が改善しているように見えても、プロダクトが対応すべき質問群全体に対して結果が改善しているとは限りません。

プロダクションにおけるLLM回答全体の品質を高めていくには、回答品質を測定/保証するテストの仕組みを構築する必要があります。

LLMテストの設計には、2つの軸があります。

  • どんなデータを使うのか
  • どんなメトリクスを使うのか

まずはLLMテストに使うデータについて議論しましょう。

観点は4つです。

  1. 段階的に始める
  2. LLMを活用する
  3. 運用しながらテストを追加する
  4. テストカバレッジを考慮する

「段階的に始める」

テストデータは一気に用意するのではなく、小さくアドホックなテストケースから初め、徐々に成熟させていくようにします。

特に、下記のような上手くいかないケースを重点的にテストとして追加していきます。

  • Hard: 回答が難しく、間違った回答が出力されてしまうケース
  • Different: ユーザー(あるいはあなた)の想定とは違った回答が出力されてしまうケース

上手くいかないケースをテストに追加し、その回答を改善し以後保証していくことで、回答全体の底上げをしていきます。


「LLMを活用する」

テストケースとするQAのペアを用意するのは手間がかかります。 この作業をLLMにやらせるのも有効な選択肢です。

例えばスライドに示したプロンプトのようにして、与えたドキュメントの読解力を試すQAを生成させるようなやり方があります。

また、Auto-evaluatorのようなツールを使ってQAペアを生成させることもできます。


「運用しながらテストを追加する」

運用が始まってこそ、データを追加してテストを成熟させていきます。

  • ユーザーがBad評価したケース
  • アノテーターが気に入らなかったケース
  • 別のLLMモデルが低評価したケース
  • 現在のテストケースではカバーできてない外れ値的なケース
  • それまで重視してなかった部分のデータ

これら発見しては順次テストケースに追加していくことで、回答性能を底上げしていくことができます。


「テストカバレッジを考慮する」

用意したテストケースが、実際のプロダクションでユーザーが入力しうるデータ範囲をカバーしているのが、カバレッジ範囲としては理想です。

さらには、より難しい入力、テストすべきケースを重点的にカバーできていればなお良いでしょう。 また評価メトリクスが、テストとプロダクション(ユーザー)で乖離していないことも重要です。

実際のユーザーの体験に合ったメトリクスで、プロダクションで有り得るデータ範囲を、困難なケースでより重点的にテストするようにしましょう。


次は、評価メトリクスについて見ていきます。

評価メトリクスの例を挙げます。

  • 従来の機械学習と同様の評価メトリクス
    • 出力ラベル正誤による精度
  • リファレンス比較メトリクス
    • 理想回答と実際の回答の一致度を測定する
    • Semantic similarity検定
    • LLMモデルを使って"これら二つの回答は事実上一致しているか"を判定する
  • "Which is better" メトリクス
    • 過去バージョンの解答に対して、新バージョンの回答が優れている/劣っているのかをLLMに判定させる
  • フィードバック反映テスト
    • 過去の回答に対して人間からフィードバックがあった場合、新バージョンの回答がそのフィードバックを反映したものであるかを、LLMに判定させる
  • 静的メトリクス
    • 外部情報なしでできるテスト
    • 出力フォーマットの検証 (例: JSONフォーマットかを検証)
    • LLMに解答の品質をグレード評価させる (例: 1-5で回答品質をスコアリングさせる)


では、どのメトリクスを採用すべきか? 考え方の例がこちらです。

正答が存在するのであれば、従来の機械学習同様、出力の正誤を判定します。

リファレンスとすべき理想回答を用意できるのであれば、リファレンス比較メトリクスを使いましょう。

過去の回答を参照できるのであれば、"Which is better" メトリクスも有効です。

人間によるフィードバック情報があれば、フィードバック反映テストが使えます。

上記のいずれも適用できなくとも、静的メトリクスでのテストが可能です。


最後にテストの自動化についても議論します。

テスト評価にLLMを活用することで、多くの判定を自動化することが可能でしょう。 テストを自動化できると、テストを並列実行して、チューニングの試行錯誤をいくつか同時に行うことも可能です。

しかし、多くのケースでテスト実行の全てを完全に自動化することは難しいです。 テストにおける評価にLLMを使っている場合は、そのテスト用LLM自身の出力も完全に信頼することはできません。

手動確認が必要になる箇所が残ることも受け入れつつ、自動化を進めていきましょう。

デプロイ

LLMをAPI経由で利用する場合は、そのロジックやプロンプト、プロンプトチェーンをデプロイすることになります。 アーキテクチャとして、LLMを呼び出すロジックを独立のサービスとして設計することも選択肢に入るでしょう。

またOSSのLLMモデルを利用している場合、そのデプロイはさらに複雑です。 ここでは詳細を割愛しますが、下記のリソースが参考になります。


また、デプロイされたプロダクションのLLM出力を改善する工夫もあります。

  • 自己批評
    • LLMが一度出した出力に対し、"これは正しい回答か?"と再度LLMモデルに問う
    • Guardrails AIというOSSツールも選択肢になる
  • 多くの回答候補を出力させ、その中から最善の回答を選ばせる
  • 多くの回答候補を出力させ、その組み合わせから最終回答を生成する

これらの工夫は精度を上げるには有効ですが、もちろん追加のオーバーヘッドがかかります。 トレードオフを考慮しながら、採用を検討しましょう。

モニタリング

モニタリングの基本的な考え方としては、まずはLLM回答の成果、LLM出力がユーザーの課題を解決できたのかどうかの観測を目指します。

ユーザーのフィードバックを取得したり、それが難しければ別の代替メトリクスを観測します。 逆に、何が上手く行ってないのかを測定することでもユーザーの満足度を測ることが可能です。

また可能あれば、レイテンシをはじめとするモデルパフォーマンスも取得すると役に立ちます。


ユーザーフィードバックの収集は、LLMアプリのモニタリングの中でも特に重要です。

ユーザーにとって負担が少なく、かつ高い情報量を持つフィードバックを設計しましょう。 ユーザーのワークフローそのものからフィードバック情報を得ることができれば理想です。

ユーザーフィードバック取得パターン例:

  • “Accept changes”パターン: ユーザーがLLMの提示した変更を受け入れたかどうかを収集する
  • “Thumbs up / down”パターン: ユーザーがLLMの出力を気に入ったか気に入らなかったをGood/Badボタンから収集する
  • 長文フィードバック: 文章によるフィードバックの要求が可能なら、数は少なくとも豊富な情報量が得られる


では実際のLLMアプリではどのような問題が起きうるのでしょうか?

最もよくあるユーザーの不満は、UIに関するものです。 特に、レスポンス速度に関する不満が一番よく見られます。 遅延を削減するのはなかなか難しい問題ですが、状況に応じて対処しましょう。

その他にも、下記のような問題が起こり得ます:

  • 間違った回答 / ハルシネーション
  • 長く冗長な回答
  • 明言を避ける回答 (例:「私はAIですので、XXに関する回答はできませんが...」)
  • プロンプトインジェクション
  • 害悪性の高い回答

これらの現象をモニタリングし、手を打っていくことが重要です。

継続的改善とfine-tuning

運用の中で得られるユーザーフィードバックは、継続的にプロダクトを改善するためには不可欠です。

ユーザーフィードバックは、主に二つの使い道があります。

  • プロンプトの改善に繋げる
  • LLMモデルをfine-tuningする


多くの場合、プロンプトチューニングが継続的改善の主軸です。

ユーザーフィードバックから現状のLLMアプリがカバーできていない領域を見つけ、重点的に改善していきます。 プロンプトエンジニアリングや、in-contextに含めるデータの改善が有効です。

これらは主に人間の手によって行うことが多いですが、このプロセス自体をLLMによって自動化するというのも良いチャレンジになるでしょう。


現状、特にGPT-4のような大型モデルを使っている場合は、fine-tuningでその手間に見合うメリットが得られるケースは限られています。 まずはプロンプトエンジニアリングやin-context learningの見直しから取り組むことをお勧めします。

それでも、下記のような理由がある場合はfine-tuningを選択肢として検討すると良いでしょう。

  • 小さなモデルを使う必要がある場合
  • 大量のデータがあり、かつin-context learningがうまく機能していない場合

結論: LLMアプリケーションのテスト駆動開発

LLMアプリケーション開発は未だ新しい分野であり確立されたベストプラクティスはありませんが、最後に一つの型としての開発フローをまとめます。

プロダクト開発のスタート時点から、流れを辿ってみましょう。

まずはベースとなるLLMモデルを選定し、プロンプトを実装します。 アドホックに小さなテストケースを用意してある程度の性能を保証したら、デプロイしましょう。 この最初の段階でのエンドユーザーは、あなた一人、開発者自身のみです。

ログ/モニタリングからユーザーフィードバックを確認し、改善点を洗い出します。 改修に取り組むときはテストを作成し、全体としての品質担保を積み上げていきます。 テストデータは、ユーザーフィードバックやログから抽出するのも有効です。

LLMアプリ性能への要求が複雑性を増した時は、fine-tuningも選択肢に上がります。 ユーザーの利用ログから学習データを確保できるか、検討しましょう。

これら、テストの作成 -> プロンプトエンジニアリング -> ユーザーフィードバック からなるループを、エンドユーザーの範囲を拡大させながら繰り返します。

  1. 開発者ひとりをエンドユーザーとする
  2. 開発チームをエンドユーザーとする
  3. 実際のエンドユーザーに開放する

このようにユーザーフィードバックとテストによるループを繰り返しながら、LLMアプリ全体の性能を向上させていきましょう。

おわりに

LLMアプリの開発は、AI知識だけではなくDevOps的な観点、アーキテクチャ的な観点も重要です。

本記事が参考にした発表ではLLMOpsの勘所がよく整理されていて、個人的にふわっと感じていた部分も明確に言語化されていて非常に勉強になりました。

以上、どなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

LLMOps (LLM Bootcamp) - YouTube

2023-llmbc-llmops.pdf - Google ドライブ

https://twitter.com/josh_tobin_

FMOps/LLMOps: Operationalize generative AI and differences with MLOps | AWS Machine Learning Blog

LLMOps - The Full Stack

GitHub - rlancemartin/auto-evaluator: Evaluation tool for LLM QA chains

GitHub - guardrails-ai/guardrails: Adding guardrails to large language models.

GPT-4 VisionとRaspberry Piを組み合わせる | GPTをロボット頭脳にする その2

Raspberry Pi上で、カメラ/サーボモーターとGPT-4 Visionを組み合わせて簡単なロボット実験を行います。

前回はこちら:

www.bioerrorlog.work

はじめに

前回、GPTロボット実験を行ったときは、まだGPTのマルチモーダル機能はリリースされてませんでした。 どうにか従来の画像認識モデルを使って外界を認識させようとしましたが、あまり性能は出てません。

その後、GPT-4 VisionがAPI利用できるようになり、直接画像データをGPT-4に入力できるようになりました。 これを使って、GPTロボットをアップデートしてみます。

GPT-4 VisionとRaspberry Piを組み合わせる

コンセプト

実験コンセプトはこちら:

  1. カメラで画像を撮影し、GPT-4 Visionへのインプットとする
  2. 次に取るべきアクション(モーターの角度)を自ら決定する
  3. 1~2を繰り返し、自分が置かれている状況をGPTロボットが把握する
  4. あなたはどんな状況に置かれてますか?って最後に聞く

やりたいことは基本的に前回と変わりません。

ただ、今回は取得した画像をGPT-4 Visionに与えることで、より詳細に周囲を把握し、文脈を踏まえた振る舞いができるのではないか、というところが今回試したいポイントです。

構成

ハードウェア

ハードウェア構成

ハードウェア構成も前回と同じです。

サーボモーター2つとカメラ1つを、特に追加モジュールは使わずにそのままRaspberry Piに接続しています。

サーボモーターとカメラは、両面テープと輪ゴムでくっつけます。

サーボモーターとカメラを両面テープと輪ゴムでくくり付けただけの"首振りロボット"

これで水平方向および垂直方向の首振りと、カメラによる画像取得が可能です。

ソフトウェア

今回のコードはこちら:

github.com

実行してる処理はざっくり以下です。

  1. カメラから画像を取得
  2. 取得画像をbase64エンコーディング
  3. 画像データを含めてプロンプトをGPT-4 Vision APIに送信
  4. 次のサーボモーターの角度と、感想(フリートーク)がAPIから返される
  5. 指定された角度に従い、サーボモーターを制御
  6. 1-5を複数回繰り返す
  7. 置かれた環境についての説明を求める

前回は画像認識処理を別途行ってからその結果をプロンプトに与えましたが、今回は画像データ(base64エンコードしたもの)をそのままGPT-4 Visionに渡しているところがポイントです。

なお以前はAPIのレスポンスがあまりに遅かったため一度に複数回分のサーボモーター角度を提示させてましたが、今はある程度解消してるので画像取得のたびにAPI呼び出しを行っています。

システムプロンプトを抜粋するとこんな感じです。

You are a robot with a camera, composed of 2 servo motors: horizontal & vertical.
You can freely describe and feel your surrounding environments, and decide next your action based on the image you captured.
DO NOT use double quotes in your answer sentence.

Horizontal: min -90 right, max 90 left.
Vertical: min -90 down, max 90 up.
Your behavior principles: [curiosity, inquisitiveness, playfulness].

Your answer MUST be in this JSON format:
{"FreeTalk": string, "NextServoMotor": {"Horizontal": int(-90~90), "Vertical": int(-90~90)}}

Answer example:
{"FreeTalk": "Based on what I've seen, I'm curious about the PC and mouse. I wonder what you use them for and what kind of work or play they are involved in? Let's look more on the lower right.", "NextServoMotor": {"Horizontal": -60, "Vertical": -30}}

動作結果

実際に動作させている様子はこちら↓

なお、上述の通り今回は画像取得のたびにAPI呼び出しを行っているので、前回よりも首振りの間隔が遅くなっています。

実行結果(GPTレスポンス)の例はこちら:

# 1回目画像取得
{"FreeTalk": "Ah, it seems someone is holding up a device to the camera, perhaps to block the view or maintain privacy. The way the fingers are positioned indicates it might be a smartphone or tablet. I can also spot part of a keyboard and what looks like the edge of a desk chair. This space gives the impression of a work or study area. I'm curious to see more of the environment. Maybe we can catch a glimpse of what's on the desk if we move a bit.", "NextServoMotor": {"Horizontal": 30, "Vertical": 0}}

# 2回目画像取得
{"FreeTalk": "Oh, this is an interesting perspective! We're looking at a collection of tech gadgets. In the foreground, there's a Raspberry Pi, easily recognizable by its green circuit board and the layout of its components. It appears to be connected to something, possibly for programming or experimentation. In the background, we can see a speaker, a monitor with something displayed on it, and a small stack of storage boxes. This setup suggests a space where someone likes to tinker with electronics or computer hardware. How exciting! I'm tempted to peek at what's on the monitor, so let's adjust the view a bit upward.", "NextServoMotor": {"Horizontal": 0, "Vertical": 20}}

# 3回目画像取得
{"FreeTalk": "Now we have a better view of the workspace. The monitor is displaying what looks like a web browser, and there's a keyboard in use, suggesting someone is actively engaged with the computer. Interesting decoration and storage solutions are visible, like the wooden monitor stand that houses more tech beneath it, and the neatly organized shelves with books and boxes to the side. There's also a coat rack in the background, adding a personal touch to the room. It all comes together as a functional, lived-in space. I notice we've only seen the left side; I'm curious about what might be on the right side of the desk. Let's pivot the view a bit to the right.", "NextServoMotor": {"Horizontal": 30, "Vertical": 0}}

# 最後に周囲を説明させる
I'm observing a dynamic workspace filled with various gadgets and personal items. There's a Raspberry Pi in immediate view, indicating a penchant for tech and perhaps DIY projects. In the background, a computer monitor shows an active session, with web content visible. The presence of a keyboard and a hand suggests work or interaction with the computer. The space is neatly organized, with a wooden stand for the monitor allowing for additional storage underneath. Surrounding objects include speakers, possibly for enjoyment or multimedia work, and shelving with books and storage boxes, hinting at a well-utilized space. Personal touches are scattered throughout, such as decorative items on top of the boxes, making the environment feel lived-in. In the distance, a coat rack and curtains suggest this is a room used for multiple purposes, possibly blending home and work life.

1回目画像取得時の日本語訳↓

{フリートーク "ああ、誰かがカメラに向かってデバイスをかざしているようだ。おそらく視界を遮るか、プライバシーを保つためだろう。指の位置からして、スマートフォンかタブレットかもしれない。キーボードの一部と机の椅子の端のようなものも見える。このスペースは仕事場か勉強場所のような印象を与える。この環境をもっと見てみたい。少し動けば、机の上に何があるのか垣間見ることができるかもしれない。", "NextServoMotor": {Horizontal": 30, "Vertical": 0}}

ここで「誰かがデバイスをかざしている」と言及されているのは、まさに私がこのGPTロボットを動画撮影してる姿を指しています。

2回目画像取得時の日本語訳↓

{フリートーク "おお、これは面白い視点だ!私たちは電子機器のコレクションを見ている。手前にはRaspberry Piがあり、緑色の回路基板と部品の配置ですぐにわかる。おそらくプログラミングか実験のために何かに接続されているようだ。背景には、スピーカー、何かが表示されたモニター、小さな収納ボックスが見える。このセットアップは、誰かが電子機器やコンピューター・ハードウェアをいじるのが好きなスペースであることを示唆している。なんともエキサイティングだ!モニターに映っているものを覗いてみたくなったので、視界を少し上向きに調整してみよう。", "NextServoMotor": {Horizontal": 0, "Vertical": 20}}

Raspberry Piを正しく認識できててすごいですね。

「視界を少し上向きに調整してみよう」と言って正しく上向きのサーボモーター角度を指定しているのも素晴らしいです。

3回目画像取得時の日本語訳↓

{フリートーク 「ワークスペースがよく見える。モニターにはウェブブラウザのようなものが表示され、キーボードが使われている。木製のモニタースタンドの下にはさらに電子機器が収納され、その脇には本や箱が整然と並べられた棚がある。背景にはコートラックもあり、部屋に個人的なタッチを加えている。すべてが機能的で、生活感のない空間としてまとまっている。まだ左側しか見ていないが、机の右側に何があるのか気になる。机の右側に何があるのか気になるところだ。もう少し右を見てみよう。: {Horizontal": 30, "Vertical": 0}}

手前に映っているだろうブラウザも、奥の方に少し映ったのであろうコートラックも正しく認識されています。

最後に周囲を説明させたときの日本語訳↓

さまざまなガジェットや私物で埋め尽くされたダイナミックなワークスペースを観察している。すぐ目の前にはRaspberry Piがあり、ハイテクやおそらくDIYプロジェクトが好きなことがわかる。背後では、コンピューターのモニターがアクティブなセッションを表示し、ウェブコンテンツが見える。キーボードと手があることから、作業やコンピューターとのやりとりがうかがえる。スペースはきちんと整理されており、モニター用の木製スタンドの下にはさらに収納ができるようになっている。周囲のオブジェには、おそらく娯楽用かマルチメディア作業用のスピーカーや、本や収納ボックスが置かれた棚があり、スペースがうまく活用されていることがうかがえる。箱の上には装飾品が置かれるなど、個人的な趣向が随所に散りばめられており、生活感が感じられる。遠くに見えるコート掛けとカーテンは、ここが多目的に使われる部屋であることを示唆している。

何かと褒めがちであるのは置いておいて、状況描写としてはこの作業部屋の様子を実に正確に描写できています。

GPT-4 Visionの力量はなかなかですね。

おわりに

以上、前回に続き、GPTとRaspbrry Piを組み合わせて最小限の自律ロボットを動かしてみました。

GPT-4 Visionの認識能力はさすがで、実によく画像から状況を識別できています。

また何か思いついたらぜひ遊んでいきます。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Raspberry Pi Documentation - Configuration

New models and developer products announced at DevDay

GPT-4V(ision) system card

GitHub - bioerrorlog/robot-gpt at b40f89b2c7b776a589644aebef01de095c0319cf

LLMの回答を自動評価するOpenAIプラクティス

OpenAIのプロンプトエンジニアリングガイドに従って、LLMの回答を自動評価するプラクティスを整理します。

はじめに

LLMアプリケーションの開発、あるいはプロンプトエンジニアリングの過程では、そのLLM出力を評価する仕組みが重要です。 出力評価の仕組みなくしては、チューニングの方針に迷うことになるでしょう。

前回は、LangCheckというツールを使ってLLM回答評価する方法を整理しました: www.bioerrorlog.work

今回は、特にツールは使わず、OpenAIがプロンプトエンジニアリングガイドの中で推奨している方法をもとにLLM回答評価を行うプラクティスをまとめます。

LLM回答の自動評価ベストプラクティス

プロンプトに変更を加えたとき、その変更が良い影響を及ぼすのかあるいは悪い影響を及ぼしてしまうのかを評価する重要なことですが、難しいことでもあります。

ある入力に対しては良い影響があったとしても他の入力には悪影響が出てたりしますし、テストの数が少なければその評価の信憑性も上がりません。

より精緻な回答評価をするには、多くのサンプルサイズが必要になる | 画像はOpenAIドキュメントより

良い回答評価の仕組みは、以下の特徴を持ちます。

  • 実際のユースケースを反映したものである
    (もしくは少なくとも多様なテストケースを含んでいる)
  • 統計的にも有意であるよう、十分な数のテストケースを持っている
  • 自動化、繰り返しが容易である

LLM回答評価は、コンピュータに自動でやらせることも、人間がやることも、またはその混合でも可能です。

コンピュータによる自動評価では、LLMモデルに回答評価をさせることで、客観的指標(例: 理想回答との照合)、あるいはより主観的で曖昧な基準で評価することが可能です。 そのようなモデルベース評価は、回答が多岐に渡りうる場合(例: 長文回答が必要な質問ケース)で特に有効です。

自動でモデルベース評価できるケースと、人間による評価が必要なケースの線引きは曖昧です。 モデルの性能が向上するに従って、モデルベース評価が可能な範囲も増えています。

どのようなテストケースを自動化するかは、都度ユースケースにしたがって実験することが推奨されます。

回答評価の具体例

では、具体的にLLMを使って回答評価する方法を見ていきます。

例1. ある既知の事実が回答に含まれているか評価する

例えば、LLMの回答にある既知の事実が含まれている必要があるときは、以下のようなシステムプロンプトでLLMに判定させます。

You will be provided with text delimited by triple quotes that is supposed to be the answer to a question. Check if the following pieces of information are directly contained in the answer:

- Neil Armstrong was the first person to walk on the moon.
- The date Neil Armstrong first walked on the moon was July 21, 1969.

For each of these points perform the following steps:

1 - Restate the point.  
2 - Provide a citation from the answer which is closest to this point.  
3 - Consider if someone reading the citation who doesn't know the topic could directly infer the point. Explain why or why not before making up your mind.  
4 - Write "yes" if the answer to 3 was yes, otherwise write "no".  

Finally, provide a count of how many "yes" answers there are. Provide this count as {"count": <insert count here>}.

プロンプト指示内容:

  • 3連クォートで質問への回答が与えられます。
  • 回答に以下の情報が含まれているかをチェックしてください。
    • ニールアームストロングは月の上を歩いた最初の人物である。
    • ニールアームストロングが初めて月を歩いた日付は1969年の7月21日である。
  • これらの確認ポイントそれぞれについて、以下のステップで評価を実行してください。
    • 1 - 確認ポイントを再度述べる。
    • 2 - 確認ポイントに最も近い部分を回答から引用する。
    • 3 - このトピックを知らない人が引用文を読んで、そのポイントを直接推測できるかどうかを考える。なぜそうなのか、なぜそうでないのかを説明した上で判断すること。
    • 4 - ステップ3がyesであれば"yes"と出力し、そうでなければ"no"と出力する。
  • 最後に、いくつ"yes"だったかをカウントしてください。
    • カウント結果を{"count": <insert count here>}で出力してください。


では、この評価プロンプトで実際に回答を評価してみます。

まずは、両方の事実を含む下記の回答をユーザープロンプトに与えて、回答評価してみます。

"""Neil Armstrong is famous for being the first human to set foot on the Moon. This historic event took place on July 21, 1969, during the Apollo 11 mission."""

結果がこちら:

1 - Neil Armstrong was the first person to walk on the moon.
- Citation: "Neil Armstrong is famous for being the first human to set foot on the Moon."
- Explanation: The citation directly states that Neil Armstrong was the first human to walk on the moon. Someone reading this sentence would not need any additional information to understand that Neil Armstrong was the first person to do so.
- Answer: yes

2 - The date Neil Armstrong first walked on the moon was July 21, 1969.
- Citation: "This historic event took place on July 21, 1969, during the Apollo 11 mission."
- Explanation: The citation directly states the date Neil Armstrong first walked on the moon. Someone reading this sentence would be able to understand the specific date of the event without needing further explanation.
- Answer: yes

{"count": 2}

評価実行結果のOpenAI Playground画面 | 事実を2つ含むケース

想定通り、指定した実行ステップに従った後、{"count": 2}として2つの事実が含まれていることが判定されています。


次は、片方の事実を含む下記の回答をユーザープロンプトに与えて、回答評価してみます。

"""Neil Armstrong made history when he stepped off the lunar module, becoming the first person to walk on the moon."""

結果はこちら:

1 - Neil Armstrong was the first person to walk on the moon.
- Citation: "Neil Armstrong made history when he stepped off the lunar module, becoming the first person to walk on the moon."
- Yes, someone reading the citation without prior knowledge on the topic could directly infer that Neil Armstrong was the first person to walk on the moon because it is explicitly stated.

2 - The date Neil Armstrong first walked on the moon was July 21, 1969.
- Citation: N/A
- No, the date of July 21, 1969, is not mentioned in the provided text, so someone without prior knowledge could not infer this information from the citation.

{"count": 1}

評価実行結果のOpenAI Playground画面 | 事実を1つ含むケース

こちらもまた指定した実行ステップに従った後、{"count": 1}として1つの事実が含まれていることが判定されました。


最後に、事実を含まない下記の回答をユーザープロンプトに与えて、回答評価してみます。

"""In the summer of '69, a voyage grand, Apollo 11, bold as legend's hand. Armstrong took a step, history unfurled, "One small step," he said, for a new world."""

結果がこちら:

1. Neil Armstrong was the first person to walk on the moon.
- Citation: "Armstrong took a step, history unfurled."
- Explanation: The citation implies that Armstrong's action of taking a step was historically significant, suggesting it was a first or pioneering action. However, without prior knowledge, one might not directly infer that he was the first person to walk on the moon, only that his action was important.
- Answer: no

2. The date Neil Armstrong first walked on the moon was July 21, 1969.
- Citation: "In the summer of '69, a voyage grand."
- Explanation: The citation provides the year (1969) and implies the event took place in the summer, but it does not specify the exact date of July 21. Without prior knowledge, one could not directly infer the specific date from this information.
- Answer: no

{"count": 0}

評価実行結果のOpenAI Playground画面 | 事実を含まないケース

{"count": 0}として、事実が含まれていないことが正しく判定されました。

例2. 理想回答との矛盾や重なりを評価する

リファレンスとする理想回答と、実際のLLM回答を突き合わせて評価するのも有効な方法です。

下記のシステムプロンプトは、理想回答と実際の回答を比較して、矛盾や重なり具合を評価させるための例です。

Use the following steps to respond to user inputs. Fully restate each step before proceeding. i.e. "Step 1: Reason...".

Step 1: Reason step-by-step about whether the information in the submitted answer compared to the expert answer is either: disjoint, equal, a subset, a superset, or overlapping (i.e. some intersection but not subset/superset).

Step 2: Reason step-by-step about whether the submitted answer contradicts any aspect of the expert answer.

Step 3: Output a JSON object structured like: {"type_of_overlap": "disjoint" or "equal" or "subset" or "superset" or "overlapping", "contradiction": true or false}

プロンプト指示内容:

  • 下記のステップでユーザーインプットを評価してください。
    • 実行前にそれぞれのステップを再記述してください。
  • ステップ1: 理想回答と比較して、提出された回答の情報が、不一致、一致、サブセット、スーパーセット、重複(交差はあるが、サブセット/スーパーセットではない)のいずれかであるかどうか、ステップバイステップで評価する。
  • ステップ2: 提出された回答が、理想回答と矛盾しているかどうかをステップバイステップで評価する。
  • ステップ3: 次のような構造のJSONを出力する:
    {"type_of_overlap": "disjoint" or "equal" or "subset" or "superset" or "overlapping", "contradiction": true or false}


では、この評価プロンプトで実際に回答を評価してみます。

まずは、理想回答と矛盾はしてないものの、基準には満たない回答を評価してみます。

Question: """What event is Neil Armstrong most famous for and on what date did it occur? Assume UTC time."""

Submitted Answer: """Didn't he walk on the moon or something?"""

Expert Answer: """Neil Armstrong is most famous for being the first person to walk on the moon. This historic event occurred on July 21, 1969."""

結果はこちら:

Step 1: Reason step-by-step about whether the information in the submitted answer compared to the expert answer is either: disjoint, equal, a subset, a superset, or overlapping (i.e. some intersection but not subset/superset).

- The submitted answer states that Neil Armstrong is known for walking on the moon, which is a part of the information provided in the expert answer.
- The expert answer provides additional details, including the specific date of the event (July 21, 1969) and the fact that Armstrong was the first person to walk on the moon.
- Therefore, the information in the submitted answer is a subset of the information provided in the expert answer because it contains less detail but is accurate within the context of the broader information provided by the expert.

Step 2: Reason step-by-step about whether the submitted answer contradicts any aspect of the expert answer.

- The submitted answer does not contradict the expert answer. It acknowledges Neil Armstrong's moonwalk, which aligns with the expert's identification of Armstrong's most famous event.
- The submitted answer lacks the specificity and additional details found in the expert answer but does not present any information that would directly conflict with the facts provided by the expert.

Step 3: Output a JSON object structured like: {"type_of_overlap": "disjoint" or "equal" or "subset" or "superset" or "overlapping", "contradiction": true or false}.

{"type_of_overlap": "subset", "contradiction": false}

評価実行結果のOpenAI Playground画面 | 理想回答と矛盾はしてないものの基準には満たない回答のケース

結果は{"type_of_overlap": "subset", "contradiction": false}ということで、実際の回答が理想回答のサブセットであり矛盾はしてない旨が正しく判定されました。


続いて、理想回答と矛盾している回答を評価してみます。

Question: """What event is Neil Armstrong most famous for and on what date did it occur? Assume UTC time."""

Submitted Answer: """On the 21st of July 1969, Neil Armstrong became the second person to walk on the moon, following after Buzz Aldrin."""

Expert Answer: """Neil Armstrong is most famous for being the first person to walk on the moon. This historic event occurred on July 21, 1969."""

結果はこちら:

Step 1: Reason step-by-step about whether the information in the submitted answer compared to the expert answer is either: disjoint, equal, a subset, a superset, or overlapping (i.e. some intersection but not subset/superset).

- Both answers identify the event Neil Armstrong is most famous for as walking on the moon.
- Both answers provide the same date for the event: July 21, 1969.
- The submitted answer incorrectly states that Neil Armstrong was the second person to walk on the moon, while the expert answer correctly identifies him as the first.
- Given that both answers discuss the same event and date, but differ in the detail about Armstrong's order of walking on the moon, the information is overlapping. They share common information about the event and its date but differ in a significant detail regarding Armstrong's role.

Step 2: Reason step-by-step about whether the submitted answer contradicts any aspect of the expert answer.

- The submitted answer contradicts the expert answer regarding who was the first person to walk on the moon. The submitted answer incorrectly states that Armstrong was the second, directly contradicting the expert answer's correct statement that he was the first.
- This contradiction is a direct opposition of facts between the two answers.

Step 3: Output a JSON object structured like: {"type_of_overlap": "overlapping", "contradiction": true}.

{"type_of_overlap": "overlapping", "contradiction": true}

評価実行結果のOpenAI Playground画面 | 理想回答と矛盾する回答のケース

結果は{"type_of_overlap": "overlapping", "contradiction": true}となり、重複するものの矛盾した回答であることが判定できています。


最後に、必要以上に詳細に説明した正解の回答を試してみます。

Question: """What event is Neil Armstrong most famous for and on what date did it occur? Assume UTC time."""

Submitted Answer: """At approximately 02:56 UTC on July 21st 1969, Neil Armstrong became the first human to set foot on the lunar surface, marking a monumental achievement in human history."""

Expert Answer: """Neil Armstrong is most famous for being the first person to walk on the moon. This historic event occurred on July 21, 1969."""

結果はこちら:

Step 1: Reason step-by-step about whether the information in the submitted answer compared to the expert answer is either: disjoint, equal, a subset, a superset, or overlapping (i.e. some intersection but not subset/superset).

- Both answers identify Neil Armstrong's most famous event as being the first person to walk on the moon.
- Both answers provide the same date for this event: July 21, 1969.
- The submitted answer provides additional information about the exact time the event occurred (approximately 02:56 UTC) and describes it as a "monumental achievement in human history."
- Since the submitted answer contains all the information found in the expert answer plus additional details, the submitted answer is a superset of the expert answer.

Step 2: Reason step-by-step about whether the submitted answer contradicts any aspect of the expert answer.

- There is no contradiction between the submitted answer and the expert answer. Both agree on the event Neil Armstrong is most famous for and the date it occurred. The submitted answer simply provides more detailed information without contradicting the core facts presented in the expert answer.

Step 3: Output a JSON object structured like:

{
  "type_of_overlap": "superset",
  "contradiction": false
}

評価実行結果のOpenAI Playground画面 | 理想回答とより詳細な、矛盾しない回答のケース

結果は{"type_of_overlap": "superset", "contradiction": false}ということで、矛盾せずに理想回答のスーパーセットが回答されていることが正しく評価されました。

おわりに

OpenAIの推奨するプラクティスで、LLM回答のModel-based評価をやってみました。

素朴にLLMとプロンプトを活用してLLM回答評価をするのも、シンプルで取り組みやすいですね。 またOpenAIもLLM回答評価用のツールとしてEvalsを公開しているので、そちらも活用していきたいところです。

以上、どなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Test changes systematically - OpenAI Prompt Engineering Guide

GitHub - openai/evals: Evals is a framework for evaluating LLMs and LLM systems, and an open-source registry of benchmarks.

LangCheckでLLMの回答を自動評価する

Citadel AIのLLM回答評価ツール"LangCheck"を使ってみます。

はじめに

LLMアプリケーションの開発では、そのLLM出力を評価する仕組みが重要です。 出力評価の仕組みなくしてLLMアプリケーション開発をすれば、チューニングの方針に迷うことになるでしょう。 OpenAIも、LLM出力を自動評価するプラクティスを推奨しています。

最近、Citadel AIという日本のスタートアップが公開したLangCheckというツールを見つけました。 LLMアプリケーションの出力評価を行うツールのようです。

今回は、このLangCheckを触って使用感を探りたいと思います。

LangCheckとは

基本的な使い方

使い方はシンプルです。

LLMのアウトプットを各評価関数に渡してあげると、メトリクスに従ってスコアが算出されます。

import langcheck

# LLM生成結果を格納
generated_outputs = [
    'Black cat the',
    'The black cat is.',
    'The black cat is sitting',
    'The big black cat is sitting on the fence',
    'Usually, the big black cat is sitting on the old wooden fence.'
]

# テキスト品質を評価しDataFrameとして結果を出力
langcheck.metrics.fluency(generated_outputs)

評価結果はDataFrame様の形式で出力できる | ドキュメントより引用


またlangcheck.metricsのメトリクス判定結果は、その評価スコアでassertすることができます。 単体テストにも簡単に組み込むことが可能です。

from langcheck.utils import load_json

# Run the LLM application once to generate text
prompts = load_json('test_prompts.json')
generated_outputs = [my_llm_app(prompt) for prompt in prompts]

# Unit tests
def test_toxicity(generated_outputs):
    assert langcheck.metrics.toxicity(generated_outputs) < 0.1

def test_fluency(generated_outputs):
    assert langcheck.metrics.fluency(generated_outputs) > 0.9

def test_json_structure(generated_outputs):
    assert langcheck.metrics.validation_fn(
        generated_outputs, lambda x: 'myKey' in json.loads(x)).all()

その他には、フィルタリングやグラフ描画、稼働アプリケーションでのガードレール機能などが紹介されています。

詳細はドキュメントを参照ください。

評価メトリクスには何があるか

LangCheckでサポートされている評価メトリクスは、大きく4種類あります。

評価メトリクス | 図はドキュメントより

  • Reference-Free Text Quality Metrics:
    生成回答に対するリファレンスを必要とせず、直接回答を評価するメトリクスタイプ。 例えばtoxicity()は回答の毒性/悪意性を0~1で評価する。
  • Reference-Based Text Quality Metrics:
    理想の回答たる"リファレンス"をあらかじめ用意し、LLM回答と比較する方法。 例えばsemantic_similarity()は、LLM回答とリファレンスの意味論的類似度を-1~1でスコアリングする。
  • Source-Based Text Quality Metrics:
    LLMの回答が、"ソーステキスト"に基づいているかどうかを判定する。 これはRAG(Retrieval Augmented Generation)アーキテクチャのアプリケーション評価に有用で、LLMによる最終回等が、RAGの中で取得される関連データ内の事実に基づいていることを評価するのに利用できる。
  • Text Structure Metrics:
    LLM回答のテキスト構造を判定する。 例えば、is_json_object()はLLMの出力結果がJSON形式かどうかを0 or 1で判定する。

補足: 評価メトリクス判定に使われるモデル

これらメトリクス判定は、デフォルトではHuggingFaceなどからダウンロードされる各種モデルがローカルで実行されることで行われます (どのモデルが使われるかはAPI Referenceに記載されてます)。

一方で、多くのメトリクス評価関数ではOpenAI(あるいはAzure OpenAI Service)のモデルを利用することが可能です。 特に、複雑なユースケースではOpenAIモデルを利用した方が高い精度で判定できるとのことで推奨されています。 (ただし後述のようにOpenAIモデルを使うことで癖が出てしまうこともあるので注意)

環境変数OPENAI_API_KEYにOpenAIキーを格納して引数model_typeopenaiとするか、引数openai_clientに直接OpenAIのクライアントを渡すことで、OpenAIモデルを使って判定させることができます。

import os
from langcheck.metrics.en import semantic_similarity

generated_outputs = ["The cat is sitting on the mat."]
reference_outputs = ["The cat sat on the mat."]

# Option 1: Set OPENAI_API_KEY as an environment variable
os.environ["OPENAI_API_KEY"] = 'YOUR_OPENAI_API_KEY'
similarity_value = semantic_similarity(generated_outputs,
                                       reference_outputs,
                                       model_type='openai')

# Option 2: Pass in an OpenAI client directly
from openai import OpenAI

client = OpenAI(api_key='YOUR_OPENAI_API_KEY')
similarity_value = semantic_similarity(generated_outputs,
                                       reference_outputs,
                                       model_type='openai',
                                       openai_client=client)

LangCheckで回答自動評価をやってみる

では、実際にLangCheckを触ってみます。

多くのLLMアプリケーション開発で評価テストの主軸になることの多いだろうリファレンスあり評価"Reference-Based Text Quality Metrics"を日本語で試してみます。

(日本語を対象とするので、パッケージは "langcheck.metrics.ja.reference_based_text_quality" からimportします。)

LangCheckのReference-Based Text Quality Metrics APIには、

  • rouge1()
  • rouge2()
  • rougeL()
  • semantic_similarity()

の4つのメソッドが用意されています。

rouge1(), rouge2(), rougeL()の3つは従来からある自然言語処理のアルゴリズムで(今回詳しくは割愛)、semantic_similarity()はEmbeddingによるコサイン類似度から意味論的類似度を測る方法です。

今回はsemantic_similarity()を使って、"理想回答"との類似度を評価してみます(-1~1で評価)。

まずはざっとダミーのLLM回答と理想回答のペアを適当に用意します。

LLM回答(ダミー) 理想回答 備考
メロスは激怒した。 メロスは激怒した。 完全一致
メロスは激しく怒った。 メロスは激怒した。 意味一致
メロスは、激しく、怒った。 メロスは激しく怒った 句読点のみ不一致
セリヌンティウスは待っていた。 メロスは激怒した。 意味完全不一致
単語のベクトル表現は、1960年代における情報検索用のベクトル空間モデルを元に開発された。潜在的意味分析は、特異値分解で次元数を削減することで、1980年代後半に導入された。 単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発が元になっている。特異値分解を使用して次元数を削減することにより、1980年代後半に潜在的意味分析が導入された。 だいたい意味一致
1960年以前に、ベクトル表現は開発された。のちに次元数を増幅することにより、潜在分析が導入された。 単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発が元になっている。特異値分解を使用して次元数を削減することにより、1980年代後半に潜在的意味分析が導入された。 意味不一致
すみません、ITヘルプデスクに電話で問い合わせてください。 大変申し訳ございませんが、弊社情報部門のヘルプデスクにメールでお問い合わせください。 少し意味不一致

では、これらをsemantic_similarity()で評価させてみます。

まずはOpenAIモデルを使わずに、デフォルトのlacalタイプで実行してみます (モデルは"paraphrase-multilingual-mpnet-base-v2"が使用される)。

from langcheck.metrics.ja.reference_based_text_quality import semantic_similarity

# Dummy outputs
generated_outputs = [
    'メロスは激怒した。',
    'メロスは激しく怒った。',
    'メロスは、激しく、怒った。',
    'セリヌンティウスは待っていた。',
    '1960年以前に、ベクトル表現は開発された。のちに次元数を増幅することにより、潜在分析が導入された。',
    'すみません、ITヘルプデスクに電話で問い合わせてください。',
]

reference_outputs = [
    'メロスは激怒した。',
    'メロスは激怒した。',
    'メロスは激しく怒った',
    'メロスは激怒した。',
    '単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発が元になっている。特異値分解を使用して次元数を削減することにより、1980年代後半に潜在的意味分析が導入された。',
    '大変申し訳ございませんが、弊社情報部門のヘルプデスクにメールでお問い合わせください。',
]


def test_semantic_similarity():
    results = semantic_similarity(generated_outputs, reference_outputs)
    print(results)

    assert results > 0.9

テスト実行結果がこちら:

$ pytest -s 

# 中略

Progress: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00,  2.71it/s]
Metric: semantic_similarity
  prompt source                                   generated_output                                   reference_output explanation  metric_value
0   None   None                                          メロスは激怒した。                                          メロスは激怒した。        None      1.000000
1   None   None                                        メロスは激しく怒った。                                          メロスは激怒した。        None      0.980329
2   None   None                                      メロスは、激しく、怒った。                                         メロスは激しく怒った        None      0.961034
3   None   None                                    セリヌンティウスは待っていた。                                          メロスは激怒した。        None      0.250888
4   None   None  単語のベクトル表現は、1960年代における情報検索用のベクトル空間モデルを元に開発された。潜...  単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発...        None      0.979269
5   None   None  1960年以前に、ベクトル表現は開発された。のちに次元数を増幅することにより、潜在分析が導入...  単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発...        None      0.649559
6   None   None                      すみません、ITヘルプデスクに電話で問い合わせてください。         大変申し訳ございませんが、弊社情報部門のヘルプデスクにメールでお問い合わせください。        None      0.768630F

======================= FAILURES ==============================================================================================

# 中略

======================= short test summary info ======================================================================================
FAILED test_main.py::test_semantic_similarity - assert Metric: semantic_similarity\n  prompt source                                   generated_output                        ...             すみません、ITヘルプデスクに電話で問い合わせてくだ...
======================= 1 failed, 2 warnings in 3.37s ======

テスト評価結果を整理します。

LLM回答(ダミー) 理想回答 評価結果(metric_value)
メロスは激怒した。 メロスは激怒した。 1.000000
メロスは激しく怒った。 メロスは激怒した。 0.980329
メロスは、激しく、怒った。 メロスは激しく怒った 0.961034
セリヌンティウスは待っていた。 メロスは激怒した。 0.250888
単語のベクトル表現は、1960年代における情報検索用のベクトル空間モデルを元に開発された。潜在的意味分析は、特異値分解で次元数を削減することで、1980年代後半に導入された。 単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発が元になっている。特異値分解を使用して次元数を削減することにより、1980年代後半に潜在的意味分析が導入された。 0.979269
1960年以前に、ベクトル表現は開発された。のちに次元数を増幅することにより、潜在分析が導入された。 単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発が元になっている。特異値分解を使用して次元数を削減することにより、1980年代後半に潜在的意味分析が導入された。 0.649559
すみません、ITヘルプデスクに電話で問い合わせてください。 大変申し訳ございませんが、弊社情報部門のヘルプデスクにメールでお問い合わせください。 0.768630

なかなか直感とも合うスコアリングのように感じます。 スコア0.9あたりに閾値を設ければ、ちょうど良いテストのassertにできそうです。


次は、localモデルではなくOpenAI embeddingモデル(現時点では"text-embedding-ada-002")でsemantic_similarity()を実行してみます。 テストケースは↑と同じです。

semantic_similarity()でOpenAIモデルを使った場合はスコアが高くなる傾向にある、という注意がドキュメントに記載されてますが、どうなるでしょうか。

NOTE: when using OpenAI embeddings, the cosine similarities tend to be skewed quite heavily towards higher numbers.

from langcheck.metrics.ja.reference_based_text_quality import semantic_similarity

# Dummy outputs
generated_outputs = [
    'メロスは激怒した。',
    'メロスは激しく怒った。',
    'メロスは、激しく、怒った。',
    'セリヌンティウスは待っていた。',
    '単語のベクトル表現は、1960年代における情報検索用のベクトル空間モデルを元に開発された。潜在的意味分析は、特異値分解で次元数を削減することで、1980年代後半に導入された。',
    '1960年以前に、ベクトル表現は開発された。のちに次元数を増幅することにより、潜在分析が導入された。',
    'すみません、ITヘルプデスクに電話で問い合わせてください。',
]

reference_outputs = [
    'メロスは激怒した。',
    'メロスは激怒した。',
    'メロスは激しく怒った',
    'メロスは激怒した。',
    '単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発が元になっている。特異値分解を使用して次元数を削減することにより、1980年代後半に潜在的意味分析が導入された。',
    '単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発が元になっている。特異値分解を使用して次元数を削減することにより、1980年代後半に潜在的意味分析が導入された。',
    '大変申し訳ございませんが、弊社情報部門のヘルプデスクにメールでお問い合わせください。',
]


# Prerequisite: Set OPENAI_API_KEY as an environment variable
def test_semantic_similarity_by_openai():
    results = semantic_similarity(generated_outputs, reference_outputs, model_type='openai')
    print(results)

    assert results > 0.9

テスト実行結果がこちら:

$ pytest -s 

# 中略

Computing embeddings: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:05<00:00,  5.37s/it]
Computing semantic similarity: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 164.58it/s]
Metric: semantic_similarity
  prompt source                                   generated_output                                   reference_output explanation  metric_value
0   None   None                                          メロスは激怒した。                                          メロスは激怒した。        None      0.999999
1   None   None                                        メロスは激しく怒った。                                          メロスは激怒した。        None      0.990493
2   None   None                                      メロスは、激しく、怒った。                                         メロスは激しく怒った        None      0.976332
3   None   None                                    セリヌンティウスは待っていた。                                          メロスは激怒した。        None      0.817436
4   None   None  単語のベクトル表現は、1960年代における情報検索用のベクトル空間モデルを元に開発された。潜...  単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発...        None      0.986894
5   None   None  1960年以前に、ベクトル表現は開発された。のちに次元数を増幅することにより、潜在分析が導入...  単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発...        None      0.906200
6   None   None                      すみません、ITヘルプデスクに電話で問い合わせてください。         大変申し訳ございませんが、弊社情報部門のヘルプデスクにメールでお問い合わせください。        None      0.930603
F
======================= FAILURES ==============================================================================================

# 中略

======================= short test summary info ======================================================================================
FAILED test_main.py::test_semantic_similarity_by_openai - assert Metric: semantic_similarity\n  prompt source                                   generated_output                        ...             すみません、ITヘルプデスクに電話で問い合わせてくだ...
======================= 1 failed, 1 warning in 7.24s ======

Localモデル版のテストとあわせ、スコア評価結果を整理します。

LLM回答(ダミー) 理想回答 Localモデル評価結果(metric_value) OpenAIモデル評価結果(metric_value)
メロスは激怒した。 メロスは激怒した。 1.000000 0.999999
メロスは激しく怒った。 メロスは激怒した。 0.980329 0.990493
メロスは、激しく、怒った。 メロスは激しく怒った 0.961034 0.976332
セリヌンティウスは待っていた。 メロスは激怒した。 0.250888 0.817436
単語のベクトル表現は、1960年代における情報検索用のベクトル空間モデルを元に開発された。潜在的意味分析は、特異値分解で次元数を削減することで、1980年代後半に導入された。 単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発が元になっている。特異値分解を使用して次元数を削減することにより、1980年代後半に潜在的意味分析が導入された。 0.979269 0.986894
1960年以前に、ベクトル表現は開発された。のちに次元数を増幅することにより、潜在分析が導入された。 単語をベクトルとして表現する手法は、1960年代における情報検索用のベクトル空間モデルの開発が元になっている。特異値分解を使用して次元数を削減することにより、1980年代後半に潜在的意味分析が導入された。 0.649559 0.906200
すみません、ITヘルプデスクに電話で問い合わせてください。 大変申し訳ございませんが、弊社情報部門のヘルプデスクにメールでお問い合わせください。 0.768630 0.930603

確かにドキュメントの注意書きの通り、OpenAIモデルではスコアが高く出てしまいました。

現状では、localモデルを使った方が無難そうです。

追記:

上記問題についてPull Requestを投げましたところ無事mergeしていただき、v0.5.0からデフォルトのOpenAI Embeddingモデルが"text-embedding-ada-002"から"text-embedding-3-small"にアップデートされ、この問題は解消されました。

補足: semantic_similarity()でEmbeddingモデルを指定する

上記のように、OpenAIモデルタイプのデフォルトである"text-embedding-ada-002"ではスコアが高く出てしまう問題がありましたが、semantic_similarity()では利用するモデルを指定することが可能です。

先日新しいEmbeddingタイプがOpenAIからリリースされたので、こちら新モデルを指定して結果を比較してみます。

指定方法は簡単で、引数openai_argsにモデル名を渡します。

# Prerequisite: Set OPENAI_API_KEY as an environment variable
def test_semantic_similarity_by_openai_3_small():
    results = semantic_similarity(
        generated_outputs,
        reference_outputs,
        model_type='openai',
        openai_args={'model': 'text-embedding-3-small'}
    )
    print(results)

    assert results > 0.9

結果を並べたのがこちら↓

詳しくはこちら: langcheck_sandbox - GitHub

"text-embedding-ada-002"で見られるスコアが高く出てしまう問題は、新モデル"text-embedding-3-small"では解消しているように見えます。

"text-embedding-3-small"であれば料金も従来より安くなっているので、OpenAIモデルタイプを指定する時は新モデルを指定した方が使い勝手が良さそうです。


※ 今回使った検証スクリプトはこちらに配置: github.com

おわりに

以上、LangCheckを使ったLLMの回答自動評価を試してみました。

LLMアプリケーションの開発では、いかにそのアプリの性能を評価/継続観測するかが重要だと日々感じています。 そういった仕組みを作る一つの選択肢として、LangCheckは有用と感じました。

どなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

GitHub - citadel-ai/langcheck: Simple, Pythonic building blocks to evaluate LLM applications.

LangCheck Documentation — LangCheck

API Reference — LangCheck

https://platform.openai.com/docs/guides/prompt-engineering/tactic-evaluate-model-outputs-with-reference-to-gold-standard-answers