Measuring Coding Challenge Competence With APPSを読んだメモ

 (GitHubリポジトリ)

概要

 自然言語の問題文を入力としてコードを出力する、競技プログラミングに似た形式のタスクについて、APPという新しいデータセットを構築した。

 データセットについてGPTモデルを評価したところ、簡単な問題についてAC率が0%~4%程度であった。

詳細

APPデータセット

  • 問題はCodewars, AtCoder, Kattis, Codeforcesから抽出
  • 総計1万問
  • 正当例となるソースコード約23万
  • 問題文の平均単語数は293.2単語
  • テストケースの数は1問あたり平均21.2ケース

 問題形式としては2種類

  • Call-Based Format problems(TopCoder形式) : 関数シグネチャは準備されたコードが与えられるので、関数内部にコードを記述
  • Standard Input Format problems(AtCoder形式) : 標準出力にprint関数などを使って答えを出力

 具体的な入力の仕様

"\nQUESTION:\n" + q_str + "\n" + starter_code_str + "\n" + "\nUse<br>Call-Based Format\n\nANSWER:\n"

 要するに

QUESTION
(問題文)
(関数のシグネチャ)
Use Call-Based Format
ANSWER:

 Standard Input Format problemsだとシグネチャは空で最後のUse ~ の部分が変わる。たとえばABC126のA問題なら

Question
You are given a string <var>S</var> of length <var>N</var> consisting of <code>A</code>, <code>B</code> and <code>C</code>, and an integer <var>K</var> which is between <var>1</var> and <var>N</var> (inclusive).
Print the string <var>S</var> after lowercasing the <var>K</var>-th character in it.

Use Standard Input Format
ANSWER:

みたいな感じだろう。latex解釈も含むという記述もあったので数式的なところもタグを残しつつ入れたりしているんじゃないか(ここは勝手な解釈)。

 問題を難易度で次の3つに分類

  1. Introductory Level
    • 1〜2年の経験を持つほとんどのプログラマーが複雑なアルゴリズムを必要とせずに答えられる問題
    • (例)部分文字列の出現数を数える、文字列が回文であるかどうかを見つける
    • 訓練データ3,639、テストデータ1,000
  2. Interview Level
    • よりアルゴリズム的で本質的に困難な問題、難しい技術面接で尋ねられる質問のレベル
    • (例)木やグラフなどのデータ構造に関連する問題や、一般的なアルゴリズムの変更が必要な問題
    • 訓練データ5,000、テストデータ3,000
  3. Competition Level
    • IOIとかICPCで出るレベル
    • 訓練データ1,361、テストデータ1, 000

評価実験

 GPT-2, GPT-3, GPT-Neoなどにこれらのタスクを解かせる。

  • GPT-2 : 事前学習済みパラメータが公開されているが、公開パラメータはソースコードをもとにした学習がされてないため、後述するような形で事前学習を追加で行い、さらにAPPデータセットでFine-Tuningする
  • GPT-3 : パラメータが公開されてないのでAPIを叩いて使うだけ(ちょっと理解に自信がない)
  • GPT-Neo : 事前学習済みパラメータが公開されているので、それをもとにAPPデータセットでFine-Tuningする

GPT-2の事前学習

 GitHubから集めたソースコードで事前学習する。GitHubのスターが1以上あるリポジトリから、APPデータセットに含まれている問題を解いているようなリポジトリを除外し、30GBのPythonコードを収集。単語数節約や表記統一のために複数スペースをタブに置き換えて学習を実行。

 (ここはちょっと知識不足で、入力・出力をどう決めるのかよくわからなかった。次の単語予測の言語モデルとして学習? それだと入力単語が自然言語文ではなくコードになるので事前学習としてどこまで意味があるのかピンとこない)

Fine-Tuning

 事前学習したGPT-2および、公開されている事前学習済みパラメータを使ったGPT-3,GPT-Neoに関して、今回作ったAPPデータセット1万問中のうち半分の5千問を使ってモデルをFineTuningする。

  • OptimizerはAdamW
  • バッチサイズ256
  • Weight Decay 0.05
  • 10エポック
  • DeepSpeedを使用(ZeRO optimizer)
  • 生成時はビーム幅5のビームサーチを使用(その他はHuggingFaceのデフォルトを使用)

評価指標

  • Test Case Average : 単純に全問題のテストケースに対しての正答率(あまり意味がなさそう)
  • Strict Accuracy : その問題についての全てのテストケースに正答できた問題の割合(要はACできた割合。これが重要そう)

結果

f:id:tokumini:20210522104313p:plain

 AC率は一番簡単なIntroductory Levelについて0.2%〜3.9%。Competition Levelでは全滅(まぁそれはそうだろう)。

 パラメータ数の多いGPT-3がGPT-2(0.1B)に負けており、Fine-Tuningは重要そう。

 Test Case Averageと構文エラー率を棒グラフで表示

f:id:tokumini:20210522104552p:plain

 構文エラー率は緑色のGPT-Neoで3%程度となっており、これはとても低い値を実現できている印象。

出力例1

f:id:tokumini:20210522112515p:plain

出力例2

f:id:tokumini:20210522112526p:plain

所感

 CodeNetはtrain/testみたいな切り分けが確かされておらず、どちらかというと入力予測とか分析系とか、そういうための元手として用意されていたのかなと感じていた。一方今回のAPPデータセットは真剣に競技プログラミング的なタスクとして確立させる気合いを感じる。

 ABCのA問題を1%でも解けるなら結構すごいことに思える。リーダーボードが出来て精度勝負が始まりだすとタスクの解決としては半分勝っているようなものに思えるので、これが流行れば競プロAIの発展も結構進むのかもしれない。

 でも結局これらは英語がメインになってしまうと思うので、母語が日本語である人らで日本語版を頑張って再現していく必要はありそう。GPT-2日本語版の学習済みパラメータが公開されていたと思うが、そこからコードの学習をしてさらにFine-Tuningして、という資源はなかなか大変か。

 競プロのプレイヤー的には一度出力して終わりではなくて、WAだったときに修正する機能みたいなのは欲しい、というか重要になるんじゃないかと感じるところ。でもタスクの定式化が難しくてあまり簡単には想像できない。

おまけ

 結局人手でデータセットを綺麗に作るのがとても大事なんだよね。

Several graduate students and undergraduates polished and refined this dataset spanning half a year, ensuring a high-quality set of problems.