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

アラフィフプログラマーが数学と物理を基礎からやり直す

ディープラーニング(深層学習)を理解してみる(TensorFlow Playgroundを試す)

はじめに

前回はパーセプトロンを多層にすることで、線型分離可能でない問題を解けることを学びました。
yaju3d.hatenablog.jp

これを視覚として見ながら学びたいということで見つけたのが「TensorFlow Playground」となります。
f:id:Yaju3D:20170624220010p:plain

しかし、初見では何がなんだか分からないので「TensorFlow Playground」のことを書いている幾つかのブログを参考に学んでいきます。

TensorFlow Playgroundとは

TensorFlow Playgroundは、A Neural Network Playgroundとも呼ばれ、Daniel SmilkovさんとShan Carterさんが開発したニューラルネットワークの仕組みを理解するための教育コンテンツです。

TensorFlow Playgroundの日本語訳を書いてくれているのが「TensorFlow Playgroundの仕組み」です。

目的

下図のように青とオレンジの正しい区切りの位置を見つけるということです。
直線だと簡単に分離できる問題もあれば、円形という複雑な問題もあるわけです。
f:id:Yaju3D:20170604230608p:plain

使い方

例題 Circle(円)、Gaussian(ガウシアン)、Exclusive or(排他or:XOR)、Spiral(螺旋)
f:id:Yaju3D:20170626230724p:plain

全体レイアウト

f:id:Yaju3D:20170625120546p:plain

  • ①は、DATA(データ)は例題となります。例題は4つあり初期値は円となっています。
  • ②は、FEATURES(特徴)は、入力するデータの特徴となります。特徴は7つあり初期値は上2つとなっています。
  • ③は、HIDDEN LAYERS(隠れ層)は中間層となります。中間層の数を「+」と「-」ボタンで増減でき初期値は2段となっています。
  • ④は、neurons(ニューロン)は、各隠れ層のノードとなります。
    ※各ノードをマウスオーバーすると⑥で拡大して見れます。ニューロンは重みの影響を受け、重みは線の太さと色で表されます。
    • ④-1が先頭の中間層で初期値は4ニューロンとなります。
    • ④-2が最後の中間層で初期値は2ニューロンとなります。
  • ⑤は、再生ボタンとなります。決定したモデルを実際に動かします。
  • ⑥は、出力結果となります。
  • ⑦は、Test loss(誤差(テスト))とTraining loss(誤差(トレーニング))の数値となります。

実際に動かしてみよう

デフォルト状態で再生してみます。右側の出力結果の平面上に点在したオレンジと青の点々に沿うようにヒートマップの色が変化していく様子が見れるはずです。 そして点々の色とヒートマップの色の分布が互いに近づいてくるに従って誤差の数値が小さくなる様子も確認できるはずです。

青枠⑦のTest loss(誤差(テスト))とTraining loss(誤差(トレーニング))の数値を見ます。これが少ないほど良い結果になります。
Epochが50くらいで図上では分離されていますが、誤差の数値的には0.022とまだあります。
Epochが100くらいで誤差の数値的には0.008くらいまで下がります。
Epochが500くらいまでいくと誤差が0.0001まで下がります。

パラメーターをいじってみる

④-1の先頭の中間層を4ニューロンから3ニューロンに減らしてみます。
f:id:Yaju3D:20170625134326p:plain
これだとあまり変化なく、Epochが500くらいまでいくと誤差が0.0001まで下がります。
さらに2層まで減らすとEpochが1000までいっても収束しません。

今度は、中間層を1つ増やしてみます。
f:id:Yaju3D:20170625145117p:plain
Epochが200くらいまでいくと誤差が0.0001まで下がるので、収束は速くなります。

各パラメーターの説明

TensorFlow Playgroundの日本語訳「TensorFlow Playgroundの仕組み」から一部抜粋します。

上側パラメーター
  • Epoch(エポック)は、学習させる回数です。用意された全トレーニングデータをニューラルネットワークに投入しパラメータを更新、修正し終えると機械学習の1サイクル(1エポック)が完了します。 統計モデルの種類が分類の場合、トレーニングデータは500個なので、この500個全部をトレーニングに使い切ると1エポック完了したことになります。
  • Learning rate(学習率)は、一度の学習でどの程度重みやバイアスの値を修正するかの率を表します。学習率が大きいと1度に修正される重み、バイアスの量が大きくなります。 小さくすると重み、バイアスの値を1度に少しだけ修正しようとします。
  • Activation(活性化関数)は、ニューロンの出力をフィルタリングします。tanh、ReLU、Sigmoid(シグモイド関数)、Liner(線形関数)があります。
  • Regularization(正則化)は、過学習を防ぐための仕組みです。None, L1, L2 があります。
  • Regularization rate(正則化項)は、正則化されたニューラルネットワークに対して正則化項を加えることで、より過学習を防ぐようになります。
  • Problem type(統計モデルの種類)は、「Classification(分類)」と「Regression(回帰)」の2種類があります。
    • Classification(分類)は、入力した画像が猫であるか猫でないかを0/1で判断する。分類の図は点々がブルー(+1)かオレンジ(-1)かの二通りの出力結果のデータの分布となります。
    • Regression(回帰)は、得点の値について-1,1だけのとびとびの離散的な値だけでなく、 その間の-0.529や0.29039などの-1から+1までの連続的な中間値も考慮に入れます。入力した画像が猫である確率を求める場合に使います。回帰の図は分類と同様に点々がブルー(+1)かオレンジ(-1)であることには変わりありませんが、白味がかった-1と+1の間の中間の値のデータも含まれます。
左側パラメーター
  • Ratio of training to test data(トレーニングデータの割合)は、「Classification(分類)」が500個、「Regression(回帰)」が1200個のデータのサンプル数となっていますので、例えばトレーニングデータの割合を60%とすると、500個のデータサンプルの内300個をトレーニングデータに、 200個のデータをテストデータに回します。
  • Noise(ノイズ)は、円やガウシアンなどの選択したデータセットに対してかけるノイズ(0〜50まで5刻みで設定)で数値は%単位です。
  • Batch size(バッチサイズ)は、1回の学習(重み、バイアスの更新)を何個のトレーニングデータで実施するかを決める数値です。例えば1エポックで500回学習とした場合にバッチサイズが25にすると、1エポックで20回学習することになります。
  • REGENARATE(再生成)は、データを再生成します。
右側下パラメーター

f:id:Yaju3D:20170626231602p:plain

過学習

過学習が発生すると、十分に小さなTraining loss(誤差(トレーニング))に対して、Test loss(誤差(テスト))が小さくならない現象が発生します。TensorFlow Playgroundで意図的に過学習を起こすことは簡単です。画面左側の「Ratio of training to test data(トレーニングデータの割合)」を10%まで下げてみます。
f:id:Yaju3D:20170626234708p:plain

スライド

例題

Problem type(統計モデルの種類)の「Classification(分類)」だけ他の例題を自分なりにやってみました。
これが正しいわけでもなく、再更新すると違う結果になったりすることもあります。

Gaussian(ガウシアン)

一番単純です。Activation(活性化関数)をLiner(線形関数)にしています。
f:id:Yaju3D:20170626232335p:plain

Exclusive or(排他or:XOR)

XORは線形分離不可能な問題です。特徴量にX1X2があるのでそのまま使っています。
f:id:Yaju3D:20170626233038p:plain

別方法として特徴量は先頭2つでやってみました。Activation(活性化関数)をReLUにすると直角的になります。
f:id:Yaju3D:20170627215236p:plain

Spiral(螺旋)

特徴量を全て使っています。過学習を防ぐためRegularization(正則化)をL1、Regularization rate(正則化項)を0.001にしてます。
なかなかTest loss(誤差(テスト))が下がらなくて、0.008が限界でした。
f:id:Yaju3D:20170626233502p:plain

特徴量を減らして、中間層を増やしてみました。Test loss(誤差(テスト))は、0.006になりました。
f:id:Yaju3D:20170627234331p:plain

参照

ディープラーニング(深層学習)を理解してみる(パーセプトロンと論理演算)

はじめに

TensorFlow関連の記事を書いている割には、ディープラーニング(深層学習)について理解度が足りてないということもあって基礎的なところから理解してみようと思いました。幸い、ここ1年で本やブログ記事が増えてきたので助かります。

参考にした下記の2つ本となります。あと、この本の内容を元にした幾つかのブログの記事などです。
自分なりに理解したことをまとめて書いていきますが、詳細はリンク先を参照してください。

線形と非線形

機械学習をやる上で「線形」と「非線形」という言葉が出てきますので、先に説明しておきます。

線形

簡単に言えば、直線的な線のことです。
一次関数「例 y = ax + b」のように定数倍と足し算・引き算で表されたものとなります。

非線形

線形以外で曲線的や変化が激しい線のことです。
二次関数「例 y = x2」のように放物線などで表されたものです。

イメージ

左図が線形、右図が非線形となります。「★」と「○」を区分ける際に直線で区分けるのは簡単ですが、曲線的でないと区分けることが出来ないのは難しいです。
f:id:Yaju3D:20170604200125p:plain

ディープラーニング(深層学習)とは

ディープラーニング機械学習の一種で、神経細胞を模したパーセプトロン(ニューロンモデル)と言う小さな計算機をたくさん用意し多層にして構築したものです。よって、多層構造のニューラルネットワークを用いた機械学習と言えます。 ※パーセプトロンニューラルネットワークの基本単位となります。

現在のディープラーニングに到るまでを順を追って書いています。

形式ニューロン

f:id:Yaju3D:20170528144340p:plain f:id:Yaju3D:20170528154127p:plain
左図が本物の神経細胞(ニューロン) で、右図が形式ニューロンです。
形式ニューロンWikipediaから引用します。

形式ニューロン(けいしきニューロン、英: formal neuron)や Threshold Logic Unit とは、1943年に神経生理学者・外科医であるウォーレン・マカロックと論理学者・数学者であるウォルター・ピッツが発表した最初の人工ニューロン(英: artificial neuron)[1]。伝達関数としてはヘヴィサイドの階段関数を使い、入出力の値は 0 または 1 の二値だけをとる。

簡単に説明すると、入力が2つあり各入力に対して重みが掛け算され、その値が閾値を超えれば出力は「1」、そうでなければ出力は「0」となります。 たとえば、入力が(1,0)、重みが(0.5, 0.7)だとすると、1×0.5 + 0×0.7 = 0.5 を計算して閾値と比較します。

形式ニューロンの場合、入力が「0」か「1」、重みが「実数」、出力が「0」か「1」となります。

パーセプトロン

心理学者のドナルド・ヘッブが、1949年に学習や記憶を進めるのは集中力や根性でなくシナプス(神経細胞同士の接合部)であると生理学的な提起をしました。「ヘッブの法則」というもので、シナプス(神経細胞同士の接合部)は、よく使うものほど強化され使わなくなると徐々に結合が弱くなります。

このヘップの法則を形式ニューロンのような神経回路モデルにあてはめることができないかということから考え出されたのが「パーセプトロン」となります。

単純パーセプトロン

f:id:Yaju3D:20170528193545p:plain
1958年にローゼンブラットが提案したパーセプトロンは形式ニューロンを発展させ、いくつか並列に組み合わせてから出力ニューロンで束ねるという2層(入力層と出力層)の構造をとることで、入力と出力のペアを学習することを示しました。

形式ニューロンと違う点としては、入力は「実数」であることと学習という過程があります。
トレーニングデータを複数を用意することによって、間違った答えを出力した場合、ある計算式に従って重みやバイアスの値を変化させます。
f:id:Yaju3D:20170604230608p:plain

基本的には線型分離可能な問題しか解くことができない(ミンスキーとパパートにより指摘)という欠点があります。

余談ですが、ローゼンブラットが提案したパーセプトロン非線形分離問題も扱える3層でしたが、その後の研究は中間層を省いた2層による単純パーセプトロンの研究が進んだため、ミンスキーとパパートの共著「パーセプトロン」(1969年出版)による批判も単純パーセプトロンだけに当てはまるものだったのです。パーセプトロンの熱は一気に冷めてしまい、パーセプトロンは線形分離可能問題しか扱えないというレッテルが貼られたのでした。

多層パーセプトロン

世の中の解きたい問題は大抵パーセプトロン(線型分離可能な問題)では解けないタイプの問題であったため、パーセプトロンの研究は廃れていきました。それ以降は人工知能の研究は学習型ではなく、知識を扱うプロダクションルール型に移行していった。 しかし、約15年後の1986年に認知心理学者ラメルハートが再発見した3層モデルのバックプロパゲーション(誤差逆伝播学習法)を発表したことで、再び脚光を浴びたのである。
再発見とは、1967年に甘利俊一先生が隠れ層のある3層以上の計算モデルを既に発表していた。
f:id:Yaju3D:20170528195430p:plain

単純パーセプトロンの真ん中の層を追加しました。この層を隠れ層(hidden layer)または中間層と呼びます。実はこれだけで線形分離可能な問題しか解けないという欠点を解決できたのです。
単純パーセプトロンでは重みを調整するのが1層で簡単だったのですが、今回は2層でそれぞれの層の調整するのが難しという問題がありましたが、誤差逆伝搬(所望の出力結果になるよう誤差を出力層から入力層に向かった逆方向に重みを調整するもの)と呼ばれる方法を使うこと良い重み調整方法を手に入れたため、3層構造でも学習可能になったのです。

f:id:Yaju3D:20170528222639p:plain
再びニューラルネットワークのブームが訪れ、あらゆるものに応用が試みられて3層より層を深くして学習効果を上げることも試されました。 しかし、バックプロパゲーションは4層以上にすると満足な精度が得られませんでした。
バックプロパゲーションを多層にすると勾配消失と過学習が発生することで、うまく学習できなくなるのです。

当時は、学習時間が非常にかかることや過学習を防ぐための理論がなく、サポートベクターマシン(SVM)など他の手法が注目されていたこともあり、再びニューラルネットワークは冬の時代を迎えたのでした。

ディープラーニング

冬の時代にも着々と進められた技術的進歩の中で、2006年にカナダのトロント大学のジェフリー・ヒントン教授が「ディープビリーフネットワーク」を発表した。これは層が深くなっても学習できていた。
f:id:Yaju3D:20170529004111p:plain
従来のニューラルネットワーク(左図)はパラメーターの更新を4層以上一度にやっていたが、ディープビリーフネットワーク(右図)では層毎に学習が完了してから次の層を付け足したことにある。1層が終わってから2層目と順に学習し、全ての学習が終わってから全層を結合してバックプロパゲーションをかけたのである。
2006年にヒントン教授の論文では層が深いニューラルネットを総称して「ディープネットワーク」と呼び、2007年にアンドリュー・ング氏が論文で「高次元データの階層的な表現の学習」に「ディープラーニング」という言葉を用いた。

2012年にアンドリュー・ング氏が畳込みニューラルネットワーク(CNN)で1000万本のYouTubeビデオ画像を学習し、ディープラーニングが学習した猫の画像を発表した。以降、ディープラーニングは爆発的なブームとなり、全てのものに応用が試みられるようになったのである。 f:id:Yaju3D:20170604203231p:plain f:id:Yaju3D:20170529010051p:plain

現在のディープラーニングには「畳込みニューラルネットワーク」、「再起型ニューラルネットワーク」、「積層自己符号化器」、「ディープビリーフネットワーク」、「ディープボルツマンマシン」など多くの種類があります。

畳込みニューラルネットワーク(CNN)

現在、画像分類の分野で主流となっているのは「畳込みニューラルネットワーク(CNN)」です。この畳込みニューラルネットワークは、福島邦彦先生の「ネオコグニトロン」が元になっています。

f:id:Yaju3D:20170529013306p:plain
畳込みニューラルネットワークは、その名の通り畳込み(コンボリューション:Convolution)を行って情報を圧縮していくネットワークで、5層(入力層、畳込み層、プーリング層、全結合層、出力層)から構成されています。畳込み層とプーリング層は複数繰り返して深い層を形成し、その後の全結合層も同様に何層か続きます。

畳込み層では、カーネルという小さな正方形をフィルターとして適用しながら、入力された画像をより小さい画像に変換します。
f:id:Yaju3D:20170604222728p:plain f:id:Yaju3D:20160417025404g:plain
引用元:http://deeplearning.stanford.edu/wiki/index.php/Feature_extraction_using_convolution

プーリング層では、畳込み層から出力された特徴マップを縮小します。最大値プーリングの場合、注目領域の最大値を特徴マップの値とします。
f:id:Yaju3D:20170611164450p:plain
引用元: http://cs231n.github.io/convolutional-networks/#pool

画像認識での話ですが、プーリングは位置と回転に不変性を与えます。ある領域についてプーリングを行うと、画像が数ピクセルだけ移動や回転をしてもその出力はほぼ同じになります。それは最大プーリングが、微妙なピクセルの違いを無視して同じ値を抽出してきてくれるからです。
自然言語処理における畳み込みニューラルネットワークを理解する

浅いレイヤーは単純なパーツ(小さい部品より具体的なもの)を学習、深いレイヤーはパーツを組み合わせた全体の学習を行います。
f:id:Yaju3D:20170604205436p:plain

qiita.com

ネオコグニトロン

1979年に福島邦彦先生が後のディープラーニング計算に使われる「ネオコグニトロン」を発表した。現在のパターン認識を行うディープラーニングの構造は、ネオコグニトロンそのものであり、S細胞をコンボリューション、C細胞をプーリングと呼んでいるだけである。 ディープラーニングとの違いは学習の仕方で、ディープラーニングバックプロパゲーションを採用しており、ネオコグニトロンは新しい入力パターンに反応する細胞がないときは新しく細胞を加えるという「add-if silent」学習則を採用している。
ネオコグニトロンは当初特許出願されていたものの、予算が厳しく特許権を放棄した。特許権を継続していれば今頃は莫大な収入を得ていたかも知れませんが、特許権が無いことでディープラーニングが開花したのかも。

パーセプトロンと論理演算

人間の脳は神経細胞(ニューロン)のネットワークで構成されています。この最小単位の神経細胞(ニューロン)を模倣したモデルがパーセプトロンとなります。このモデルは入力値が閾値を超えた場合に「1」を出力(この場合を「ニューロンが発火する」と表現)し、そうでない場合は「0」を出力します。このように入力値から出力値を生むまでの計算を活性化関数と呼びます。

活性化関数

活性化関数とはニューロンが入力から出力を生むまでの計算のことで、活性化関数には非線形関数が用いられます。線形の活性化関数では非線形分離できないためです。
パーセプトロンでは活性化関数にステップ関数(入力に対してある閾値を境に階段(ステップ)のように出力が1か0か決まる)を使っていた。
f:id:Yaju3D:20170603024904p:plain

ニューラルネットワークは学習をする際に微分を含む計算を行うため、微分するとゼロになるステップ関数は都合が悪いことからシグモイド曲線(sigmoid)などが使用されている。

シグモイド曲線は入力した値を0から1の間に収めてくれる関数の1つです。多くの自然界に存在する事柄は、このようなS字曲線を取ります。欠点として1に近づくほど1そのものにならない性質があります。
f:id:Yaju3D:20170602002203p:plain

論理演算

コンピュータの演算には四則演算(+、-、×、÷)のほかに論理演算(AND、OR、NOT、XOR)があります。論理演算とは、2つ以上の1または0入力値に対して、1つの演算結果(1または0)を出力する演算のことです。
論理演算と四則演算の大きな違いは、論理演算が2進数の1桁(=1bit)を対象としていることと、演算結果が決して桁上がりしないことです。コンピュータは、内部的にすべてのデータを2進数で取り扱っているからこそ、コンピュータの世界では論理演算が重要なのです。

清水亮著「はじめての深層学習(ディープラーニング)プログラミング」の「2.2 論理演算を学習をさせてみる」として、Chainerを使用して論理演算の「AND」と「OR」と「NAND」および「XOR」を学習させています。
※初版本を購入したため、ソースリストにも誤りがありました。参照:お詫びと訂正

前回の記事「Chainer ver2.xをWindowsにインストールしてみた」でChainerを入れたこともあって、そのまま利用しています。tensorflow版は「tensorflow 論理演算」で検索してみて下さい。

仕組みそのものを知りたい方は「ゼロから作るDeep Learning」の本が「Python + numpy」のみで説明しています。参照:ゼロから作るDeep Learning 2章「パーセプトロン」

#!/usr/bin/env python
# coding: utf-8

import numpy as np
import chainer.functions as F
import chainer.links as L
from chainer import Variable, optimizers,Chain

class Model(Chain):
    def __init__(self):
        super(Model, self).__init__(
            l1 = L.Linear(2, 1),
            )
    def __call__(self, x):
        # h = self.l1(x)
        # sigmoid function
        h = F.sigmoid(self.l1(x))
        return h
    
model = Model()
optimizer = optimizers.MomentumSGD(lr=0.01, momentum=0.9)
optimizer.setup(model)

x = Variable(np.array([[0,0],[0,1],[1,0],[1,1]], dtype=np.float32))
# OR
t = Variable(np.array([[0],[1],[1],[1]], dtype=np.float32))
# AND
#t = Variable(np.array([[0],[0],[0],[1]], dtype=np.float32))
# NAND
#t = Variable(np.array([[1],[1],[1],[0]], dtype=np.float32))

for i in range(0, 3000):
    optimizer.zero_grads()
    y = model(x)
    loss = F.mean_squared_error(y, t)
    loss.backward()
    optimizer.update()
    
    print("loss:", loss.data)

print(y.data)
#print(y.data.round())

「OR」の実行結果 四捨五入すれば上から[ 0, 1, 1, 1]となります。

︙
loss: 0.01094332616776228
loss: 0.01093930285423994
[[ 0.15879413]
 [ 0.90393192]
 [ 0.90352207]
 [ 0.99786234]]

このソースコードでは「OR」が実行されるようになっています。「AND」または「NAND」を実行するには対象コメントを外して、他のところは逆にコメントを付けてください。あと、急に「NAND」が出てきましたが何故かは後述します。

f:id:Yaju3D:20170601010201p:plain f:id:Yaju3D:20170601010218p:plain f:id:Yaju3D:20170601010235p:plain

この中に「XOR」が無いのには理由があります。上図が示すように「OR」、「AND」、「NAND」については1本の判別直線で表現することが出来ます。つまり単純パーセプトロンで線型分離可能となっているわけです。

f:id:Yaju3D:20170601011628p:plain

ところが「XOR」の場合は非線形(もしくは2本の判別直線)にしないと判別することが出来ません。 これを判別できるようにするには、単純パーセプトロンの中間層(隠れ層)を追加して多層パープセトロンにすればいいのです。
f:id:Yaju3D:20170605010116p:plain

修正したのは上側部分で変数l2の追加と変数tをXORに変更したくらいです。

#!/usr/bin/env python
# coding: utf-8

import numpy as np
import chainer.functions as F
import chainer.links as L
from chainer import Variable, optimizers,Chain

class Model(Chain):
    def __init__(self):
        super(Model, self).__init__(
            l1 = L.Linear(2, 2),
            l2 = L.Linear(2, 1),
            )
    def __call__(self, x):
        # sigmoid function
        h = F.sigmoid(self.l1(x))
        return self.l2(h)
    
model = Model()
optimizer = optimizers.MomentumSGD(lr=0.01, momentum=0.9)
optimizer.setup(model)

x = Variable(np.array([[0,0],[0,1],[1,0],[1,1]], dtype=np.float32))
# XOR
t = Variable(np.array([[0],[1],[1],[0]], dtype=np.float32))

for i in range(0, 3000):
    optimizer.zero_grads()
    y = model(x)
    loss = F.mean_squared_error(y, t)
    loss.backward()
    optimizer.update()
    
    print("loss:", loss.data)

print(y.data)
#print(y.data.round())

「XOR」の実行結果 四捨五入すれば上から[ 0, 1, 1, 0]となります。

︙
loss: 0.010527125559747219
loss: 0.01044147927314043
[[ 0.05130053]
 [ 0.8998214 ]
 [ 0.89989913]
 [ 0.13812399]]

NANDについて

余談ではあるのですが、「NAND」は「NOT + AND」の組合せたもので[ 1, 1, 1, 0]となります。
ソフトウェア側だとだから何だと思われるのですが、ハードウェア側の論理回路から見ると、すべての論理演算(OR,AND,NOT,XOR)はNAND回路を組み合わせれば出来てしまうのです。同様に「NOR」でもすべての論理演算が作れます。

詳しくは下記サイトを見て下さい。

最後に

脳を真似たモデルが最終的には凄い結果を出せるようになったわけで、生物って凄いなーとつくづく思います。

人間の身体全体が60兆個の細胞でできている中で、脳細胞は140億個と言われています。
PCのメモリ容量が2GB(160億ビット)として2値(0か1)なのでデータ量は2160億通り、脳のニューロンモデルが2値(発火しないか発火する)とすると2140億通りとすると、もう充分ではないかと思えるわけですが、実際はグリア細胞というニューロン細胞以外の神経細胞のために出力はディジタルではなくアナログ信号に近いとのことです。

生物は奥が深い。

この資料は良かったです。ディープラーニングが人工ニューロンから計算グラフに変わってきている。

参照

Chainer ver2.xをWindowsにインストールしてみた

はじめに

2017/02/23に「Chainer」の大幅アップデートが公開されました。
気になっていたサンプルプログラムがChainer用だったこともあり、インストールしてみました。
Anacondaを使用しているのでパッケージ管理システム(conda)によりChainer用環境で作成しています。

環境

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

下記サイトを参考にしてください。自分は、「C:\Anaconda3」をインストール先にしました。 yaju3d.hatenablog.jp

AnacondaのChainer用環境を作成

Anaconda3 (64-bit)メニュー配下から「Anaconda Prompt」を選択します。 Chainer用環境を作成するため、コマンドプロンプト上で下記のコマンドを入力します。
名前は「chainenv」にしました。envは環境(environment)の略称 ※(ユーザー)のところは各自違います。

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

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

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

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

The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    python-3.5.3               |                0        30.8 MB

The following NEW packages will be INSTALLED:

    pip:            9.0.1-py35_1
    python:         3.5.3-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 ...
python-3.5.3-0 100% |###############################| Time: 0:00:35 906.77 kB/s
Extracting packages ...
[      COMPLETE      ]|##################################################| 100%
Linking packages ...
[      COMPLETE      ]|##################################################| 100%
#
# To activate this environment, use:
# > activate chainenv
#
# To deactivate this environment, use:
# > deactivate chainenv
#
# * for power-users using bash, you must source
#

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

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

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

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

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

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

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

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

Chainer ver2.xのインストール

※chainer 2.0.0a1はアルファ版なので –preを入れないとchainer1.21.0が入ります。

(chainenv) C:\Users\(ユーザー)>pip install chainer --pre
Collecting chainer
  Downloading chainer-2.0.0a1.tar.gz (260kB)
    100% |################################| 266kB 426kB/s
Requirement already satisfied: filelock in c:\anaconda3\lib\site-packages (from chainer)
Requirement already satisfied: nose in c:\anaconda3\lib\site-packages (from chainer)
Requirement already satisfied: numpy>=1.9.0 in c:\anaconda3\lib\site-packages (from chainer)
Collecting protobuf (from chainer)
  Using cached protobuf-3.2.0-py2.py3-none-any.whl
Requirement already satisfied: six>=1.9.0 in c:\anaconda3\lib\site-packages (from chainer)
Requirement already satisfied: setuptools in c:\anaconda3\envs\chainenv\lib\site-packages\setuptools-27.2.0-py3.5.egg (from protobuf->chainer)
Building wheels for collected packages: chainer
  Running setup.py bdist_wheel for chainer ... done
  Stored in directory: C:\Users\hirap_000\AppData\Local\pip\Cache\wheels\e6\9a\0b\c4e3932853d1c6837b9528f7a98a74e5e22a9fafb4f00376d4
Successfully built chainer
Installing collected packages: protobuf, chainer
Successfully installed chainer-2.0.0a1 protobuf-3.2.0

Jupyter ipykernelのインストール

rootにJupyter Notebookが入っているんだから、Jupyter Notebookのインストール不要にならないかと調べてみましたが、結論からするとインストールが必要と思われます。
インストールしないで下記サイトで環境を切り替えようとしましたが、そもそも「chainenv」が表示されませんでした。

qiita.com

Jupyterの設定ファイル生成

rootに戻ってから実行してください。

jupyter notebook --generate-config

C:\Users(ユーザー)\.jupyterフォルダに「jupyter_notebook_config.py」という設定ファイルが生成されます。
jupyter_notebook_config.pyの末尾に下記を追加します。自分の場合はインストール先環境フォルダ(C:/Anaconda3/envs/)を指定しています。

c.EnvironmentKernelSpecManager.conda_env_dirs = [ 'C:/Anaconda3/envs/' ]

今回はJupyter Notebookのインストールの代わりに、下記サイトを参考にJupyter Notebookのカーネルのみをインストールしました。
参照:Python2, Python3 を切り替えて jupyter notebook を使う|熱血エンジニアのブログ

(C:\Anaconda3) C:\Users\(ユーザー)>activate chainenv
(chainenv) C:\Users\(ユーザー)>conda install jupyter ipykernel

Jupyterの起動

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

Jupyter上でchainenvが表示され切り替え出来るようになっています。 f:id:Yaju3D:20170322015143p:plain

動作テスト

動作テストとして下記サイトの実験用のソースコードを動かしてみました。古いバージョンのChainerで作られているため、2点修正しています。
1. FunctionSetをChainに変更
2. model.collect_parameters() を modelのみに変更 qiita.com

#!/usr/bin/env python
# coding: utf-8

__author__ = 'k_morishita'

"""
N bit の 2進数で表される 2**N 個の数字を 2**N個のOutputのどれかを1にするということを学習させる。
"""

import numpy as np
from chainer import cuda, Function, Chain, gradient_check, Variable, optimizers
import chainer.functions as F


def forward(model, x_data, y_data):
    x = Variable(x_data)
    t = Variable(y_data)
    if hasattr(model, "l2"):
        h1 = model.l1(x)
        y = model.l2(h1)
    else:
        y = model.l1(x)
    return F.softmax_cross_entropy(y, t), F.accuracy(y, t)

def generate_training_cases(n_bit):
    x_data = []
    t_data = []
    output_len = 2**n_bit
    for i in range(output_len):
        x_data.append(list((int(x) for x in ("0"*n_bit + bin(i)[2:])[-n_bit:])))
        t_data.append(i)
    return np.array(x_data, dtype=np.float32), np.array(t_data, dtype=np.int32)

def main(n_bit, h1_size):
    if h1_size > 0:
        model = Chain(
            l1=F.Linear(n_bit, h1_size),
            l2=F.Linear(h1_size, 2**n_bit)
        )
    else:
        model = Chain(
            l1=F.Linear(n_bit, 2**n_bit)
        )
    optimizer = optimizers.SGD()
    optimizer.setup(model)
    x_data, t_data = generate_training_cases(n_bit)
    for epoch in range(10000):
        optimizer.zero_grads()
        loss, accuracy = forward(model, x_data, t_data)
        loss.backward()
        if epoch % 100 == 0:
            print("epoch: %s, loss: %s, accuracy: %s" % (epoch, loss.data, accuracy.data))
        if accuracy.data == 1:
            break
        optimizer.update()
    print("epoch: %s, loss: %s, accuracy: %s" % (epoch, loss.data, accuracy.data))
    return epoch, accuracy.data

if __name__ == '__main__':
    fp = open("result.txt", "w")
    fp.write("N\tH1\tepoch\taccuracy\n")
    for n_bit in range(4, 5):
        for h1_size in [0, n_bit, n_bit * 2, n_bit * 4, 2**n_bit]:
            epoch, accuracy = main(n_bit, h1_size)
            fp.write("%s\t%s\t%s\t%s\n" % (n_bit, h1_size, epoch, accuracy))

実行結果

epoch: 0, loss: 3.287376642227173, accuracy: 0.125
epoch: 100, loss: 3.181671142578125, accuracy: 0.125
︙
epoch: 4167, loss: 1.5223073959350586, accuracy: 1.0
epoch: 0, loss: 3.0385913848876953, accuracy: 0.0625
epoch: 100, loss: 2.8190338611602783, accuracy: 0.0
︙
epoch: 2538, loss: 0.8443756103515625, accuracy: 1.0
epoch: 0, loss: 2.8999969959259033, accuracy: 0.125
epoch: 100, loss: 2.708193063735962, accuracy: 0.1875
︙
epoch: 1319, loss: 1.2255289554595947, accuracy: 1.0
epoch: 0, loss: 3.109937906265259, accuracy: 0.0625
epoch: 100, loss: 2.705632209777832, accuracy: 0.125
︙
epoch: 1130, loss: 1.066486120223999, accuracy: 1.0
epoch: 0, loss: 2.917494773864746, accuracy: 0.125
epoch: 100, loss: 2.641525983810425, accuracy: 0.125
︙
epoch: 981, loss: 1.286677360534668, accuracy: 1.0

最後に

Chainerも公開されているプログラムが多いので、これでいろいろ試してみます。

Shizuoka.py #6 and shizudevの資料公開

はじめに

2017/02/18(土)に「Shizuoka.py #6 and shizudev」が開催され、静岡県島田市の会場に11名集まりました。Shizuoka.pyは名前の通りPython向けの勉強会で、shizudev(静岡Developers勉強会)は開発全般の勉強会で今回共同開催となりました。昨年は人工知能ブームで「TensorFlow」が話題になり、静岡Developers勉強会では2016年は4月に「人工知能ハンズオン」を開催しました。その流れでPythonが繋がった次第です。参照:Shizuoka.pyを2/18にやります

TensorFlowの件でPythonの勉強会をやるなら、昨年に「TensorFlowでキュウリの選別・仕分け」で話題になったキュウリ農家の小池さんが静岡県人だったので、なんとか勉強会に呼んでセッションをしてもらいたいと思っており、今回実現することが出来ました。

共同開催

shizudev(静岡Developers勉強会)とShizuoka.pyが共同開催にした理由は下記の3つです。本当は昨年の11月頃に今回の「Shizuoka.py #6 and shizudev」の話があって年2回になるはずだったんですが、発表者の予定があわず2017年に持ち越しとなった次第です。

  • 勉強会の実績として年数回の1つにしたかった
  • 会費がまだ残っていて使い切る必要がある
  • 会場の会議室を過去に使用したことがある

宣伝効果

今回の勉強会用に「数学史」のセッションを作成していたのですが、資料をまとめるのが大変で飽きてしまい、その合間に以前から疑問に思っていたPythonについてのブログを書きはじめたのですが、これも年表を作成し始めたら大変になってしまった(^-^;
このブログ内に勉強会の宣伝を入れておいたところ、神奈川から1人参加して頂きました(キュウリが目的です)

qiita.com

勉強会内容

資料はこちら→Shizuoka.py #6 and shizudev - 資料一覧 - connpass

セッション 発表者
Bottle RESTサービスをWebTestでテストしてみる & Pythonメタプログラミングでテストの自動生成 @oec014
clickでお手軽コマンド作成 @fmkz___
数学の歴史 @yaju
TensorFlowを使ったキュウリの仕分けあれこれ @ike_jpn
TensorFlowでFizzBuzz @yaju
AWS Lambda Pythonについて @aoshiman
LT 確定申告をpythonで乗り切る @hrs_sano645

気になったこと

全部は書けないので2つのみ。

TensorFlowを使ったキュウリの仕分けあれこれ

キュウリの仕分け機は試作3号機を制作していて、カラー画像を活かしてキュウリの表面の傷なども認識したいとのことです。
資料の22ページにある「教師データの錬金術」の話が興味深かったです。本来キュウリにしても不良品を作らないように頑張っているわけですが、教師データには不良品が大量に必要になるわけです。どうしたら良いのかと見つけたのが下記の論文(PDFダウンロード)です。
[1612.03019] Automatic Model Based Dataset Generation for Fast and Accurate Crop and Weeds Detection

下図は野菜と雑草を見分けるのに、Unityを使って仮想上にデータを作成しているわけです。
「そもそも集まらない場合は、仮想世界で瞬時に大量生産したデー タで学習して、現実世界に適用すればよい。 最近のゲームを見ても分かる通り、高品質なテクスチャだけでなく、光効果、物理現象す らもリアルに再現するよ。 」ってことで、まさに錬金術ってことです。
f:id:Yaju3D:20170301005602p:plain

この話を聞いて帰宅後に思い出したのが、Googleが自動運転カーで仮想空間を走行させているって記事でした。Googleだから自動走行のシミュレーションをたくさんやれると思われ、日本企業で同じことをやるにはサーバー代のコストが問題となりそう。どんどん差がついて、敵わなくなりそうだ。 gigazine.net

AWS Lambda Pythonについて

AWS Lambdaとは、AWSの新サービスで、従来は複雑な仕組みを必要としたイベントドリブンなアプリケーションを簡単に開発できるプラットフォームとのことです。例えばメールを受け取ったら、別のサービスを起動させるみたいな。

以前、違う方法にしていたのをAWS Lambdaに切り替えたとの話です。

  • 子供の習い事の送迎バスは到着10分前にメールをくれる
  • しかしメールに気づかない場合が多い
  • 音声などで知らせてくれる仕組みが必要

AWS Lambdaを使ってメール通知を受け取ったらクラウド電話APIサービス「Twilio」を呼び出す、自宅の固定電話(ナンバーディスプレイ付き)を鳴らす、ナンバーディスプレイの音声読み上げ機能を使って「バスが来ます」と知らせてくれる。
システム構成図:個人ユースにおけるAWS Lambda Python事例

ナンバーディスプレイは自宅でも使用していますが、携帯電話では一般的な機能なのに400円と高いです。NTTさんどうにかして下さい。
Twilioも使い方次第で便利そう、価格的にも悪くない。

最後に

キュウリの仕分けってソフトウェア側だけでなくハードウェア側があるから凄いんですよね。やはりハードウェアってやってみたくなりました。今なら「Raspberry Pi」や「Arduino」を使ってモーターを動かしたり、3D CAD/CAM ソフトウェア「Fusion 360」で歯車や部品とか作って3Dプリンタに出力できるんですよね。あとはやる気と勉強次第です。

身近な人を楽にさせてあげようと作ったものが、次第に周りに広まって大きくなっていく。

有名な発明や開発のきっかけとかってこんな感じですよね。

懇親会はとても楽しかったです。とある理由で不覚にもホテルに泊まることになってしまったけどね。

「サザエさんのじゃんけん データ分析」の2016年の結果

はじめに

明けましておめでとうございます。

昨年は東芝の不正会計について触れたのですが、また今年も東芝のことを触れるとは思っていませんでした。 不正会計後に少しずつ回復傾向にあったのに、まさか昨年末に再度危機的状況になるなんて。 東芝家電のためにサザエさんがあるのに家電売却したら意味が無いんじゃないと思うんですが、まー国民的アニメですから東芝がスポンサー降りたら別のスポンサーになるだけですよね。

さてさて、2016年のサザエさんのじゃんけん結果はどうなったでしょう。 ちなみに、2015年のサザエさんのじゃんけん結果は、32勝9敗9分(勝率0.78)でした。

R言語からPythonに移植

もともと2013年に静岡Developers勉強会で機械学習を学んだ際にR言語を覚えたのですが、その後に1年に1回だけサザエさんのじゃんけんのためだけにR Studioを起動するだけになっていて、操作も思い出す感じでやっている状態だったのです。
昨年、Visual Studio CodeでPythonの開発環境を整えることが出来たので、R言語からPythonに移植してみました。とはいっても、Pythonを本格的に意識して組むこと自体は今回初めてなので、そこそこ苦労しました。

はてなブログPythonソースコードを掲載しようとしたら表示がおかしくなるため、Qiitaにしました qiita.com

次の手の予測アルゴリズム

  • チョキが多いので、グー > チョキ > パーの優先順位とする
  • 前回と違う手を出すので、上記の優先順位で勝手を選ぶ
  • 二手前と一手前が違う手なら、残りの手を出すので勝手を選ぶ
  • 三手の中に同手がある場合、 残りの手を出すので勝手を選ぶ
  • 二手前と一手前が同じ手なら、勝手を出すので負手を選ぶ

2016年の勝敗結果

年月 サザエさんの手 予想の手 勝敗結果
01月03日 休み
01月10日 チョキ グー 勝ち
01月17日 グー グー 引き分け
01月24日 チョキ チョキ 引き分け
01月31日 グー チョキ 負け
02月07日 パー チョキ 勝ち
02月14日 チョキ グー 勝ち
02月21日 チョキ パー 負け
02月28日 グー パー 勝ち
03月06日 パー チョキ 勝ち
03月13日 パー グー 負け
03月20日 グー グー 引き分け
03月27日 チョキ グー 勝ち
04月03日 パー チョキ 勝ち
04月10日 グー パー 勝ち
04月17日 グー グー 引き分け
04月24日 チョキ グー 勝ち
05月01日 チョキ チョキ 引き分け
05月08日 パー チョキ 勝ち
05月15日 パー パー 引き分け
05月22日 グー パー 勝ち
05月29日 パー グー 負け
06月05日 チョキ グー 勝ち
06月12日 グー パー 勝ち
06月19日 パー チョキ 勝ち
06月26日 グー グー 引き分け
07月03日 チョキ グー 勝ち
07月10日 チョキ チョキ 引き分け
07月17日 パー チョキ 勝ち
07月24日 チョキ パー 負け
07月31日 グー パー 勝ち
08月07日 グー チョキ 負け
08月14日 チョキ チョキ 引き分け
08月21日 パー チョキ 勝ち
08月28日 チョキ パー 負け
09月04日 パー パー 引き分け
09月11日 グー パー 勝ち
09月18日 グー グー 引き分け
09月25日 パー グー 負け
10月02日 チョキ グー 勝ち
10月09日 グー パー 勝ち
10月16日 チョキ チョキ 引き分け
10月23日 休み
10月30日 パー チョキ 勝ち
11月06日 チョキ パー 負け
11月13日 グー パー 勝ち
11月20日 グー チョキ 負け
11月27日 パー チョキ 勝ち
12月04日 パー グー 負け
12月11日 チョキ グー 勝ち
12月18日 グー パー 勝ち
12月25日 パー チョキ 勝ち

結果は、27勝11敗12分(勝率0.71)となりました。

ちなみに、サザエさんじゃんけん研究所 公式ウェブサイトサザエさんの手の予想と勝負結果(2016年)が22勝13敗15分(勝率0.628)でした。

これまで研究所公式側に僅差で負けていましたが、今回は勝ちました。といってもアルゴリズムは何も変えてないので、単に相手側がミスったということですね。

データ分析 研究所公式
2013 24勝13敗12分(勝率0.65) 25勝9敗17分(勝率0.735)
2014 30勝10敗11分(勝率0.75) 30勝9敗12分(勝率0.769)
2015 32勝9敗9分(勝率0.78) 33勝9敗8分(勝率0.785)
2016 27勝11敗12分(勝率0.71) 22勝13敗15分(勝率0.628)

スライド

2013年に静岡Developers勉強会で機械学習を学び、2014年1月にネタとしてSlideShareに公開しました。

サザエさんのじゃんけん データ分析 from yaju88

最後に

本当は、TensorFlowを使って人工知能ディープラーニングで予測手を作りたかったのですが、まだ組むだけの理解度(n-gramモデル)が足りないため持ち越しです。
でも、今年中には実現したいと思っています。

Visual Studio CodeをPythonの開発環境として使ってみる

はじめに

これまでPythonを使用するのに「Jupyter Notebook」を使用してきたのですが、簡単な確認ならこれで十分なんですが本格的に開発するとなるとブレークポイントを使ったデバッグが出来ないと自分には辛いということで、Python開発環境を整えることにしました。

候補として以前使用したことがあるPython統合開発環境(IDE)「PyCharm (パイチャーム)」とマイクロソフト発のクロスプラットフォームテキストエディターである「Visual Studio Code」があります。
今回は、話題になっている「Visual Studio Code」を使用してみます。

ちなみに、PyCharm (パイチャーム)については下記サイトを参考にするといいでしょう。

qiita.com

環境

OS:Windows10 Home(64bit)
Python:Python 3.5.2 :: Anaconda 4.2.0.0 (64bit)
エディタ:Visual Studio Code version 1.8.1 → 1.10.2(2017/03/12)

Visual Studio Codeのインストール

Windows版をダウンロードして、実行します。 code.visualstudio.com

Python実行環境を整える

下記サイトを見ながらデバッグ出来る環境まで整えます。 renga.hatenadiary.com

先にAnacondaにてTensorflow用のテスト環境として専用の環境「tensorenv2」を作ってTensorFlowをインストールしました。

(C:\Anaconda3) C:\Users\(ユーザー)> conda create --name=tensorenv2 python=3.5」
(C:\Anaconda3) C:\Users\(ユーザー)> activate tensorenv2
(tensorenv2) C:\Users\(ユーザー)>pip install --upgrade https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-0.12.0rc1-cp35-cp35m-win_amd64.whl

ところが「print(“test”)」といった実行は出来たのです、4つの問題が発生しました。

デバッグブレークポイントが止まらない

本来なら先頭に黄色マークが出て処理が止まるはずなのですが、止まりません。ブレークポイントをセットしてもそのまま実行されてしまいます。
この理由が全然分からなくて、「launch.json」を削除してやり直したり、「Python拡張機能をアンインストールしてから再度インストールもしてみたのですが、結果が変わらない。
指定したフォルダが「C:\Anaconda3\envs\tensorenv2\test」だったので、試しに「C:\DEV」としてフォルダの場所を変更してみたところ先頭に黄色マークが出てデバッグが出来るようになりました。
フォルダ階層が深いとダメなのかも知れませんね。 f:id:Yaju3D:20161231224452p:plain

デバッグ実行でimport Errorが発生する

「test2.py」として下記ソースコードを作成しましたが、先頭行で「tensorflow」がimport Errorとなります。

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

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

静岡Developers勉強会仲間である@uroshika_yの下記のブログ記事が解決の糸口となりました。 uroshika.blogspot.jp

これはTensorflow用のテスト環境(tensorenv2)にしかtensorflowがインストールされてないからです。
なので、Pythonの実行環境の場所を変更する必要があります。
参考にしたサイトでは「launch.json」内の「pythonPath」の設定値を変更するように書かれていますが、ここは「"${config.python.pythonPath}“」のままにしておきます。

先ず、ファイル→基本設定→ワークスペース設定を選択します。 「Python Configration」内の「"python.pythonPath": “python”,」のペンアイコンをクリックで設定コピーして、PythonPathの場所を書き換えます。 f:id:Yaju3D:20161231231501p:plain

tensorenv2環境内に「python.exe」があるので絶対パスを指定します。この際に"\“(バックスラッシュ)は”/“(スラッシュ)に書き換えます。

// 既定の設定とユーザー設定を上書きするには、このファイル内に設定を挿入します
{
    "python.pythonPath": "C:/Anaconda3/envs/tensorenv2/python.exe"
}

ワークスペース設定なので、「C:\DEV.vscode」フォルダ内に「settings.json」が作成されます。
f:id:Yaju3D:20161231232217p:plain

これにより、「import Error」とならずにデバッグが出来るようになりました。

スクランナーの実行でimport Errorが発生する

「Ctrl」+「Shift」+「B」のショートカットで「test2.py」が実行することが出来るのですが、「import Error」となってしまいます。
どうもデバッグとは設定が別のようなので変更する必要があります。 「tasks.json」内の「"command": “pyhon”,」を「launch.json」内の「pythonPath」の設定値と同じにするため下記に変更します。

【追記 2017/03/12】
出力ウィンドウで日本語が文字化けする問題の対応で、「options」属性を追加しました。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "0.1.0",
    "command": "${config.python.pythonPath}",
    "isShellCommand": true,
    "args": ["${file}"],
    "showOutput": "always",
    "options": {
        "env": {
            "PYTHONIOENCODING": "UTF-8"
        }
    }
}

「Ctrl」+「Shift」+「B」のショートカットで結果「[7.0]」が求まりました。
f:id:Yaju3D:20161231234049p:plain

「出力」での文字化け

print(“あいう”)として「Ctrl」+「Shift」+「B」のショートカットで実行した場合、「出力」で文字化けしてしまいます。どうもVisual Studio Codeのバグのようです。
デバッグ コンソール」では正常に表示されるので、とりあえずはいいかな。 teratail.com

【追記 2017/03/12】「tasks.json」内で「options」属性を追加することで文字化けは解決しました。 segmentfault.com

最後に

これで最低限のPythonの開発環境が整いました。
あとはLintなど警告エラーなどをどうしていくのか考えていきます。

参照

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