LLM Prompt Recoveryに挑戦| Kaggleチャレンジ記録
Kaggleのコンテスト「LLM Prompt Recovery」へチャレンジした記録です。今回は、終了2週間ちょっと前から参加ということでキャッチアップくらいしかできなかったです。
結果は、713/2204696/2175位とイマイチでした。
時間もなく、あまり取り組めなかったですが一応記録として残しておきます。
LLM Prompt Recoveryの概要
①元の文章に対して、②プロンプトで書き直しを指示し、③Gemmaで書き直された文章を出力させた時の、①と③のペアから②の書き直しの指示を予測するコンペです。
評価指標はsentence-t5-baseモデルを使って計算したシャープコサイン類似度です。
つまり、このコンペは、プロンプトに何が書いてあったのかを出力結果から推定するコンペになります。
このコンペでは、トレーニングデータが1行(1つ)、テストデータ1つ(トレーニングデータと同じ)と、学習用のデータやサンプルが全然ないことが特徴です。
なので、指示プロンプトとして、どんなのがくるか全くわからない状態です。
たとえば、「この文章を歌に変えて」もあるだろうし、「主人公を〇〇に入れ替えて」もあるだろうし、「文章をフォーマルに」などもあるだろうし、もっと細かな指示がある可能性もあります。
取り組み内容
とりあえず、公開コードとディスカッションを眺めてみる
公開コードをみると、全部に対して平均プロンプト(なんとなく無難なプロンプト)を使うだけでもメダル圏内のスコアになっていました。
逆に、LLMモデルを学習させるもののLBはイマイチといった感じです。
ディスカッションでも、平均プロンプトの話題が出ている感じです。
今回はノートブックを日本語に翻訳できるchromeの拡張機能が役に立ちました
学習コードを作成
公開コードを参考に、学習コードをGoogle Colab上に作成しました。Lolaを使ったやつでそこまでコードが難しくないので、いろいろカスタムしました。最終的には、Mistral 7Bを学習させるコードに変更し、結果をデータセットとしてkaggleにアップするようにしました。
また、対となるinferenceコードも作成して結果を確認しつつ学習を繰り返しました。
いろいろハイパーパラメータを変更して試したけど、あまりスコアが上がらない・・・
この時点でちょっと困りました。
データセットを自作
最初は、他の方が作成したデータセットを利用して学習していましたが、データセットを自作してみることにしました。データセットは、GPTやローカルで動かしているgemmaで作成していきました。
とりあえず、1500データくらい作成して学習させてみましたが、逆に悪化。
ネイティブじゃないので、英語の細かい表現の差がわからず、LLMの出力した書き換え後がちゃんと指示どうりか確認できなかったのもスコアが上がらなかった原因かもとか考えていますが、単に指示のパターンがコンテストの指示と違うという可能性も。
ここまででの取り組みで、残り1週間になりました。
方向性を変更
ディスカッションを眺めていると、ちょっと気になるノートブックの情報を発見。プロンプトに擬似的な入力→LLMの回答を入れる(?)というものです。
面白かったので以下の記事にまとめています。
学習より、こちらのやり方の方が出力がコントロールしやすいことがわかったので、学習したモデル+このやり方にトライしてみることにしました。
最終的に、この取り組みのコードがLBベストになりました。
その他取り組み
sentence-t5-baseの評価を知りたかったので、平均プロンプトをいくつか作成してみて変化を見ていました。が、変化の法則を見つけられず。途中で諦めました。
上位解放は、評価モデルに対して敵対的攻撃をする手法が紹介されています。sentence-t5に対する取り組みのレベルの差を感じました。
結果と感想
結果は、713/2204696/2175位でした(終了してしばらくして順位が変化しました。不正アカウントが削除されたと思われます)。
LLMは少しいじってますが、ここまで思考錯誤したことがなかったのでLLMの学習・プロンプトエンジニアリング等の学習として、参加してかなりよかったと感じています。
正攻法(?)で、学習させても結果が出にくいコンペということで、敵対的攻撃(平均プロンプト発見)に上位手法が集中してました。キーワードで出てくる「lucrarea
ってなんだよ」と思ってしまいます。
コンテスト終了後にlucrarea
をsentence-t5のvocabで調べてみると、存在していました。ブルートフォースアタックしていたら見つけたのかも。ただ、個人の嗜好として、結局、そちら方向にはエネルギーを費やさなかった気がします。
コンテスト後に以下のようなコードで実験してみるとlucrarea
が登場しました。以下のコードは、sentence-t5のvocabから単語を拾って、コサイン類似度が一番上がる単語をつなげていくというものです。
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('sentence-transformers/sentence-t5-base')
# スペシャルトークンを除去した、トークンリストを作成
tokenizer = model.tokenizer
vocab = tokenizer.vocab
vocab_list = []
for e in vocab :
if "<" not in e : vocab_list.append(e)
# ターゲットとする指示をエンコード
target = ["Please improve this sentence more formally.",
"Convert this into a sea shanty",
"Improve this text by transforming the tone into poetic lyrics.",
"Rewrite this text by infusing it with the charm and whimsy of a romantic comedy.",
"Rewrite this text to evoke mystery."]
target_enc = model.encode(target)
s = ""
cur_sim = -1
for i in range(20):
enc = model.encode([s + e for e in vocab_list])
sim = cosine_similarity(target_enc, enc).sum(axis=0)
sel = np.argmax(sim)
if sim[sel] > cur_sim :
s += vocab_list[sel]
cur_sim = sim[sel]
else: break
print(s, (cur_sim/len(target))**3)
print(s)
下記のようにlucrarea
が登場します。ちなみに、これを計算するのにT4で約3分でした。いくつかのプロンプトを用意してスコアがあがるように総当たりすると確かに登場するようです。
ちなみに、この出力をそのまま使ってサブすると0.63のスコアが達成できました。これだけでとりあえず、結果をみると0.67ですが、少し下がるのはターゲットとするプロンプトが適当すぎるからだと思います。とはいえ、簡単に0.63です・・・
結果
▁modificări 0.5116659052147181
▁modificări▁this 0.5895178193225697
▁modificări▁this▁writing 0.6195698084142054
▁modificări▁this▁writingaesthetically 0.6442036323090553
▁modificări▁this▁writingaestheticallyley 0.6517300797073368
▁modificări▁this▁writingaestheticallyley▁pitched 0.656351273539928
▁modificări▁this▁writingaestheticallyley▁pitchedlucrarea 0.6671248219217195
▁modificări▁this▁writingaestheticallyley▁pitchedlucrarea. 0.6706090414279353
▁modificări▁this▁writingaestheticallyley▁pitchedlucrarea.
まとめ
今回は、LLMの学習方法などを理解することが目的だったので、2週間という短い期間でしたが参加してよかったです。これまでよりLLMについて理解が深まりました。