ページ

ラベル machine_learning の投稿を表示しています。 すべての投稿を表示
ラベル machine_learning の投稿を表示しています。 すべての投稿を表示

2016年7月9日土曜日

機械学習のフレームワークTensorflowを試す 8 - ソフトマックス回帰 -


前回はMNISTのデータを見てみましたが、今回は続きをやっていきたいと思います。

前回MNISTの画像データを[60000, 784]のn次元配列として扱うと書きました、 そして画像に対応するラベルもテンソルとして扱います。
ラベルは画像が0〜9のどの数値を現しているかになります。画像枚数分(60000)あるので、
[60000, 10]のn次元配列として表すことができます。
例) 3を表す場合
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]

Softmax Regressions (ソフトマックス回帰)

データをテンソルでどう扱うかは分かりましたが、実際に学習する方法として、
MNISTの学習ではSoftmax Regressions (ソフトマックス回帰)を使用するようです。

ソフトマックス回帰とは?
ここで回帰(regression)という言葉が出てきましたが、
回帰とはデータから関数を導こうとする手法になります。
という訳でソフトマックス回帰とは、
ソフトマックスというものを使って関数を導き出す です。
次はソフトマックスを調べてみます。

ソフトマックスとは?
n次元実数ベクトルX = (X1, ・・・ Xn)を受け取って
n次元実数ベクトルY = (Y1, ・・・ Yn)を返す。
ただし、Yi = E^Xi / E^X1 + E^X2 + ・・・ E^Xn

・・・・
ん〜分かったような分からないような^^;

ソフトマッックス関数の性質
  • 0 < Yi < 1
  • Y1 + ・・・ + Yn = 1
  • Xの各成分の中でXiが大きい、Yiはほぼ1でYの他の成分はほぼ0
具体例でいうと
x = (10, 1, 2)
をソフトマックス関数にかけると・・・
y = (0.9999・・, 0.0001・・, 0.0002・・・)
になる。つまり一番大きい成分を1に近づけ、
それ以外は0に近づけるといった感じでしょうか。

MNISTでソフトマックス回帰

話を戻してMNISTで実際にどうソフトマックス回帰を使うかというと、

  1. 入力された[0-9]の画像データを重みとバイアスを使ってラベルと照らし合わせながら、重要なピクセルとそうでないピクセルの重みを分布させる。
  2. 分布された重みをソフトマックス関数を使って活性化する。

大雑把ですが、、、
↑の2でソフトマックス関数を使って一番大きい成分を1に近づけ、それ以外は0に近づけると行った活性化させるような役割を行います。

次はサンプルコードを見ながら処理の流れを見てみたいと思います。

2016年6月25日土曜日

機械学習のフレームワークTensorflowを試す 7 - MNIST事始め -


今回からは、機械学習のHello Worldという事らしい、MNISTをやっていきたいと思います
以前の記事でデモを実行してはいますが、 今度は実際に学びながらやっていきます。
MNIST For ML Beginners」を元に進めて行こうと思います。

MNISTでどんな機械学習をさせるか

以前も書きましたが、MNISTは手書きの数字の画像のデータセットです。
↑は0〜9まで色んなタッチで書かれてある。というのは人間からしたら簡単に予想がつきます。
ですがコンピュータからすれば数字が書かれてあるなんて分からないので
学習してもらって、何の数字が書いてあるか解析してもらおうと思います

MNISTデータ

使用するMNISTデータはYann LeCun's websiteで提供されているので、
そちらのデータを使用します。
一度ダウンロードしてデータセットがどんなものか見てみたいと思います。
提供元のページにいき、↓の4つをダウンロードし解凍します。

それぞれ
  • 手書き数字の画像データ
  • 手書き数字に対応するラベルデータ
  • テスト用の画像データ
  • テスト用の画像に対応するラベルデータ
となっています。

データ構造
  • train-images-idx3-ubyte.gz
    ファイルには28×28ピクセルの画像が60000枚分書き込まれてます。
    ・ファイルフォーマット
    [offset] [type]          [value]          [description]
    0000     32 bit integer  0x00000803(2051) magic number
    0004     32 bit integer  60000            number of images
    0008     32 bit integer  28               number of rows
    0012     32 bit integer  28               number of columns
    0016     unsigned byte   ??               pixel
    0017     unsigned byte   ??               pixel
    ........
    xxxx     unsigned byte   ??               pixel
    
    ※提供元ページから抜粋
  • train-labels-idx1-ubyte.gz
    ファイルには画像に対応するラベルが60000個書き込まれてます。
    ・ファイルフォーマット
    [offset] [type]          [value]          [description]
    0000     32 bit integer  0x00000801(2049) magic number (MSB first)
    0004     32 bit integer  60000            number of items
    0008     unsigned byte   ??               label
    0009     unsigned byte   ??               label
    ........
    xxxx     unsigned byte   ??               label
    
    ※提供元ページから抜粋

MNISTデータ読み込み

最終的には、画像データを読み込んでテンソルに格納します。
テンソルは[60000, 784(28*28)]の2次元配列で格納します。
今回は、ファイル読み込む所までやってみます。
import numpy as np

data = open("train-images.idx3-ubyte","rb")
dt = np.dtype("int32").newbyteorder('>')
# 1.
info = np.frombuffer(data.read(16), dtype=dt)
print(info) # => [ 2051 60000    28    28]

size = info[1] * info[2] * info[3]
dt = np.dtype("int8").newbyteorder('>')
# 2.
imageBuff = np.frombuffer(data.read(size), dtype=dt)
print(len(imageBuff)) # => 47040000
1.では先頭から16バイト分読み込んで、画像の情報を出力しています
また、2.では読み込んだ画像データのサイズを出力しています。

2016年6月18日土曜日

機械学習のフレームワークTensorflowを試す 6 - 変数の可視化とスコープ付け(TensorBoard) -


前回やった可視化をさらに進めてみたいと思います。
変数を可視化

前回はtf.constantで[3,4,5]のテンソル値を宣言していたのですが、
今回は可視化する為にtf.Variableメソッドを使って宣言します。
修正したコードがこちら
# coding: UTF-8
import tensorflow as tf

with tf.Graph().as_default():
    array_var = tf.Variable(tf.zeros([3]), name="array")
    square = tf.square(array_var)
    reduce = tf.reduce_mean(square)

    init = tf.initialize_all_variables()
    sess = tf.Session()
    sess.run(init)

    tf.merge_all_summaries()
    summary_writer = tf.train.SummaryWriter('report', sess.graph)

    ret = sess.run(reduce, feed_dict={array_var: [3.0, 4.0, 5.0]})
    print(ret) # => 16.6667
今回結果が16.6667となってますが、これはtf.Variable
tf.zeros([3])を使っている為です。
tf.zerosは指定しないとtf.float32でオール0のテンソルを作成します。
tf.float32で計算する為、結果も少数値になってます。
値は、sess.runfeed_dictに[3,4,5]を指定し、array_varに値を設定しています。

TensorBoardで確認

それでは実際にTensorBoardを起動して確認してみたいと思います。

真ん中にname="array"で指定したtf.Variableが表示されています。
クリックすると内容が見れたりします。

スコープ付け

処理が複雑になってくると可視化も見づらくなってくるので、
そんな時の為にスコープを設定してみたいと思います。
実際にスコープを付けてみたソースがこちら
# coding: UTF-8
import tensorflow as tf

with tf.Graph().as_default():
    with tf.name_scope('variable') as scope:
        array_var = tf.Variable(tf.zeros([3]), name="array")

    with tf.name_scope('op') as scope:
        square = tf.square(array_var)
        reduce = tf.reduce_mean(square)

    with tf.name_scope('init') as scope:
        init = tf.initialize_all_variables()
        sess = tf.Session()
        sess.run(init)

    tf.merge_all_summaries()
    summary_writer = tf.train.SummaryWriter('report', sess.graph)
    ret = sess.run(reduce, feed_dict={array_var: [3.0, 4.0, 5.0]})
    print(ret)
TensorBoardを起動して見てみると指定したスコープで
区切られているのが分かるかと思います。


2016年6月11日土曜日

機械学習のフレームワークTensorflowを試す 5 - データフローグラフを可視化(TensorBoard) -


前回やった配列[3, 4, 5]の2乗した値の平均値を算出するデータフローグラフを
可視化してみたいと思います。
可視化するに当たってTensorBoardというツールを使用します。
Tensorflowをインストールすると使えます。
基本的な使い方は
$ tensorboard --logdir=<ログディレクトリのパス>
として実行し、ブラウザでhttp://0.0.0.0:6006にアクセスすると
可視化されたものが見られます。

可視化する為にコード修正

まずは修正前のコードです。
# coding: UTF-8
import tensorflow as tf

array = tf.constant([3,4,5])
square = tf.square(array)
reduce = tf.reduce_mean(square)
sess = tf.Session()
ret = sess.run(reduce)
print(ret) # => 16
このコードを可視化する為にちょこっと修正します。
# coding: UTF-8
import tensorflow as tf

array = tf.constant([3,4,5])
square = tf.square(array)
reduce = tf.reduce_mean(square)
sess = tf.Session()
ret = sess.run(reduce)
# 以下の行を追加
tf.train.SummaryWriter('report', sess.graph)
print(ret) # => 16
tf.train.SummaryWriterクラスを作成する行を追加のしています。
上では第一引数でイベントファイルを出力するディレクトリ名を、
第二引数でセッションのグラフを渡しています。
今回は単純にグラフを表示させるだけです。

TensorBoardで確認

修正したコードを実行するとreportディレクトリが作られているかと思います。
--logdirにreportディレクトリのパスを指定してTensorBoardを起動してみます。
↓ブラウザでアクセスしGRAPHのタグを表示させた結果です。

それっぽいのが表示されています。
丸が定数のノードで、楕円が計算処理を行うノードです。
次に各ノードをクリックして詳細を見てみます。
まずはConstつまりは配列の[3,4,5]です。クリックすると

右上に詳細が表示されています。Attributesにデータ型と値が確認できます。
次はSquareをクリックしてみます。二乗の計算処理を行うノードです。

Inputが先ほどのConstでOutputがRankMeanとなっています。
Meanは最終的な平均値を求める計算処理を行うノードというのは想像できるんですが、 他のRankrangeは、、?
調べてみると、
tf.reduce_meanは引数としてreduction_indiceskeep_dims
の引数を与えることができるようです。
例)
>>> import tensorflow as tf
>>> array = tf.constant([[3.,4.],[5.,6.],[7.,8.]])
>>> reduce = tf.reduce_mean(array)
>>> reduce0 = tf.reduce_mean(array, 0)
>>> reduce1 = tf.reduce_mean(array, 1)
>>> sess = tf.Session()
>>> ret = sess.run(reduce)
>>> ret0 = sess.run(reduce0)
>>> ret1 = sess.run(reduce1)
>>> print(ret)
5.5
>>> print(ret0)
[ 5.  6.]
>>> print(ret1)
[ 3.5  5.5  7.5]
tf.reduce_meanの第二引数で渡しているreduction_indicesの値が
何も指定しない場合は、 (3 + 4 + 5 + 6 + 7 + 8) / 6 = 5.5となります。
0の場合、(3, 5, 7), (4, 6, 8)の平均値を求めます。
(3 + 5 + 7) / 3 = 5(4 + 6 + 8) / 3 = 6
1の場合、(3, 4)、(5, 6), (7, 8)の平均値を求めます。
(3 + 4) / 2 = 3.5(5 + 6) / 2 = 5.5(7 + 8) / 2 = 7.5
どういった平均を求めるか設定してるようです。

今回のサンプルではreduction_indicesに値を
設定していない為、[9,16,25](square)(9 + 16 + 25) / 3 = 16.66...
として計算されています。
Ranktf.rankという次元数を求めるもので、rangetf.rangeという
その名の通り範囲を求めるものです。
reduction_indicesを指定しなかった場合のみ表示されるので、
tf.ranktf.rangeの結果を内部で使っているのではないか・・・と思います。

具体的にここで使ってる!!というのを見つけたかったのですが今回はここまで。

2016年6月1日水曜日

機械学習のフレームワークTensorflowを試す 4 - データフローグラフを理解する -


前回のサンプルコードでは事前に計算する方法を定義して、
最後に実際の計算を行ってました。
これこそがデータフローグラフの形になります。
データフローはデータの流れです。ではグラフはというとデータ構造になります。

上の図のように、ノードとそのノード間を連結するエッジで構成されます。
ノードとノードの繋がり方に着目したものになります。

Tensorflowのデータフローグラフ

Tensorflowではノードを計算操作(Operation)としています。
そしてノードが扱うデータ形式が前回も出てきたテンソル(Tensor)になります。
ここで例えば、配列[3, 4, 5]の2乗した値の平均値を算出してみます。
通常のプログラムだと・・
[3, 4, 5].map { |v| v *v }.inject(:+) / 3
# => 16
上のように、全ての要素を2乗し合計したものを要素数3で割って算出しています。
これをTensorflowで計算させると・・
$ python
>>> import tensorflow as tf
>>> array = tf.constant([3,4,5])
>>> square = tf.square(array)
>>> reduce = tf.reduce_mean(square)
>>> sess = tf.Session()
>>> ret = sess.run(reduce)
>>> print(ret)
16
上の例でのノードはarraysquarereduceになります。
[3,4,5]のデータは各ノードを通り、最終的に計算された値が出力されます。

セッション

実際に計算を行う為にTensorflowではセッションを作成します。
sess = tf.Session()
runメソッドにノードを渡すことで対象のノードを計算します。
sess.run(reduce)
ちなみに上のarraysquarereduceの各ノードを実行させると・・
$ python
>>> sess = tf.Session()
>>> array = tf.constant([3,4,5])
>>> ret = sess.run(array)
>>> print(ret)
[3 4 5]
>>> square = tf.square(array)
>>> ret = sess.run(square)
>>> print(ret)
[ 9 16 25]
>>> reduce = tf.reduce_mean(square)
>>> ret = sess.run(reduce)
>>> print(ret)
16
となり、各ノード毎の計算が行なわれているのが確認できているかと思います。