e4exp / paper_manager_abstract

0 stars 0 forks source link

Self-Supervised Bug Detection and Repair #497

Open e4exp opened 3 years ago

e4exp commented 3 years ago

近年、機械学習を用いたプログラム解析は、形式的な推論と確率的な推論を統合してソフトウェア開発を支援するものとして期待されています。 しかし、大規模なアノテーションされたコーパスがない場合、これらの分析をトレーニングすることは困難です。 この問題を解決するために、我々はBugLabを発表する。 BugLabは、バグの検出と修復を自己教師付きで学習するアプローチである。 BugLabは2つのモデルを共同学習する。 (1)コードのバグを検出・修復することを学習する検出器モデル、 (2)検出器が学習データとして使用するバグのあるコードを作成することを学習する選択器モデル。

Pythonで実装されたBugLabは、2374個の現実のバグからなるテストデータセットにおいて、ベースラインの手法に比べて最大30%向上し、オープンソースソフトウェアに含まれる19個の未知のバグを発見しました。

e4exp commented 3 years ago

1 はじめに

ソースコードのバグを検出・修正するためには,データや制御の流れなどの形式的な構造や,識別子名,コーディングイディオム,コメントなどの曖昧な情報に対する強力な推論能力が必要となる. 従来のプログラム解析では、形式的な推論や組み合わせ検索によって重要なバグを検出することができますが、専門家が手作業でコードを作成する必要があります。 これは時間とコストのかかる作業であり、コード内に蔓延する曖昧な情報を利用する機会を逃してしまいます。 このような手法の適用範囲を広げ、曖昧な情報を活用するために、深層学習に基づくバグ検出手法が研究されている[21, 3, 13]。 これらの手法は、私たちが日常的に利用しているソフトウェアのエンジニアリングをさらに向上させる可能性があります。 しかし、大規模な教師付き学習コーパスがない場合に、広範囲の一般的なバグをカバーするロバストなバグ検出および修復手法を作成するなど、この分野の多くの課題は未解決のままです。 既存の研究では,ランダムに挿入されたバグ[21, 13],Clozeテストのプロキシタスク[3],バグを含む可能性のある小さなコード編集のコーパス[9],ビルドエラー[27]などに注目している. これらのアプローチはすべて、非常に限られたサイズのデータセットや、実際のコードで発見されるバグの特性を代表していないことが知られているデータセットに依存しています。

本研究では、BUGLABを提案する。 BUGLABは、検出困難なバグを生成することを学習するバグセレクタを共同訓練することで、ロバストなバグ検出器を訓練する自己監視型のアプローチである(セクション2)。 例えば、2つの適切な名前の変数を持つコードスニペットでは、変数の誤使用のバグは簡単に検出・修正できるかもしれませんが、間違った比較演算子は特定が非常に難しいかもしれません。 我々はBUGLABのためのニューラルアーキテクチャを提案し(Sec. 3)、それをPythonに実装する(Sec. 4)。 この実装では、4つの広範なクラスのバグを考慮しており、手作業で精査した2374個の実在するバグからなる新しいテストセットにおいて、ランダムに挿入されたバグを用いた学習よりも高い性能を示した(Sec.5)。 さらに、学習したモデルをオープンソースのPythonパッケージでテストしたところ、これまで報告されていなかった19件のバグを特定することができましたが、偽陽性率はまだ実用的ではありません。 このようなバグを早期に発見し、開発者を支援する機械学習手法を構築することで、ソフトウェアの開発速度が向上し、エンジニアがより堅牢なソフトウェアを提供できるようになることを期待しています。

貢献内容 (a) 現実のバグの検出と修復を学習するための自己教師付きアプローチであるBUGLABを紹介する。 (b)Pythonで作成した2374個の実在するバグの手動精査データセット (c) グラフニューラルネットワークとリレーショナルトランスフォーマーを用いたBUGLABのPython実装の評価では、広範囲の現実的なバグをカバーし、自己教師なしのベースラインやバグ検出のためにマスクされた言語モデリングの事前学習を使用する単純な方法に比べて30%の改善を示した。

e4exp commented 3 years ago

7 考察と結論

学習したプログラム解析は、ソフトウェアの開発方法を改善する可能性を秘めています。 また、形式的推論と確率的推論を組み合わせた機械学習モデルを研究する絶好の機会でもあります。 これらを達成するために、我々はBUGLABを発表しました。 BUGLABは、学習プログラム分析のための自己教師付きアプローチで、ベースラインの手法を改善し、実際のコードのバグを検出します。 また、これまで知られていなかったバグ検出の機械学習手法の限界を明らかにし、今後の研究に役立てます。 特に、先行研究でよく用いられているランダムに挿入されたバグのコーパスと現実のバグでは、既存の手法の性能に大きな差があることが明らかになりました。

e4exp commented 3 years ago

2 自己監視型バグ検出

本節では、まずコード書き換えの概念を紹介し、それを用いてバグ検出・修復の自己監視型学習のフレームワークであるBUGLABを定義します。

コードの書き換え

書き換えは、コンパイラやその最適化、テスト駆動型の検索ベースのバグ修復ツール、ミューテーションテスト、リファクタリングツールなどでよく行われます。 リライトには、セマンティクスを保持するもの(例:ローカル変数のリネーム)と、セマンティクスを変更するもの(例:>=を !=に置き換える)があります。

Sをすべての構文木(言語文法の開始記号をルートとする必要はない)の集合を表すとする。 構文木s∈Sにおける構文木の位置 ℓ ∈ {eps} ∪ N ^∗は再帰的に定義され、s|eps=s、ℓ=ℓ ′ ◦ iについてs|ℓはs|ℓ ′のi番目の子(すなわちs|(2,3)はsの2番目の子の3番目の子を示す)とする。 書き換えルールρ=(mρ,tρ)を、マッチング関数mρ : S → {true, f alse}と変換関数tρ : S → Sのペアとして定義します。 マッチング関数mρ(s)は、サブツリーsのルートでルールρが適用できる場合にtrueをもたらします。 便宜上、tρ(s) = s iff mρ(s) = falseと定義します。 そして、可能な場合はρを使って、そうでない場合はID関数を使って、構文木sの修正を示すためにρ(s)と書きます。 また、可逆的な書き換え規則ρについては、ρ -1 (ρ(s)) = sが成立するような逆規則をρ -1と表記します。 具体的な書き換え規則ρについては、項4で説明する。

書き換え規則Rが与えられた場合、構文木sにおける「潜在的な書き換え」の集合をR^R_s = {<ℓ, ρi> | ρ∈R, ℓ location in s, mρ(s|ℓ) = true}と定義する。 BUGLABでは、R^R_sからの書き換えを利用してバグの挿入や修復を行うモデルを学習します。 このようなニューラルモデルについては、Sec.3で説明します。

BUGLAB

image

BUGLABでは、注釈のないコードベースCを対象に、パラメータθを持つロバストなバグ検出モデルDθを自己教師付きで学習することに関心があります。 Rをバグの挿入と修復を可能にする書き換えルール2のセットとします。 このため、書き換えられたコードスニペットs[ρ]ℓに対するDθの損失L_{D_θ}を考慮し、モデルが修復する書き換え<ℓ, ρ^{-1}>を予測する必要があるとする。 形式的には、以下の目的を最小化したいと考えています。

image

しかし、どんな有用な検出器でも、書き換えの集合RR sは一般的に非常に大きく、または境界がなく、すべてのhℓ,ρi∈RR sにわたる最大値を計算することは、実際には気の遠くなるような作業です。 この問題を解決するために、BUGLABはバグセレクターモデルSφ(パラメータφ付き)を導入し、その目的は気の遠くなるようなarg maxhℓ,ρi∈RRs LDθ (-)を近似することです。 そして、最大値を計算する代わりに、Sφから書き換えをサンプリングすることができます。 これをhℓ, ρi ∼ Sφ(s)とすると、BUGLABの学習目的全体は、min-max最適化問題として書くことができます。

image

BUGLABの2つのモデルSとDは、どちらもコードスニペットの書き換えを予測するという意味では「対称的」であり、目的が異なるだけです(一方はバグの導入を目的とし、一方はバグの修復を目的としています)。 実際には、SとDの両方をモデル化するために同じアーキテクチャを使用することができ、実際に使用しています。 テスト時には、Sを破棄し、訓練された検出器Dのみを使用してバグの発見と修復を行います。

e4exp commented 3 years ago

3 ニューラルモデル

本節では、BUGLABにおけるコードの表現方法と、セレクタモデルとディテクタモデルでコードの書き換え方法を学習するために使用するニューラルモデルについて説明します。

コードの表現

ソースコードを、型付き関係e_k∈Eで相互に関連するエンティティv_i∈Vの集合と考えます。 コードの実体とその関係を選択することは、高レベルの特徴抽出の一形態である。 Pythonの具体的なエンティティと関係については、第4章で説明する。 また、投影関数Ptokを定義する。 Ptokは、VとEを受け入れ、VのトークンエンティティのシーケンスVtokと、Eのすべての関係をVtokの要素に決定論的にマッピングしたものを返す、すなわちEtok = {(p(vi), r, p(vj ))}を定義する。 Ptokは関係変換モデルに使用されます。 コードエンティティviの神経表現を学習するために、まず、各エンティティの内容を初期のD次元表現にマッピングする埋め込み関数e(vi)を定義する。 Allamanisら[4]やその他の先行研究と同様に、各ノードの文字列表現を決定論的にサブトークンに分割し(例えば、fooBarはfooとBarに分割される)、学習した埋め込み行列を介してそれらを埋め込み、maxプーリングを用いて1つのベクトルを得る。 次に,次の2つのモデルのいずれかを用いて,G内のエンティティ表現を「文脈化」する. すなわち,MLPベースのGNNモデルと,Hellendoornら[13]のGREAT関係変換器を用いて,トークン列と関係Vtok, Etok = Ptok(V, E)を変換する. GREATはEtokの位置エンコーディングと投影関係の両方を使用します。 詳細なアーキテクチャの説明はAppx.Aを参照してください。 実体表現を計算するモデルは他にもありますが,本研究では検討しませんでした。 ここでは、位置ℓにおけるエンティティのベクトル表現の計算結果を、モデルによらず、rℓで表します。 これらの表現を用いて、確率的なコード書き換えモデルを定義する。

確率的コード書き換えモデル

バグ選択やバグ検出では、バグの導入や修復のために、コードスニペットsのある位置に特定の書き換えを適用する確率をモデル化する必要があります。 このため、我々はこのタスクをローカライゼーション・モデルとリライト・ギブン・ロケーション・モデルに分解する。

image

ここで、NoBugは、コードがバグっていないことを示すための特別な場所である。 実際には、ポインタネット[19]と同様に、rℓという表現を用いて実装する(詳細はAppx.A参照)。 書き換えを選択するために、書き換えタイプ固有の学習可能なルールスコア関数wρ (rℓ,Mρ(s, ℓ))を使用します。 この関数は、エンティティrℓ(および潜在的な追加メタデータ)のベクトル表現を、スカラースコアにマッピングする。 一部のルールでは、追加のルール固有のメタデータMρ(s, ℓ)が存在します(例えば、場所ℓで使用可能な他のエンティティの表現など)。 3つの具体的なルールスコア関数については、Sec.4で説明します。 書き換え確率分布prewは、対象となる場所ℓで適用可能なすべての書き換えのスコアに対するソフトマックス、iによってモデル化される。

image