ページ

2016年6月15日水曜日

Googleの新しいビルドツールBazelを試してみる


Bazelとは?
Google自信が使っていたビルドツールを公開したものです。
Android、iOSなどでも使えるとのこと。現在はベータ版。
余談
なぜBazelを試そうかと思ったかというと、、
最近やってるTensorflowでBazelが使われていたからです、、はい。

環境準備 & インストール


2016年6月現在サポートされているプラットフォームは
  • Ubuntu Linux
  • Mac OS X
です。
あとJDK8以降が必要とのこと。
今回はVagrantでUbuntuの環境を用意してそこで試してみたいと思います。
UbuntuのバージョンがTrusty (14.04 LTS)であれば以下コマンドで
JDK8をインストールします。
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer
ちなみに途中でsudo apt-get updateを実行しないと、
E: Unable to locate package oracle-java8-installer
のエラーが出るのでお忘れなく^^;
Ubuntuのバージョンが'Wily (15.10)'の場合は以下コマンドでインストール。
$ sudo apt-get install openjdk-8-jdk
正常にインストールできたか確認
$ java -version
java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)
良さそうです^^
あとは一気にBazelのインストールを行います。
$ echo "deb http://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
$ curl https://storage.googleapis.com/bazel-apt/doc/apt-key.pub.gpg | sudo apt-key add -
$ sudo apt-get update && sudo apt-get install bazel
$ sudo apt-get upgrade bazel
インストール確認
$ bazel version
Extracting Bazel installation...
Build label: 0.3.0
Build target: bazel-out/local-fastbuild/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Fri Jun 10 11:38:23 2016 (1465558703)
Build timestamp: 1465558703
Build timestamp as int: 1465558703

簡単なJavaプロジェクト作成


試しに簡単なJavaのプロジェクトを作成し、ビルドしてみます。
  • ディレクトリ構成
.
├── BUILD
├── WORKSPACE
└── src
    └── main
        └── java
            └── com
                └── slowhand
                    └── Sample.java
Bazelではworkspace毎の場所で作業します。
workspaceにはルート直下にWORKSPACEファイルが必要になります。
WORKSPACEはライブラリの外部参照を記述したりしますが、
今回は依存は無いので空のファイルを作成します。
  • Sample.java
単純にHello bazelと表示するだけのクラスです。
package com.slowhand;

public class Sample {
  public static void main(String args[]) {
    System.out.println("Hello bazel");
  }
}
  • BUILD
BUILDファイルにはソースコードの配置や参照ライブラリなど記述します。
java_binary(
  name = "sample",
  srcs = glob(["**/*.java"]),
  main_class = "com.slowhand.Sample",
)

ビルド&実行


それではビルドしてみます。
$ bazel build //:sample
INFO: Found 1 target...
Target //:sample up-to-date:
  bazel-bin/sample.jar
  bazel-bin/sample
INFO: Elapsed time: 10.765s, Critical Path: 7.52s
ビルドが成功するとbazel-binの配下に実行モジュールが作成されます。
$ bazel-bin/sample
Hello bazel
ちゃんと実行されてます^^
ちなみに、、WORKSPACEファイルがないと以下のエラーになります。
The 'build' command is only supported from within a workspace.

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がRankとMeanとなっています。
Meanは最終的な平均値を求める計算処理を行うノードというのは想像できるんですが、 他のRankとrangeは、、?
調べてみると、
tf.reduce_meanは引数としてreduction_indicesとkeep_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...
として計算されています。
Rankはtf.rankという次元数を求めるもので、rangeはtf.rangeという
その名の通り範囲を求めるものです。
reduction_indicesを指定しなかった場合のみ表示されるので、
tf.rankとtf.rangeの結果を内部で使っているのではないか・・・と思います。

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

2016年6月8日水曜日

いつものアラートに飽きた時のオシャレなアラート Sweet Alert iOS


iOSにしてもAndroidにしても標準のアラートは味気ないものです。。
今回はそんな味気ない標準のアラートをシャレたアラートにしてくれる
Sweet Alert iOSを使ってみます。

標準のアラート

まずは標準のアラートです。
sweet_alert_1
はい、いたってシンプルです。

メッセージのみ

ではSweet Alert iOSを使ってアラートを表示させてみます。
まずはシンプルなメッセージのみのアラート
SweetAlert().showAlert("message")
sweet_alert_2
表示する時にアニメーションが付いてリッチな感じです。

タイトル + Success

次はアラートにタイトルを付け、Successのアラートスタイルで表示させてみます。
SweetAlert().showAlert("message", subTitle: "subTitle", style: AlertStyle.Success)
sweet_alert_3
アラートスタイルはenumで定義されており、
  • Success
  • Error
  • Warning
  • None
  • CustomImag(imageFile:String)
の5種類が設定できます。格段オシャレになりました。

ボタンイベント

最後にアラートにカスタムボタンを表示されてみます。
SweetAlert().showAlert("message", subTitle: "subTitle", style: AlertStyle.Warning, buttonTitle:"Cancel", buttonColor:UIColor.redColor() , otherButtonTitle: "OK", otherButtonColor: UIColor.blueColor()) { (isOtherButton) -> Void in
    if isOtherButton == true {

        print("Cancel Button Pressed")
    }
    else {
        SweetAlert().showAlert("OK", subTitle: "subTitle", style: AlertStyle.Success)
    }
}
sweet_alert_4
OKボタンが押されると別のアラートを表示させています。
アラート一つで雰囲気が全然変わりますね〜。



2016年6月5日日曜日

道の駅を巡ってみる 12 - 手打ちそばが美味しい 耶馬トピア -


今回は大分県の中津市にある道の駅「耶馬トピア」です。
「やぱトピア」と読むらしいです。

ここはそばづくしの道の駅で、そば打ち体験などもできるようです。





奥に進んでいくと食事処が。当然おそばをいただきました^^




注文したのは山かけ肉そばです。
そばが手打ちだけあって美味しいのは当然ですが、とろろも粘りが強く
甘辛い味付けの肉とマッチしていてとても美味しかったです^^。

また、ここの道の駅が自然に囲まれたような道の駅で、
とてもゆっくりとした時間を過ごせるようなところでした。






関連ページ





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
上の例でのノードはarray、square、reduceになります。
[3,4,5]のデータは各ノードを通り、最終的に計算された値が出力されます。

セッション

実際に計算を行う為にTensorflowではセッションを作成します。
sess = tf.Session()
runメソッドにノードを渡すことで対象のノードを計算します。
sess.run(reduce)
ちなみに上のarray、square、reduceの各ノードを実行させると・・
$ 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
となり、各ノード毎の計算が行なわれているのが確認できているかと思います。