TensorFlowインストール覚え書き

学生のころ画像処理を専攻しており、物体認識など少しかじっていたのでちょっと気になっていたTensorFlowをインストールして使ってみました。
といっても物体認識まではできておりませんが。

参考サイト

http://www.tensorflow.org/get_started/os_setup.html#download-and-setup
TensorFlowで Hello Worldを動かしてみた&その解説 | Developers.IO
Python - TensorFlowを算数で理解する - Qiita

ほぼこちらの公式サイトや参考サイトを元にしています。
こうやって試したことを残すのは素晴らしいですね。感謝です。

TensorFlowのインストール

TensorFlowのサイトによると、MacでTensorFlowを使うにはPythonとvirtualenvが必要とのことなのでそれらをインストールします。

Pythonのインストール
brew install python
pipのインストール

pipとはpythonのパッケージ管理システムです。

sudo easy_install pip
virtualenvのインストール

virtualenvとは、Pythonの仮想環境を提供するパッケージです。
TensorFlowはvirtualenvでの実行が推奨されていますのでこちらもインストールします。

sudo pip install virtualenv
virtualenv環境設定

`--system-site-package`の意味がよくわかりませんが、とりあえず公式サイトに有るとおりに実行します。

virtualenv -—system-site-packages ./tensorflow
virtualenv環境を実行
cd tensorflow
source bin/activate
TensorFlowのインストール
pip install https://storage.googleapis.com/tensorflow/mac/tensorflow-0.5.0-py2-none-any.whl

これでTensorFlowの環境が構築完了です。

TensorFlowで数値計算

sample.py
import tensorflow as tensorflow

def ax2_plus_b(a, x, b):
	_a = tensorflow.constant(a)
	_x = tensorflow.constant(x)
	_b = tensorflow.constant(b)
	result = tensorflow.square(_x)
	result = tensorflow.mul(_a, result)
	result = tensorflow.add(result, b)
	return result

with tensorflow.Session() as session:
	result = session.run([ax2_plus_b(2, 3, 4)])
	print result

実行

ax2 + bを実際に計算してみます。
a = 2, x = 3, b = 4なので、結果は2 * 3 * 3 + 4 = 22となるはずです。

$ python sample.py

実行結果は下記です。

[22]

ちゃんと22となっていることがわかります。

所感

とりあえず公式サイトのGet Startedや参考にさせていただいたサイトを参考にインストールと数値計算はできました。
ただメインである機械学習はまだまだなので、教師データ用意して学習させて物体認識とかいろいろできたら面白そうだとは思います。
私が学生だったころはHaar-Like特徴とAdaBoostを用いて物体認識を行っていましたが、TensorFlowを使うことでそれらができるのか、簡単にできるのかが気になります。

Ruby on Rails 覚え書き①

ドットインストールのRuby on Rails 4入門を勉強しましたので覚え書きとして。

アプリケーションの作成
rails new app_name
Modelの作成
rails g model モデル名 属性名:型

modelの後にはモデル名を先頭大文字、単数形(Modelsは☓)で記述。
その後ろには属性の名前:型を記述する。stringの場合は型を省略可能。
マイグレーションファイルが作成される。

DBへの反映
rake db:migrate
サーバーの起動
rails s
Controllerの作成
rails g controller コントローラー名

controllerの後ろにはコントローラー名を先頭大文字、複数形で記述。
通常はモデル名の複数形を指定する。

config/routes.rbの編集(ルーティング)
resources :コントローラー名(先頭小文字)
ルーティングの確認
rake routes
controlles/projects_controller.rbの編集
def index
  @projects = モデル名.all
end

@projectsは後述するViewの中から参照可能。

views/projects/index.html.erbの作成

ファイルを作成し、ファイルにHTML形式で表示するコードを記述する。

<h1>タイトル</h1>
<ul>
  <% @projects.each do |project| %>
  <li><%= link_to project.title, project_path(project.id) %></li>
  <% end %>
</ul>
rootアクセス時の設定(routes.rb)
root 'projects#index'

rootアクセス時に/projects(のindex.html)を表示する。

formの作成

projects_controller.rb

def new
  @project = Project.new
end

new.html.erb

<%= form_for @project do |f| %>

<p>
  <%= f.label :title %><br>
  <%= f.text_field :title %>
<p/>

<p>
  <%= f.submit %>
<p/>
<% end %>
actionで共通に行う処理
before_action :メソッド名, only: [:action名, ...]

private 
def メソッド名
  共通処理
end

before_actionは各アクションを実行する前に共通して行う処理を書く。after_actionもある。
onlyを指定しなければ、全アクションで実施する。

悪玉コレステロール

5月に健康診断をした時に、悪玉コレステロールの値が150台と基準値を超えていたため、食事に気をつけるようにしていたのですが、10月に再度検査したところなんと160になってしまいました。
ここ最近いろいろとドタバタしており、自分で料理せず毎日お弁当を買って食べたり、普段間食はしないのに間食したりしていたのが影響したのかと反省。

いろいろ調べたところ、160を超えた場合は薬による治療が必要になってくるとのことで、私の場合はぎりぎり160だったので、食事療法で下げようと思います。
コレステロールを下げるには、野菜を取ることはもちろんのこと、きのこや納豆などの大豆類、青魚などを取るといいそうなので、これらをメインに頑張り、次の検査の時は基準値にできるようにシていこうと思います。

しかし以前150代になったときも最初は食事に気をつけてましたが、途中から弁当になったりしてしまったので、なんとか1年間続けられるようにモチベーションを上げていくための方法を考えていかなくてはならないです。
私は意思弱いので・・・

そのようなWebサービスあったらいいと思いますが、食事のログを取るものなどは既にありますね。
何か思いついたら簡単なもの作ってみようと思います。

トレイの明かりが点灯したら音楽を流すAndroidアプリ

自宅のトイレの照明としてシャープのプラズマクラスターのLED照明を使っています。
これには人感センサーがついており、トイレに入るときにいちいち照明のスイッチを押さなくても勝手に点いてくれるので結構重宝しています。

手元にほとんど使っていないNexus7があるのですが、Nexus7には光センサーがついているので、上記のLED照明と連携して何かできないかなーと思い、ちょっとしたアプリを作りました。

そんな大したものではないですが、トイレに入ると自動的にLED照明が点灯し、その光を検知して、Nexus7の画面に「座って用を足してね!」という画面表示と爽やかーなBGMが流れるといったAndroidアプリです。もちろんLED照明が消灯すると、BGMはストップします。

Android4.4からSensor Batchingという機能がはいり、センサーへのアクセスを今までの一定時間によるイベント通知ではなくバッチ処理でアクセスすることができ、これによりスリープ状態でもセンサーの状態を知ることができるようになったとのことなので、LED照明が消灯のときはスリープし、LED照明が点灯したときにはスリープを解除し画面表示とBGMを流す!

・・・と本来ならしたかったのですが、Nexus7はどうやらSensor Batchingに対応していないようですので、消費電力が大きくなってしまいますが、常に画面をON状態(画面は黒で表示)でやることにしました。

コードなどはググれば簡単にでてくるので省きますが、結構簡単に実現できましたし(数時間程度)、トイレに入った時にちょっとしたイベント?といいますか、変化を自分含め入った人に見せられるようにできたので、かかった労力に比べて結構面白いことできたなーと勝手に思っています。

もうちょっとちゃんとしたもの作れたら、そのうちストアにアップしてみたいですが、どうせだすならSensor Batchingに対応したものでないと消費電力がやばい(おそらく1日くらいしかもたない)ですし、それ対応するためにはSensor Batchingできるデバイス買わないとなので、しばらく後になりそうです。

Chart.jsで円グラフが表示できない

作成中の時間計測サービスで、今まで計測した時間を円グラフで表示するためにChart.jsを使ってみました。www.chartjs.org

しかし、いざ使ってみると円グラフが表示されなく、なかなか原因が特定できなかったため、スタックオーバーフローで質問したところ、下記のような回答を得て解決しました。ja.stackoverflow.com

Chartというオブジェクトを初期化する際、canvasという要素のoffsetWidthやoffsetHeightが必要ですが、pagebeforeshowというイベントが引き起こされる時にはjQuery Mobileのスタイルによってdisplayがnoneなので、ブラウザはoffsetWidthやoffsetHeightを計算できません。

ですから、pagebeforeshowをpageshowに置き換えると、正しく動くと思います。

pagebeforeshowイベントで円グラフデータを作成し表示していたのですが、pageshowイベントに変更したところ円グラフが表示されました。
しかし、ここで分からない点が3点ありました。

  1. Chartオブジェクト初期化時にcanvasのoffsetWidth, offsetHeightが必要。
  2. pagebeforeshowイベント発生時にはdisplayがnoneなのでoffsetWidth, offsetHeightを計算できない。

ということで一体どんなことなのか調べてみました。

Chartオブジェクト初期化時にcanvasのoffsetWidth, offsetHeightが必要

Chart.jsのvar Chart = function(context) {...}を調べたところ、下記のようなコードがありました。

//Variables global to the chart
var computeDimension = function(element,dimension)
{
	if (element['offset'+dimension])
	{
		return element['offset'+dimension];
	}
	else
	{
		return document.defaultView.getComputedStyle(element).getPropertyValue(dimension);
	}
}

var width = this.width = computeDimension(context.canvas,'Width');
var height = this.height = computeDimension(context.canvas,'Height');

ここでoffsetWidth, offsetHeightを取得していますね。
それらが初期化時に取得できない場合は別の値を返していますが、これではうまくいっていないのでしょうか。。。

pagebeforeshowイベント発生時にはdisplayがnoneなのでoffsetWidth, offsetHeightを計算できない

調査中。

herokuでmongolabを使ってみる

現在作成中の時間計測サービスで、計測した時間をデータベースに保存することが必要なので調べたところ、mongolabというherokuのアドオンが無料で使えるとのことで使ってみました。

アドオンの追加はherokuコマンドで追加できますが、herokuのダッシュボードでクレジットカードを登録していないと、下記のようなエラーが発生するので予めクレジットカードを登録しておく必要があります。
無料版を使っていれば課金されることは無いですが、登録しておくのはちょっと不安。。。

 !    Please verify your account to install this add-on plan (please enter a credit card) For more information, see https://devcenter.heroku.com/categories/billing Verify now at https://heroku.com/verify 

無料版のmongolabのアドオンの追加コマンドは下記です。
sandboxが無料版のようです。

heroku addons:create mongolab:sandbox

実行すると下記のような出力があれば成功です。

Creating practicing-duly-3222... done, (free)
Adding practicing-duly-3222 to 'herokuの自分のURL'... done
Setting MONGOLAB_URI and restarting 'herokuの自分のURL'... done, v6
Welcome to MongoLab.  Your new subscription is being created and will be available shortly.  Please consult the MongoLab Add-on Admin UI to check on its progress.
Use `heroku addons:docs mongolab` to view documentation.

あとはmongodbに接続するURLを取得します。
下記コマンドを実行すると、「MONGOLAB_URI」が出力されます。

heroku config
MONGOLAB_URI: mongodb://mongodbのURL(自動生成されたユーザー名とパスワード付き)

このURLを使ってmongodbに接続すればOKです。

~~~
var MongoClient = mongodb.MongoClient;
var url = 'mongodb://mongodbのURL(自動生成されたユーザー名とパスワード付き)';
MongoClient.connect(url, function(err, db) {
	if(err) {
		callback(err);
		return;
	}
        ~~~
});
~~~

追記

たとえば、settings.jsというファイルを作成し、下記のようなコードを記述し、別のコードからこの関数を使うことで、ローカルとheroku上で別々のmongodbを使えるようになります。
mongolabのurlにはパスワードとか含まれていてgithubに上げたくないので重宝します。

// settings.js
exports.mongodbUrl = function() {
	if(process.env.MONGOLAB_URI) {
		return process.env.MONGOLAB_URI;
	} else {
		return 'mongodb://127.0.0.1:27017/idealtimetest';
	}
}

Buttonのvalueの値を動的に変更する

JQuery 2.1.4でButtonを押した時にボタンに表示されているテキストを変更する処理をしたいのですが、ネットで調べた「.val('変更後のテキスト')」の方法では変更できず難航していましたが、下記サイトでrefreshを使わないと反映されないとありました。

www.buildinsider.net

下記のようなコードにしたところ、ボタンを押した時にテキストが変更されました。

~~~
input(type='button', id='start-stop-button', name='start-stop-button' value='Start')
~~~
$(document).on('click', '#start-stop-button', function() {
	var value = $(this).val();
	if(value === 'Start') {
                // .valの後に.button('refresh')をする。
		$(this).val('Stop').button('refresh');
		$('#time').html('00:00:00');
		hour = 0;
		min = 0;
		sec = 0;
		timer = setInterval(timerCount, 1000);
	} else {
		clearInterval(timer);
		$(this).val('Start').button('refresh');
	}
});

JQueryのバージョンが変わってから方法が変わったのでしょうか。