デジタル・デザイン・ラボラトリーな日々

アラフィフプログラマーが数学と物理と英語を基礎からやり直す。https://qiita.com/yaju

Tensorflowの上位ラッパーライブラリ Kerasを試してみる

はじめに

これは、TensorFlow Advent Calendar 2016の16日目の記事です。

本当は、Tensorflowで足し算をやりたかったのですが、間に合いませんでした。足し算といっても桁上りがあるので簡単ではなさそうです。
下記サイトのNPI(Neural Programmer-Interpreters)とか理解できるようになりたいところ。 qiita.com

私がTensorFlowをやるようになったのは、静岡Developers勉強会で2016/4/23「人工知能ハンズオン」を開催するためでした。ともかく流行りで話題になっているのを勉強会として企画したんですが、何も分からない状態で数週間前から準備しただけですから、勢いだけで良くやったよねって感じです。
その時のTensorFlowのインストール記事だけが、未だにアクセス数を稼いでいます。 yaju3d.hatenablog.jp

勢いでやっただけで人工知能は凄いとは思いつつも、数学も苦手だし普通のWindowsのノートPCしかない、MNISTの手書き文字の認識率が高くなったからって何が楽しいのってことでモチベーション的には停滞してました。

そんな中でJoel Grusさんの「Fizz Buzz in Tensorflow」の記事を知ることになります。 これは、プログラマー採用試験としてFizzBuzz問題のプログラムを書きなさいというIT会社面接官に対して「では、まずTensorFlowをインポートします…」というジョークとして話題になりました。つまり人工知能によってFizzBuzz問題を解くという更に高度な提案をしたわけです。
実際に試してみて数分くらいで結果が出て、これは面白いと思いました。これがTensorFlowにちゃんと向き合うきっかけになりました。
FizzBuzz問題Deep Learning入門としては良い題材と思います。 yaju3d.hatenablog.jp

では、本題に入ります。

Keras とは

KerasはPython製の深層学習ライブラリです。バックエンドとしてTheanoとTensorflowの両方が使え、より高レイヤな表現で深層学習のさまざまなアルゴリズムが記述できる。インドネシア語でkerasは"強い"や"硬い"を意味する ギリシャ語で"角"を意味するそうで読み方は「ケラス」です。
メイン開発者はGoogleのFrançois Chollet(フランソワ・ショレ)さんで迅速な実験を可能にすることに重点を置いて開発されました。 Tensorflowの上位ラッパーライブラリなので、今後はTensorflowよりkerasで書かれたソースが多くなることでしょう。

Keras のインストール

TensorFlow 0.12からWindowsをサポートしたので、Windows版で行います。「TensorFlow 0.12.0rc1」となります。

yaju3d.hatenablog.jp

(tensorenv) c:\Anaconda3>pip install keras

Kerasのインストールエラー

途中で下記のエラーが発生してインストールが止まります。

numpy.distutils.system_info.NotFoundError: no lapack/blas resources found

scipyが悪さしているようなのでインストールします。「pip install Scipy」ではエラーとなったため、「conda install scipy」でインストールしました。その後に再度、「pip install keras」とします。

(tensorenv) c:\Anaconda3>conda install scipy
The following NEW packages will be INSTALLED:

    mkl:   11.3.3-1
    numpy: 1.11.2-py35_0
    scipy: 0.18.1-np111py35_0

Proceed ([y]/n)? y


(tensorenv) c:\Anaconda3>pip install keras
Collecting keras
Collecting theano (from keras)
Collecting pyyaml (from keras)
  Using cached PyYAML-3.12-cp35-cp35m-win_amd64.whl
Requirement already satisfied: six in c:\anaconda3\envs\tensorenv\lib\site-packa
ges (from keras)
Requirement already satisfied: numpy>=1.7.1 in c:\anaconda3\envs\tensorenv\lib\s
ite-packages (from theano->keras)
Requirement already satisfied: scipy>=0.11 in c:\anaconda3\envs\tensorenv\lib\si
te-packages (from theano->keras)
Installing collected packages: theano, pyyaml, keras
Successfully installed keras-1.1.2 pyyaml-3.12 theano-0.8.2

設定ファイルの書き換え

kerasのバックエンドのデフォルトは「Theano」になっていますので、「Tensorflow」に設定ファイルを書き換えます。
設定ファイルは「import keras」を実行した際に作られます。 作られる場所は、下記コマンドで知ることが出来ます。pythonは「CTRL + Z」で停止します。

(tensorenv) C:\Anaconda3>python
Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul  5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> print(os.path.expanduser('~'))
C:\Users\(ユーザー)

「import keras」を実行します。最初に「ImportError: No module named ‘keras'」と出たので、「Anaconda Prompt」を起動し直しました。
pythonは「CTRL + Z」で停止します。

(tensorenv) C:\Anaconda3>python
Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul  5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import keras
Using TensorFlow backend.

C:\Users(ユーザー).keras\keras.jsonファイルを開きます。
“backend”: “theano” → "tensorflow" に変更します。

{
    "image_dim_ordering": "tf",
    "backend": "tensorflow",
    "floatx": "float32",
    "epsilon": 1e-07
}

Keras の動作確認

jupyter notebook を起動します。

(tensorenv) C:\Anaconda3>jupyter notebook

「keras XOR」で検索して見つけたサイトstewartpark/xor.pyソースコードを変更して「AND」に変更してみました。これは「nb_epoch=1000」だと、jupyter notebook上では応答なしになるし、「XOR」だとnb_epochの値を少なくすると正しい値にならないためです。

論理演算をするのに下記サイトではTFLearnという別のライブラリーですが参考になると思います。

qiita.com

清水 亮さんの「はじめての深層学習(ディープラーニング)プログラミング Kindle版」でも論理演算を入門として扱っています。

from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import SGD
import numpy as np 

X = np.array([[0,0],[0,1],[1,0],[1,1]])
y = np.array([[0],[0],[0],[1]])

model = Sequential()
model.add(Dense(8, input_dim=2))
model.add(Activation('tanh'))
model.add(Dense(1))
model.add(Activation('sigmoid'))

sgd = SGD(lr=0.1)
model.compile(loss='binary_crossentropy', optimizer=sgd)

model.fit(X, y, show_accuracy=True, batch_size=1, nb_epoch=100)
print(model.predict_proba(X))

結果ですが、1と1の組み合わせでは0.94108927と1に近い値となっています。他の「OR」や「NAND」や「XOR」もやってみるといいでしょう。

Epoch 100/100
4/4 [==============================] - 0s - loss: 0.0367     
4/4 [==============================] - 0s
[[ 0.0010068 ]
 [ 0.03769387]
 [ 0.03732052]
 [ 0.94108927]]

最後に

TensorFlowにちゃんと向き合うきっかけになった。Joel GrusさんのFizzBuzz問題pydata-chicago 2016の説明用に「keras」を使っています。 github.com www.youtube.com

ちなみにJoel GrusさんのFizzBuzzを動かすのに、下記のインストールが必要でした。

pip install matplotlib
pip install pillow
pip install pyqt5
conda install pyqt=4
conda install h5py

自分としては、FizzBuzzや論理演算や足し算など身近で分かりやすい題材で人工知能に向き合っていくつもりです。下記のような小ネタもたまにはやります。 yaju3d.hatenablog.jp

線形回帰で二乗和を2で割る理由について

はじめに

これは、機械学習に必要な高校数学やり直しアドベントカレンダー Advent Calendar 2016の10日目の記事です。

線形回帰 ー 誤差の和の式(データ個数 n 個の場合)

\displaystyle E(\theta)=\frac{1}{2}\sum_{i=1}^{n}(y^{(i)}-f\theta(x^{(i)}))^2

2乗することに関しては、以前書いた下記の記事にてピタゴラスの定理で距離を求めるという理解を得ることが出来ました。
正の数と負の数が混ざっていると都合が悪いから、必ず正の数にするために2乗するってことです。
それなら絶対値を取った値でもいいと思われるが、目的関数を微分することになった時に絶対値の微分より2乗の微分の方が簡単になる。
絶対値だと微分ができない場所があるのと、場合分けをしないといけないから面倒なのです。 yaju3d.hatenablog.jp

でも、全体を 2 で割ってる理由はなんだろうという疑問を持ちました。

経緯

「やる夫で学ぶ機械学習 - 単回帰問題 -」とgihyo.jpの「機械学習 はじめよう 第9回 線形回帰」も、全体を 2 で割る理由について、もやっとする感じな書き方なんです。

全体を 2 で割るのが、やる夫が言っているように「おまじない的なものは気持ち悪いお…、」なんです。本筋ではないので記事的に省略するのは仕方ないですけどね。

やる夫
全体を 2 で割ってるのは何だお?

やらない夫
後で E(θ) を微分することになるんだが、微分した式をちょっとだけ簡単にするためのトリックだ。最適化問題は、何か定数が全体に掛かっていたとしても、求まる答えは変わらないからこういうことができる。まあ、あまり深く考えなくていいさ。

やる夫
おまじない的なものは気持ち悪いお…、うーん、全体像はわかったけど、ちょっと、まだピンときてないお。
出典:やる夫で学ぶ機械学習 - 単回帰問題 -

ただし一般的な記法にあわせて,二乗和を2で割ったものを使います(注1)。
注1
2で割っていることは今回の範囲では全く本質的ではないのですが,次回以降の話との整合性のためにこの形式を用います。
出典: 機械学習 はじめよう 第9回 線形回帰[後編]

調査

ネットで数時間かけて検索してみたのですが、ぜんぜん見つからないです(笑)。こういう時は人に頼るということで、 Yahoo!知恵袋に質問しました。

線形回帰の求め方で二乗和を2で割るの理由? - 数学 | Yahoo!知恵袋

2人から回答をいただきました。その内の1人はブログに書き起こしくれました。 勉強会で知り合った@K_Ryuichirouさんです。 線形回帰の求め方で二乗和を2で割る理由 - Qiita

では、解決したのかというとそうではなく、理解する知識がまだ自分にはなかったのです、まずは微分を理解する必要があります。

理解

Yahoo!知恵袋のzatsugakusanさんの回答を一部抜粋すれば

例えば

f(x)=(x-1)2

を最小にするxを求めればx=1となりますが、

f(x)=100(x-1)2

を最小にするxを求めてもx=1になります。

二乗和の式をこれから微分すると分かっているのですから、微分して「2」が出てくることも予めわかっています。

ですから、二乗和の損失関数に1/2を掛けていれば微分したときに消えてくれるのでそうしておく。ただそれだけのことです。そうして求まるパラメータ自体には何の影響もありません。
「2で割るのは、単に二乗和が微分したら2が出てくることが分かっているからです。」

導関数の定義では、二次関数 y=x^2微分すると y=2x になる。

参照:

この2を打ち消すということだが、まだピンとこない。

修正量による考え

修正された値をxとし、2つの計測値を a_1a_2とする。それぞれの計測値に修正を加える修正量を v_1v_2とした場合、これらの間には「計測値+修正量=修正された計測値」の関係が成り立ち、これを数式にしてみる。

a_1 + v_1 = x
a_2 + v_2 = x

これらを修正量=・・・の形式に書き換えます。

v_1 = x - a_1
v_2 = x - a_2

これを修正量の2乗の総和を S とすれば次のように計算できる。

S = v_1^2 + v_2^2
  = (x-a_1)^2 + (x-a_2)^2
  = 2x^2 - 2(a_1+a_2)x + a_1^2 + a_2^2

総和 S は、二次関数になるのでグラフが下向きの放物線になります。 そして、放物線の頂点が最小値ということになります。 総和 S を x で微分した上で「微分した値 = 0」とすれば目的の値を求めると次のような計算になります。

\displaystyle \frac{dS}{dx}=4x-2(a_1+a_2)=0

\displaystyle 4x=2(a_1+a_2)

\displaystyle 2x=(a_1+a_2)

\displaystyle x=\frac{(a_1+a_2)}{2}

f:id:Yaju3D:20161209030620p:plain

よって、最小値は図の赤丸のところで下記の式となる。

\displaystyle x = \frac{(a_1+a_2)}{2}

これはa_1a_2の平均である。

でも、これは平均でたまたま2つだから2で割っただけで、3つになったら意味が違うかも知れない。

参照: わかりやすい測量の数学 ―行列と最小二乗法― 著者: 小白井 亮一 Kindle版

微分係数とは何か

f(x)=(x-1)2

を最小にするxを求めればx=1となりますが、

f(x)=100(x-1)2

を最小にするxを求めてもx=1になります。

つまり、最小値に微分係数は関係ないようだ。そこで微分係数で検索していたら下記サイトを見つけた。

微分係数は、ある点における接線の傾きともいうことができます。虫めがねの図を思い出してください。
最小値をとるところ、つまり、x=0では接線の傾き(=微分係数)はどうなりますか?
・・・接線は水平になりますね。
ということは、傾きは・・・ 0ですね。
だから、微分係数が0になる点が最小値(yの値ですよ。)になるのです。

参照:6.微分の応用

http://www.minc.ne.jp/~ryokan/bibun/bibun26.gif

結論

微分係数はある点における接線の傾きで最小値は水平となるので、微分係数は無視してx=0を代入した値が最小値となる。

二乗和を微分したら微分係数に2が付くけど、微分係数は無視するので求まる答えは変わらない。
微分係数2は数式上は1/2を掛けて(2で割る)相殺しておくことが、数学として一般的な記法なっているということです。

最後に

これで、やらない夫の「何か定数が全体に掛かっていたとしても、求まる答えは変わらない」とYahoo!知恵袋のzatsugakusanさんの「2で割るのは、単に二乗和が微分したら2が出てくることが分かっているからです。」が分かったような気がします。

ただ、理解が間違っていたらご教示ください。

追記(2017/09/01)

実際に計算した結果をみると理解しやすいです。

yaju3d.hatenablog.jp 上記サイトでリンゴとミカンの最小値はリンゴ90円とミカン30円ですが、今回は求める上で2乗誤差の平均値を使ったので3で割っています。別に平均値ではなく合計値のままでもいいし、公式通りに1/2にしてもいいです。でも求まる最小値はリンゴ90円とミカン30円で結果は変わらない。 数学の通例として公式では1/2にしているだけです。

追記(2019/03/24)

もう少しいい説明として下記の本を参考にしました。

今回の式は目的関数と呼ばれるもの。

\displaystyle E(\theta)=\frac{1}{2}\sum_{i=1}^{n}(y^{(i)}-f\theta(x^{(i)}))^2

E(\theta)E は、誤差を英語で言った時の Error の値を文字から取っている。
この E(\theta) の値が一番小さくなるような \theta を見つけるのが目的で、こういうのを最適化問題という。

今回のように勝手に定数 \displaystyle\frac{1}{2} を掛けてもの問題ないのは、誤差 E を求めるのではなく最小値を求めるのが目的だから。

下図の f(x)=x^{2}のグラフで左側の場合の最小値は x=0 、定数を掛けた f(x)=\displaystyle\frac{1}{2}x^{2}のグラフで右側の場合の最小値も同じように x=0 となる。
f:id:Yaju3D:20190324150422p:plain

正の定数を掛けてもグラフの形が横に潰れたり縦に細くなるだけで、どこで最小値になるのかという場所は変わらない。
よって、 f(x)=x^{2}微分した時の微分係数 2 は数式上は \displaystyle\frac{1}{2} を掛けて( 2 で割る)相殺しておくことが、数学として一般的な記法なっている。

TensorFlowがWindowsサポートしたのでインストールしてみた

はじめに

TensorFlow 0.12からWindowsをサポートするようになりました。これにより、VirtualBoxやDockerを使う必要がなくなります。

【追記 2017/03/02】
2017/02/16にTensorFlow 1.00がリリースされました、遅ればせながら今回TensorFlowをバージョンアップしました。

【追記 2017/11/25】
2017/11/08にTensorFlow 1.40がリリースされました、遅ればせながら今回TensorFlowをバージョンアップしました。
TensorFlow 1.4.0 リリースノート(翻訳)

(tensorenv) C:\Users\(ユーザー)>pip install --ignore-installed --upgrade tensorflow 

(tensorenv) C:\Users\(ユーザー)>python -c "import tensorflow; print(tensorflow.__version__);"
1.4.0

※TensorFlow(読み方:テンソルフローではなくテンサーフロー 参照:https://togetter.com/li/1027115)

qiita.com

yaju3d.hatenablog.jp

TensorFlowバージョンアップによる変更点

【追記 2017/03/08】
過去ブログのTensorFlow用プログラムでは、TensorFlowバージョンアップによりエラーや警告が出ますので、下記の点を修正してください。

tensorflow 1.0 error: ValueError: Only call sigmoid_cross_entropy_with_logits with named arguments (labels=..., logits=..., ...)
https://github.com/tensorflow/tensorflow/issues/7814

tf.nn.sigmoid_cross_entropy_with_logits(u, y_)
↓ labels=, logits=を付ける
tf.nn.sigmoid_cross_entropy_with_logits(logits=u, labels=y_)

TensorFlowのinitialize_all_variablesがDeprecatedになった件

tf.initialize_all_variables
↓ 置き換える
tf.global_variables_initializer

環境

Python数値計算環境「Anaconda」のWindows 64bit版をインストール

AnacondaとはPython数値計算環境を構築するために様々なパッケージをまとめた無料のディストリビューションです。 Anacondaをインストールをすると、NumPy,SciPy,matplotlib、scikit-learn等のパッケージがインストールされます。

下記サイトからAnaconda 4.2.0 For Windows PYTHON 3.5 64-BITをダウンロードしてください。
2017/11/25現在では、Anaconda 5.0.1になっています。
https://www.continuum.io/downloads#windows

自分は、「C:\Anaconda3」をインストール先にしました。

Anacondaのアップデート

2017/11/25現在では、Anaconda 5.0.1になっているので、全パッケージをアップデートしてみました。

(C:\Anaconda3) > conda list anaconda
# packages in environment at C:\Anaconda3:
#
anaconda                  4.2.0               np111py35_0
anaconda-clean            1.0.0                    py35_0
anaconda-client           1.5.1                    py35_0
anaconda-navigator        1.3.1                    py35_0
nb_anacondacloud          1.2.0                    py35_0

下記コマンドを入力して、20~30分待ちます。
パッケージ管理を行う conda 自身を更新してから、他のパッケージを更新します。
通信エラーが出たら、再度「conda update --all」をします。

(C:\Anaconda3) > conda update conda
(C:\Anaconda3) > conda update --all

anacondaのバージョンがcustomになってしまったので、「conda update anaconda」を追加しました。

(C:\Anaconda3) > conda list anaconda
# packages in environment at C:\Anaconda3:
#
anaconda                  5.0.0            py35h91a80f2_0
anaconda-clean            1.1.0                    py35_0
anaconda-client           1.6.5            py35h18499f7_0
anaconda-navigator        1.6.8            py35h84e1151_0
anaconda-project          0.8.0            py35h54b767f_0
nb_anacondacloud          1.4.0                    py35_0

AnacondaのTensorflow用環境を作成

Anaconda3 (64-bit)メニュー配下から「Anaconda Prompt」を選択します。

使用していくうちに開発環境を使い分けたい場合(共存できないライブラリがあったり新しいライブラリを試したいなど)がでてきます。そのような場合に環境管理システム(virtualenvやpyvenv)を使うのですが、Anacondaにはその上位版としてパッケージ管理システム(conda)があります。
参照:データサイエンティストを目指す人のpython環境構築 2016
今現在は開発環境を使い分ける必要がない方は、下記の「conda create」の作業は不要です。
「TensorFlowのインストール」に進んで下さい。

Tensorflow用環境を作成するため、コマンドプロンプト上で下記のコマンドを入力します。
名前は「tensorenv」にしました。envは環境(environment)の略称 ※(ユーザー)のところは各自違います。

(C:\Anaconda3) C:\Users\(ユーザー)> conda create --name=tensorenv python=3.5

環境が作成されていきます、途中のProceedの確認は「y」を入力します。

Fetching package metadata .........
Solving package specifications: ..........

Package plan for installation in environment C:\Anaconda3\envs\tensorenv:

The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    pip-9.0.1                  |           py35_0         1.7 MB

The following NEW packages will be INSTALLED:

    pip:            9.0.1-py35_0
    python:         3.5.2-0
    setuptools:     27.2.0-py35_1
    vs2015_runtime: 14.0.25123-0
    wheel:          0.29.0-py35_0

Proceed ([y]/n)? y

Fetching packages ...
pip-9.0.1-py35 100% |###############################| Time: 0:00:02 786.13 kB/s
Extracting packages ...
[      COMPLETE      ]|##################################################| 100%
Linking packages ...
[      COMPLETE      ]|##################################################| 100%
#
# To activate this environment, use:
# > activate tensorenv
#
# To deactivate this environment, use:
# > deactivate tensorenv
#
# * for power-users using bash, you must source
#

以下のコマンドで作った環境の一覧を表示できます。

(C:\Anaconda3) C:\Users\(ユーザー)>conda info -e
# conda environments:
#
tensorenv                C:\Anaconda3\envs\tensorenv
root                  *  C:\Anaconda3

作成した環境を有効にするには下記のコマンドを入力します。
Windows版はsourceコマンドが無いため、activateからとなります。

(C:\Anaconda3) C:\Users\(ユーザー)>activate tensorenv

これで先頭に「(tensorenv)」が付くようになります。

(tensorenv) C:\Users\(ユーザー)>

ちなみに作成した環境から戻るには下記のコマンドを入力します。

(tensorenv) C:\Users\(ユーザー)> deactivate

TensorFlowのインストール

【追記】2017/11/25
TensorFlow 1.40が2017/11/08リリースされました。もはや普通に入れればいい。

(tensorenv) C:\Users\(ユーザー)>pip install --ignore-installed --upgrade tensorflow
Collecting tensorflow
  Using cached tensorflow-1.4.0-cp35-cp35m-win_amd64.whl
 ︙
Successfully installed bleach-1.5.0 enum34-1.1.6 html5lib-0.9999999 markdown-2.6.9 numpy-1.13.3 protobuf-3.5.0.post1 setuptools-37.0.0 six-1.11.0 tensorflow-1.4.0 tensorflow-tensorboard-0.4.0rc3 werkzeug-0.12.2 wheel-0.30.0

Anaconda Navigatorを使えばもっとシンプルでインストールできる。
geeknavi.net

もはや、ごちゃごちゃしてしまっているが、下記はメモとして残しておく。

TensorFlowには、「CPU only」と「GPU enabled」の2種類が用意されています。今回は「CPU only」版をインストールします。 ファイル名はPython35にしているので「tensorflow-(version No)-cp35」となります。 バージョンは現時点(2016/12/06)で最新の「0.12.0」を入れます。

入力が長いのでクリップボードにコピーして貼り付ければいいです。

参照:https://www.tensorflow.org/versions/r0.12/get_started/os_setup.html#pip-installation-on-windows

【追記】2016/12/18
2016/12/18に確認したところ「0.12.0rc1」になっていましたので、下記は書き換えました。

(tensorenv) C:\Users\(ユーザー)>pip install --upgrade https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-0.12.0rc1-cp35-cp35m-win_amd64.whl

【追記】2017/03/02
2017/02/16にV1.00がリリースされましたのでTensorFlowサイトに従いインストールしてみたところ、下記のエラー(not a supported wheel on this platform)が発生しました。

(tensorenv) C:\Users\(ユーザー)>pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-1.0.0-cp35-cp35m-win_x86_64.whl

tensorflow-1.0.0-cp35-cp35m-win_x86_64.whl is not a supported wheel on this platform.  

Anaconda用のWindows版でPython3.5のCPU版と何も間違ってないのにプラットフォーム違いなのは何でと、ネットで検索して同様のエラーの方が質問されていました。

stackoverflow.com

ここの回答によると、「win_x86_64.whl」版ではなく「win_amd64.whl」版をインストールしたら成功したとのこと。
下記の通りに無事、tensorflow 1.0.0 にバージョンアップ出来ました。

(tensorenv) C:\Users\(ユーザー)>pip install -U --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-1.0.0-cp35-cp35m-win_amd64.whl
 ︙
Successfully installed appdirs-1.4.2 numpy-1.12.0 packaging-16.8 protobuf-3.2.0 pyparsing-2.1.10 setuptools-34.3.0 six-1.10.0 tensorflow-1.0.0 wheel-0.29.0

(tensorenv) C:\Users\(ユーザー)>python -c "import tensorflow; print(tensorflow.__version__);"
1.0.0

ちなみに拡張子「whl」はWheelの略で、Wheelとは最近になって導入された Python の新しいパッケージング規格です。whlファイルは単なる ZIP アーカイブなので unzip コマンドなどを使って容易に中身を見ることができます。
wheelはコンパイル済みのバイナリファイルを含むことができるのが大きな特徴です。
pip installするとその場でライブラリのコンパイルが走るのですが、コンパイル環境が無い場合はエラーでコケルというデメリットがあります。最近の pip が新しいパッケージング規格である Wheel をこっそりと裏側で使っています。 参照:Python: pip と Wheel キャッシュについて

インストールされます。(下記以降は記事当初の「0.12.0rc0」のままです。)

Collecting tensorflow==0.12.0rc0 from https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-0.12.0rc0-cp35-cp35m-win_amd64.whl
  Downloading https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-0.12.0rc1-cp35-cp35m-win_amd64.whl (12.2MB)
    100% |################################| 12.2MB 27kB/s
Collecting six>=1.10.0 (from tensorflow==0.12.0rc0)
  Downloading six-1.10.0-py2.py3-none-any.whl
Collecting protobuf==3.1.0 (from tensorflow==0.12.0rc0)
  Downloading protobuf-3.1.0-py2.py3-none-any.whl (339kB)
    100% |################################| 348kB 475kB/s
Collecting numpy>=1.11.0 (from tensorflow==0.12.0rc0)
  Downloading numpy-1.11.2-cp35-none-win_amd64.whl (7.6MB)
    100% |################################| 7.6MB 38kB/s
Requirement already up-to-date: wheel>=0.26 in c:\anaconda3\envs\tensorenv\lib\site-packages (from tensorflow==0.12.0rc0)
Collecting setuptools (from protobuf==3.1.0->tensorflow==0.12.0rc0)
  Downloading setuptools-30.2.0-py2.py3-none-any.whl (472kB)
    100% |################################| 481kB 396kB/s
Installing collected packages: six, setuptools, protobuf, numpy, tensorflow
  Found existing installation: setuptools 27.2.0

TensorFlowのインストールエラー

途中で下記のエラーが発生してインストールが止まります。

Cannot remove entries from nonexistent file c:\anaconda3\envs\tensorenv\lib\site-packages\easy-install.pth

パッケージの依存関係のコンフリクトが原因のようで、下記サイトの「2. pip で setuptools を TensorFlow と互換性があるものに upgrade する」で対応します。※下記サイトは、mac版です。
datalove.hatenadiary.jp

よって、下記コマンドを入力して再インストールします。
pip自体のupgradeが必要かも知れません。先に「pip install --upgrade pip」を実行するといいでしょう。
Permission Errorが発生した場合は、「python -m pip install --upgrade pip」 にする。

(tensorenv) C:\Users\(ユーザー)>pip install --upgrade -I setuptools
Collecting setuptools
  Using cached setuptools-30.2.0-py2.py3-none-any.whl
Installing collected packages: setuptools
Successfully installed setuptools-30.2.0


(tensorenv) C:\Users\(ユーザー)>pip install --upgrade https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-0.12.0rc0-cp35-cp35m-win_amd64.whl
Collecting tensorflow==0.12.0rc0 from https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-0.12.0rc0-cp35-cp35m-win_amd64.whl
  Using cached https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-0.12.0rc0-cp35-cp35m-win_amd64.whl
Collecting numpy>=1.11.0 (from tensorflow==0.12.0rc0)
  Using cached numpy-1.11.2-cp35-none-win_amd64.whl
Collecting protobuf==3.1.0 (from tensorflow==0.12.0rc0)
  Using cached protobuf-3.1.0-py2.py3-none-any.whl
Requirement already up-to-date: wheel>=0.26 in c:\anaconda3\envs\tensorenv\lib\site-packages (from tensorflow==0.12.0rc0)
Requirement already up-to-date: six>=1.10.0 in c:\anaconda3\envs\tensorenv\lib\site-packages (from tensorflow==0.12.0rc0)
Requirement already up-to-date: setuptools in c:\anaconda3\envs\tensorenv\lib\site-packages (from protobuf==3.1.0->tensorflow==0.12.0rc0)
Installing collected packages: numpy, protobuf, tensorflow
Successfully installed numpy-1.11.2 protobuf-3.1.0 tensorflow-0.12.0rc0

TensorFlowの動作確認

バージョンが表示されればインストール成功です。

(tensorenv) C:\Users\(ユーザー)>python -c "import tensorflow; print(tensorflow.__version__);"
0.12.0-rc0

Jupyter Notebookのインストール

Web上の実行環境である「Jupyter Notebook」はAnacondaと同時にインストールされているのですが、自分はTensorFlow専用の環境(tensorenv)を作成しているため、インストールする必要があるようです。そうしないと、「ImportError: No module named tensoflow」となります。

(tensorenv) C:\Users\(ユーザー)>pip install jupyter 

【追記】2017/11/25
新しいバージョンでは専用に環境作成しても、 既にインストール済みとなります。

(tensorenv) C:\Users\(ユーザー)>pip install jupyter 
Requirement already satisfied: jupyter in c:\anaconda3\lib\site-packages

Jupyterの起動

カレントフォルダを移動しておきます。

(tensorenv) C:\Users\(ユーザー)>cd C:\Anaconda3 
(tensorenv) C:\Anaconda3 >jupyter notebook

Webブラウザが起動しますので、そこからanaconda3/envs/tensorenvフォルダまで移動させます。 f:id:Yaju3D:20161206022332p:plain

更にtensorenvフォルダ配下に移動して、右横の「New」で新規ファイルを「Python 3」で作成します f:id:Yaju3D:20161206022344p:plain

それでは、下記サイトの演算を実際に実行してみましょう。 qiita.com

では、実際にTensorFlowを使って計算してみます。最初は、以下の式を書いてみます。

y = x^2 + b
import tensorflow as tf

def x2_plus_b(x, b):
    _x = tf.constant(x)
    _b = tf.constant(b)
    result = tf.square(_x)
    result = tf.add(result, _b)
    return result

print resultではエラーとなったため、print(result)に修正しました。

with tf.Session() as sess:
    result = sess.run([x2_plus_b(2., 3.)])
    print(result) 

実行結果(printの出力)は以下のようになります。

2^2 + 3 = 7

なので、きちんと計算できていることがわかります。

f:id:Yaju3D:20161206023119p:plain

TensorBoardの可視化

TensorFlowには、TensorBoardという強力なビジュアライゼーションツールが付いている点も特徴の一つになっています。

WindowsでのTensorBoardですが、TensorFlowのバージョンが「0.12.0rc0」では動作しないので「0.12.0rc1」にしてください。
※2016/12/18以降なら「0.12.0rc1」になっています。

先ほどの続きとして下記ソースを入力します。

import tensorflow as tf

def monitor_calculation(x, b):
    title = "b = {0}".format(b)
    c = x2_plus_b(float(x), float(b))
    s = tf.scalar_summary(title, c)
    m = tf.merge_summary([s])  # if you are using some summaries, merge them
    return m

with tf.Session() as sess:
    writer = tf.train.SummaryWriter("log", graph_def=sess.graph_def)    
    xaxis = range(-10, 12)

    for b in range(3):
        for x in xaxis:
            summary_str = sess.run(monitor_calculation(x, b))
            writer.add_summary(summary_str, x)

これを実行すると、ログがフォルダ(C:\Anaconda3/envs/tensorenv/log)に出力されます。

f:id:Yaju3D:20161218235453p:plain

TensorBoardの実行

WindowsでのJupyter notebook上ではTerminalがありません。 その為、「Anaconda Prompt」をもう1つ起動します。

logdirには絶対パスを指定します。

(C:\Anaconda3) C:\Users\(ユーザー)>activate tensorenv

(tensorenv) C:\Users\(ユーザー)>cd c:\Anaconda3

(tensorenv) c:\Anaconda3>tensorboard --logdir=c:\anaconda3\envs/tensorenv/log
Starting TensorBoard b'39' on port 6006
(You can navigate to http://192.168.99.1:6006)

Webブラウザにて、下記URLを入力します。

localhost:6006/

f:id:Yaju3D:20161219000417p:plain

最後に

ようやっとWindowsをサポートされることになりましたが、いろいろやっていくと不足しているところが出てくるかも知れませんね。

VirtualBoxにUbuntu16.04 LTS と TensorFlow をインストール

はじめに

日本語形態素解析システム「JUMAN++」をインストールするために、久しぶりにVirtualBoxのUbuntuを使ったのですが、各システムのバージョンも古くなってきているので新規にインストールし直します。
以前書いた下記の記事(2016年3月27日)を基にインストールをしたのですが、バージョンが新しくなって記事内容があわなくなってきたので書き直しました。 yaju3d.hatenablog.jp

環境

  • Windows 10 Home 64bit
  • Oracle VM VirtualBox 5.1.10

VirtualBoxにUbuntu(64bit)をインストール

下記サイトを参考にVirtualBoxにUbuntu 16.04 LTSをインストールしました。 サイトとの違いとして、メモリは2048MByte、仮想ハードドライブサイズは20GByteにしています。 qiita.com 仮想ハードドライブサイズは後で変更することが出来ますが、面倒なので最初からそれなりの大きさにしておきましょう。 qiita.com

画面サイズは1024x768になっています。

インストール時のエラー

Ubuntu(64bit)を入れようとするとPCによっては下記のエラーが出ます。 「This kerner requures an X86-64 CPU, but only detected an i686 CPU」 これはVirtualBoxのUbuntu 32bit用に64bit版をインストールしようとしたためです。 何故、VirtualBoxにUbuntu 64bit用がリストに表示されないのかというと、PCのBIOSの仮想化機能が有効になっていないためです。有効にするためには、BIOSの設定(Lenovoでは再起動時にF1キーを押す等)で、Security→Vitualizationを「Enabled」にして保存後に再起動する必要があります

Guest Additionsのインストール

Guest Additionsは、ビデオ性能の向上、共有フォルダ、クリップボード共有等の機能を提供するVirtualBoxの追加コンポーネントです。
Guest Additionsインストール前だとUbuntu 16.04のディスプレイ解像度は2種類だけですが、インストール後だと任意の解像度に変更できます。

VirtualBoxのメニューのデバイスにある「Guest Additions CD イメージの挿入」をクリックします。インストールが成功したら、Ubuntu 16.04を再起動します。

Ubuntu 16.04: VirtualBox上のUbuntu 16.04にGuest Additionsをインストールする - Narrow Escape

クリップボードの共有

Ubuntuのインストールが完了したら、VirtualBoxメニューのデバイスの「クリップボードの共有」を双方向にしておくとWindowsのクリップボードを貼り付け出来たりして便利です。また、「ドラッグ&ドロップ」も同様に双方向にするといいでしょう

ターミナルの起動

先ずはWindowsのコマンドプロンプトのようなのを起動する必要があります。
Ubuntuの左横のパネルメニューから「コンピューターとオンラインリソースの検索」をクリックします。
検索ボックスで「terminal」を入力すると「端末」(ターミナル)が出てきますのでクリックします。

pipのインストール

ターミナルが起動したら、最初に「pip」をインストールして下さい。
pipとは、Pythonで書かれたパッケージソフトウェアをインストール・管理するためのパッケージ管理システムです。RubyのRubyGemsやPerlのCPANやWindowsのNuGetといったところです。
ターミナル上で下記のコマンドを入力します。

$ sudo apt-get install python-pip
$ pip install --upgrade pip

※$より前の部分は自分の環境では「yaju@yaju-VirtualBox:~$」です。これはインストール環境によって変わります。説明する上で便宜上省略しています。

Python数値計算環境「Anaconda」のLinux版をインストール

AnacondaとはPythonの数値計算環境を構築するために様々なパッケージをまとめた無料のディストリビューションです。 Anacondaをインストールをすると、NumPy,SciPy,matplotlib、scikit-learn等のパッケージがインストールされます。

Ubuntu上のWebブラウザ「FireFox」で下記サイトからAnaconda for Linux PYTHON 3.5 LINUX 64-BITをダウンロードしてください。ファイルの保存先は「ダウンロード」にしました。 https://www.continuum.io/downloads

※Python2.7ではなくPython3.5にしたのは、サイト「http://learningtensorflow.com/lesson1/」を参考にしたためです。

ターミナル上で「bash 」と入力したら、Ubuntuの左横のパネルメニューから「ファイル」からダウンロードフォルダにある「Anaconda3-4.2.0-Linux-x86_64.sh」をドラッグ&ドロップしました。引用符は付いたままでもいいかも知れませんが、一応消しました。

$ bash /home/yaju/ダウンロード/Anaconda3-4.2.0-Linux-x86_64.sh

AnacondaのTensorflow用環境を作成

Anacondaのインストールが終わったら、一旦ターミナルを閉じて下さい。
これはTensorflow用環境を作成する際に使用する「conda」コマンドがまだ有効になっていないためです。

Tensorflow用環境を作成するため、ターミナル上で下記のコマンドを入力します。
名前は「tensorenv」にしました。envは環境(environment)の略称

$ conda create --name=tensorenv python=3.5

環境が作成されていきます、途中のProceedの確認は「y」を入力します。

The following NEW packages will be INSTALLED:

    openssl:    1.0.2j-0     
    pip:        9.0.1-py35_0 
    python:     3.5.2-0      
    readline:   6.2-2        
    setuptools: 27.2.0-py35_0
    sqlite:     3.13.0-0     
    tk:         8.5.18-0     
    wheel:      0.29.0-py35_0
    xz:         5.2.2-0      
    zlib:       1.2.8-3      

Proceed ([y]/n)? y

Fetching packages ...
pip-9.0.1-py35 100% |################################| Time: 0:00:02 742.12 kB/s
Extracting packages ...
[      COMPLETE      ]|###################################################| 100%
Linking packages ...
[      COMPLETE      ]|###################################################| 100%
#
# To activate this environment, use:
# > source activate tensorenv
#
# To deactivate this environment, use:
# > source deactivate tensorenv
#

以下のコマンドで作った環境の一覧を表示できます。

$ conda info -e

Using Anaconda Cloud api site https://api.anaconda.org
# conda environments:
#
tensorenv                /home/yaju/anaconda3/envs/tensorenv
root                  *  /home/yaju/anaconda3

作成した環境を有効にするには下記のコマンドを入力します。

$ source activate tensorenv

これで先頭に「(tensorenv)」が付くようになります。

(tensorenv)$

ちなみに作成した環境から戻るには下記のコマンドを入力します。

(tensorenv)$ source deactivate

TensorFlowのインストール

TensorFlowには、「CPU only」と「GPU enabled」の2種類が用意されています。今回は「CPU only」版をインストールします。
ファイル名はPython35にしているので「tensorflow-(version No)-cp35」となります。ちなみにPython27は「cp27」です。
バージョンは現時点(2016/11/27)で最新の「0.11.0」を入れます。
入力が長いのでクリップボードにコピーして貼り付ければいいです。

参照:https://www.tensorflow.org/versions/r0.11/get_started/os_setup.html

(tensorenv)$ pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.11.0-cp35-cp35m-linux_x86_64.whl

Building wheels for collected packages: numpy あたりで10分程度かかりました。

Collecting tensorflow==0.11.0 from https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.11.0-cp35-cp35m-linux_x86_64.whl
  Downloading https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.11.0-cp35-cp35m-linux_x86_64.whl (39.8MB)
    100% |████████████████████████████████| 39.8MB 9.8kB/s 
Requirement already up-to-date: wheel>=0.26 in ./anaconda3/envs/tensorenv/lib/python3.5/site-packages (from tensorflow==0.11.0)
Collecting protobuf==3.0.0 (from tensorflow==0.11.0)
  Downloading protobuf-3.0.0-py2.py3-none-any.whl (342kB)
    100% |████████████████████████████████| 348kB 258kB/s 
Collecting six>=1.10.0 (from tensorflow==0.11.0)
  Downloading six-1.10.0-py2.py3-none-any.whl
Collecting numpy>=1.11.0 (from tensorflow==0.11.0)
  Downloading numpy-1.11.2-cp35-cp35m-manylinux1_x86_64.whl (15.6MB)
    100% |████████████████████████████████| 15.6MB 22kB/s 
Collecting setuptools (from protobuf==3.0.0->tensorflow==0.11.0)
  Downloading setuptools-29.0.1-py2.py3-none-any.whl (472kB)
    100% |████████████████████████████████| 481kB 290kB/s 
Installing collected packages: setuptools, six, protobuf, numpy, tensorflow
  Found existing installation: setuptools 27.2.0

TensorFlowのインストールエラー

途中で下記のエラーが発生してインストールが止まります。

Cannot remove entries from nonexistent file /home/yaju/anaconda3/envs/tensorenv/lib/python3.5/site-packages/easy-install.pth

パッケージの依存関係のコンフリクトが原因のようで、下記サイトの「2. pip で setuptools を TensorFlow と互換性があるものに upgrade する」で対応します。※下記サイトは、mac版です。
datalove.hatenadiary.jp

よって、下記コマンドを入力して再インストールします。

(tensorenv)$ pip install --upgrade -I setuptools
Collecting setuptools
  Using cached setuptools-29.0.1-py2.py3-none-any.whl
Installing collected packages: setuptools
Successfully installed setuptools-29.0.1

(tensorenv)$ pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.11.0-cp35-cp35m-linux_x86_64.whl
 ︙
Successfully installed numpy-1.11.2 protobuf-3.0.0 six-1.10.0 tensorflow-0.11.0

TensorFlowの動作確認

バージョンが表示されればインストール成功です。

(tensorenv)$python -c "import tensorflow; print(tensorflow.__version__);"

0.11.0

最後に

これでやっとTensorFlowを始められます。

これ以降は下記サイトを参考にして下さい。Web上の実行環境である「Jupyter Notebook」はAnacondaと同時にインストールされています。
yaju3d.hatenablog.jp

TensorFlowコトハジメ Word2Vecで「君の名は。」と戯れてみた

はじめに

前回、Word2Vecを初めて試してみて面白いと思ったので、日本語に挑戦することにした。 yaju3d.hatenablog.jp

日本語に挑戦するにあたり、どうせなら旬なネタがいいなと思って、今のお気に入りは火曜ドラマ「逃げるは恥だが役に立つ」で「みくに - 平匡」の結果がどうなるか見てみたいと思ったわけですが、元となるデータ(2chデータやTVの感想)を収集するのが面倒くさいのと、まだドラマが中盤なので後回しにしました。
その代わりとして思いついたのが新海誠さんの「君の名は。」です。小説が出ているので小説をそのまま取り込めば、ノイズが入らないのでいい結果が得られると思ったからです。ただデータ量としては少ないのが懸念です。

小説のテキスト化

小説 君の名は。 (角川文庫) Kindle版を購入しました。

下記の手順に従って、「君の名は。」をテキスト化しました。個人でデータマイニングする上で問題ないので。
【追記 2017/02/10 参照サイトが削除されていたため、手順を記述しました。】
Kindleで購入した電子書籍には DRM(デジタル著作権管理)プロテクトが掛かっているので解除が必要です。DRM解除機能は「 Calible + DeDRM 」の合わせ技で実現できます。
参照:完全無料!Amazonで購入したKindleの縦書き電子書籍をPDFに変換する方法

Step1:Kindle for PCをインストールします。
Step2:Calibreをインストールします。
Step3:DeDRM(tools_v6.2.1.zip)をダウンロードし、解凍するとDeDRM_calibre_pluginフォルダ内に「DeDRM_plugin.zip」が見つかります。
Step4:Kindle for PCに対象の本をダウンロードします。
Step5:Calibreを起動し、マイドキュメントの「My Kindle Content」フォルダにある対象の本「.azw」ファイルをCalibreにドラッグ&ドロップしてください。
Step6:Calibreで「設定」→「プラグイン」→「ファイルからプラグインを読み込む」で「DeDRM_plugin.zip」を選択します。 その際にセキュリティリスクの警告が表示されますが、そのまま「はい」→「OK」とクリックしていきます。プラグインを有効にするために、Calibreを再起動します。
Step7:Calibreで対象の本を選択し、「本を変換」の変換画面で出力フォーマットを「TXT」にして「OK」をクリックすると変換が開始されます。
Step8:変換されたTXTファイルは、マイドキュメントの「Calibre Library」フォルダに保存されています。

形態素解析

テキスト化された「君の名は。」ですが、Word2Vecで使用するには「分かち書き」にする必要があります。
分かち書きとは、ある単位ごとに区切って、その間に空白を置くことです。
形態素解析として、「MeCab」より「JUMAN++」の方が、表記揺れや話し言葉に強いということで、「JUMAN++」を使用することにしました。 qiita.com

JUMAN++のインストール

最初はいつも通りにDocker上のTensorFlowでターミナルを使用としたのですが、「boostlib」のインストールが出来ないため断念、Dockerを使う前に作成したVirtualBoxにUbuntu(64bit)とPython数値計算環境「Anaconda」の環境があったため、こちらを久しぶりに使用しました。OSはUbuntu 14.04.2 LTSからアップグレードして、Ubuntu 16.04 LTSにしています。

yaju3d.hatenablog.jp

JUMAN++のインストールには下記サイトを参考にしました。 foolean.net
ただ、「sudo python setup.py install」としても「from pyknp import Jumanpp」で「ImportError: No module named pyknp」となるため、ネットで検索して「pip install ./pyknp-0.3」としたりして何とか使えるようになりました。ここらへんの仕組みがまだ理解出来てないですね。

JUMAN++は、VirtualBox上から使用しているから余計なんですが遅いなと思って、今見たらVirtualBox上のメモリが1GByteのままでした、JUMAN++の推奨はメモリ4GByteです。

JUMAN++による分かち書き

JUMAN++による分かち書きは、下記サイトのプログラムを使用させて頂きました。 foolean.net

最初にオプションを付けないまま、分かち書きをしてWord2Vecを使ったのですが、思ったような結果が得られないとTwitter上で呟いたところ、@K_Ryuichirouさんから、ストップワードを省いてみたらとのアドバイスを頂いて、ストップワードを省いて再挑戦しました。
ストップワードとは、一般的すぎる語や低頻度すぎる語などで、助詞や助動詞などの機能語(日本語ならば「は」「の」「です」「ます」など)のことです。

python3 main.py input.txt -t 名詞 動詞 形容詞 副詞

メモリが少ないこともあって、テキストデータを4つに分割してから、結果を結合しています。あと、事前にあとがき以降と空行を削除しています。

Gensim版Word2Vecのインストール

前回、Gensimを使わない「pip install word2vec」でインストールしたのですが、テキストファイルを読む「word2vec.Text8Corpus」メソッドが無いことに気がつきました。テキストファイルを読む処理などを作り込めばいいのですが、面倒なので素直にGensim版Word2Vecのインストールすることにしました。

今度は、前回と同じ環境であるDocker上のTensorFlowで構築した環境を使用します。
※別にそのままVirtualBox上の環境でも構いません。

$ easy_install -U gensim
Installed /usr/local/lib/python2.7/dist-packages/boto-2.43.0-py2.7.egg                                                                                        
Finished processing dependencies for gensim
$ pip install cython

Cythonを入れるのは、word2vecをスピードアップ(70倍違うとか)させるためです。

Word2Vecと戯れる

先にJupyter notebook上で分かち書きした「yourname.txt」をUploadしておきます。
※yourname.txtは、2000行で176KByteです。

「三葉」と「瀧」のそれぞれの結果で、「俺」と「私」が出てくるのは物語通りですね。

from gensim.models import word2vec
data = word2vec.Text8Corpus('yourname.txt')
model = word2vec.Word2Vec(data, size=200)

out=model.most_similar(positive=[u'三葉'])
for x in out:
    print x[0],x[1]

#結果0.999974846840.999966681004
する 0.9999563694
して 0.9999560117720.999956011772
こと 0.9999519586560.9999514818190.999950230122
先輩 0.999950110912
自分 0.999948740005
from gensim.models import word2vec
data = word2vec.Text8Corpus('yourname.txt')
model = word2vec.Word2Vec(data, size=200)

out=model.most_similar(positive=[u'瀧'])
for x in out:
    print x[0],x[1]

#結果0.9999613165860.999957501888
三葉 0.999945700169
して 0.999944329262
した 0.99993789196
先輩 0.999935507774
もう 0.9999344348910.9999333024020.9999322891240.999930977821

「俺 + 私 - 三葉」の結果が「瀧」ですね。

from gensim.models import word2vec
data = word2vec.Text8Corpus('yourname.txt')
model = word2vec.Word2Vec(data, size=200)

out=model.most_similar(positive=[u'俺',u'私'],negative=[u'三葉'])
for x in out:
    print x[0],x[1]

#結果0.99993789196
して 0.999936521053
こと 0.999934196472
した 0.999931871891
テッシー 0.9999276399610.999927401543
言う 0.999924242496
もう 0.9999235272410.9999231100080.999921619892

同様に「俺 + 私 - 瀧」の結果が「三葉」ですね。

from gensim.models import word2vec
data = word2vec.Text8Corpus('yourname.txt')
model = word2vec.Word2Vec(data, size=200)

out=model.most_similar(positive=[u'俺',u'私'],negative=[u'瀧'])
for x in out:
    print x[0],x[1]

#結果
三葉 0.999938130379
こと 0.9999338388440.999928653240.999924600124
テッシー 0.999921619892
して 0.999921500683
彗星 0.99992030859
する 0.9999191761020.9999167323110.999916255474

「三葉 - 瀧」の結果が「愛」なんてイキですね。

from gensim.models import word2vec
data = word2vec.Text8Corpus('yourname.txt')
model = word2vec.Word2Vec(data, size=200)

out=model.most_similar(positive=[u'三葉'],negative=[u'瀧'])
for x in out:
    print x[0],x[1]

#結果0.0158168040216
トンビ 0.0155568365008
地点 0.0151626057923
置いた 0.0145640941337
情報 0.0137448376045
金色 0.0131560843438
光って 0.0130646442994
古い 0.0127832395956
おばちゃん 0.0127398446202
地面 0.0123804248869

※この「愛」は「愛(いと)おしい」と思われます。

最後に

実際にやってみて、そこそこの結果が得られて良かったです。
データ量が少ないのか「WARNING:gensim.models.word2vec:under 10 jobs per worker: consider setting a smaller `batch_words' for smoother alpha decay」と警告が出ていますので、調整が必要なんだと思います。

Kindleなどの電子小説ならテキスト化できるので、自分の好きな小説を試してみるのも楽しいと思います。

参照

TensorFlowコトハジメ Word2Vecによる自然言語処理を試す

はじめに

以前、ベイジアンフィルタを実装して自然言語処理に興味を持ち始めたので、とりあえず「king - man + woman = queen」で有名になった「Word2Vec」を動かしてみたいと思った次第です。
yaju3d.hatenablog.jp

Word2Vecとは

Word2Vecは米グーグルの研究者であるトマス・ミコロフ氏らが提案した機械学習の分野で使われる、ニューラルネットというモデルを使ったツール/ライブラリです。名前の通り、word(単語)をvector(ベクトル)に変換します。
この技術をベースに、「単語」だけではなく「文書」にも意味を持たせてベクトルとして捉えて利用できる技術「Doc2Vec」も作成されました。

ベクトルは1行m列やn行1列のこと、または「大きさと向き」を持つ量のことです。単語を文字列としているだけでは分類することは出来ないので何かしら意味のある数値にするわけです。こうすることでベクトル同士の足し算・引き算・コサイン類似度などを計算できるようになり、有名になった「king(王様) - man(男) + woman(女性) = queen(女王)」ということが可能になるわけです。
他にも「東京 - 日本 + フランス = パリ」となるという例もあり、これは「首都」であるという関連情報が上位にあるからです。

単語をベクトル表現する方法は「word2vec」以前にもあったのですが、類似度の特徴を満たしていたものの足したり引いたりといった操作までは出来ませんでした。なので、「word2vec」が発表された時は一般には衝撃的だったのです。

enakai00.hatenablog.com

ベクトル空間モデル

word2vec以外で基本的なベクトル空間モデルを2点を列挙します。

BoW(Bag of Words)モデル

テキストデータを単語ごとの出現回数だけで表す方法です。ちなみに、bagは多重集合(multiset)の別名とのこと。
単語の出現順は考慮しないため。「彼女と僕」と「僕と彼女」は同じベクトルになる。

N-gramモデル

テキストデータをN文字単位で文字列を分解して表す方法です。
「彼女と僕」→ 彼女、彼女と、と僕、僕
「僕と彼女」→ 僕、僕と、と彼女、彼女

N-gramモデルでは、隣り合った文字列または単語の組み合わせを「共起関係」と呼びます。
また、「共起関係」がどの程度現れるかを集計した結果を「共起頻度」と呼びます。

実装環境

Pythonは、Docker上のTensorFlowで構築した環境を使用しています。
参照:WindowsユーザーがTensorFlowをインストールしてみた(Docker版) - デジタル・デザイン・ラボラトリーな日々

環境

  • Docker
  • Jupyter
  • Python 2.7
  • Word2Vec 0.9.1
  • CPython 0.25.1

Word2Vecのインストール

Word2Vecをインストールしたら「ImportError: No module named Cython.Build」とエラーになりましたので、先に「Cython」をインストールします。
※Word2Vecは、Pythonから扱える自然言語処理ライブラリ(Gensim)に含まれているのですが、今回はGensimを使わない方法にしました。
※pipはアップグレードしておいただけです。

# pip install --upgrade pip
 ︙
Successfully installed pip-9.0.1  
# pip install Cython
 ︙
Successfully installed Cython-0.25.1
# pip install word2vec
 ︙
Successfully installed word2vec-0.9.1

Word2Vecを試す

下記のword2vecのexamplesサイトを試しに動かしてみます。 http://nbviewer.jupyter.org/github/danielfrg/word2vec/blob/master/examples/word2vec.ipynb

text8.zipのダウンロードと解凍

Word2Vecのデモ用としてtext8という100MB程のコーパスのデータが用意されていますので、ダウンロードして解凍します。
wgetコマンドが無かったので、curlコマンドを使用します。

# curl http://mattmahoney.net/dc/text8.zip > text8.gz                                                                                                         
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                                                               
                                 Dload  Upload   Total   Spent    Left  Speed                                                                                 
100 29.8M  100 29.8M    0     0   497k      0  0:01:01  0:01:01 --:--:--  396k                                                                                
# gzip -d text8.gz -f                                                                                                                                         

Jupyter Notebook

Inの番号が飛んでいるのはミスしたからで意味はありません。 examplesサイトではtext8の格納フォルダ「/Users/drodriguez/Downloads/」になっていますが、自分はカレントフォルダに格納したのでフォルダは付けていません。

「king - man + woman」の部分

indexes, metrics = model.analogy(pos=['king', 'woman'], neg=['man'], n=10)
indexes, metrics
model.generate_response(indexes, metrics).tolist()

結果として、「queen」が先頭になっています。

[(u'queen', 0.2905402467729655),
 (u'empress', 0.2734506828577926),
 (u'prince', 0.2709167973829251),
 (u'wife', 0.2679356346054478),
 (u'monarch', 0.26728773557223445),
 (u'son', 0.2666904115522106),
 (u'throne', 0.2657155461401751),
 (u'regent', 0.26416170868397304),
 (u'pope', 0.2637096213206423),
 (u'pharaoh', 0.2619265026976325)]

最後に

Word2Vecをインストールして英語用のデモを試して雰囲気を楽しんだだけでしたが、次回は日本語を使っていろいろ試してみたいと思います。
今回初めて、GitHub Gistを使ってブログにJupyter Notebookを表示してみました。これ結構いけますね。

参照

TensorFlowコトハジメ 偶数と奇数に分類

はじめに

久しぶりにTensorFlowをさわってみました。
人工知能を勉強しようとしてもハードルが高いし、手書きの文字を分類したからって何って感じ、画像を集めるのも大変だし結果を出すにも時間がかかるしね。
先ずはリハビリとして何をやろうかと思ったのが、以前やったFizz-Buzz問題を応用して偶数と奇数に分類させてみるというもので、結果がすぐ出るのがいいよね。

yaju3d.hatenablog.jp

仕組み

101から127(27-1)までのデータで学習したニューラルネットワークに対して、1から100までの答え(偶数ならeven、奇数ならodd)の予測を出力するプログラムになっています。こんなんでも、贅沢にもディープラーニングを使ってます。
訓練する際に偶数か奇数かを振り分けるのに2の剰余(余り)を使っていますが答えを出すのに2の剰余(余り)を使っていません、コンピューターが学習して判断しています。

最低限で正しい結果が出るようにしたかったので、出来るだけ関連する数値を減らしています。

  • NUM_DIGITS = 7 … 101から学習させる範囲で2の指数値
  • NUM_HIDDEN = 5 … 隠れ層のユニット数
  • BATCH_SIZE = 1 … バッチ数
  • range(30) … エポック(学習ループの単位)の範囲

ソースコード

# coding: utf-8
# even odd in Tensorflow!

import numpy as np
import tensorflow as tf

NUM_DIGITS = 7

# Represent each input by an array of its binary digits.
def binary_encode(i, num_digits):
    return np.array([i >> d & 1 for d in range(num_digits)])

# One-hot encode the desired outputs: ["even", "odd"]
def even_odd_encode(i):
    if   i % 2 == 0: return np.array([1, 0])
    else:            return np.array([0, 1])

# Our goal is to produce even odd for the numbers 1 to 100. So it would be
# unfair to include these in our training data. Accordingly, the training data
# corresponds to the numbers 101 to (2 ** NUM_DIGITS - 1).
trX = np.array([binary_encode(i, NUM_DIGITS) for i in range(101, 2 ** NUM_DIGITS)])
trY = np.array([even_odd_encode(i)           for i in range(101, 2 ** NUM_DIGITS)])

# We'll want to randomly initialize weights.
def init_weights(shape):
    return tf.Variable(tf.random_normal(shape, stddev=0.01))

# Our model is a standard 1-hidden-layer multi-layer-perceptron with ReLU
# activation. The softmax (which turns arbitrary real-valued outputs into
# probabilities) gets applied in the cost function.
def model(X, w_h, w_o):
    h = tf.nn.relu(tf.matmul(X, w_h))
    return tf.matmul(h, w_o)

# Our variables. The input has width NUM_DIGITS, and the output has width 2.
X = tf.placeholder("float", [None, NUM_DIGITS])
Y = tf.placeholder("float", [None, 2])

# How many units in the hidden layer.
NUM_HIDDEN = 5

# Initialize the weights.
w_h = init_weights([NUM_DIGITS, NUM_HIDDEN])
w_o = init_weights([NUM_HIDDEN, 2])

# Predict y given x using the model.
py_x = model(X, w_h, w_o)

# We'll train our model by minimizing a cost function.
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(py_x, Y))
train_op = tf.train.GradientDescentOptimizer(0.05).minimize(cost)

# And we'll make predictions by choosing the largest output.
predict_op = tf.argmax(py_x, 1)

# Finally, we need a way to turn a prediction (and an original number)
# into a even odd output
def even_odd(i, prediction):
     return ["{0:3d}".format(i) + ":even", "{0:3d}".format(i) + ":odd "][prediction]

BATCH_SIZE = 1

# Launch the graph in a session
with tf.Session() as sess:
    tf.initialize_all_variables().run()

    for epoch in range(30):
        # Shuffle the data before each training iteration.
        # print(range(len(trX)))

        p = np.random.permutation(range(len(trX)))
        trX, trY = trX[p], trY[p]

        # Train in batches of 1 inputs.
        for start in range(0, len(trX), BATCH_SIZE):
            end = start + BATCH_SIZE
            sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end]})

        # And print the current accuracy on the training data.
        if epoch % 10 == 0:
            print(epoch, np.mean(np.argmax(trY, axis=1) ==
                             sess.run(predict_op, feed_dict={X: trX, Y: trY})))

    # And now for some even odd
    numbers = np.arange(1, 101)
    teX = np.transpose(binary_encode(numbers, NUM_DIGITS))
    teY = sess.run(predict_op, feed_dict={X: teX})
    output = np.vectorize(even_odd)(numbers, teY)

    print(output)

出力結果

見事に1から100まで偶数と奇数に分類することが出来ました。

(0, 0.66666666666666663)
(10, 0.85185185185185186)
(20, 1.0)
['  1:odd ' '  2:even' '  3:odd ' '  4:even' '  5:odd ' '  6:even'
 '  7:odd ' '  8:even' '  9:odd ' ' 10:even' ' 11:odd ' ' 12:even'
 ' 13:odd ' ' 14:even' ' 15:odd ' ' 16:even' ' 17:odd ' ' 18:even'
 ' 19:odd ' ' 20:even' ' 21:odd ' ' 22:even' ' 23:odd ' ' 24:even'
 ' 25:odd ' ' 26:even' ' 27:odd ' ' 28:even' ' 29:odd ' ' 30:even'
 ' 31:odd ' ' 32:even' ' 33:odd ' ' 34:even' ' 35:odd ' ' 36:even'
 ' 37:odd ' ' 38:even' ' 39:odd ' ' 40:even' ' 41:odd ' ' 42:even'
 ' 43:odd ' ' 44:even' ' 45:odd ' ' 46:even' ' 47:odd ' ' 48:even'
 ' 49:odd ' ' 50:even' ' 51:odd ' ' 52:even' ' 53:odd ' ' 54:even'
 ' 55:odd ' ' 56:even' ' 57:odd ' ' 58:even' ' 59:odd ' ' 60:even'
 ' 61:odd ' ' 62:even' ' 63:odd ' ' 64:even' ' 65:odd ' ' 66:even'
 ' 67:odd ' ' 68:even' ' 69:odd ' ' 70:even' ' 71:odd ' ' 72:even'
 ' 73:odd ' ' 74:even' ' 75:odd ' ' 76:even' ' 77:odd ' ' 78:even'
 ' 79:odd ' ' 80:even' ' 81:odd ' ' 82:even' ' 83:odd ' ' 84:even'
 ' 85:odd ' ' 86:even' ' 87:odd ' ' 88:even' ' 89:odd ' ' 90:even'
 ' 91:odd ' ' 92:even' ' 93:odd ' ' 94:even' ' 95:odd ' ' 96:even'
 ' 97:odd ' ' 98:even' ' 99:odd ' '100:even']

ちなみに、隠れ層のユニット数「NUM_HIDDEN = 3」にした場合、間違った答えになります。

(0, 0.33333333333333331)
(10, 0.66666666666666663)
(20, 1.0)
['  1:odd ' '  2:odd ' '  3:odd ' '  4:odd ' '  5:odd ' '  6:odd '
 '  7:odd ' '  8:odd ' '  9:odd ' ' 10:odd ' ' 11:odd ' ' 12:odd '
 ' 13:odd ' ' 14:odd ' ' 15:odd ' ' 16:even' ' 17:odd ' ' 18:odd '
 ' 19:odd ' ' 20:odd ' ' 21:odd ' ' 22:odd ' ' 23:odd ' ' 24:odd '
 ' 25:odd ' ' 26:odd ' ' 27:odd ' ' 28:odd ' ' 29:odd ' ' 30:odd '
 ' 31:odd ' ' 32:even' ' 33:odd ' ' 34:odd ' ' 35:odd ' ' 36:odd '
 ' 37:odd ' ' 38:odd ' ' 39:odd ' ' 40:even' ' 41:odd ' ' 42:odd '
 ' 43:odd ' ' 44:odd ' ' 45:odd ' ' 46:odd ' ' 47:odd ' ' 48:even'
 ' 49:odd ' ' 50:odd ' ' 51:odd ' ' 52:odd ' ' 53:odd ' ' 54:odd '
 ' 55:odd ' ' 56:even' ' 57:odd ' ' 58:odd ' ' 59:odd ' ' 60:odd '
 ' 61:odd ' ' 62:odd ' ' 63:odd ' ' 64:even' ' 65:odd ' ' 66:odd '
 ' 67:odd ' ' 68:even' ' 69:odd ' ' 70:odd ' ' 71:odd ' ' 72:even'
 ' 73:odd ' ' 74:odd ' ' 75:odd ' ' 76:even' ' 77:odd ' ' 78:odd '
 ' 79:odd ' ' 80:even' ' 81:odd ' ' 82:odd ' ' 83:odd ' ' 84:even'
 ' 85:odd ' ' 86:even' ' 87:odd ' ' 88:even' ' 89:odd ' ' 90:even'
 ' 91:odd ' ' 92:even' ' 93:odd ' ' 94:odd ' ' 95:odd ' ' 96:even'
 ' 97:odd ' ' 98:odd ' ' 99:odd ' '100:even']

最後に

人工知能を使っていろいろやってみたいのですが、それをどうやって組むのかがまだピンと来ないんですよね。
前回、「確率を理解してみる-ベイジアンフィルタを実装」をやってみて自然言語が面白そうなので挑戦してみます。

スポンサーリンク