エンジニアのtetsuです。
今回はDoc2Vecを使ってpythonスクリプトを学習させたお話をします。
Doc2Vecとは何かというと、簡単にいってしまえば、ディープラーニングを用いて英語や日本語の文書をベクトルに変換する手法です。ベクトル同士の近さを測る方法は色々存在しますので、文書をベクトルに変換することで文書同士の近さを計算できるようになります。文書同士の近さを計算できれば、ある文書に似ている文書を探したり、似ている文書のグループを作ったりすることが可能になります。
文書の場合と同様にpythonスクリプトをDoc2Vecで学習させることで、似ているpythonスクリプトを探すことができるのかを試してみます。Doc2Vecはgensimというpythonライブラリに実装されているため、今回はgensimを使用します。
なお、ここではDoc2Vecの仕組みについてはお話しませんので、ウェブ上の他の記事や論文などを参照していただきたいと思います。
pythonスクリプトの処理
Doc2Vecでは文書を単語毎に分割する必要があります。例えば、”I have a pen.”という文書に対しては’I’、’have’、’a’、’pen’、’.’の5つに分割する必要があります。pythonスクリプトに対しても同様の処理をおこないます。標準で提供されている字句解析ライブラリのtokenizeを使用することで、例えば次のスクリプト
1 2 |
a = 1 print(a) |
は’a’、’=’、’1’、’\n’、’print’、'(‘、’a’、’)’に分割することができます(’\n’は改行コードです)。なお、スクリプト中にコメントと空行がある場合は分割後に削除しています。このような処理を約9万個のpythonスクリプト(各10行から1000行程度)に対しておこない、学習に用いました。
Doc2Vecでの学習
Doc2Vecでの学習時に与える情報は文書を分割してできた単語の集まりだけではなく、タグというものとの組になります。これは
1 |
TaggedDocument(words, tags=[file_name]) |
のようにして生成できます。wordsが1つのスクリプトの単語の集まりで、file_nameはそのスクリプトのファイル名です。タグにはファイル名を付与しました。
学習はTaggedDocumentのリストのdocsを生成してから、次のようにおこないました。
1 |
model = Doc2Vec(docs, iter=30, alpha=0.050, min_alpha=0.001, workers=4, window=8, dm=1, min_count=5, size=300) |
dm=1とdm=0では学習するアルゴリズムが異なり、それぞれPV-DMとPV-DBOWと呼ばれています。Doc2Vecの論文にはPV-DMの方が精度が良いという記述があります。また、PV-DMの場合には文書だけではなく、単語をベクトルで表現する方法も学習しますので、こちらを使用しています。
Doc2Vecで学習したモデルでの実験
単語の検索
前述の通り、Doc2Vecの学習時にdm=1とした場合は、文書をベクトルとして表現するだけではなく、各単語もベクトルで表現することができるようになります。これを使って、まずは単語のベクトル表現の学習が上手くできているかどうかをみてみます。pythonで使われる”append”、”+”、”list”にそれぞれ似ている単語を検索します。例えば”append”に似ている単語を検索したい場合には
1 |
model.most_similar("append") |
とします。これにより”append”をあらわすベクトルにcosine類似度の意味で近い単語のベクトルを見つけてきます。以下に類似度が大きい上位3つの単語を示します(類似度が大きいほど似ています)。
- “append”での検索結果
単語 単語の類似度 extend 0.72 += 0.56 add 0.55 - “+”での検索結果
単語 単語の類似度 += 0.51 / 0.50 – 0.46 - “list”での検索結果
単語 単語の類似度 tuple 0.62 dict 0.50 len 0.44
“append”の結果の上位2つはリストの結合に使われる関数、演算子ですね。addは何かのスクリプトで定義されているものかもしれません。”+”と”list”の検索結果にも、同様にある意味で似たものが選ばれています。少なくとも単語に関しては上手く学習ができているようです。
文書の検索
次に文書の検索をおこなってみます。学習データの中には私の書いたfizzbuzzのスクリプトと他の人が書いたfizzbuzzのスクリプトを混ぜておきました。私のmyfizzbuzz.pyという名前のスクリプトで検索をかける場合は次のようにします。
1 |
model.docvecs.most_similar(["myfizzbuzz.py"]) |
この結果を以下に示します。
スクリプト | スクリプトの類似度 |
---|---|
他の人のfizzbuzz | 0.60 |
あまり関係のなさそうなスクリプト1 | 0.53 |
あまり関係のなさそうなスクリプト2 | 0.51 |
fizzbuzzのスクリプトが一番上位になっていることがわかります。ただし”Fizz”や”Buzz”などの単語自体は学習されていないことに注意していただきたいと思います。つまり”Fizz”や”Buzz”がどちらのコードにも含まれているから検索結果の上位に出てくる、というわけではないです。
最後に
今回はDoc2Vecを用いてpythonスクリプトをベクトルで表現する方法を学習させました。なんとなくでpythonを選んたのですが、他の言語を学習させてみると面白い結果が得られるかもしれません。