ダッシュで2015年を振り返る

気がついたら12月31日で、こたつで紅白を見ている自分に気がついたので、ささーっと2015年を振り返ってみようと思います。お酒を飲みながら書いている間に完全に私的備忘録になっちゃったけどまあそれはそれで。

月別振り返り

1月

新年早々卒論がゲシュタルト崩壊を起こしていました。Twitterを振り返ると1月3日に卒論発表会の原稿を出して「よいお年を!』などと呟いてます。なんだか大変そうです。

2月

卒論を出し終わって平穏な月でした。学生最後のサークル合宿に行ったり、卒業旅行で富山に行ったりしました。バイト先ではRails+knockoutjsを学んでフロントエンドがっつり開発マンになっていました。

3月

大学生最後の春休み、旅行やらバイトやら飲み会やらで充実した日々を過ごす傍学会の原稿を書くなどしていました。旅行で台湾に行ったのですが、初海外でした。現地の人みんな日本語で話しかけてくれるので海外きた感あんまなかったけど、初海外は初海外です。

4月

大学院生になったという実感はあまりなく、授業をまた受けるようになったというくらいでした。Twitterを遡ると小川一水「天冥の標」シリーズにどハマりしていました。個人的な今年一番のヒットはこれです。いつかブログにまとめたいなとか思ったりします。

5月

5月は月末の学会準備に追われていました。学会では函館に行き、初めて発表をしました。函館は先生にご馳走になったお寿司が美味しかったし、一人で見た函館山からの夜景はとてもきれいでした。学会サイコー。

6月

学会が終わった反動からか、ゆるゆるな一ヶ月を過ごしていました。有意義だったことといえば、前期途中から始まったFSNLP勉強会に参加し出して、古き良き自然言語処理周りのお勉強をしたことですかね。

7月

(大学院)1年生なので、そこそこ試験勉強とかレポートに追われていたようです。月末に行ったKURAND SAKEマーケットの日本酒飲み放題がとても美味しかったことを覚えています。

8月

研究室にいるロボットのデモを行うことになり、その開発に追われていました。Java力の復活。以前のBloggerからはてなBlogに移行したのもこの時期だったような。あとこの時期はプロコンをやり始めて、毎週Atcorderに取り組んでいました。最近やってないなあ。

9月

インターンで2週間大阪に行っていました。インターン自体よりも2週間会社の寮で一人、という非日常で生き生きしていました。週末は京都や大阪を観光したし、期間限定社会人を全力で満喫しましたね。

10月

スケジュール帳とか見返してみてもあんまり予定ないですね・・・何してたんだろ?

11月

開発系ではtmuxを知り開発効率が格段に上がった月でした。もっと早くに知っておきたかった。月末に社会人の友人を訪ねて山梨旅行に行ったりしました。紅葉にはちょっと遅かったけど、昇仙峡は綺麗だったし、ワインは美味しかったし良い息抜きになりました。今年は息抜きしてばっかですね。

12月

なう。今年は忘年会をあまりしていません。「忘年会」って語感から一年を忘れるための行事かと思いきや、ネットを調べると「一年を忘れないための会」とか、「嫌なことを忘れる会」とか色んな意見があってちょっとわからなくなりました。まあ、忘れたいことを銘々に忘れればいいんじゃないでしょうか?

分野別振り返り

研究

卒論もなく、修論もない修士一年という立場を利用してかなり自由に色んなことをさせてもらいました。その分進捗がgg... 来年は修論が書けるようにがんばらねば。

趣味

ボードゲーム

ボードゲームにより一層はまった年でした。ゲームマーケットに2回共参加して散財し、幾つかボードゲーム会にも顔を出したりしました。購入したのはパーティーゲーム系が多く、中でも「私の世界の見方」は4年越しに手に入れることができて満足でした。

ミステリ・SF

今年は去年以上に本が読めなくなってしまいました。電車の中で寝てしまうというのが主な原因です。 一番のヒットは上にも書いた小川一水「天冥の標」。全10巻まであって最近9-1が出たのですが、新刊が楽しみでなりません。他にSFだと法条遥「リライブ」、スタニスワフ・レムソラリス」が面白かったですかね。 ミステリで一番は「戦場のコックたち」。

開発

去年アルバイトでRailsの開発をするようになって、それはそれで実装力はついたのですが、今年は「より綺麗なコードを書く」ということを意識して開発に臨めた一年だったかなと思います。周りの方々の影響って大きい。 また、いろんな組織の中での大きなプロジェクト開発に携わる機会が多かったため、そういった保守性がいかに大事であるか、というのを認識できたというのもあります。

まとめ

良いお年を!

TensorFlow Tutorial でニューラルネットワークを使う[Python]

f:id:yoghurt1131:20151112021353j:plain

Googleが発表した人工知能ライブラリTensorFlowを動かしてみました。 チュートリアルを追いながら、ニューラルネットワークの勉強(復習)をしたので理解は深まりましたが、誤りや間違いもあると思います。見つけた場合はご指摘ください。

Download & Install

MacOSでのダウンロードは次のようになります。Ubuntu/LinuxだとGPU使うバージョンもダウンロードできる模様 ダウンロードページ

# Only CPU-version is available at the moment.
$ pip install https://storage.googleapis.com/tensorflow/mac/tensorflow-0.5.0-py2-none-any.whl

動作確認

$ python

>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
"can't determine number of CPU cores: assuming 4
I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 4"
>>> print sess.run(hello)
Hello, TensorFlow!
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print sess.run(a+b)
42

動作はしましたが僕のマシンでは警告がでました

>>> sess = tf.Session()
[f:id:yoghurt1131:20151112021353j:plain]can't determine number of CPU cores: assuming 4
I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 4

CPUのコア数がわからないとのこと。どこかで設定すればいいのかな?

MNIST For ML Beginners

ページに行くと二つのチュートリアルが用意されている

  • intro_mnist:初心者向け
  • expert_mnist:Machine Learning経験者・上級者向け

初心者向けのチュートリアルでやります。 このチュートリアルではMNISTのデータセットを用いて手書き数字を識別するための識別器を作成します。

MNIST

Download Data Set

公式ページから落としてきてもいいんですが、Googleさんがデータセットを取ってくるPythonプログラムを用意してくれています。

Call Data

これを使ってデータセットを呼び出すことができます

import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
mnist.train # 訓練データ
mnist.test  # テストデータ

画像データやそのラベルは次のコードで呼び出せます

mnist.train.images # 画像データ
mnist.train.labels   # ラベルデータ

画像は28x28ピクセルで表されているため、一つ一つの画像データ・ラベルデータはサイズが28x28=784の配列で表現されています。これは多次元配列ではなくフラットな一次元の長さ784の配列になっています。 mnist.train.imagesを呼び出すと画像60000枚x784ピクセルの2次元配列が呼び出されることになります。 ラベルデータは数字0〜9の10次元のベクトルの中で、正解の数字に1が立つようなベクトルになっています。例えば、0が書かれた画像のラベルデータは[1,0,0,0,0,0,0,0,0,0,0]となります。

Softmax Regressions

最終的には、画像を認識させてそれが0〜9のどの数字に当てはまるかを確率値で出力します。活性化関数にはソフトマックス関数を用いています。ソフトマックス関数は多クラス分類における出力値を正規化するような役割を果たしています。

ソフトマックス関数では、 1. 出力のevidenceを求める 2. それを確率値にする という2つのステップがあります。

まず、ニューラルネットワークの出力evidenceは、次のような形で求められます。Wは重み・bはバイアスになります。

 {evidence_i = \sum_j W_{i,j} x_j + b_j}

これにソフトマックス関数をかけて確率値yを得ます。

 {y = softmax(evidence_i)}

イメージはこんな感じ

f:id:yoghurt1131:20151111142323p:plain

数式で表すならばシンプルに次のように書けます。

 { y = softmax(Wx + b) }

Implementing the Regression

インストール時に書きましたがTensorFlowのライブラリは次のように読み込めます。

import tensorflow as tf`

次にデータの入れ物(placeholder)を用意します

x = tf.placeholder("float", [None, 784])

重みとバイアスも宣言が必要です。これらの値は計算中に頻繁に変わることが予想されるのでTensorFlowのVariableというメソッドで扱います。

W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))

モデルは次のように呼び出せます。

y = tf.nn.softmax(tf.matmul(x,W) + b)

Training

コスト関数としてクロスエントロピーを導入します。コスト関数は学習された重みwとバイアスbがどれだけ目指す値に近づいたかの指標となります。

 {H_{y'}(y) = - \sum_i y_i' \log y_i }

yは予測確率分布、y'は正解のベクトルです

クロスエントロピーを導入するために、正解ラベルを入れるためのプレースホルダーを定義し、それを使ってクロスエントロピーの式を定義します。

y_ = tf.placeholder("float", [None,10])
cross_entropy = -tf.reduce_sum(y_*tf.log(y))

このコスト関数の値を最小化する重みとバイアスを見つけるのが、最終的な目標となります。 コスト関数の最小化は勾配降下法を用いて行い、プログラムでは次のように記述されます。

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

tf.train.GradientDescentOptimizer(0.01)が勾配降下法でありその際の学習率は0.01としています。 後に述べますが実際には計算量の関係から確率的勾配降下法というのを用いて全てのデータを用いてコスト関数の最小化を図るのではなく、無作為に少量のデータを抽出しそれを用いてコスト関数の最小化を目指します。

それでは学習するための準備をしていきます。

init = tf.initialize_all_variables()  # 値の初期化
sess = tf.Session()                     # セッションの初期化
sess.run(init)                              

直前に書いたように確率的勾配降下法を用いて少しずつ学習を行います。訓練データセットから100個ずつ無作為にデータを持ってきてそれ1000回を学習させています。これによってニューラルネットワーク内の重みwとバイアスbが決まっていきます。

for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

Evaluating Our Model

最初に、予測ラベルが正解ラベルと一致しているかの判定を次の文で定義します。

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

この結果をfloatに変換して平均を取ります。下記のコードは[True, False, True, True]が与えられると[1,0,1,1]に変換して、平均0.75という結果を求めます。

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

最後に結果の出力。sessionを通して出力されます。

print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})
# > 0.9126

91.26%の精度で認識ができていることが確認できました。チュートリアルでも91%くらいの精度が出ると書いてあるので、機能しているようです。

参考

macにtmuxを導入する

tmuxとは

端末多重化ソフト(terminal multiplexer) ちなみに読み方は``てぃーまっくす''とのこと. sshでリモートの端末に入って作業する際に,いくつも画面を開かなくて済む,一度切れても開き直せるというのが特徴のよう. 便利そうだ!

インストール

MacならHomebrewで入れられます. ishin$ brew install tmux

使い方

tmuxで起動します.

prefix+ 以下のコマンドで操作ができます.prefixはデフォルトでCtrl-b

  • bind-key d: tmuxを終了
  • bind-key c:新しい画面を作成 新しく画面を作成すると一つだったターミナルにもう一つ画面が増えたよ,というのが画面下に出ます.

f:id:yoghurt1131:20151101011339p:plain:w120 f:id:yoghurt1131:20151101011343p:plain:w200

  • <prefix> n:次の画面へ移動
  • <prefix> p:前の画面へ移動
  • <prefix> %:画面を縦に分割
  • <prefix> ":画面を横に分割
  • <prefix> o:分割した画面間を移動
  • <prefix> w:現在開いているウィンドウのリストを表示

セッションを保存しておけるので一旦作業を終了し,帰宅した後にそのまま作業を再開することができます.

<prefix> d # デタッチして作業を終了
exit            # ログアウト
ssh remote      # 自宅で再度ログイン
tmux attach -d # 前回のセッションを開いて作業再開

参考

Rubyの配列操作をPythonで書くと?

こんにちは

最近rubyで書いたりpythonで書いたりを繰り返しており、頭の中がごちゃごちゃになりつつあります。 「この書き方pythonだとどうやるんだったっけ?」とか「あれ、これrubyの文法じゃねえpythonだ」みたいなのが増えてきたのでちょっと整理も兼ねてメモ程度に書いてみようかと思います。

部分配列

ruby.slice[]と同じ役割です。

# 宣言
pry(main)> x = (1..5).to_a
=> [1, 2, 3, 4, 5]

# index0番から3番まで
pry(main)> x[0..3]
=> [1, 2, 3, 4]
pry(main)> x.slice(0..3)
=> [1, 2, 3, 4]

# index1番から3個
pry(main)> x[1, 3]
=> [2, 3, 4]
pry(main)> x.slice(1, 3)
=> [1, 2, 3]

# index2番以降
pry(main)> x[2..-1]
=> [3, 4, 5]

pythonでは終了インデックスの次の数字まで指定します。 

# 宣言
>>> x = range(1, 6)
[1, 2, 3, 4, 5]

# index0番から3番まで
>>> x[0:4]
[1, 2, 3, 4]

# index1番から3個
>>> x[1:4]
[2, 3, 4]

# index2番以降
>> x[2:]
[3, 4, 5]

include?

# 3が含まれているか
pry(main)> x.include?(3)
=> true
# 3が含まれているか
>>> 3 in x
True

empty?

# 配列が空か
pry(main)> x.empty?
=> false
# 配列が空か
>>> len(x) == 0
False

map

# 配列内の要素を10倍にして返す
pry(main)> x.map{ |item| item * 10 }
=> [10, 20, 30, 40, 50]
# 配列内の要素を10倍にして返す
>>> map(lambda item:item*10, x)
[10, 20, 30, 40, 50]
# リスト内包表記
>>> [item * 10 for item in x]
[10, 20, 30, 40, 50]

select

# 配列内の奇数を返す
pry(main)> x.select{ |item| item % 2 != 0 }
=> [1, 3, 5]
# 配列内の要素を10倍にして返す
>>> filter(lambda item:item%2!=0, x)
[1, 3, 5]
# リスト内包表記
>>> [item for item in x if (item % 2) != 0]
[1, 3, 5]

Eclim機能メモ

Eclimの環境を作った時はEclimの公式サイトが死んでたので改めて,以前に書いたのも再度ここにまとめます.

  • :JavaNew {class | abstract | interface enum} パッケージ.ファイル名:新規でJavaFileを作成してくれます
  • :JavaConstructorコンストラクタを追加してくれます
  • :JavaImple:新しいウィンドウが開きimplementsなどで実装しているインターフェースのメソッドが確認できます.メソッドの行でエンターを押すとそのメソッドが自動挿入されます
  • :JavaCorrect:エラーの出てる行の修正候補を出してくれます
  • :JavaImportOrganize:現在のファイルに必要なimport文を自動で挿入してくれます
  • :JavaSearchContext:カーソルが当たっているクラス・変数等の宣言へと飛ぶことができます

  • :JavaCallHierarchy:カーソルが当たっているメソッドの呼び出し階層が確認できます

  • :JavaHierarchy:現在開いているクラスの継承・実装関係が確認できます

Ruby風かつ高速と噂の言語Crystalを使ってみた

ちょっと興味を持ったので巷(?)で盛り上がっているCrystalを入れてみました.使ってみたというより触ってみた程度です.

Crystalとは

公式サイトによると,次のような特徴があるそうな.

  • Ruby風味の文法
  • 静的な型チェックがある
  • Cのコードが呼び出せる?
  • 効率的なネイティブコードへとコンパイルできる

インストール

githubからインストールページに飛べます.macだとHomebrewから以下のようにインストールができるみたいです.

brew tap manastech/crystal
brew update
brew install crystal-lang

Hello,world!

Crystalのファイル拡張子crだそうです.

puts "Hello, crystal!"

実行結果

$ crystal hello.cr
Hello, crystal!

crystaloコマンdでコンパイルと実行をやってくれるみたいですね. crystal run ファイル名でもできるそう.

また,コンパイルして実行ファイルを生成することもできます.Crystalの特徴はここですね.

$ crystal build hello.cr
$ ./hello

各種文法

コメント

#でコメントができます.

# This is a comment
puts "Hello, crystal!"   # => Hello, crystal!

以降rubyと同じところは飛ばしていきます

Integers・Float

精度指定ができる

Crystalには整数型がいくつかあり何も指定をしなければInt32Int64UInt64から適当なのが選ばれるみたいです.後ろにi8, i16, i32, i64などをつけることでそれぞれの精度で扱われます.iをuにすると符号なしとなります.

a = 2     
b = 2_i16   
c = 2_u64   
puts a.class    # => Int32
puts b.class    # => Int32
puts c.class    # => UInt64

Floatも同じです.

  1.0_f32  # Float32
  1_f32    # Float32

アンダースコア表記ができる

カンマの代わりに,変数をアンダースコアで繋げて書くことができます.見やすくなりますね.でもこんな大きな数使わないような

under_score_num = 111_222_333
puts under_score_num    # => 111222333

Char & String

Char型はシングルクオート',String型はダブルクオート"を使います.

'a' # char
"abc" #string

なのでこういうことはできません.

puts 'Hello, crystal'
$ crystal hello.cr
Syntax error in ./hello.cr:1: [1munterminated char literal, use double quotes for strings

puts 'Hello, crystal!'
      ^

Array

rubyと違って,配列内の型が何であるかに気を使わなければなりません.

a = [1, 2, 3]
b = [1, "Hello", 'w']
puts a.class    # => Array(Int32)
puts b.class# => Array((String | Int32 | Char))

x = [] of (Int32 | Char)
y = Array.new(String)

最初に中身のある配列を与えた場合はcrystalで勝手に型を与えてくれますが,配列の初期化を行う際には型の宣言が必要です.

x = [] of (Int32)
x << "hello" # => no overload matches 'Array(Int32)#<<' with types String

Tuple

Tuple型があります.pythonとかを使っている人には馴染みのものですね.

tuple = {1, "hello", 'x'}
puts tuple          # => {1, "hello", 'x'}
puts tuple.class    # => {Int32, String, Char}
puts tuple[1]      # => hello

実行速度

とまあ簡単なところを比較してみたところで,実行速度についても比較してみました.

rubyとcrystalで単にループを回しただけです.もっといい比較方法はあるよなきっと・・・.

プログラムはこんな感じ.rubyもほぼ同じような感じです.違うのは時間を呼び出すメソッドくらい.

# 比較用プログラム

start_at = Time.now.to_i * 1000 + Time.now.millisecond

n = ARGV[0].to_i
x = 0
y = 0

n.times do |i|
  x += 1
  y -= 1
end

end_at = Time.now.to_i * 1000 + Time.now.millisecond

puts x 
puts y

puts "crystal" + "-" * 23
puts "loop: #{n}"
puts "Time:#{end_at - start_at}"
puts "-" * 30

実行結果

ループ回数 ruby実行時間(msec) crystal実行時間(msec)
100000 7 1
1000000 77 3
10000000 810 27
100000000 8102 349

速いですね. ちなみにこれは純粋にループの前後の時間のため,コンパイルの時間などを考慮してはいないです.

それと,余談ですがCrystalではコマンドライン引数は--の後に書きます.こんな感じ.

crystal loop.cr -- 10000000

もっと色々利点や特徴があるのでしょうが,パッと比較できるのはこの程度.もう少し触ってみようかなあ.


追実験

もうちょっとましなコード?でやろうと思ってフィボナッチ数でもやってみました.コードと実験結果です.

# フィボナッチ数を求めるプログラム

def fibonacci(n)
  if n == 0
    return 0
  elsif n==1
    return 1
  else
    return fibonacci(n-1) + fibonacci(n-2)
  end
end

n = ARGV[0].to_i

start_at = Time.now.to_i * 1000 + Time.now.millisecond
fibonacci(n)
end_at = Time.now.to_i * 1000 + Time.now.millisecond

puts "crystal" + "-" * 23
puts "number: #{n}"
puts "Time:#{end_at - start_at}"
puts "-" * 30
n番目 ruby実行時間(msec) crystal実行時間(msec)
10 0 0
20 1 0
30 180 11
40 26267 1327

Written with StackEdit.

Eclipseの機能をVimで使うEclimの環境をMacOSで構築する

タイトル通りです.Eclimの紹介です.

開発のエディタはずっとVimを使っているのですが,JavaだけはEclipseで開発をしていて,もどかしさをずっと感じていました.ソースコード読むのとか,Eclipseはとっても便利なんですよね.Vrapperとか使ったりしてVimキーバインドにはしてたんですけど,物足りない.

 
そんなこともあり調べていたらEclimというEclipseの機能をターミナルから叩けるソフトが存在することを知り,便利そうなので使ってみることにしました.

環境

OSはOSX Yosemiteで,EclipseのバージョンはLuna Service Release 2 (4.4.2)です.
 

Eclimのインストール

こちらからEclimをダウンロードしてきます.jarファイルになっているためそのまま実行し,インストールします.
また,antが必要となるので,
brew install ant
としてantを入れます.この際に,リンク切れみたいなメッセージが出たためbrew updateしてからinstallを行いました.
またvimrcに以下を追記しBundleInstallします.
" for Java
NeoBundleLazy 'ervandew/eclim', {'build': 
    {'mac': 'ant-Declipse.home=/opt/homebrew-cask/Caskroom/eclipse-java/4.4.0/eclipse -Dvim.files='.escape(expand('~/.bundle/eclim'), ''    )}
    }
autocmd FileType java NeoBundleSource eclim

Eclimの起動

Eclipseから,Eclimを立ち上げ?ます.EclipseのWindow→Show View→OtherからEclim→Eclimdを選択します.
 
VimにてEclimの起動確認を行います.
:PingEclim
としてEclimとEclipseのバージョンが帰って来れば成功です.

Eclipseプロジェクトの作成

:ProjectCreate /path/to/eclipse/project_name -n java

Eclipseプロジェクトが作成されます.

:e /path/to/eclipse/project_name/src/sample/eclim/Main.java

などとしてファイルを作成することができ,

:CProjectConfigs

によってclasspathなどの設定も行ってくれるようです.

:ProjectBuild
:ProjectProblems

でプロジェクトのビルド,エラー表示などが行われます. エラー表示ではQuickfix Listというウィンドウが開かれエラーがずらっと表示されます.ちなみにこれは同期が取れているみたいで,Quickfix Listを開きながら元のソースコードを直していくと保存されるたびにエラーが減っていきます.もちろん直っていればですが.
ちなみに,エラー,または警告があると以下の6行目のようにマークがつきます.デフォルトはEclipseの警告と同じレベルなので,煩わしかったらエラー出力のレベルを変更するといいかもしれません.





Eclimの機能諸々

補完

Eclipseの補完候補が表示されたりします.

Eclipseの機能として僕がよく使ってたのはOpen Declarationと,Open Call Hierarchyだったのでそれぞれについても調べました.

Open Declaration(タグジャンプ)
ソース内のクラス,メソッドなどにカーソルが当たっている状態で
:JavaSearchContext
してあげるとそれが宣言された箇所に飛びます.

呼び出し階層表示

こちらもメソッドなどに焦点を当てた状態で
:JavaCallHierarchy

としてあげると呼び出し階層が次のように表示されます.これはメソッドout()の呼び出し階層ですね.












 

 

 

Eclimにはまだまだ機能もあるので,適宜調べながらvimrcに使いやすいようにキーの割り当てをしていこうと思っています.
最高ですね!

参考

追記

:Java %
で現在開いているプログラムを実行できます