Cookpad Drinkup at RubyKaigi 2024 を開くために気にしていたこと

レシピ事業部バックエンド基盤グループの石川です。

2024 年 5 月 15 日から 17 日にかけて、RubyKaigi 2024 が開かれました。クックパッドは Wi-Fi スポンサーとして協賛しており、また 16 日の夜には Cookpad Drinkup at RubyKaigi 2024 と称して懇親会を開きました。

RubyKaigi 2024 のロゴが大きく描かれた壁の前で人々が並んで写真に写っています。
クックパッド一行

居酒屋の入口が写っています。ひとりの男性が入口のそばで手を広げて参加者を歓迎しています。
懇親会のお店の様子

この記事では、カンファレンスで懇親会を開くにあたって気をつけていたことや、うまくいったこと、うまくいかなかったことをまとめます。RubyKaigi に関わらず、技術者コミュニティを盛り上げる手段のひとつとしてご覧ください。

続きを読む

クックパッドは RubyKaigi 2024 に参加していました!イベントレポート

はじめに

こんにちは。レシピ事業部プロダクト開発グループの堀内 (@Sota_Horiuchi)です。普段はバックエンドの開発を行っている新卒2年目のエンジニアです。

RubyKaigi 2024が 2024 年 5 月 15 日から 17 日に沖縄県那覇市で開催され、クックパッドからは総勢 24 名が参加しました。参加したメンバーのうち 13 名が新卒 3 年目までのエンジニアであり、社内の若手バックエンドエンジニアがほぼ参加していました。 また、クックパッドは Wi-Fi スポンサーとして協賛しており、更に 16 日の夜には Cookpad Drinkup at RubyKaigi 2024 と称して懇親会を開きました。 ドリンクアップの話はまた後日記事として公開されると思います。

RubyKaigi 2024 について

セッションは全部で 53(去年 51 )で、スポンサー数は 97(去年 89 )でした。スポンサー数は個人スポンサーが存在していた 2011 年を抜けば過去最大の値でした。 今回最も大きく変わっていたのはイベントの数であり、今年は 23(去年 9 )のイベント(パーティ)が設定されていました。夜な夜な那覇市のどこかで Rubyist の集まりが開かれており、自分も連日さまざまなところで飲みいろいろな方と交流ができました。 また、夜だけでなく昼には他社のエンジニア同士で集まりランチに向かうという取り組みがちらほら起こっており、他社の Rubyist の方と交流することができました。

RubyKaigi 2024の全体感

今回の RubyKaigi のセッションをテーマ別にざっくり分類してみると、パフォーマンスに関するセッションが多く見られました。

パフォーマンスについては Matz さんの Keynote でも第1にパフォーマンス、第2にパフォーマンス...とにかくこれからは(も)パフォーマンス改善に注力していきたいと述べられていました。具体的には VM の高速化、メモリ効率の改善、スレッド=パフォーマンス改善という需要への対応、ソフトウェア面での高速化等で、今後どれだけ改善していくか楽しみです。

また、パフォーマンス以外では、型やパーサー、 wasm の話も多くありました。型については day 3 の Ruby Committers and the World でも白熱した議論が起こり面白かったです。Ruby の型についてはまだまだ方が付きそうにありませんね。 パーサーの話で言えば、Matz さんからシンタックス・モラトリアムという、少なくとも今年いっぱいは文法に手を加えないようにし、パーサ周りの改善に注力していこうという提案がなされました。手書きパーサの Prism と文法定義から生成する Lrama が今後それぞれどのように発展し、互いに影響を与えていくのか注目です。世はまさに大パーサ時代。

パフォーマンス

先ほどRubyKaigi 2024ではパフォーマンスの話が多かったと述べましたが、ここでは特に印象に残ったパフォーマンスのトークについて紹介します。

取り上げるのはRubyそのものの実行速度の向上を目的とした、Speeding up Instance Variables with Red-Black Trees です。

本トークは Ruby のインスタンス変数へのアクセスを平衡二分探索木である赤黒木で高速化したという内容です。既にこの内容は Ruby 3.4にマージされており、Pull Request は右です (https://github.com/ruby/ruby/pull/8744 )。 この高速化においては、Ruby 3.2 で導入された、インスタンス変数の管理方法である Object Shape が前提となっています。( RubyKaigi 2022でCRubyに実装された時の発表 https://rubykaigi.org/2022/presentations/jemmaissroff.html

このトークを取り上げた理由としては、私自身がデータ構造やアルゴリズムを使った高速化について興味があったのと、思ったより前提となるこの Object Shape の日本語解説が少なく、Object Shape を理解する上で誰かの参考になればと思い取り上げました。

そもそも Ruby (CRuby) ではインスタンス変数を配列で保存しているため1、インスタンス変数にアクセスするには、当該配列においてインスタンス変数と対応している要素のindexを知る必要があります。Ruby VM ではインラインキャッシュと呼ばれるしくみにより、index をキャッシュすることで高速化を行なっています。しかし、同じインスタンス変数名があるクラスが複数登場するとキャッシュがうまく機能しないという問題がありました。そんな時、Ruby 3.2で導入された Object Shape がこれを解決しました。 Object Shape により「別のインスタンスだが、同名インスタンス変数のindexが同じである」ということを認識することができるようになり、index が同じなので使いまわせるとして、キャッシュヒット率を向上させることができるようになりました。

それでもキャッシュヒットしない(キャッシュミス)が起こる事例はかなりあるようで、例えば下のようなメモ化は Object Shape と相性が悪いようです。

class Sample
  def initialize(x)
    @hoge = x
  end

  def foo(x)
    @_foo ||= x
  end

  def bar(x)
    @_bar ||= x
  end
end

Object Shape ではインスタンス変数の初呼び出しにより Shape が決定されます。そのため、インスタンスにおける foo と bar の最初の呼び出しの順番が異なるだけで違う Shape になってしまい、キャッシュを使うことができません。結果としてキャッシュミスが起こります。キャッシュミスが起こるとインスタンス変数の index を獲得する必要があります。Object Shape を使った場合、そのクラスが複雑な Shape でない場合はインスタンス変数の index を獲得するために O(|インスタンス変数|) の計算処理が必要でした。 そのため、キャッシュミス時の index の高速取得が求められていました。

Object Shape 自体はそもそも木構造でそれぞれの Shape を管理していて且つそれぞれのインスタンス変数の index が各ノードに格納されています。本トークのアイディアはこの木構造をできるだけ均一の高さにすることで index の探索を早くするというものです。

個人的な感想として、赤黒木は同じ平衡二分探索木であるAVL木に比べて木の形が歪になりやすいことが知られているので、ノードの検索は AVL 木の方が速いはずです。そのため、AVL 木で実装した場合とどちらが速いのか気になりました。 また、本トークを聴くまでは Object Shape についてあまり詳しく知らなかったので、本セッションにより Object Shape の気持ちも多少感じることができました。 加えて、Ruby の高速化のため Object Shape に優しいコード(インスタンス変数の代入は同じ順序で行う方が良い)を書こうという気になれました。 ただ一方で社内の人と議論をした際、「Ruby のユーザーとしてはどう書いてもある程度速くなってほしい」という話題になり、普段から Object Shape を考えながらコードを書くことは難しいよねという話になりました。 もちろん普段から常に意識することは難しいですが、例えばメモ化をできるだけ控えるとか、コンストラクタにおける変数初期化の際に変数の順番を一定にするツールを使う(あるのか?)とかである程度 Object Shape フレンドリーなコードを書くことができるのかなとも思いました。参考2

今後もどのような高速化手法が出てくるか楽しみです。

終わりに

次回の RubyKaigi 2025 は愛媛県松山市にて開催予定です。 愛媛県には千と千尋の神隠しの舞台になった道後温泉やゆるキャラのバリィさん3などがいるのでとても楽しみです。

NLP2024 に参加しました

こんにちは! 技術部機械学習グループの山口 (@altescy) です。

先月、神戸にて開催された言語処理学会第30回年次大会 (NLP2024)に同じく機械学習グループの深澤 (@fufufukakaka)と共に参加してきました。 昨年に引き続き今年も過去最多の参加者数となり、言語処理研究の盛り上がりを実感しました。

特に去年の年次大会 (NLP2023) のタイミングで GPT-4 が発表されて以降、自然言語処理の研究は大きな転換期を迎えていると感じます。 大規模言語モデル (LLM) が研究の主流となる中、どんな課題や発見があるのか、期待をもって参加する大会となりました。

この記事では NLP2024 にてクックパッドから発表した 2 つの研究と、その他の興味深かった研究についていくつか紹介します。

発表内容の紹介

クックパッドからは以下 2 つの研究を発表しました。

P2-11: Sequential Recommendation におけるテキスト情報を活用した未知アイテムへの対処法に関する分析

推薦モデルの一種として、Sequential Recommendation Modelがあります。これはアイテムIDの系列情報を基に次にアクションすべきアイテムを推薦するモデルです。このモデルは未知のユーザーであっても、既知のアイテムで構成された履歴があれば推薦が可能です。しかし、未知のアイテムが入力として与えられた場合、そのアイテムはモデルにとってout-of-vocabularyであり、入力に使用することはできません。実際のサービスで推薦モデルを運用する上では、学習時に存在しなかった新着アイテムを無視せざるを得ないですが、仮にそうしたアイテムだけを見ているユーザがいたとすると、そのユーザには推薦を表出できません。 この研究では、未知のアイテムが入力された際に最も効果的にそれを取り扱う方法を検討しました。

本研究ではクックパッドにおける実際の閲覧履歴データ、及びNII IDRで公開しているつくれぽデータセットを使用しました。Sequential Recommendation Modelとしては、2021年SIGIRで発表されたCOREを使用します。

今回、未知アイテムを取り扱う方法として3つの手法を提案しました。

  1. テキスト情報を用いた未知アイテムのID埋め込み推測(Embedding Mapping)
    • 未知アイテムが持つ情報としてテキスト情報(本研究ではレシピタイトル)を使用します。
    • 予め学習された推薦モデルのID埋め込みとアイテムのテキスト情報を対にして、テキスト情報からID埋め込みを推定するモデルを学習します。
    • 未知アイテムが入力された際には、そのアイテムのテキスト情報を用いてID埋め込みを推定し、そのID埋め込みを用いて推薦を行います。
    • この手法の構築にはBERT及びLSTMを使用しました。
  2. 類似度が高いアイテムによる置換(Replace Similar Item)
    • 未知アイテムが入力された際に、そのアイテムとテキストの類似度が高い既知アイテムを入力履歴から探し出し、そのアイテムを未知アイテムの代わりに入力として使用します。
  3. 未知アイテムを入力履歴から除外(Ignore)
    • 未知アイテムが入力された際に、そのアイテムを入力履歴から除外し、残りのアイテムのみを使用して推薦を行います。

履歴の先頭または末尾から最大5つが未知アイテムであると仮定します。未知アイテムとなったものについては、推薦モデルから対象のID埋め込みを削除して入力に利用できないようにします。

以下が実験結果となります。それぞれのデータセットに対して、各手法を適用した際のNDCG@50の結果です。

NDCG@50 の結果一覧

まず分かる基本的なこととして、履歴の先頭側よりも末尾側(より最近のアイテム)が未知である場合の方が精度影響が大きいことが見て取れます。各手法に関する結果としては、今回提案した手法である Embedding Mapping が他手法と比べて十分な精度を出すには至らず、多くの場合でシンプルな別手法が上回る結果となりました。今回対象とした系列が10要素以上のもののみを対象としていたこともあり、単純に未知アイテムを除外する Ignore がほとんどのケースで最も良い性能を示しました。ただ、閲覧データ・つくれぽデータのどちらを対象としていたかによって若干結果は異なっており、類似アイテムが並びやすい閲覧データに対しては Replace Similar Item が有効に働く場面もありました。

この結果に関連して以下のような分析を行いました。 事前にレシピテキストで学習されたfastTextベクトルでコサイン類似度が0.8以上となるタイトル類似ペアを100組抽出します。その後、Embedding Mapping(LSTM)とCOREのID埋め込みベクトルを使ってペアのコサイン類似度を計算し、その平均を算出しました。

類似ペアの調査

この結果を見ると、本来近づけたかった Embedding Mapping(LSTM) と CORE との間で全く異なる傾向が見られています。fastTextベクトルの類似度が高いレシピ同士であっても、CORE のID埋め込みの類似度は比較的低めであることがわかりました。 このことから、今回提案した Embedding Mapping では捉えきれない性質が CORE の ID埋め込みに備わっていることが考えられます。ID埋め込みを復元するように学習することで性質を獲得できないか、と考えて取り掛かったのですがまだ改善できる点があるようでした。

Sequential Recommendation Model はオンライン推薦を実装する上で非常に重要な選択肢の一つです。一方で実サービスでの運用を考えると、モデル学習後に登録される新着アイテムを上手く推論に利用できるようになれば、今まで以上にユーザの行動を捉えられるようになるはずです。 今後の研究では、より広いパラメータ設定ので実験を行うと共により良い ID埋め込みの推定方法を模索するなどに努めていきたいと思います。

P3-8: RecipeSTS: レシピのための類似性評価

レシピは自然言語で書かれる文書形態の一種であるものの、通常のテキストとは異なる特徴を持っているため既存のデータセットで評価された基盤モデルがレシピを上手く扱えるかどうかは定かではありません。 この研究では言語モデルのレシピ処理能力を理解するための第一歩として、レシピタイトルを対象にした STS (Semantic Textual Similarity) データセットを構築し、既存の言語モデルの評価と今後の研究方針を示しました。

データセットの作成にあたっては、2つの異なるレシピタイトルのペアに対して以下のアノテーション基準に基づき人手によるアノテーションを実施しました。 500件のペアについて、1ペアあたり 5 人の作業者が 0 ~ 5 のスコアを付与し、その平均値を正解のスコアとして採用しました。

RecipeSTS のアノテーション基準

作成した RecipeSTS データセットを用いて言語モデル (BERT / T5) の性能を評価した結果が以下の図になります。 各言語モデルから作成したレシピタイトルの埋め込み表現のコサイン類似度と、アノテーションされたスコアのスピアマン順位相関係数を示しています。 また、+ fine-tuning は事前学習済みモデルに対して独自のレシピデータで追加学習したモデルを表しています。

RecipeSTS の評価結果

今回試した中で最も高い性能を示したのはレシピデータで追加学習した BERT モデルでした。 合わせて評価を行った JSTS の結果と比べると、既存の言語モデルは一般的なテキストに比べてレシピテキストの処理は不得意な傾向があるように見えます。

また、追加で OpenAI Embedding API を使った評価も上図下部に記載しました。 論文執筆時点では text-embedding-3 の公開前であったため追加学習したモデルが最も高い性能を示していましたが、text-embedding-3-large は今回比較したモデルの中で最高性能を達成しています。 それでもやはり JSTS の結果と比べるとレシピテキストを不得意とする傾向はあるようで、レシピ処理における課題は依然として残されていると言えるでしょう。

RecipeSTS の事例

いくつかの事例をピックアップしてみると、上図の (a)、(b)、(d) のように表層的な類似・相違の影響で意味的な類似性を捉えられていないケースが複数存在しました。 また、事例 (c) はどちらも「オイスター炒め」であるものの、調理法や食材など着目する観点によって類似性の評価が変化するケースと考えられます。 レシピの類似性評価においては、より多面的な基準が必要になりそうです。

類似性評価はモデル選択など機械学習タスクの基礎のみでなく、検索や推薦といった応用においても重要な要素です。 今後の研究では、調理法・食材・味付けといったよりレシピに特化した多面的な基準に基づくデータセットの構築や、レシピに適した基盤モデルの開発に取り組みたいと考えています。

気になった発表

以下は NLP2024 で発表された研究の中から、山口・深澤が特に興味深かったものをピックアップして紹介します。

A4-3: LLM の出力結果に対する人間による評価分析とGPT-4 による自動評価との比較分析

題の通り、LLMの出力結果を人間、GPT-4で評価した結果を比較分析するという研究です。 GPT3.5-turbo-1106 (GPT-3.5) と houou-instruction-7b-v2 (houou) を対象に、Rakuda ベンチマークを用いてそれぞれの応答について関連性・正確性など複数の観点で評価を行っています。 実験の結果、人間とGPT-4の判断には乖離があり、GPT-4 は houou の方が優れていると評価した一方、人間は GPT-3.5 の方が優れていると評価したケースが多かったとのことです。

houou は具体的な数値や情報を含む応答を生成する傾向があるらしく、GPT-4 はそうした情報の具体性を評価したと考えられています。 しかし、人間が事実確認も含めて houou を評価したところ、ハルシネーションが多く、特に正確性の点で劣っていると判断されたようです。 houou の学習に利用された ichikara-instruction データセットは具体的な情報を含む例が多く、その傾向が houou の出力にも反映されていると考えられています。

この研究を見ると、LLMを評価に利用することやインストラクションデータセットを設計・構築する難しさを感じます。 情報の具体性と正確性のトレードオフについて示唆を得られる興味深い発表でした。

P6-25: 自己認知は LM as KB の信頼性を高めるか

真偽値で回答可能なQAタスク (StrategyQA) を対象に、予測の不確実性を考慮して応答を行う仕組みを提案した研究です。 予測が不確実な場合は質問を等価な命題集合・論理式へと再帰的に分割し、それぞれの命題に対して回答を得ることで与えられた質問に答えるという手法 (Back-off LMKB) を提案しています。 不確実性を考慮しない場合や間接証明しない場合と比べて、提案手法を用いることでより正確な回答を得られることを示しています。

応答が真偽値であることを利用して質問を論理式に分解するという発想は合理的で興味深いと感じました。 最初の回答で真偽不明だった質問においても間接証明により正確な回答が得られていて、提案手法の有効性が示されています。 一方、課題にも書かれているように不確実性の推定や命題集合の生成精度については今後の発展が期待されます。

個人的に自己認知的なアプローチは LLM をはじめとした AI システムの能力向上につながるのではないかと期待しています。 モデル自身が出力を再帰的に検証するという仕組みは、他のタスクにも適用できる可能性があると感じました。

P10-6: 事前学習済みの分散表現は表層的な知識を獲得しているか

現在の LLM、例えば GPT-3.5 では 『「人類学者」の 3 文字目は何ですか?』といった表層に関関する質問に正しく回答できない場合が多くあります。 この研究ではWord2Vec・BERT・T5・Llama2 など複数の学習済みの言語モデルを対象に、分散表現や生成結果を用いてモデルに表層的な情報がどの程度含まれているかを調査しています。 文字数や構成文字の予測といったタスクを通して、学習済み言語モデルが表層の情報を部分的には獲得しているものの、出力に表層の知識を反映させることが不得意であったり、出現位置や順序の情報は十分獲得できていないことが示されています。

特に興味深かったのは、文字数を予測するタスクにおいて分散表現から予測した場合とテキスト生成で予測した場合の性能の差です。 BERT や Llama2 において、分散表現を利用した場合にはある程度予測できているものの、テキスト生成で予測した場合にはその性能が大きく低下したとのことです。 モデルの内部に表層の情報を獲得できたとしても、出力のメカニズムによってそれを反映できていない可能性がありそうです。

文字数制限のある要約など、タスクによっては表層の情報が重要になる場合もあるはずです。 言語モデルの振る舞いや能力を理解するためには、意味的な評価と合わせて表層の情報を扱う能力について考えることも大切だと感じました。

A10-4: 平均プーリングによる文埋め込みの再検討: 平均は点群の要約として十分か?

文章などをベクトル化することは近年の検索拡張生成(RAG) などを実装する上で必要不可欠な技術として認識されてきています。こちらの研究では文埋め込みを作る際に最もよく用いられる平均プーリングが、単語埋め込みの空間的な広がりの情報を潰してしまう問題を指摘しています。つまり、「意味の異なる点群なのに平均が近くなる」という問題です。 これを確かめるための実験として、WMD(Word Mover's Distance) による点群としての類似度と平均プーリング後のL2距離、人手評価による類似度を用意し、それぞれの類似度を比較しています。結果として、WMDによる類似度が低い場合に平均プーリング後のL2距離が高いケースがいくつか存在していることが確認できたとのことです。この結果は経験的に平均プーリングが有効であることを示していますが、同時に考慮しなければならないケースが有ることも示しています。

点群を点群のまま捉えられるリーズナブルなモデルを用意できればいいのですが、基本的に点として圧縮されている平均プーリングの方が現時点ではやはり扱いやすいです。ただ、個人的にも平均プーリングという操作が言葉の意味を正しく捉えられているかというと疑問がある、と常々感じていたため、こちらの研究におけるクエスチョンは非常に共感できました。 今回調査した STS データでは平均プーリングでほとんどのケースに対応できていましたが、ドメインを絞ったりしてみると特有のドメインでは問題が発生しやすいなどがあるかもしれないと思っています。とても今後が気になる興味深い研究でした。

E6-2: 意味変化の統計的法則は1000年成り立つ

意味変化の統計的法則とは、頻度語ほど意味変化の度合いが小さく多義語ほど意味変化の度合いが大きくなるという、ACL2016 にて Hamilton らが発表したものを指しています。先の研究における時間範囲は 1800年から2000年でしたが、こちらの研究では聖書を対象に含めることで、Hamilton が発見した意味変化の統計的法則が1000年経過しても成り立つことを調べています。シード語を設定し、聖書を構成するラテン語とラテン語をもとにして派生したロマンス語との間で意味変化が成り立つかを調べたところ、頻度が高い・多義性の低いラテン語語源ほどロマンス語形との意味のずれが小さくなる傾向が見られ、1000年単位であっても意味変化の統計的法則が成り立つことを示したとのことでした。

個人的に Hamiltion の研究は当時読んだときからとても印象に残っていました。こちらの研究は聖書に着目してその時間範囲を広げた分析を行う、というのがユニークだなと感じ、紹介させていただきました。意味変化の法則が長い時間を書けても変化しない普遍的なものだとすると、今後も同様の変化が今我々が扱っている言葉でも起きうるということになります。例えばマルチエージェンシミュレーションなどで人工言語のモデリングを行う際などにも今回の法則を取り入れることでより自然な言語生成が可能になるかもしれません。非常に興味深い研究でした。

B7-4: 文脈構造を利用した埋め込み表現学習の提案

文章や画像に対する埋め込み表現は、検索を始めとした様々なアプリケーションで利用されています。この研究では、文脈構造を利用することで埋め込み表現の表現能力を向上させるための最適輸送を用いた教師なし埋め込み学習手法を提案しています。BERT を対象として考えた時、先行研究では CLS トークンのみに着目した学習が行われます。一方で提案手法では最適輸送を用いてシャッフルした文章の各トークンについて輸送コストを最小化するように学習させることで、文脈構造を考慮した埋め込み表現を獲得することに成功しています。得られたモデルは SimCSE などの先行研究で提案されたモデルよりも STS タスクなどにおいて高い性能を示しているとのことです。

こちらの研究を紹介させていただいた理由は、先に示した平均プーリングに関する調査を行った論文と同じモチベーションによるものです。つまり、平均プーリングで潰す・CLSだけに着目するよりももっと良い方法があるのではないか、という問いです。こちらの論文は最適輸送によって点群全体での学習を行う、というアプローチで、非常に納得しやすいものでした。発表後の質疑応答で、点群全体を見る分どうしても計算時間がかかってしまう、という問題があるとのことでしたが、今後も追いかけたい研究だな、と感じました。

おわりに

今回の記事では NLP2024 の参加レポートをお届けしました。

冒頭にも書いた通り、去年と比較して NLP2024 は特に LLM の存在感を強く感じる大会だったように感じます。 LLM の構築や評価の研究はもちろん、その他の研究においても LLM との比較や LLM の活用を意識した研究を多く見かけました。 きっとこの流れはまだしばらく続くのでしょう。 激動の時期を迎える中、今大会で得られた知見をもとに LLM をはじめとした最新の言語処理技術を実際のサービスにも活用していきたいと思います!