kuro_reraのブログ

新米エンジニアのブログ。いろいろと模索中。

Word2VecでWikipediaに現れる単語の意味を学習する

自然言語処理においては、単語に「意味」をもたせることで文章を「解釈」する。
ここでいう「意味」はベクトルで表すことを示す場合が多い。
手法はTF-IDFやWord2Vecなどさまざまだが、いずれも大量の文章群から文章/単語の特徴を数値化するものだ。

Wikipediaから単語の意味を学習する

ここでは、「大量の文章群」としてWikipediaの記事を選択する。
また、形態素解析にはMeCab(辞書はmecab-ipadic-NEologd)を利用する。
(MeCabの環境設定についてはこちらも参照ください)
Wikipediaからの文章抽出にあたってこちらの記事を参考にさせていただいた。 Wikipediaの文章は、ここから取得できる。
全記事だとあまりに膨大になってしまうので、ここでは分割されたもの(jawiki-latest-pages-articles.xml-*****.bz2)をダウンロードした。

ダウンロードファイルにはXML形式の記事が圧縮されている。
これをWikiextractorというスクリプトを用いて文章だけを取り出す。

$ git clone https://github.com/attardi/wikiextractor.git
$ python wikiextractor/WikiExtractor.py -b 100M jawiki-latest-pages-articles*.xml-******.bz2

-bは文書ファイル1つあたりのサイズを指定するオプションである。
デフォルトは1MBだが、これだと数百ファイルできてしまうので、ある程度の量を指定するといいだろう。
出力ファイルを指定したい場合は、-oオプションを使えばよい。
文章だけ取り出すのには1時間弱必要とした。

作成されたファイルをcatコマンドで連結する。

$ cat wiki_* > corpus

こうしてコーパスが作成された。

単語ベクトルを作成する

コーパスから単語ベクトルを作成するにあたって、まず文章を単語ごとに分かち書きする。
分かち書きの方法もさまざま(助詞は除くなど)だが、今回は単純に分かち書きしてみる。

$ mecab corpus -O wakati -o corpus_wakati

-oは出力ファイル名を指定するオプションである。
これで、Wikipediaから単語の意味を学習することができた。

Word2Vecで遊んでみる

単語を学習できたので、これを使って遊んでみる。
それぞれの単語はベクトルで表されているわけだが、似ている単語のベクトルは似ているといえよう。
most_similar関数を使うと、入力に対し近い単語を出力してくれる。

from gensim.models import word2vec
model = word2vec.Word2Vec.load('model_wiki')
print(model.most_similar('野球'))
[('サッカー', 0.8565059304237366), 
('ボクシング', 0.7676202654838562), 
('ラグビー', 0.7625299096107483), 
('プロレス', 0.7522695660591125), 
('柔道', 0.7483185529708862), 
('プロ野球', 0.7468701601028442), 
('バスケットボール', 0.7369800806045532), 
('レスリング', 0.7255582809448242), 
('スポーツ', 0.7190646529197693), 
('練習', 0.7177714705467224)]

これらの単語が、「野球」に近いとされた単語である。
単語の右の数字はベクトル間のコサインの値を示す。
すなわち、まったく同じベクトルの場合1になり、1に近いほど単語の意味が近いといえる。

most_similar関数は、単語の足し算・引き算を行うこともできる。

print(model.most_similar(positive=['東京', 'フランス'], negative=['日本']))
[('パリ', 0.7332836985588074), 
('ベルリン', 0.7104079723358154), 
('ハンブルク', 0.6936348676681519), 
('ロンドン', 0.6928915977478027), 
('ミラノ', 0.691125214099884), 
('マルセイユ', 0.6871293783187866), 
('ケルン', 0.6853926777839661), 
('ウィーン', 0.6830347776412964), 
('ミュンヘン', 0.6771801114082336), 
('フランクフルト', 0.6715824007987976)]

「東京」-「日本」は首都、大都市のような意味をもつベクトルになるのだろう。
そのベクトルに「フランス」を足すと、予想通り「パリ」が結果として出てきた。

この単語ベクトルを使って、次回は何か面白いことができないかと思っている。

MeCabをインストールしPythonから呼び出す

Google HomeAmazon Echoなど、AIアシスタントが流行している。
これらは人間の声に対応し処理を行うものであるが、その処理は、
「声を受け取る→文にする→文の内容を解釈する→それに対応した出力をする」
、といったプロセスをとると考えられる。

さて、ここにおける「文の内容を解釈する」はどのようなことを指すだろうか。
おそらくではあるが、AIアシスタントにおける処理パターンは有限で、入力に近いパターンを判断しているのだろう。
こうした「判断」ひいては「解釈」にあたっては、大雑把に言えば単語それぞれにベクトルを与えるのが主流である。

しかし、日本語の処理においてこれらの手法にはやや壁がある。それは、文から単語を取り出すことにある。
というのも、日本語では欧米言語と異なり、単語と単語が空白で区切られていない。
つまり、日本語の処理においてはまず単語と単語を区切ることから始まるのである。

それらは、「形態素解析」によって実現することができる。
代表的なツールとしてMeCabJanomeがあるが、ここではMeCabを使う。
MeCabは高速かつ的確で人気である(と思う。)が、使用するまでにやや難があるため記事としたい。 なお、このページなどを参考にしている。

まずはMeCabをインストールする。
環境は以下の通りである。

いろいろと設定するのが面倒なので、MeCabのインストールはapt-getで行う。
apt-getはパッケージ管理システムであり、apt-getでインストールすると環境設定が楽にできる。

$ sudo apt-get install mecab mecab-ipadic mecab-ipadic-utf8 libmecab-dev

これで、MeCabのインストール自体は完了である。
実際にターミナル上で動かしてみる。

$ mecab
青木宣親選手が日本球界に復帰することになった
青木    名詞,固有名詞,人名,姓,*,*,青木,アオキ,アオキ
宣      名詞,サ変接続,*,*,*,*,宣,セン,セン
親      名詞,一般,*,*,*,*,親,オヤ,オヤ
選手    名詞,一般,*,*,*,*,選手,センシュ,センシュ
が      助詞,格助詞,一般,*,*,*,が,ガ,ガ
日本    名詞,固有名詞,地域,国,*,*,日本,ニッポン,ニッポン
球界    名詞,一般,*,*,*,*,球界,キュウカイ,キューカイ
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
復帰    名詞,サ変接続,*,*,*,*,復帰,フッキ,フッキ
する    動詞,自立,*,*,サ変・スル,基本形,する,スル,スル
こと    名詞,非自立,一般,*,*,*,こと,コト,コト
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
なっ    動詞,自立,*,*,五段・ラ行,連用タ接続,なる,ナッ,ナッ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
EOS

このように単語ごとに分割してくれるが、デフォルトの辞書では固有名詞の扱いに弱い。
(ちなみに青木宣親選手は筆者の一番好きな野球選手である。)
そこで、固有名詞にも対応した辞書を追加でインストールする。

使うのはmecab-ipadic-NEologdという辞書である。
好意で定期的に更新されている辞書である。頭が下がる。
gitを経由してインストールするのが一番筋が良い。

$ sudo apt-get git
$ git clone https://github.com/neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd
$ ./bin/install-mecab-ipadic-neologd -n -a

辞書のデータは結構膨大で、2~3分はかかると思っていい。
完了したら、階層を移動しインストールファイルを実行する。
なお、デフォルトでは辞書のインストール先は/usr/lib/mecab/dic/mecab-ipadic-neologdとなっている。
変更したい場合は/usr/mecab/mecab-config--dicdirを編集すればよい。

新しくインストールした辞書は、-dオプションで指定すると利用できる。

$ mecab -d /usr/lib/mecab/dic/mecab-ipadic-neologd/
青木宣親選手が日本球界に復帰することになった
青木宣親        名詞,固有名詞,一般,*,*,*,青木宣親,アオキノリチカ,アオキノリチカ
選手    名詞,一般,*,*,*,*,選手,センシュ,センシュ
が      助詞,格助詞,一般,*,*,*,が,ガ,ガ
日本球界        名詞,固有名詞,一般,*,*,*,日本球界,ニッポンキュウカイ,ニッポンキ ューカイ
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
復帰    名詞,サ変接続,*,*,*,*,復帰,フッキ,フッキ
する    動詞,自立,*,*,サ変・スル,基本形,する,スル,スル
こと    名詞,非自立,一般,*,*,*,こと,コト,コト
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
なっ    動詞,自立,*,*,五段・ラ行,連用タ接続,なる,ナッ,ナッ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ

このように、「青木宣親」が一つの固有名詞と判断されている。
しかしながら、いちいち辞書を指定するのも面倒なので、これをデフォルトの辞書に設定してしまおう。
mecabrcファイルを編集するが、通常は編集できないのでパーミッションを変更しよう。

$ sudo chmod 777 /etc/mecabrc
$ vi /etc/mecabrc
dicdir = /usr/lib/mecab/dic/mecab-ipadic-neologd
$ sudo chmod 644 /etc/mecabrc


これでデフォルトでインストールした辞書を使用できる。

$ mecab
青木宣親選手が日本球界に復帰
青木宣親        名詞,固有名詞,一般,*,*,*,青木宣親,アオキノリチカ,アオキノリチカ
選手    名詞,一般,*,*,*,*,選手,センシュ,センシュ
が      助詞,格助詞,一般,*,*,*,が,ガ,ガ
日本球界        名詞,固有名詞,一般,*,*,*,日本球界,ニッポンキュウカイ,ニッポンキ ューカイ
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
復帰    名詞,サ変接続,*,*,*,*,復帰,フッキ,フッキ
する    動詞,自立,*,*,サ変・スル,基本形,する,スル,スル
こと    名詞,非自立,一般,*,*,*,こと,コト,コト
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
なっ    動詞,自立,*,*,五段・ラ行,連用タ接続,なる,ナッ,ナッ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
EOS


さて、MeCabコマンドライン上で利用できるようになったが、実際に利用するのはプログラム上であるのがほとんどであろう。
ここでは、PythonからMeCabを呼び出せるよう設定する。
といっても、mecab-python3パッケージをインストールするだけでよい。

$ pip install mecab-python3


これで、次のようにPythonからMeCabを利用できる。

import MeCab

mecab = MeCab.Tagger("-O wakati")
print(mecab.parse("青木宣親選手が日本球界に復帰することになった。"))

なお、MeCab.Taggerの引数はオプションである。
-Oは出力の形式を変更するオプションで、wakatiは分かち書き(単語と単語の間に空白を入れる)をする形式である。

$ python mecab_test.py
青木宣親 選手 が 日本球界 に 復帰 する こと に なっ た 。

このように、PythonからMeCabを呼び出すことができた。

LinuxにPython3とAnacondaをインストール

LinuxにはPythonがデフォルトでインストールされている。
したがって、特に何もインストールしていない状態でもPythonを利用できる。

$ python
Python 2.7.12 (default, Nov 20 2017, 18:23:56)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

このようにPythonを利用できるが、気を付けたいのはそのバージョンである。
ここではPython2.7.2と表示されているが、Python2と現在主流のPython3はいくぶん仕様が違う。
例えばprint文の記法が違うのであるが、困ったことにPython2とPython3では互換性がない。
そうであれば最初からPython3を使うようにしてしまおう、というのが今回の目的である。

ところで、Python数値計算ライブラリの充実が魅力として知られている。
ライブラリは通常その都度インストールしなければいけないが、それはそれで面倒なこともあるだろう。
それらのライブラリをディストリビューションという形でまとめたのがAnacondaである。
すなわち、Anacondaをインストールしてしまえばそれだけで多くのライブラリを使えるのだ。
なお、AnacondaにはPython3も同梱しているので、Python3を個別でインストールする必要もないのである。
(Python3だけのインストールももちろんできるが、環境変数の設定などで結構ハマる。Anacondaならその心配は不要だ)

Anacondaのインストール

Anacondaはこのページからダウンロードできる。
今回はLinuxにインストールするので、OSでLinuxを選択してからインストーラをクリックする。
執筆時点でのAnacondaのバージョンは5.0.1だった。
DownLoadボタンを押すと.shファイルがダウンロードされるので、これをWinSCPを利用してゲストOS側に移動する。(あるいは、ゲストOS上でダウンロードする。)
WinSCPについては前回の記事を参照されたい。
なお、.shファイルを利用したインストールにおいては、シェルを実行したユーザにのみインストールされるはず。
全ユーザに対応させたい場合は、(全ユーザで同じことをやることもできますが)このやり方は非推奨になると思います。ご承知おきください。

ゲストOS上に.shファイルを置いたら以下のコマンドで実行する。.shファイルの置き場所はどこでもよい。
$ sh Anaconda3-5.0.1-Linux-x86_64.sh
シェルを叩いて進めると利用規約が出てくる。同意すると、Anacondaのインストール先を聞かれる。

Anaconda3 will now be installed into this location:
/home/ユーザ名/anaconda3

  - Press ENTER to confirm the location
  - Press CTRL-C to abort the installation
  - Or specify a different location below

[/home/ユーザ名/anaconda3] >>>

特にこれで問題なければそのままEnterを押す。
インストール先を指定したければそのパスを指定する。
数分でインストールが完了すると、anacondaのコマンドを優先的に使うよう環境変数のPATHに含めてよいか聞かれる。
一見問題ないようだがここは議論の分かれるところで、この設定をすると既存の設定があった場合にも優先してAnacondaのコマンドが使われてしまう。
そのためデフォルトはnoとなっている。ただし今回は上書きされても特に問題ないのでyesとする。

Do you wish the installer to prepend the Anaconda3 install location
to PATH in your /home/ユーザ名/.bashrc ? [yes|no]
[no] >>> yes

これにてAnacondaのインストールが完了する。

Anacondaがインストールされていることの確認

インストールが完了したので、それを確認する。pythonと入力してみよう。

$ python
Python 2.7.12 (default, Nov 20 2017, 18:23:56)

Python3と表示されると思いきや、デフォルトのままである。
実は、この状態ではまだAnacondaは有効になっていない。
以下のコマンドを打ってAnacondaを有効にする。

$ export PATH=/home/ユーザ名/anaconda3/bin:$PATH

Anacondaをインストールしたパスを環境変数に設定した。
再度確認してみよう。

$ python
Python 3.6.3 |Anaconda, Inc.| (default, Oct 13 2017, 12:02:49)

Python3がインストールされていることが確認できた。

WinSCPを利用してホストOSとVirtualBox上のゲストOS間でファイルをやりとりする

前回Tera Termを導入し、ホストOSからゲストOSをコマンドで動かすことができるようになった。
今回は、ホストOSとゲストOSの間でファイルをやりとりできるようにするのが目的だ。
ここでは、WinSCPというソフトを利用する。

ファイル転送通信プロトコルについて

ファイルのやりとりにはひと昔前にはFTPというプロトコルが使われていた。
15年以上前にHP作成などをしていたものだが、当時はFFFTPなんかをよく使っていたものだ。(最近になってサービスが終了したらしい。ララランドっぽいですよね)
しかし、FTPはセキュリティ上で問題があり、通信データが暗号化されてないために盗んだときにそのまま漏れてしまうという難点があった。
そこを暗号化したのがSFTPなりSCPというプロトコルで、これで安全にデータをやりとりできる。
それをできるのがWinSCPってわけだ。

WinSCPのインストール

ダウンロードページは こちら。執筆時の最新バージョンは5.11.3だった。
ダウンロードしたファイルを開くとインストーラが開くので、素直に従って進める。
インターフェイスは「コマンダー」と「エクスプローラー」の2種類あるが、好きなほうを選べばよい。
ちなみにコマンダーは左右に接続元/先のディレクトリ構造を表示するもので、
エクスプローラーは左右ではなく2つのウインドウに表示するものだ。

WinSCPによる接続

ゲストOSに接続する上である種当然ではあるが、ゲストOSは起動しておく。
インストールしたWinSCPを開くと、次のようなダイアログが表示される。
ここでは、赤枠のなかの4つを以下のように書き換える。
f:id:kuro_rera:20180114115736p:plain

  • ホスト名→127.0.0.1
  • ポート番号→前回の記事で設定した、ホスト側のポート番号(ここでは3000)
  • ユーザ名→ゲストOSで接続するユーザ名
  • パスワード→上のユーザのパスワード

なお、ここで「保存」を押すと入力した内容が保存される。
毎度入力するのも面倒な場合は保存しておくとよいだろう。
初回接続時には、例によってセキュリティ警告のダイアログが出る。
ここも「はい」を押して問題ない。

接続はこれで完了した。
ファイルの移動には、ドラッグ&ドロップでよい。
ゲストOS上のファイルも、WinSCP上でそのまま編集できる。(編集対象ファイルを右クリックから、テキストエディタで開ける)

これでファイルのやり取りもできるようになった。

Tera TermでVirtualBox上のUbuntuとホストOSを接続する

購入したマシンにはWindows 10 Homeがプリインストールされているが、まずはLinux環境を構築するところから始める。
必ずしもLinuxで開発しなくてもよいのだが、パッケージ管理が簡単だろうというのが一番の理由である。
また、LPICを受験するつもり(Level1だが)なので、ついでに慣れてしまおうという魂胆である。

VirtualBoxUbuntuの導入

  • Linux環境の構築においてダウンロードしたもの
    • VirtualBox(5.2.4)
    • Ubuntu(16.04.3 LTS) ※Ubuntu(17.10)はBIOSが破壊されるバグが発覚しただのしないだので、導入を見送り

以下のページなどを参照しながら。
このあたりは調べればだいたい出てくる。
【初心者でもわかる】VirtualBoxインストール方法を詳しく!
VirtualBoxにUbuntu16.04をインストール - Qiita

で、Ubuntuの導入はたいして躓かなかった。
素直に従っておけばよかろう。

Tera Termのダウンロード

さて、Ubuntuは画像のようにGUIをもっている。
f:id:kuro_rera:20180111225248p:plain
(新井さんがいたからキャプチャをとった)
わりとシュッとしたいいデザインで、動作も軽くよいOSだと思う。
しかし、あくまで仮想環境であって、コマンド上で動けば十分という場合もあるだろう。

そこで、ホストOS上(Windows)でゲストOS(Ubuntu)を動かせるようにする。
具体的には、Tera Termというソフトをダウンロードする。執筆時点での最新Verは4.97だった。
Tera Termは、ここでは接続先のターミナル(コマンドを打つところ)になるもので、SSH接続(めっちゃ安全な通信)ができたりマクロを使えたり、みたいな特徴もある。

Tera Termダウンロードページは以下。
Tera Term (テラターム) プロジェクト日本語トップページ - OSDN
以下のページなどを参考にした。
【ゼロからわかる】Teratermのインストールと使い方 TeraTerm(Win7)からVirtualBox(Ubuntu14)へNAT経由でSSH接続 - Qiita

インストール先のデフォルトはProgram Files(x86)だったが、そのままで特に問題なかった。32bitなのだろう。
コンポーネントの選択」では標準インストールのデフォルトを選択した。

VirtualBoxの設定

さて、Tera Termのダウンロードが終わったところでVirtualBox側でちょっと操作をする。
Ubuntuを起動していない状態でUbuntuを選択し、「設定(歯車のアイコン)」>「システム」と選択する。
デフォルトでは「起動順序」の「ネットワーク」にチェックがついていなかったが、ここにチェックをつける。
f:id:kuro_rera:20180112083249p:plain

その後、左のメニューから「ネットワーク」を選択する。
「割り当て」で「NAT」を指定すると、「ポートフォワーディング」が有効になるので、(ボタンがない場合は「高度」の左三角をクリックすれば出てくる)これをクリック。 f:id:kuro_rera:20180112083853p:plain
すると「ポートフォワーディングルール」が開くので、右上のアイコンをクリック。
新たにルールが追加されるので、ホストポートに適当な空いてる数字(ここでは3000とした)をセット。ゲストポートに22(これは固定)をセットする。
f:id:kuro_rera:20180112084105p:plain

Ubuntu側の設定

この設定が終わったらUbuntuを起動する。
デスクトップ上で右クリック→Open Terminalを選択すると、ターミナルが出てくる。
まずは、ここで service sshd status と入力する。
これは、「今この環境はリモートからSSH接続できる状態か?」を確認するものだ。
Active: active(running) が出ていればSSH接続できる状態だが、
Ubuntu入れたての環境では以下のように表示された。

$ service sshd status  
●sshd.service  
    Loaded: not-found (Reason: No such file or directory)
    Active: inactive (dead)  

そもそもそんなもんないよと言われている。
ここで、 sshd とやらをインストールしよう。

その前に、まず sudo apt-get update と入力する。
apt-get はパッケージ管理コマンドといって、インストールなりアップデートなりを簡単にできるコマンドである。
updateapt-get のオプションで、インストール先のパッケージを最新の状態にしてくれる。
sudo はおまじないと思えばいいが、どうやら apt-get を打つときは必要っぽい。
数分でアップデートは終わるはず。

ここから実際にパッケージをインストールしていく。
sudo apt-get install openssh-server と入力する。
(参考資料では sysv-rc-conf をインストールしていたが、私の場合はそれではうまくいかなかった。)
「続行しますか?[Y/n]」と出てくるので、Yを入力してEnter。
すぐにインストールは終了する。

インストールが終了したら、改めて service sshd status を入力してみよう。
3行目あたりに Active: active (running) と出れば成功だ。
これで、ホストOSからSSH接続できるようになった。

Tera Termの設定

ここで、やっとTera Termのお出ましである。
インストールしたTera Termを開くと、下図のような画面になる。 f:id:kuro_rera:20180112215138p:plain
ホストに127.0.0.1:3000(コロンの後は設定したホストポート)を、TCPポートに22を入力する。
127.0.0.1は言わずと知れたIPで、自分自身を指すものである。
OKを押すと初回はセキュリティなんたらという警告が出るが、かまわずOKする。(画面は撮り損ねた)
すると「SSH認証」としてユーザ名とパスワードを要求されるので、Ubuntu上に登録したユーザ名とパスワードをそれぞれ入力する。
下のほうは「ブレインパスワードを使う」にしておけばよい。

f:id:kuro_rera:20180112215901p:plain

これで、ホストOS上でゲストOSを操作できるようになった。
とりあえず今回はここまで。

今後の目標

先月21日にブログを開設したものの、三日坊主はおろか最初の記事を書いただけで放置してしまっていた。
言い訳はいろいろあるが、ひとまず今日から記事を書くようにしていきたい。

というのも、マシンを新しく購入し、やっと手が動かせるようになりそうだからという点がある。
マシンのスペックは以下である。

GPU: GeForce GTX1080
CPU: Core i7-7700
メモリ: 16GB 
SSD: 500GB
HDD: 3TB
電源ユニット: 最大550W

ディープラーニングにもまあ十分といったところだろうか。
メモリはいずれ増設を検討する。

さて、エンジニアとして生きていく上で、目標を立てるということはある程度意味があろう。
近頃は猫も杓子もAIといった姿勢が各企業に見受けられ、ここ数年はそれが続きそうだ。
そんなこともあり、目標としては「3年間でAI開発のスペシャリストになる」ことを掲げようと思う。
漠然とはしているが、現時点での知識・技量では体系的な知識を身に付けることがまず優先されよう。

ひとまずの目標はこんなところだ。
* Pythonの習熟
* ディープラーニングの理解

ゆくゆくは画像認識、自然言語処理に手を伸ばしたい。

このブログについて

初めまして、くろれらです。
某企業でエンジニアをやっています。まだまだ若手のつもり。
業務ではPythonJavaなどを書いています。

ひとまずブログを書いてみます。
とりあえずは自分の勉強用・知識整理用です。
コメントなどもらえると喜びます。

よろしくお願いします。