読者です 読者をやめる 読者になる 読者になる

paiza開発日誌

paiza(https://paiza.jp ギノ株式会社)の開発者が開発の事、プログラミングネタ、ITエンジニアの転職などについて書いています。

機械学習初心者向け、Word2VecとDoc2Vecでディープラーニングやってみた

f:id:paiza:20170315144200p:plain
秋山です。

機械学習が人気ですが、「Word2Vec」「Doc2Vec」という、文章などを分析するニューラルネットワークモデルを知っていますか?

すごーく簡単に言うと、「Word2Vec」は単語の類似度のベクトル、「Doc2Vec」は文章の類似度のベクトルを表現します。

結構前に話題になったので既に知っている人も多いかもしれませんが、今回はpaizaのスキルチェック問題に提出された一部のコードを対象に、「Word2Vec」と「Doc2Vec」でどんなことができるかやってみたいと思います。(※スキルチェック問題や回答の内容は判別できないように処理しています)

■Word2Vecについて

ざっくり言うと、ある単語の周辺に別の単語が出現する確率……みたいなものを見てくれます。ニューラルネットワークを使って、類似度を求めています。Word2Vecは隠れ層1、出力層1の、2層のニューラルネットワークです。

例えば、「ピーマン」と「焼肉」という単語の比較を考えてみましょう。

「ピーマン」は「おいしい」、「焼肉」は「まずい」と思う人もいるとは思いますが、それは珍しいケースだった場合に
「ピーマン」の周りには「まずい」の頻度が高い
「焼肉」の周りには「おいしい」の頻度が高い
という結果が出たら、「ピーマン」と「焼肉」という単語はベクトルとして異なるんだな、ということがわかります。何となくわかるでしょうか。(※これはあくまで分析データ内にそういう文が多かったら、という例です。私は焼肉もピーマンもおいしいです)

■Doc2Vecについて

Doc2Vecは、単語ベクトルとパラグラフベクトルを組み合わせることで、文章自体のベクトルを求めます。

実際にPythongensimというライブラリを使って試してみました。

対象は、スキルチェック問題へ提出されたコードのうち、Pythonで書かれたコードとします。(ブロックインデントでスペース区切りが多く、関数名とか変数名とかバラしやすいから)

gensimのインストールに関してはPythonですので

pip install gensim

だけで済みます。

ディープラーニングをやってみる

今回は、前にこのブログでデータ分析をやってみた記事(後でリンク貼ります)でも使った、Jupyter上で実際に動かして結果を見てみましょう。

Doc2Vecを作ればWord2Vecの方も一緒に参照できるので、まずDoc2Vecから求めます。

Doc2Vecに与えるデータとしては、提出されたPythonのコードのうち、「B問題で1点以上を獲得したもの」を対象とします。また、コメントは取り除き、スペース、タブ、改行区切りで単語に分解します。

コードのラベルとしては、提出したユーザーのランクを割り当てます。

これで、例えばあるランクのユーザーが提出したコードは、その前後のランクのユーザーが書いたコードに類似しているかどうか……みたいなことがわかるのでは?と想定しています。

データ取得に関しては、以前データ分析をやってみた記事と同じ方法でSQLを叩いて、必要な部分だけを取り出しています。
f:id:paiza:20170315133557j:plain

上記のような入力をcodeに関しては空白文字で分割して使用します。

import gensim
from gensim.models.doc2vec import Doc2Vec
from gensim.models.doc2vec import TaggedDocument
training_code = []
for i in df.iterrows():
     training_code.append(TaggedDocument(words=i[1].code.split(), tags=[str(i[1].user_rank)]))
model = Doc2Vec(documents=training_code, size=100 , window=3, min_count=1, dm=1)

TaggedDocumentでwords="対象の文章", tags=["タグ"] というように、文章とタグを引数として与えます。

それをまずリストに入れて、Doc2Vecで documents=TaggedDocumet のリストを指定し、その他のオプションを指定していきます。

sizeは単語ベクトルの次元数、windowはどの周辺単語まで見るか、min_countは未満の出現頻度の単語は無視する、dm=1はdmpvというアルゴリズムを使う、ということをそれぞれ指定しています。

パラメータのチューニングの余地はまだあるかもしれませんが、windowが3単語なのは、ソースコードにおいてそこまで広い範囲で単語の関係性はないのでは?という理由です。その他は公式のドキュメントのデフォルトの値(size=100など)にしました。

■結果を見てみる

まずWord2Vecの結果として、似ている単語について見てみましょう。

model.most_similar(positive="if") とすると、"if"に類似している単語上位10件を取得できます。

for i in model.most_similar(positive="if"):
    print(i[0], i[1])

これを実行した結果がこちら。
f:id:paiza:20170315124331p:plain
なんとなーくandとかelseとかelifとかが引っかかりますね。ただ単語の分割が微妙で、変なワードも含まれています。もう少し入力データを整えてからの方がよかったかもしれません……。

続いて、"True"に類似している単語は以下のような結果が出ました。
f:id:paiza:20170315124404p:plain
Falseはまさに、という感じですね。他にも"flg1"や"deta"などは条件文とかで出てきそうなので、近い感じがありますね。


今度はDoc2Vecを使い、ユーザーのランクをタグとして、ソースコードの類似度を比較していきましょう。
model.docvecs.most_similar(['S']) とすると、'S'をタグとして上位10件の類似度を出力できます。今回はタグがS、A、B、C、Dの5種なのでどれかのタグを指定すると4件結果が返ってきます。
f:id:paiza:20170315124509p:plain
Sランクのコードに似ているのはどのランクのコードなのか?Sランクは最高ランクなので、A、B、C、Dとランクの高い順に似ているのでは?と思いますが、実際はDランクユーザーの書いたコードが2番目に近いという結果が出ました。

Dランクユーザーの解答はシンプルなコードが多く、それで逆にSランクのコードとの類似度が上がってしまうのかな?という感じがします。

同様に、CランクのコードもBランクのコードより類似していますね。Sランクユーザーは、上位問題で正解できることはもちろん、よりシンプル化したコードを提出している傾向がある?ということが言えるかもしれません。

では、サンプル対象のコードをさらに絞ってみます。Dランク問題への提出コードで、点数が100点のものだけに絞り込んでみました。
f:id:paiza:20170315124545p:plain
ランクの高い順に近づきましたね。ただ、やはりDとCが微妙に前後していますね……パラメータのチューニングによってはもう少しよくなるかも?

<参考>

以前Jupyterを使ってデータ分析してみた記事はこちら
paiza.hatenablog.com

■まとめ

こういう調査を進めていくと、Dランク問題を解いてもらうだけでランクがわかってしまうとか、実行結果を見なくても書いたコードを分析すれば高ランク取得者かそうでないかがわかってしまうとか……もしかしたら、そんな可能性もあるのかもしれませんね。

できれば単純な単語分割だけでなく、Pythonのastとかでコードの構文木などをデータに落とし込んで詳しく分析してみたいのですが……それはまた別の機会にしたいと思います。


機械学習どころかプログラミング自体が初心者なので、Pythonを基礎から学びたい!」という方は、プログラミングが動画で学べる「paizaラーニングPython入門編から始めてみると、無理なく基礎を習得できると思います。
paiza.jp

Pythonの講座も公開中!プログラミングが動画で学べるレッスン


paizaは、プログラミング未経験者・初心者向け学習サービス「paizaラーニングを、新サービスとして独立オープンいたしました。

今回記事の中で使用しているPythonの入門講座も好評公開中です。ぜひごらんください!

↓詳しくはこちら
paiza.jp

そして、paizaでは、Webサービス開発企業などで求められるコーディング力や、テストケースを想定する力などが問われるプログラミングスキルチェック問題も提供しています。
paiza.jp
スキルチェックに挑戦した人は、その結果によってS・A・B・C・D・Eの6段階のランクを取得できます。必要なスキルランクを取得すれば、書類選考なしで企業の求人に応募することも可能です。「自分のプログラミングスキルを客観的に知りたい」「スキルを使って転職したい」という方は、ぜひチャレンジしてみてください。

ITプログラマ・エンジニア向け転職・就活・学習サービスのpaiza

プログラミング入門講座|paizaラーニング

PHP入門編Ruby入門編Python入門編Java入門編JavaScript入門編C言語入門編C#入門編アルゴリズム入門編