日本ソフトウェア科学会第 34 回大会 (2017 年度) 講演論文集

再帰型ニューラルネットワークを用いたコーディングスタイルの自動検査手法の提案
小林 佑樹

西田典紀

千葉滋

機械学習を応用したコーディングスタイルの自動検査手法を提案する．近年，Ruby を代表とする文法的に自由な言語が多く利用されるようになり，コーディング スタイルの組織内での統一がより重要視されるようになった．一方で，従来はコーディングスタイルを ルールとして手動で明文化したり，組織が採用する規約を予め明示的に選択して検査する手法しか存在しなかったため，コーディングスタイルを継続的に検査するための運用コストが課題であった．コーディングスタイルをより低コストで統一できる手法として，本手法では自然言語処理の分野で盛んに利用されている再帰型ニューラルネットワークを応用してソースコード内のコーディングスタイルをコーディング規約ではなく統計を基に自動で検査する．今回の提案では文法の自由度が高い Ruby のコーディングスタイルを自動検査できるシステムとして設計を行った．

We propose a method for evaluating the coding style of source code automatically with machine learning.
Recently, programming languages which are acceptable to variant grammar especially Ruby are used, and
it is important for teams and organizations to consistently use the same coding style, especially in programming languages that allow various coding styles like Ruby. However, the coding style must be clarified andcustomized manually. In our research, we represent coding style not by conventions but by likelihood andevaluate the coding style of source code automatically. We derive a likelihood function that represents acoding style from a set of programs which is written in the coding style that is considered to be correct by
the team. We calculate the likelihood of token sequences with the likelihood function which we derived anddetect tokens which have a low likelihood of being the wrong coding style. We built a system using thisapproach.

コーディングスタイルを修正することも容易であっ

1 はじめにた．しかし近年は Ruby を代表するような文法的にコーディングスタイルとはプログラムの表現作法を自由度の高い言語が利用されるようになった．文法的指す．C 言語のようなプログラミング言語が利用さに自由度が高い言語は同じ機能を実装する際にも様々れていた時から組織などで定められたコーディングな書き方が可能となるため，コーディングスタイルがスタイルに則ってコードを書くことは重要とされて多様化してしまう．結果的にコーディングスタイルにいた．C 言語や Java のような言語は文法の自由度が則ってコードを書くことや自動でコーディングスタイ低く，一般的に利用されるコーディングスタイルも少ルを修正することが難しくなった．

なかったため，コーディングスタイルに則ってコード

本論文ではコーディングスタイルを規則ではなく，を書くことは難しくなかった．またエディタや IDEトークン列の尤度で表現し，コーディングスタイルのの formatting 機能を利用して自動でソースコードの適合評価を自動で行う手法の提案を行う．スタイルに

Proposal of automatic inspection method of coding
style using recursive neural network
Yuki Kobayashi, Shigeru Chiba, Noriki Nishida, 東京大学情報理工学系研究科創造情報学専攻, Graduate School Information and Science Technology, The
University of Tokyo.

合致するプログラム群から導かれる尤度関数をそのスタイルとみなすことでコーディングスタイルの自動抽出を行う．導いた尤度関数を用いて検査対象のプログラム中で尤度を計算し，尤度の低いトークン列を
コーディングスタイルに不適合なものとして検出する．さらに本手法を使ったシステムを実際に Pythonを用いて構築し，Ruby の静的コード解析ツールのRubocop と本手法を使ったシステムでコーディングスタイルの判定精度を比較した．

2 コーディングスタイルの統一
複数の開発者で一つのソフトウェアを開発するよう

123456789

LineLength :Max : 128
Style / N um e ri cL i te r al s :Enabled : true
Layout / IndentArray :Enabled : true
EnforcedStyle : consistent

図1

Rubocop の設定ファイルの例

な組織内ではコーディングスタイルを統一することで長期間開発されるソフトウェアの保守性が向上するな

目では Style というグループの NumericLiterals

どのメリットが生まれる．近年は Ruby のような文法という Cops をオンにすることで, 5 桁を超える数の自由度が高い言語が登場し，組織で採用されるコー値を表記する際には 1 000 000 のように 3 桁毎にアディングスタイルが多様化したため，より組織内で意ンダースコアを挿入しているかをチェックするよう識的にコーディングスタイルを統一する必要性が出て設定している．7 から 9 行目では Layout というグきた．

ループの IndentArray という Cops をオンにして，組織内でコーディングスタイルを統一する既存手法

EnforcedStyle オプションを consistent に設定しとしては採用しているコーディングスタイルをルールている．この Cops は Ruby の配列リテラルのインデとして明文化し，ドキュメントとして組織内で共有すントのコーディングスタイルをチェックするルールでる手法がある．しかしこれはドキュメントの作成や維あり，EnforcedStyle オプションに望ましいインデ持に人手が常にかかってしまう．

ントルールを指定する．これに指定できるオプション

また Ruby の Rubocop [1] のような静的解析ツーは以下の 3 つである．

ルでコーディングスタイルを自動評価する手法も存在(a) special inside parentheses

する．例えば Rubocop では YAML 形式の設定ファ(b) consistent

イルにユーザが設定したいコーディングスタイルに(c) align brackets

対応するルールをドキュメントから探し出して記述(a) の special inside parentheses を指定する

する．Rubocop には Cops というコーディングスタと図 2 に示すように，普通の式中に配列を書く際にイルに対応したクラスが用意されていて，自分が採はその式の行頭を基準としてインデントを行う一方．

用したいコーディングスタイルに対応したクラスをメソッド呼び出しの引数として配列を書く場合には開設定ファイルに記述することでソースコード内でそきブラケットの位置を基準にインデントを行わなけれのコーディングスタイルに準拠した書き方になってばならない．(b) の consistent を指定すると，図 3いるかどうかを Rubocop がチェックするようになる．に示すようにメソッド呼び出しの引数としての配列もCops にはパラメータを指定でき，自分たちが採用す行頭を基準にしてインデントを行わなければならなるコーディングスタイルに対応するパラメータを指定

い．一方，(c) の align brackets を指定すると図 4することで自分たちがどのコーディングスタイルを採に示すように普通の式中の配列も，開きブラケットを用しているのかを Rubocop に明示的に指定する．

基準にしてインデントを行う．

図 1 に Rubocop の設定ファイルの記述例を示す．

しかし Rubocop のようなツールは予めツールに

図 1 に示すようにユーザーは自分がチェックしたいルールを人手で設定しなくてはならない．ルール設定

コーディングスタイルに関するルールを順番に記述の際には，人手で用意された Rubocop のドキュメンする．この例では 3 つのルールが設定されている．

トを確認しながら，望む Cops の名前をみつけては設

1, 2 行目では Linelength という Cops で，一行に定する．文法の自由度が高い言語ではルールの設定の許容する文字数を 128 文字に設定している．4, 5 行数が増え，現状のままでは初期コストが増大する．

それを用意することは現実的に十分可能である．例
12345678# special_inside_parentheses
array = [: value]

えば Git の master ブランチにコミットされたコードa r r a y _ i n _ a _ m e t h o d _ c a l l ([ソース化したプロジェクト内のソースコード群など: value])

レビュー済みのソースコード群や，組織がオープンは，きちんと組織のコーディングスタイルに則って記述されたコードかどうかを組織内で優秀なエンジニ

図2

special inside parentheses オプション

アがレビューしていることが多い．そのようなソースコード群は組織が採用するコーディングスタイルに則ったソースコード群であると考えられる．提案する

12345678# consistentarray = [: value]

手法では，組織に実在するこのようなソースコードの量から，学習に必要な十分なコーパスを生成できる．
正しいコーディングスタイルで書かれたプログラムa r r a y _ i n _ a _ m e t h o d _ c a l l ([: value])から実際に学習に用いるコーパスを生成するために，(i) トークン列化と (ii) トークン列の分割をおこなう．
図3

consistent オプション(i) トークン列化では，通常のコンパイラで実施する
ようなトークン化と異なり，コーディングスタイルの表現に適したトークンにプログラムのテキストを変換

1
2
3
4
5
6
78

# align_brackets
array = [: value]

する．従来のトークン化と異なり，まず，本来であればトークン化されない空白や改行もトークン化する．
これは図 5 のように中括弧の前後にスペースがある

a r r a y _ i n _ a _ m e t h o d _ c a l l ([: value])

場合とない場合の異なる 2 つのコーディングスタイルが存在するなど，コード中のどこで改行を行うかが

図4

align brackets オプション

コーディングスタイルを評価する上で重要な情報になるためである．次にインデントは前行と比較した相対的なインデントの深さの数を保持している．例えば

3 機械学習を応用した統計的アプローチ

図 6 の中の 2 から 4 行目と 7 から 9 行目では内容は

我々は，コーディングスタイルをプログラム中の同一の記述だが，2 から 4 行目は関数 func 内で定義トークン列の尤度で表現する方法を提案する．機械学されているため，7 から 9 行目よりもインデントが 1習を利用してこの尤度を計算することで，与えられたつ深くなっている．絶対的なインデントの深さを保持プログラムのコーディングスタイルがどれだけ正しそした場合には，この二つのコーディングスタイルは異うかを機械的に判定できるようになる．機械学習を用なるものとして学習されてしまうが，インデントを前いることでこれまでコーディングスタイルを統一する行との相対的な情報として保持すれば 2 から 4 行目

ために組織毎に手動で行われてきた作業が不要になと 7 から 9 行目のコードは同じコーディングスタイ

り，より低いコストでコーディングスタイルの統一をルで書かれたコードとして学習することが可能とな行うことが可能となる．

る．さらに，クラス名や変数名など各ソースコード固本手法において，正しいコーディングスタイルと有の情報は，同一のトークンに変換し，抽象化していは，正しいコーディングスタイルにしたがって書かれる．これはソースコード固有の情報はコーディングスたプログラムをコーパスとしたときのトークン列のタイルを学習する上では不要な情報であるためであ尤度となる．したがって本方式を利用するには，そのる．プログラムの構成要素とトークンの対応表を 表ようなコーパスを予め用意できなくてはいけないが，1 に示す．

1234
5

# Space有10. times { puts ’ Hello ␣ world ’ }# Space無10. times { puts ’ Hello ␣ world ’}

図5123456789

スペースの有無の違い

していき，1 つのソースコードから複数の学習データ群を生成する．これにより少ない量のプログラムから学習に必要な十分な量のコーパスを生成する．プログラムの 1 行を 1 回の学習に用いる 1 つの学習デー
タとして扱ってしまうと行を跨って表現されるコーディングスタイルを学習することができない．一方でdef func
puts [1 , 2 , 3]. map {| i |i * i}endputs [1 , 2 , 3]. map {| i |i * i}

1 つのソースコード全体をそのまま 1 つの学習デー
タとして扱うと，1 回の学習に用いる学習データがが長くなるため，上手く学習が行われない場合がある．そこで sliding window algorithm を用いて適切なウィンドウサイズを設定することで，複数行に跨ったコーディングスタイルを効率よく学習させる．一方

図6

インデントのレベルが異なる同一コード

で sliding window algorithm はウィンドウサイズをユーザーが指定するため，分割する行数の選び方が学

表1

プログラムの構成要素と対応するトークン

習結果に影響を与える可能性がある．
学 習 に は Bi-drectional LSTM を 用 い る ．Bi-

プログラムの構成要素

トークン

空白

<SPACE>たニューラルネットワークで，入力された学習データ

改行<NEWLINE>のシーケンスを前向きと後ろ向きの双方から学習す

インデント<INDENTX>

る．学習に用いる情報量が多いため，N-Gram や単変数

<ID>

一の LSTM では，尤度を高い精度で計算できない．

クラス<CLASS>

Bi-Directional LSTM は自然言語処理の分野でも文インスタンス変数<INSTANCE VAL>

章中のコンテキストを学習する研究 [3] などで利用さ関数<FUNCTION>

れている．

文字列

<STRING>

本方式では，この学習結果を用いて，与えられたプ

数値<NUMBER>

ログラムが正しいコーディングスタイルに沿っている

リテラル<LITERAL>

かを判定する．各トークンの尤度を計算し，尤度が低オペレーター<OPERATOR>

いと見積もられたトークンを正しいコーディングスタ

クラス変数<CLASS VAL>

イルに沿わないトークンと判断する．判定結果はヒー定数<CONSTANT ID>

トマップを用いて可視化する．ソースコードのどの部

名前空間<NAMESPACE>

分が不適切なコーディングスタイルか認識できるよう

グローバル変数<GLOBAL VAL>に，プログラム全体を表示し，尤度がより低いと判定

コメント<COMMENT>されたトークンの背景をより濃い赤で表示する．

解析に失敗したトークン<ERROR>

Directional LSTM は 2 つの LSTM を組み合わせ

4 実装と実験(ii) トークン列の分割には sliding window algo-

Python を使って本手法を利用したシステムを実装

rithm [2] を用いる．sliding window algorithm は予した．Bi-Directional LSTM の実装には Chainer をめユーザが設定したウィンドウサイズ分の行数を 1 つ利用し，その他の処理については独自に実装した．のウィンドウとして，ウィンドウ内のコードを 1 つのソースコードをトークン化する前処理では字句解析学習データとする．このウィンドウを 1 行ずつずら器を作成する必要があるが，Python の Pygments と表2を自動で判定する手法を提案した．Python で本提案

学習に用いたパラメータ

埋め込み層

隠れ層

ウィンドウサイズ

閾値

150

256

150.0005

いうモジュールが提供する字句解析器を使って実現した．また本実装は Ruby を対象言語として実装している．
実装したシステムを使ったコーディングスタイルの自動評価の精度を測定するために Rubocop との性能比較実験を行った．実験では Rubocop の判定結果を正解として，提案手法を用いて実装されたシステムが図7

ウィンドウサイズを変化させた際の指標値の変化どれだけの精度を出せるのかを precision，recall，F値の 3 つの値を使って計測した．比較するための実験

表3

データはクックパッド株式会社の協力を得て，同社がgithub 上で公開しているオープンソースプロジェク

提案手法の判定精度

precision

recall

F値

0.40

0.72

0.51

トを学習データに，社内に保有する内部データを検査対象のデータにした．またニューラルネットワークの次元数，ウィンドウサイズ，システムが誤りと判定す手法を基にしたシステムを構築し，システムの実用性る尤度の閾値の 3 つのパラメータを判定精度が上がるを検証するためにクックパッド株式会社から提供されように調整した．学習に利用したソースコードはファた実際のソースコードで実験を行い，精度を測定しイル数で 507 ファイル，行数で 21439 行であった．

た．ウィンドウサイズによって学習の精度に大きな差実験の結果， 表 2 のパラメータのとき，最も精度がでてしまうため，プログラムの構造などを解析してがよくなり， 表 3 の結果が得られた．実験では，ウィ自動的に適切なウィンドウサイズを設定すること等がンドウサイズの値が精度に大きく影響を与えていた．

今後の課題である.

図 7 は閾値を 0.005，埋め込み層次元数を 150，隠れ層次元数を 256 に固定し，ウィンドウサイズを変化謝辞させた際の指標値の変化を表す．図 7 が示すように実験に協力いただいたクックパッド株式会社に感謝ウィンドウサイズを大きくすると指標値が改善され，いたします．

ウィンドウサイズが 15 の時に F 値が最も大きな値をとる．また全実験を通して precision と recall の相関

参 考 文 献は正の相関関係が観察された．この結果から我々が実[1] https://github.com/bbatsov/rubocop.
[2] Koç, C. K.: Analysis of sliding window techniques
for exponentiation, Computers & Mathematics withApplications, Vol. 30, No. 10(1995), pp. 17–24.
[3] Melamud, O., Goldberger, J., and Dagan, I.:
context2vec: Learning Generic Context Embedding
with Bidirectional LSTM., CoNLL, 2016, pp. 51–61.

装したシステムにはコーディングスタイルの検査を得意とするソースコードとそうでないソースコードがあると考えられる．

5 まとめ
ニューラルネットワークを用いた尤度計算によって組織のコーディングスタイルに則ったコードかどうか