[自然言語処理/NLP] Word2VecをSageMaker上で使ってみる (実行編)

2019.09.26

こんにちは、Mr.Moです。 Word2Vecについて理論を学んだので、次は実際に使ってみたいと思います。

ちなみに理論については下記の記事にまとめました。

[自然言語処理/NLP] Word2Vec触ったので備忘録としてざっくりまとめておく (理論編)

前提

この記事ではSageMaker上で動かすことを前提に進めていきます。 SageMakerについては弊社ブログで情報を発信しておりますのでこちらも参考にしてみてください。 https://dev.classmethod.jp/referencecat/amazon-sagemaker/

事前準備

SageMakerでノートブックインスタンスの作成

まずはじめにSageMakerの画面を開きます。

https://ap-northeast-1.console.aws.amazon.com/sagemaker/home?region=ap-northeast-1#/notebook-instances

次にノートプックインスタンスを作成します。 下記の要領で赤枠の部分を対応して後はデフォルトのままで大丈夫です。

image.png image.png

ノートブックはconda_python3の環境で実行します。

image.png

MeCabのインストール

ノートブックのセルに下記のコードをコピペしておもむろに実行してください。完了まで少し時間がかかります。

参考:https://qiita.com/YuukiMiyoshi/items/00b9878a1fa32b859a43

%%bash
sudo yum install -y bzip2 bzip2-devel gcc gcc-c++ git make wget curl openssl-devel readline-devel zlib-devel patch file

# 作業フォルダを作成して移動
mkdir -p ~/source/mecab
cd ~/source/mecab

# ソースをダウンロードして解凍して移動
wget 'https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE' -O mecab-0.996.tar.gz
tar zxvf mecab-0.996.tar.gz
cd mecab-0.996

# インストール先フォルダを作成
sudo mkdir -p /opt/mecab

# configure(コンパイルのための設定)を実行し、コンパイルしてインストール
./configure --prefix=/opt/mecab --with-charset=utf8 --enable-utf8-only
make
sudo make install

# bashの場合
echo "export PATH=/opt/mecab/bin:\$PATH" >> ~/.bashrc
source ~/.bashrc

sudo bash -c "echo \"/opt/mecab/lib\" > /etc/ld.so.conf.d/libmecab.conf"
sudo ldconfig

# 作業フォルダを作成して移動
mkdir ~/source/mecab-ipadic
cd ~/source/mecab-ipadic

# 辞書ファイルを取得して解凍して移動
wget 'https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7MWVlSDBCSXZMTXM' -O mecab-ipadic-2.7.0-20070801.tar.gz
tar zxvf mecab-ipadic-2.7.0-20070801.tar.gz
cd mecab-ipadic-2.7.0-20070801

# 設定してmakeしてインストール
./configure --with-mecab-config=/opt/mecab/bin/mecab-config --with-charset=utf8
make
sudo make install

# 作業フォルダに移動してファイルを取得
cd ~/source
git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git

# 設定とともにインストールを実行
./mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -y -p /opt/mecab/lib/mecab/dic/neologd

Word2Vecの学習済みモデルダウンロード

今回は学習済みのモデルを使わせていただきましょう。 ノートブックのセルに下記のコードをコピペして実行します。

参考:http://aial.shiroyagi.co.jp/2017/02/japanese-word2vec-model-builder/

!wget http://public.shiroyagi.s3.amazonaws.com/latest-ja-word2vec-gensim-model.zip
!unzip latest-ja-word2vec-gensim-model.zip

各種モジュールのインストール

こちらも同様にコードをノートブックのセルにコピペして実行してください。

!pip install --upgrade pip
!pip install gensim
!pip uninstall numpy -y
!pip install numpy
!pip install mecab-python3

モデルの読み込み

同様。

from gensim.models.word2vec import Word2Vec
import gensim

model_path = './word2vec.gensim.model'
model_w2v = Word2Vec.load(model_path)

Word2Vec使ってみる

準備が整ったのでさっそく試していきましょう。

単語の演算

下記は 王様 - 男 + 女 の計算です。ちゃんとそれっぽい結果になっているのが面白いですね。

model_w2v.wv.most_similar(positive=['王様','女'], negative=['男'], topn=5)

image.png

文章の類似を判定してみよう

Word2Vecは基本的に単語単位での処理を行いますが、実際は文章単位で扱いたくなりますよね。 下記の記事を参考にちょっとやってみましょう

参考:https://qiita.com/yoppe/items/512c7c072d08c64afa7e

下準備

必要な処理を関数に定義しておきます。 下記、関数のコードもノートブックのセルにコピペして実行しておいてください。

  • 分かち書き用関数
import MeCab
mecab = MeCab.Tagger("-Owakati -d /opt/mecab/lib/mecab/dic/neologd")

def get_wakati(sentence):
return mecab.parse(sentence).replace(' \n', '').split()
  • 類似度算出用関数
import numpy as np
def avg_feature_vector(sentence, num_features):
words = get_wakati(sentence)
feature_vec = np.zeros((num_features,), dtype="float32") # 特徴ベクトルの入れ物を初期化
print(words)
for word in words:
feature_vec = np.add(feature_vec, model_w2v.wv[word])
if len(words) > 0:
feature_vec = np.divide(feature_vec, len(words))
return feature_vec
from scipy import spatial
def sentence_similarity_w2v(sentence_1, sentence_2):
num_features=50
sentence_1_avg_vector = avg_feature_vector(sentence_1, num_features)
sentence_2_avg_vector = avg_feature_vector(sentence_2, num_features)
# 1からベクトル間の距離を引いてあげることで、コサイン類似度を計算
return 1 - spatial.distance.cosine(sentence_1_avg_vector, sentence_2_avg_vector)

文章の類似度を見てみる

だいたい同じ意味の2つの文章で見てみましょう。文章内の単語は違うもので構成したのですが類似している文章と判断されているのが類似度の数値の高さ(0.9309...)から見て取れますね!

result = sentence_similarity_w2v(
"昔、高校の運動部で厳しい練習をしていた",
"かなり前、学校の陸上部でハードなトレーニングをしていた"
)
print(result)

image.png

ちなみに文章を扱う場合、Word2Vecを拡張したDoc2Vecというものもあるのでついでに使ってみます。

Doc2Vec

事前準備

SageMakerでノートブックインスタンスの作成

SageMakerの画面を開きます。

https://ap-northeast-1.console.aws.amazon.com/sagemaker/home?region=ap-northeast-1#/notebook-instances

次にノートプックインスタンスを作成します。 下記の要領で赤枠の部分を対応して後はデフォルトのままで大丈夫です。

image.png image.png

ノートブックはconda_python3の環境で実行します。

image.png

MeCabのインストール

本記事の上の方に記載しているものと同じなので、そちらをご覧ください。

モデルのダウンロード

ノートブックのセルに下記のコードをコピペして実行します。(結構時間がかかります。サイズも大きいのでご注意)

%%bash
wget https://www.dropbox.com/s/njez3f1pjv9i9xj/jawiki.doc2vec.dmpv300d.tar.bz2?dl=0
mv jawiki.doc2vec.dmpv300d.tar.bz2?dl=0 jawiki.doc2vec.dmpv300d.tar.bz2
tar -jxvf jawiki.doc2vec.dmpv300d.tar.bz2

各種モジュールのインストール

本記事の上の方に記載しているものと同じなので、そちらをご覧ください。

モデルの読み込み

ノートブックのセルに下記のコードをコピペして実行します。

from gensim.models.doc2vec import Doc2Vec
model_d2v = Doc2Vec.load("jawiki.doc2vec.dmpv300d.model")

関数

必要な処理を関数に定義しておきます。 下記、関数のコードもノートブックのセルにコピペして実行しておいてください。

import MeCab
mecab = MeCab.Tagger("-Owakati -d /opt/mecab/lib/mecab/dic/neologd")

def get_wakati(sentence):
return mecab.parse(sentence).replace(' \n', '').split()
def sentence_similarity_d2v(sentence_1, sentence_2):
w1 = get_wakati(sentence_1)
w2 = get_wakati(sentence_2)

return model_d2v.docvecs.similarity_unseen_docs(model_d2v, w1, w2)

文章の類似を判定してみよう

準備が整ったのでさっそく試しましょう。

result = sentence_similarity_d2v(
"昔、高校の運動部で厳しい練習をしていた",
"かなり前、学校の陸上部でハードなトレーニングをしていた"
)
print(result)

image.png

数値が 1 に近いほど類似していることを表します。 こちらも文章内の単語は違うもので構成した2つの文章ですが、類似度は高い数値(0.843...)となっていますね!

ご注意

作業が終わったら余計な課金が発生しないよう、起動したノートブックインスタンスを停止(もしくは削除)しておいてください。 image.png

まとめ

今回扱ったWord2Vec、Doc2Vecは使用しているモデルの背景も異なるので単純に精度の比較はできないですが、双方とも文章の意味を捉えてるかのような結果を出せているのが良いですね。 新しい手法もまだまだ出ていますので、触ったらまた記事にしていきたいと思います。