2015年8月16日日曜日

fluentd output plugin s3

fluentdからs3にログを残す。
s3プラグイン: http://docs.fluentd.org/articles/out_s3
以下はstoreの設定例。

    type s3 #plugin名
    aws_key_id <アクセスキー>
    aws_sec_key <シークレットキー>
    s3_bucket <バケット名>
    s3_region <リージョン名>
    format json #レコードの出力をjsonに変更
    path webapi/ #バケット配下の階層
    buffer_path /var/log/td-agent/buffer/s3_e #バッファ用ファイルのprefix
    time_slice_format %Y%m%d/%Y%m%d-%H #sliceのフォーマット
    #time_slice_wait 10m
    s3_object_key_format %{path}%{time_slice}_%{index}_%{hostname}_error.%{file_extension} #s3上のファイル名
    utc #標準時形式
    include_time_key true #出力レコードに時刻を追加
    include_tag_key true #出力レコードにタグを追加
    buffer_chunk_limit 256m #バッファファイルが256MBになったら送信
    flush_interval 60s #60秒ごとに送信
    store_as json #保存形式をgzからjsonに変更(AWS Console上で内容を確認したい)

fluentdの基本: centralized logging middle ware

ログシステムの保証レベル
at-most-once:最高で1回の送信。ただし到達を保証しない
at-least-once:少なくとも1回の送信。ただし重複の可能性がある
exactly-once:at-most-onceとat-least-onceの両方を満たす


ログ採取ミドルウェアfluentd
chmod +x install-redhat.sh
./install_redhat.sh
sudo service td-agent start //起動default port 24224


ログ/メッセージに任意のタグをつけて逐次的に収集。
フィルタ(データ加工、集計)、バッファ、ルーティングの後に各種データ出力先へ保存(Output Plugin)する。

fluentd メッセージ
[tag, time, record]

in_exec: 一定間隔ごとに指定パスにあるスクリプトをコマンド実行して、結果を収集する
out_exec_filter: tailプラグインなどで収集したログメッセージに対してデータ加工を行う
out_exec: 収集したログメッセージを指定パスにあるスクリプトの引数として渡して実行する

flush_interval: バッファリングしたメッセージを一括で受け渡しする時間間隔

tailプラグイン:既存のアプリログを収集するのに便利


fluentd設定ファイル
/etc/td-agent/td-agent.conf

有効ディレクティブ
<system> // Fluentdのコア部分の動作を決定する
<source> // プラグインの指定
<match> // ログデータの加工、フィルタリング、外部出力
include // 内部または外部の設定ファイルのロード

以下、設定ファイルの各ディレクティブの説明。[]内はデフォルト設定


system
コマンドラインの引数より優先される
log_level: [info]
suppress_repeated_stacktrace: 連続した同一エラー出力を抑制 [抑制無し]
emit_error_log_interval: 指定時間内の同一エラー出力を抑制 [抑制無し]
suppress_config_dump: 起動時に設定ファイルの標準ログ出力を抑制


source
ログの入力元を決定する。
type: Inputプラグインの指定

<source>
  type <name of plugin>
  tag <output tag>
  <option of plugin>
</source>

tailの場合、formatが必須。formatは正規表現で記述可能。例えばapachなどプリセットも用意されている。


match
ログの出力先を決定する。
type: outputプラグインの指定。フィルタリング、ルーティングも可能。

<match <マッチさせるタグ>>
  type <プラグイン名>
  <プラグインのオプション>
</match>

一度受信したtagをルーティングして、vhostのドメイン部分をタグに含めて再度ルーティングすると、vhostの情報を含むログを出力できる。
outputのプラグインには、fileやs3、mongo、stdoutなどがある。
ルーティング目的では、copy、rewrite_tag_filterなどがある。
一旦matchして出力してしまうと以降のmatchでは引っかからないので、copyなどを利用してうまく設定することが必要。


マッチングタグの記述
*: 1つのタグ要素に合致
**: 0個以上のtag要素に合致
{x, y, z}: x, y, zにマッチ。x, y, zはマッチしたいパターン


fluentdテスト用コマンド
fluent-cat: td-agent付属のコマンド

// 標準出力
echo '{"message":"Hello World."}' | /usr/lib64/fluent/ruby/bin/fluent-cat debug.test // fluent-catにはタグ名を渡す

// ログファイルの参照
sudo less /var/log/td-agent/td-agent.log


example) apache

ログファイルの権限などに注意。間違っている場合td-agent.logにエラーが出力されるので容易にわかる。

2015年8月9日日曜日

Lispによる関数型プログラミング入門2 記法

Lispの記法

・前置記法
1 + 2
→ 
 (+ 1 2)

つまり、関数(ここでは和演算)を最初に宣言して、引数を渡す。これはf(x)と記述するのと同じである。

・defun
means define-function

例)
フィボナッチ数計算:
> (defun fib(n)
>   (if (<= n 1)
>     1
>     (+ (fib (- n 1)) (fib(- n 2)))
>   )
> )

> (fib 5)
 8
> (fib 21)
 17711


Lispの評価と特殊形式quote、function

・quote
関数を評価せずにそのままかえす

例)
> (quote (1 2 3))
 (1 2 3)

・function
シンボルの関数をかえす特殊関数
略記 #'

例)
> (function +)

#<SYSTEM-FUNCTION +>

2015年8月3日月曜日

Lispによる関数型プログラミング入門

SoftwareDesignの2015Aug を読んでLispに興味をもったので、何回かにわけて入門のメモを残す。

Lispの前に、関数型プログラミングの特徴から。

関数型プログラミング

グローバル変数や代入文など副作用を生じる機能を使わずにプログラミングを行う。

・従来の考え方
上記のように変数や配列などの状態をループなどを用いて変更し結果を得る

・関数型プログラミングの考え方
関数(主に高階関数)を利用して副作用無しに結果を得る

・関数型プログラミング向きの問題
状態をもたない再帰的な問題
→探索、整列

・人間には再帰的思考が向いている
数学的帰納法(具体的で小さい問題から大きな全体の問題へ向かう)

・並列処理に対する強み
状態を持たないので、並列処理を自然に(というのは同期や排他が必要無い)できる。
クラウドやビックデータ向きである。

・関数呼び出しに対する弱み
関数呼び出しはコストが大きいので、低機能コンピュータには向いていない。高機能コンピュータ上で並列処理するのに向いている。

・動的なプログラミングに対する強み
関数自身をオブジェクトとして扱えるため、動的な関数生成や変更をすることができる。(サービス指向コンピューティング)

・抽象的なプログラミングに対する強み
うまく作れれば、状態をもたないので仕様変更に柔軟であるはず。

・バグの現象
副作用が少ないので、バグの温床がつくられることを防げる。

Lisp
・言語仕様が小さい
・インタプリタ言語であり、実行が簡単
・GC、ラムダなど最近の言語では常識であるアイデアの元となった言語
・動的型付け(型推論ではない)
・かっこが多くて見難い
・前置記法が見難い
・動的型付けはリソースを食う

数学的帰納法だと考えるとわかりやすい
・再帰をみつける = 同じことの繰り返しをみつける。

例)
階乗:
・関数型
 →5(N)の階乗は4(N-1)の階乗の結果に5を掛けること
・手続き型
 →1 x 2 x 3 x 4 x 5

Lispのインストール(OSX)

$ brew intall clisp
$ clisp [~]
i i i i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I 8 8 8 8 8 o 8 8
I \ `+' / I 8 8 8 8 8 8
\ `-+-' / 8 8 8 ooooo 8oooo
`-__|__-' 8 8 8 8 8
| 8 o 8 8 o 8 8
------+------ ooooo 8oooooo ooo8ooo ooooo 8
Welcome to GNU CLISP 2.49 (2010-07-07) <http://clisp.cons.org/>
Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2010
Type :h and hit Enter for context help.
[1]>
view raw list_install.sh hosted with ❤ by GitHub
次回はLispの記法から。

2015年6月28日日曜日

アルゴリズムプログラム 積

アルゴリズムをプログラムする方法を学ぶ。

積を計算することは、現代では0位取り表記によって大変容易になったが、古代エジプトなどでは専門性を求められるものであった。

積は和を複数回繰り返すことによって実現できる。コンピュータではビット演算を組み合わせることによってより効率的に積を計算することができる。

以下は、アーメスのアルゴリズムとその改善版を記述したコードである。
コードが最適化されているか常に思考し、よりよいコードに変換する作業を繰り返すことが大切だとわかる。


//
// multiplication.cpp
// CplusplusPractice
//
// Created by masai on 2015/06/27.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
// xの最上位ビットを評価する(奇数判定する)
bool odd(int n){ return n & 0x1; }
// xを右へ1つシフトする(1/2する)
int half(int n){ return n >> 1; }
// 乗法1 a + a + ... + a
int multiply0(int n, int a){
if(n == 1) return a;
return multiply0(n - 1, a) + a;
}
// 乗法2 a + a + a .. + a = (a + a) + (a + a) + ... + a
int multiply1(int n, int a){
if (n == 1) return a;
// a + a + a + a = (a + a) + (a + a)
int result = multiply1(half(n), a + a);
// (a + a) + (a + a) + (a + a) (nの2進数表現における1の数(population count) - 1 だけ呼ばれる)
if(odd(n)){
std::cout << "plus" << std::endl;
result = result + a;
}
return result;
}
// おまけ: 16進数表現
void output16(int a){
printf("a = 0x%x", a);
}
// 15倍の加法連鎖
int multiply_by_15(int a){
int b = (a + a) + a;
int c = b + b;
return (c + c) + b;
}
// 乗累算1(関数呼び出しを減らす)
int multi_acc0(int r, int n, int a){
if(n == 1) return r + a;
if(odd(n)){
return multi_acc0(r + a, half(n), a + a);
}else{
return multi_acc0(r, half(n), a + a);
}
}
// 乗累算2(記述を単純化する)このような状態を末尾再帰(tail-recursive)という
int multi_acc1(int r, int n, int a){
if(n ==1)return r + a;
if(odd(n)) r = r + a;
return multi_acc1(r, half(n), a + a);
}
// 乗累算3 比較回数の削減(比較の順序によって計算回数が減るケースがある)
int multi_acc2(int r, int n, int a){
if(odd(n)){
r = r + a;
if(n ==1)return r;
}
return multi_acc2(r, half(n), a + a);
}
// 乗累算4 正確なtail-recursive → 再帰から繰り返し構造に置き換えることが簡単
int multi_acc3(int r, int n, int a){
if(odd(n)){
r = r + a;
if(n ==1)return r;
}
n = half(n);
a = a + a;
return multi_acc3(r, n, a);
}
// 乗累算5 再帰から繰り返し構造への置き換え
int multi_acc4(int r, int n, int a){
while(true)
{
if(odd(n)){
r = r + a;
if(n ==1)return r;
}
n = half(n);
a = a + a;
}
}
// ヘルパー1
int multiply2(int n, int a){
if(n == 1) return a;
return multi_acc4(a, n - 1, a);
}
// ヘルパー2
int multiply3(int n, int a){
// nが奇数になるまで、1/2を繰り返す
while(!odd(n)){
a = a + a;
n = half(n);
}
return multiply2(n, a);
}
// ヘルパー3
int multiply4(int n, int a){
// nが奇数になるまで、1/2を繰り返す
while(!odd(n)){
a = a + a;
n = half(n);
}
if(n == 1) return a;
// かならずnが奇数で呼び出すので奇数のときに行われる処理を事前に行っておく
return multi_acc4(a, half(n - 1), a + a);
}
int main(int argc, char* argv[]){
std::cout << "multiplication." << std::endl;
// 和の再帰で積を表現
std::cout << "multipliycation = add." << std::endl;
std::cout << multiply0(3, 2) << std::endl;
// 奇数
std::cout << "odd" << std::endl;
std::cout << odd(13) << std::endl;
// 偶数
std::cout << "even" << std::endl;
std::cout << odd(12) << std::endl;
// 1/2
std::cout << "1/2" << std::endl;
std::cout << half(5) << std::endl;
// 積(アーメスのアルゴリズム)
std::cout << "egyption multiplycation." << std::endl;
std::cout << multiply1(6, 2) << std::endl;
// おまけ: 16進表現
output16(100);
// 15の加法連鎖
std::cout << "multipy by 15." << std::endl;
std::cout << multiply_by_15(30) << std::endl;
// 乗累算
std::cout << multi_acc1(0, 5, 100) << std::endl;
std::cout << "optimize multipy." << std::endl;
std::cout << multi_acc2(0, 5, 100) << std::endl;
std::cout << multi_acc3(0, 5, 100) << std::endl;
std::cout << multi_acc4(0, 5, 100) << std::endl;
// ヘルパー呼び出し
std::cout << multiply2(5, 100) << std::endl;
std::cout << multiply3(5, 100) << std::endl;
std::cout << multiply4(5, 100) << std::endl;
return 0;
}

2015年6月21日日曜日

vagrantとansibleを使ってdocker開発環境をつくる

vagrantは開発環境用のVM構築と共有を簡単に行うためのVMラッパーツールであるが、ansibleを利用して開発環境の設定(プロビジョニング)も繰り返しを避けることができる。

vagrantは、プロビジョニング用の設定をVagrantfileに記述することが可能である。
今回は、プロビジョニングにansibleを利用する。ansibleはplaybookと呼ばれるyaml形式の設定ファイルを参照する。

Vagrantfileには以下のように追記する。ansibleはplaybook.ymlを参照する。

config.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"
end
view raw Vagrangfile.txt hosted with ❤ by GitHub
ansibleに使用するplaybookを作成する。

---
- hosts: all
tasks:
- name: install latest docker
shell: curl -sSL https://get.docker.com/ubuntu/ | sudo sh
- name: add vagrant user to docker group
command: gpasswd -a vagrant docker
sudo: yes
view raw playbook.yml hosted with ❤ by GitHub
Vagrantfileと同じディレクトリにplaybook.ymlを入れておく。
vagrant up で playbookを利用してプロビジョニングできる。既に vagrant up 済みのVMは以下のように明示的にプロビジョニングする必要がある。

#vagrant provision [~/vagrant/ubunt1404]
==> default: Running provisioner: ansible...
PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/Users/masai/vagrant/ubunt1404/.vagrant/machines/default/virtualbox/private_key --user=vagrant --connection=ssh --limit='default' --inventory-file=/Users/masai/vagrant/ubunt1404/.vagrant/provisioners/ansible/inventory playbook.yml
PLAY [all] ********************************************************************
GATHERING FACTS ***************************************************************
ok: [default]
TASK: [install latest docker] *************************************************
changed: [default]
TASK: [add vagrant user to docker group] **************************************
changed: [default]
PLAY RECAP ********************************************************************
default : ok=3 changed=2 unreachable=0 failed=0

2015年6月19日金曜日

Pythonの軽量WEBフレームワークBottle (WebAPIを手軽に記述)

BottleはPythonの軽量WEBフレームワークである。テスト用に素早くAPIを公開したいなと考えたところ、ピッタリだと思った。

インストール
pipでインストールできる。
pip install bottle

サンプルコード api.py
以下の様な短いコードでWeb APIが動作する。

from bottle import route, run
# アノテーションでURLを記述
@route('/deepapi/json/:name')
def hello(name):
return '<h1>Deep %s!</h1>' % name
# オプションをつけるとデバッグ実行
run(host='masai-no-MacBook-Pro.local', port=8080, debug=True, reloader=True)
#run(host='localhost', port=8080)


起動
python api.py
めちゃくちゃ楽できる・・・。今まで使わなかったことを後悔するくらいだ。

2015年6月17日水曜日

vagrantのboxを使って仮想マシンを起動する

vagrantは追加されたboxの内容にしたがって、以下のコマンドで仮想マシンの起動設定を作成することができる。

# vagrant init <box名>

Vagrantfileが作成されるので、以下のコマンドで起動する。

# vagrant up

起動したVMには以下のコマンドでssh接続できる。

# vagrant ssh

vagrantでWeb開発環境用仮想マシンができるところまでをまとめるつもりである。

vagrantのboxを追加する(vagrantコマンドで直接URLを指定してSSLエラーが出る場合)

vagrantのbox追加で指定するURLはローカルファイルでももちろん可能である。以下は、curlでローカルに保存したboxファイルをvagrantに追加する手順である。

# curl -L https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box > centos.box
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 280M 100 280M 0 0 2068k 0 0:02:18 0:02:18 --:--:-- 4524k
# ls
centos.box
# vagrant box add centos centos.box
==> box: Adding box 'centos' (v0) for provider:
box: Downloading: file:///root/vagrant/centos/centos.box
==> box: Successfully added box 'centos' (v0) for 'virtualbox'!
view raw vagrant_add.sh hosted with ❤ by GitHub

vagrant box list で追加できているか確認できれば完了である。

2015年6月16日火曜日

gvmを利用してgradleをインストールする(OSX)

GVM(Groovy management tool)はGroovy環境構築用ツールである。Groovyの実行バージョンの管理や、Groovyを利用するツールのインストールが可能である。

インスール
curl -s get.gvmtool.net | bash

PATHに追加
export PATH=$PATH:$HOME/.gvm/bin

実行
~/.gvm/bin/gvm-init.sh

gradleのインストール
gvm install gradle

以上で完了。zshを利用している場合には、.zshrcもしくは.zshenvにPATHとコマンド初期化の設定が追加されることを確認すること。

2015年6月12日金曜日

Bing画像検索API Pythonクライアント

学習画像を収集するための、Bing画像API Pythonクライアント。
保存ディレクトリとか検索ワードの指定をパラメータで引き渡すようにして少し使いやすくしたつもり。収集する画像の最大枚数を指定することも可能。

#conding:utf-8
import sys
import os
import urllib
import urllib2
import json
import requests
KEY = '<Your Bing Developer Key>'
OUTPUT = '/images/bing/'
MAX = 100
count = 1
def bing_search(query, directory, skip):
global count
bing_url = 'https://api.datamarket.azure.com/Bing/Search/v1/Image'
print 'search count: ' + str(count) + ', url: ' + bing_url + ', skip: ' + str(skip)
pm = urllib2.HTTPPasswordMgrWithDefaultRealm()
pm.add_password(None, bing_url, KEY, KEY)
handler = urllib2.HTTPBasicAuthHandler(pm)
opener = urllib2.build_opener(handler)
urllib2.install_opener(opener)
if skip > 0:
params = urllib.urlencode({'Query': "'" + query + "'", 'Adult': "'Off'", '$skip': skip ,'$format': 'json'})
else:
params = urllib.urlencode({'Query': "'" + query + "'", 'Adult': "'Off'", '$format': 'json'})
response = urllib2.urlopen(bing_url+'?'+params)
data = json.loads(response.read())
results = data['d']['results']
for item in results:
if count > MAX:
print 'finish. count: ' + str(MAX)
return
image_url = item['MediaUrl']
root,ext = os.path.splitext(image_url)
if ext.lower() == '.jpg':
print image_url,
try:
r = requests.get(image_url)
fname = OUTPUT + directory + "/bing%04d.jpg" % count
f = open(fname, 'wb')
f.write(r.content)
f.close()
print "...save", fname
except:
print "error", fname
count += 1
bing_search(query, directory, count)
if __name__ == '__main__':
argvs = sys.argv
argc = len(argvs)
if(argc != 3):
print 'Usage: python %s query directory' % argvs[0]
quit()
query = argvs[1]
directory = argvs[2]
print 'get bing image: %s ' % query
bing_search(query, directory, 0)

Gemでログを標準出力にする(Ruby)

Gemfileに以下を指定して、rails_stdout_logginライブラリを利用する。
gem 'rails_stdout_logging'

2015年6月11日木曜日

Objective-C メモリ管理

Objective-CSwiftはクラスのインスタンスを参照カウンタで管理する。参照回数が1以上であれば、インスタンスはメモリ上に保持される。

ARC(Automatic Reference Counting)は自動で参照カウンタを管理する仕組みである。retain及びreleaseを明示的な記述を禁止し、自動で行う。

オーナーシップはオブジェクト間の関係性を表すが、強参照と弱参照がある。
強参照は参照先のオブジェクトのオーナーシップを持ち、自分が参照を捨てるまで確実に参照可能である。new(alloc)するとインスタンスへの強参照をもつことになる。

一方、弱参照はオーナーシップをもたず、オブジェクトが破棄されると参照できない。delegateやblocksで用いることが多い。

お互いに強参照の関係にある場合、循環参照と呼ばれる。片方の参照を弱参照にすることで回避できる。


docker ログ出力の設定

dockerでコンテナを作成する際は、ログをコンテナ内に残さないほうが良い。

ログを標準出力に出すように変更する。dockerは標準及びエラー出力されたログをホストの/var/lib/docker/containers/<コンテナID>/<コンテナID>-json.logにJSONファイルとして出力する。

docker logsコマンドで見ることのできるログは、上記のファイルである。Docker Remote APIを介して取得することも可能である。

基本方針

  • コンテナに依存せず、ログを収集する仕組みを準備する
  • ログ収集プロセス自体をコンテナとして動作する

標準出力の設定

各コンテナに割り当てたアプリケーションごとに標準及びエラー出力に設定する。


ログ収集
以下の様なツールを起動するコンテナを準備する。

  • Logspout:dockerコンテナ用のログルータ。Docker Remote APIを介して、同一ホストの全コンテナのログを取得する。LogspoutコンテナからSyslogサーバなどへルーティングすると、複数ホスト上で動くコンテナ郡のログをSyslogサーバで確認することができる。
  • Fluentd:fluentdにはdocker用のプラグインがある。/var/lib/docker/containers以下のログファイルを読み込んで、別のあるファイルへ出力させる。またはS3や集計サービスへ送信する。

ログ集約サービス
Logentries:SaaS型のログ集約サービス



2015年6月10日水曜日

Objective-C 基礎

Objective-Cは触ったことがほとんど無い。基礎からひと通り触る際の記録。

// NSLogの第一引数はフォーマット指定子
NSLog(@"%@", [MixiSampleClass getStaticString]);
// インスタンス生成
MixiSampleClass* obj = [[MixiSampleClass alloc]init];
(void)[obj initWithName:@"abcdefg" sampleType:SampleTypePiyo];
NSLog(@"%@", obj.name);
NSLog(@"%@", obj.name.addSample);
view raw main.m hosted with ❤ by GitHub
Sample.h
//
// MixiSampleClass.h
// TrainingObjectiveC
//
// Created by masai on 2015/06/09.
// Copyright (c) 2015年 masai. All rights reserved.
//
#import <Foundation/Foundation.h>
// 列挙型(SampleType enum)
typedef NS_ENUM(NSInteger, SampleType){
SampleTypeHoge = 0,
SampleTypeHuga,
SampleTypePiyo,
};
@interface MixiSampleClass : NSObject
// プロパティ nonatomic=排他制御しない、strong=オーナーシップをもっている、setter&getterの自動生成
// -setName, -name
@property (nonatomic, strong) NSString *name;
// インスタンスメソッド -
-(id)initWithName:(NSString*) name sampleType:(SampleType) sampleType;
// クラス・メソッド +
+(NSString*) getStaticString;
@end
view raw Sample.h hosted with ❤ by GitHub
Sample.m
//
// MixiSampleClass.m
// TrainingObjectiveC
//
// Created by masai on 2015/06/09.
// Copyright (c) 2015年 masai. All rights reserved.
//
#import "MixiSampleClass.h"
// クラス定数 const
static NSString* const constString = @"const";
// クラス変数 static
static NSString* staticString = @"static";
// 無名カテゴリ(privateなプロパティの拡張、無名クラス無いで宣言したpropertyやメソッドはprivate扱いになる)
@interface MixiSampleClass()
@property (nonatomic, assign) BOOL isEnabled;
@property (nonatomic, assign) SampleType sampleType;
@end
@implementation MixiSampleClass
// インスタンスメソッド -
-(id)initWithName:(NSString*) name sampleType:(SampleType) sampleType
{
self = [super init];
if(self){
// access iVar, self.<var>や_<var>でアクセスが可能
_name = name;
_isEnabled = YES;
_sampleType = sampleType;
}
return self;
}
// クラス・メソッド +
+(NSString*) getStaticString
{
return staticString;
}
@end
view raw Sample.m hosted with ❤ by GitHub

カテゴリ
あるクラスのメソッド郡を別のモジュールとして宣言する。

NSString+SampleAddition.h
//
// NSString+SampleAddition.h
// TrainingObjectiveC
//
// Created by masai on 2015/06/10.
// Copyright (c) 2015年 masai. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (SampleAddition)
-(NSString *)addSample;
@end
NSString+SampleAddition.m
//
// NSString+SampleAddition.m
// TrainingObjectiveC
//
// Created by masai on 2015/06/10.
// Copyright (c) 2015年 masai. All rights reserved.
//
#import "NSString+SampleAddition.h"
@implementation NSString (SampleAddition)
-(NSString *)addSample
{
return [NSString stringWithFormat:@"%@sample", self];
}
@end

vagrantによるdocker環境の構築

vagrantとはVMのラッパーツールである。設定ファイル(Vargrantfile)を使用してVMを起動することができ、環境構築の再現性を高めてくれる。また、Dockerが64bitOSにしか対応していないのに対して、32bitOSをサポートしているため、環境構築のホストOSへの依存度も低下する。

ここでは、vagrantのインストール及びvagrantを使ってdockerコンテナを扱う際の基礎的なコマンドについて記載する。

vagrantはパッケージでインストールする。

vagrantはデフォルトの仮想化ソフトに VirtualBox または VMWare を使うため、どちらかインストールしておく。ここでは、VirtualBoxを利用する。

また、vagrantのプラグイン dotenv をインストールする。
$ vagrant plugin install dotenv
Installing the 'dotenv' plugin. This can take a few minutes...
Installed the plugin 'dotenv (2.0.1)'!

vagrantでVMを起動する
vargrant up

vagrantで起動したssh接続する
vargrant ssh

vagrantのVMのステータスを確認する
vagrant status

vagrantでVMを停止する
vagrant halt

ホストとのファイル共有
synced_folderを使用してローカルマシンとVMの間で特定のディレクトリを共有する。
ソースコードやDockerfileを変更して、そのままVM上でDockerイメージをビルドするために用いる。

      config.vm.synced_folder(
        "../",
        "/home/core/#{File.basename(File.dirname(Dir.pwd))}",
        id: "vmid",
        :nfs => true,
        :mount_options => ['nolock,vers=3,udp'],
      )

Dockerfileを書く際の基本方針
イメージを小さくすること。コンテナの起動、イメージのビルド、push、pullにかかる時間を短くすることができる。

ビルドのレイヤー数
Dockerfileには、関連するコマンドを連結(&&とバックスラッシュを利用すると、コマンドを連結できる)してビルドのステップ数を少なくする。

Vagrantfileとansibleでdockerをインストールする方法はこちら


2015年6月8日月曜日

dockerを使用したシステム設計の原則

dockerを用いてシステム設計する際に注意すべきことがある。1バーチャルマシン(つまりサーバ1台)として捉えるとうまく設計できない。

dockerを用いる場合、「再現性」、「構築フロー」、「デベロッパーがサーバ管理できる」といったメリットがある。

しかし、コンテナやホストマシンの管理、docker自体の頻繁なアップデートによる学習コストなどがデメリットである。

システム設計で大切なこと
dockerコンテナの運用方法自体が簡潔になる方向を模索する。

1コンテナは1デーモンと考える
コンテナはサーバ上で起動する1デーモンと考えること。

コンテナに永続化するデータが存在しないこと
ログを含む永続化対象のデータはすべて、コンテナ外へ保存すること。

設定はすべてアプリケーションコード外で管理すること
設定がアプリケーションコードに依存していると、アプリケーションの変更によって接続先が変わってします可能性があるため。

ホストマシンには出来る限り直接パッケージをインストールしないこと
ミドルウェアを含めた環境全体をコンテナとして動かすこと。
ホストマシンの管理を不要にし、可能な限りコンテナのアップデートコストのみにする。

buildには基本Dockerfileを使用すること
シンプルで簡単だからである。

dockerを扱う際のコマンド

dockerで使用する基礎的なコマンド。環境用のツールにはboot2dockerを使用する。

仮想マシンの初期化
boot2docker init

1回だけ実行すれば良い。2回目は以下の様なメッセージが表示される。
Virtual machine boot2docker-vm already exists

仮想マシンの起動
boot2docker start

シェルの初期化
$(boot2docker shellinit)

dockerのバージョン確認
docker -v

dockerイメージ一覧の表示
docker imges

dockerイメージの起動
docker run -p <local ポート番号>:<コンテナ無いのポート番号> <Dockerイメージ名> <コンテナで実行するコマンド> <引数>

ローカルにイメージが無い場合はpullしてからrunが実行される
コンテナは使い捨てである。ファイルに変更が無い場合、buildしてから使用する。


dockerイメージの作成(コンテナからイメージを作成する)
buildコマンドを使う。buildコマンドは「Dockerfile」ファイルと適用してDockerイメージを作成するコマンドである。(commitはミスの原因になるので使用しない)
docker build -t=<イメージ名:{タグ名}> <Dockerfileを含むコンテナのディレクトリ>

dockerイメージをDocker Hubなどのレジストリにpushする
docker push <イメージ名>


Docker Hubへのログイン
docker login
ユーザ名、パスワード、メールアドレスを入力する

Docker Hub は Dockerレジストリの1つである。Docker社が公式で提供するレジストリであり、イメージの共有をすることができる。


Dockerfileについて
Dockerfileはmakeに対するMakefileのようなもので、Dockerコンテナの構成ファイルを記述するテキストファイルである。以下が参考になる。

2015年6月6日土曜日

Python Vim 開発設定

Vimを使ってPython開発を快適に行うための設定

開発する上で目指したいのは、以下の様なことではないだろうか。

  • コードの記述量を減らす
  • コードの書式チェックを自動で行う
  • テキストエディタ同様の表示書式
  • 記述中にインタプリタを実行する

設定方法

コードの記述量を減らす

Python補完のVimプラグインを使用するため、jedi-vimを導入する。
以下のページがシンプルでわかりやすい。jedi-vimのインストール部分だけ実行すれば良い。
Vim+Python環境設定メモ


コードの書式チェックを自動で行う
コードの保存時などに、コードをチェックする。

sudo pip install flake8 pyflakes pep8 pylint


テキストエディタ同様の表示書式
~/.vimrcに以下を追加する。

"#####表示設定#####
set number "行番号を表示する
set title "編集中のファイル名を表示
set showmatch "括弧入力時の対応する括弧を表示
syntax on "コードの色分け
set tabstop=4 "インデントをスペース4つ分に設定
set smartindent "オートインデント

"#####検索設定#####
set ignorecase "大文字/小文字の区別なく検索する
set smartcase "検索文字列に大文字が含まれている場合は区別して検索する
set wrapscan "検索時に最後まで行ったら最初に戻る


記述中にインタプリタを実行する
~/.vimrcに以下を追加する。rubyとperlの実行も追加しておくと便利。

autocmd BufNewFile,BufRead *.rb nnoremap <C-e> :!ruby %
autocmd BufNewFile,BufRead *.py nnoremap <C-e> :!python %
autocmd BufNewFile,BufRead *.pl nnoremap <C-e> :!perl %

これでだいぶ作業しやすくなるはず。

2015年6月2日火曜日

Convolutional Neural Network の 畳込み層を出力してみた

オリジナルのCNN実装を使って、Le-Net5でMNISTデータを学習した後の畳み込み層を出力してみた。

conv1





conv2



conv3


2015年6月1日月曜日

lombok (Java)

Lombokはボイラープレートコード(getter/setterなどの決まりきっているが記述が必要なコード)を簡潔に記述するためのライブラリである。

@Data
getter/setterをコンパイル時に記述するアノテーション

package jp.masazdream.ds;
import lombok.Data;
/**
* Lombokのサンプルクラス
*
* @author masai
*
*/
@Data
public class Lombok {
private String mA;
private String mB;
Lombok(String a, String b){
mA = a;
mB = b;
}
}
view raw Lombok.java hosted with ❤ by GitHub
ただし、staticなメンバ変数については@Dataや@Getterを指定してもgetterが宣言されないので注意すること。

@Builder
を利用すると、コンストラクタとgetterが宣言される。

Gradleでビルドする場合は、依存関係に以下を追加する。

dependencies {
...
provided 'org.projectlombok:lombok:1.12.2'
}

2015年5月31日日曜日

htop (cmd) OSX

htopコマンドはLinuxのプロセスおよびメモリ使用量のビューアである。macではtopコマンドのオプションがLinuxと異なるため、同様の情報をみたい場合に便利である。
導入も非常に簡単である。

# brew install htop [/usr/local/Cellar/tbb/4.3-20140724/include/tbb]
==> Downloading https://github.com/max-horvath/htop-osx/archive/0.8.2.2.tar.gz
######################################################################## 100.0%
==> ./autogen.sh
==> ./configure --prefix=/usr/local/Cellar/htop-osx/0.8.2.2
==> make install DEFAULT_INCLUDES='-iquote .'
==> Caveats
htop-osx requires root privileges to correctly display all running processes.
You can either run the program via `sudo` or set the setuid bit:
sudo chown root:wheel /usr/local/Cellar/htop-osx/0.8.2.2/bin/htop
sudo chmod u+s /usr/local/Cellar/htop-osx/0.8.2.2/bin/htop
You should be certain that you trust any software you grant root privileges.
==> Summary
🍺 /usr/local/Cellar/htop-osx/0.8.2.2: 11 files, 184K, built in 19 seconds
view raw htop_install.sh hosted with ❤ by GitHub
以下が実際に表示した様子である。Linuxのtopコマンドのオプション1よりも視認性が良い。


TBB OSX (C++)

OSXでTBBを利用したいときの最もお手軽な(だと思う)方法

# brew install tbb [/Library/Frameworks]
==> Downloading https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20140724oss_src.tgz
######################################################################## 100.0%
==> make tbb_build_prefix=BUILDPREFIX compiler=clang arch=intel64
/usr/local/Cellar/tbb/4.3-20140724: 104 files, 1.9M, built in 4.2 minutes

1 minute intro: Intel TBB parallel_for (C++)

TBB(Threading Building Blocks)は C++で並列化プログラムを簡単に記述するためのライブラリである。Intelが基本的な関数の使い方のビデオを公開している。以下はparallel_forのもの。機械学習のコードで大変よく登場する。


コードは以下である。
Threading Building Blocks
//
// tbb_intro.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/31.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <cmath>
#include <tbb/tbb.h>
double *output;
double *input;
int main(){
const int size = 20000000;
output = new double[size];
input = new double[size];
for(int i = 0; i < size; ++i){
input[i] = i;
}
tbb::parallel_for(0, size, 1, [=](int i){
output[i] = sqrt(sin(input[i]*sin(input[i]) + cos(input[i])*cos(input[i])));
}
);
return 0;
}

2015年5月30日土曜日

stringstream(C++)

stringstreamは、C++のストリームをstringに結びつける機能をもつクラスである。

stringstreamはstringに対して、<< や >>  演算子を提供する。
ostringstreamは出力のみ提供する。逆にistringstreamは入力のみを提供する。

//
// stringstream.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/30.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <string>
#include <sstream>
int main(int argc, char* argv[]){
// stringstream
std::stringstream ss;
ss << "a";
ss << " ";
ss << 'b'; // 1文字であればcharを使うこと。strlenの最適化分のコンパイルが効率化できる。
std::cout << ss.str() << std::endl;
// ostringstream 書き出し
std::ostringstream oss;
// 様々な型をstringに流せる
oss << "test" << " " << 100;
std::cout << oss.str() << std::endl;
// istringstream 読み込み
std::istringstream iss(oss.str());
int n;
std::string s1;
std::string s2;
// 入力の順番で取得
iss >> s1 >> s2 >> n;
std::cout << s1 << std::endl;
std::cout << s2 << std::endl;
std::cout << n << std::endl;
}

2015年5月29日金曜日

numeric_limits(C++)

numeric_limitsは数値型の取りうる値の範囲についての情報を得るときに利用する。

以下のように使用する。

//
// limits.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/19.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <limits>
typedef long HashValueLong;
typedef unsigned long HashValueULong;
int main() {
// マクロ定義による取得
std::cout << "int max: " << INT_MAX << std::endl;
std::cout << "int min: " << INT_MIN << std::endl;
// クラステンプレートによる取得
std::cout << "int max: " << std::numeric_limits<int>::max() << std::endl; //2147483647
std::cout << "long max: " << std::numeric_limits<long>::max() << std::endl; //2147483647
std::cout << "long min: " << std::numeric_limits<long>::min() << std::endl;
std::cout << "long lowest: " << std::numeric_limits<long>::lowest() << std::endl;
std::cout << "double max: " << std::numeric_limits<double>::max() << std::endl;
std::cout << "double min: " << std::numeric_limits<double>::min() << std::endl;
std::cout << "double lowest: " << std::numeric_limits<double>::lowest() << std::endl;
// 型に依存しない書き方
std::cout << "HashValue(long): " << std::numeric_limits<HashValueLong>::max() << std::endl;
std::cout << "HashValue(unsigned long): " << std::numeric_limits<HashValueULong>::max() << std::endl;
return 0;
}
最小値を得たい場合に注意が必要である。
min()は必ずしも-max()を返すわけではなく、整数型と浮動小数点型とで意味が異なる。
C++11からはlowest()を利用すると良い。

minmax_element (C++)

minmax_elementはC++11から追加された機能であり、最小値/最大値を一括して求めるアルゴリズムの実装である。Boostのminmaxとはことなるので注意。

minmax_elementはvectorなどのコンテナを対象として最小値/最大値を求める。
戻り値の型はstd::pair型である。要素はポインタである。

minmaxもstd::pair型であるが、要素はminmaxのテンプレートのclass型である。

//
// minmax.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/29.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <vector>
int main(int argc, char* argv[]){
double x = 10.34, y = 3.5, z = 4.3;
// コンテナ
std::vector<double> v = {x, y, z};
auto minmax = std::minmax_element(v.begin(), v.end());
std::cout << "min: " << *minmax.first << std::endl;
std::cout << "max: " << *minmax.second << std::endl;
// 初期化子
auto t1 = std::minmax(1,999);
std::cout << "min: " << t1.first << std::endl;
std::cout << "max: " << t1.second << std::endl;
}
view raw minmax.cpp hosted with ❤ by GitHub

2015年5月28日木曜日

swap(C++)

swapは2つのオブジェクトの値を交換するときに使われるが、オブジェクトによって実装が異なるので動作に注意すること。

//
// swap.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/28.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char* argv[]){
// プリミティブ型
int a, b;
a = 10;
b = 20;
std::swap(a, b);
std::cout << a << std::endl;
std::cout << b << std::endl;
// array
int array_a1[4] = {10, 20, 30, 40}, array_b1[4] = {1,2,3,4};
std::swap(array_a1, array_b1);
for(auto i : array_a1){
std::cout << i << std::endl;
}
for(auto i : array_b1){
std::cout << i << std:: endl;
}
// array2
int array_a2[4] = {10, 20, 30, 40}, array_b2[4];
std::swap(array_a2, array_b2);
for(auto i : array_a2){
std::cout << i << std::endl; //初期化されていない
}
for(auto i : array_b2){
std::cout << i << std:: endl;
}
// array3
int array_a3[4] = {10, 20, 30, 40}, array_b3[5] = {1, 2, 3, 4, 5};
// std::swap(array_a3, array_b3); //NG 要素数の異なるarrayをswapできない
// vector
std::vector<std::string> v1;
std::vector<std::string> v2;
v1.emplace_back("abc");
v2.emplace_back("efg");
v2.emplace_back("hij");
// vectorは要素数がことなってもまるごと入れ替わる
v1.swap(v2);
for(auto i : v1){
std::cout << i << std::endl;
}
for(auto i : v2){
std::cout << i << std::endl;
}
// vector2
std::vector<std::string> v11;
std::vector<int> v22;
v11.emplace_back("abc");
v22.emplace_back(1);
v22.emplace_back(2);
// vectorは要素数がことなってもまるごと入れ替わる
// v11.swap(v22); //NG vectorは型が異なるとswapできない
}
view raw swap.cpp hosted with ❤ by GitHub

プリミティブ型の最大値を超えた場合のstatic_castの動作(C++)

プリミティブ型の最大値を超えている場合、static_cast はどのように動作するか。
//
// static_cast.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/28.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
using namespace std;
int main(int argc, char* argv[]){
cout << static_cast<unsigned short>(-1) << endl;
cout << static_cast<unsigned short>(0) << endl;
cout << static_cast<unsigned short>(1) << endl;
cout << static_cast<unsigned short>(65535) << endl;
cout << static_cast<unsigned short>(65536) << endl;
cout << static_cast<unsigned short>(65537) << endl;
}
view raw short_cast.cpp hosted with ❤ by GitHub
出力は以下のようになる。
65535
0
1
65535
0
1

2015年5月25日月曜日

typeid (C++)

typeid演算子を利用して、型情報を取得できる。typeid演算子は、type_infoオブジェクト(type_infoクラスへの参照)を得る。

//
// typeinfo.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/25.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <typeinfo>
#include <string>
#include <cxxabi.h>
using namespace std;
template<typename T>
void func(T t){
cout << abi::__cxa_demangle(typeid(t).name(), 0, 0, 0) << endl;
}
int main(int argc, char* argv[]){
func<int>(12);
func<double>(12.0);
func<string>("abc");
}
view raw typeid.cpp hosted with ❤ by GitHub

emplace_back(C++11)

emplace_backはvectorの要素の追加を効率的に行えるようにC++11から追加された。

暗黙的型変換を利用して emplace_back により値をコンテナに格納するとコピーコンストラクタが呼ばれない。その分効率的に処理することが可能だ。ただし、暗黙的型変換を利用せず、自ら引数のオブジェクトのコンストラクタを呼び出すとコピーコンストラクタが呼ばれるので注意。
//
// emplacement.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/25.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <vector>
using namespace std;
class A{
public:
A(int i){
cout << "constructor" << endl;
}
A(const A& a){
cout << "copy constructor" << endl;
}
~A(){
cout << "descructor" << endl;
}
};
int main(int argc, char* argv[]){
cout << "push_back ---" << endl;
vector<A> vec;
vec.push_back(0);
vec.clear();
cout << "emplace_back ---" <<endl;
vector<A> vec_e;
vec_e.emplace_back(0);
vec_e.clear();
cout << "emplace_back 非暗黙的変換 ---" <<endl;
vector<A> vec_en;
vec_en.emplace_back(A(0));
vec_en.clear();
cout << "emplace_back 事前確保 ---" <<endl;
// 事前確保
vector<A> vec_r;
vec_r.reserve(3);
vec_r.emplace_back(1);
vec_r.emplace_back(2);
vec_r.emplace_back(3);
vec_r.clear();
// vectorのvector
vector<vector<float>> vec_vec;
// vectorに3つの要素を初期値5でいれる
vec_vec.emplace_back(3, 5);
// vec_vecには1つのベクトルが入る
cout << vec_vec.size() << endl;
// vec_vec.backはvec_vec[0]と同じ
cout << vec_vec.back().size() << endl;
// ベクターには3つの要素
cout << vec_vec[0].size() << endl;
// 5で初期化
cout << vec_vec[0][0] << endl;
}
view raw emplacement.cpp hosted with ❤ by GitHub

CharTraits(C++)

CharTraitsはよくわかってない。標準出力などのbasic_streamを引数に受け取って流し込むようにtemplateに指定する使用方法を記載する。
//
// chartraits.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/25.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
using namespace std;
struct result{
result(int num_success, int num_total){
num_success_ = num_success;
num_total_ = num_total;
}
double accuracy() const{
return (num_success_ * 100.0 / num_total_);
}
template<typename Char, typename CharTraits>
void print_summary(std::basic_ostream<Char, CharTraits>& os) const{
os << "accuracy: " << accuracy() << "% (" << num_success_ << "/" << num_total_ << ")" <<endl;
}
int num_success_;
int num_total_;
};
int main(int argc, char* argv[]){
result r(93, 100);
r.print_summary(std::cout);
}
view raw chartraits.cpp hosted with ❤ by GitHub

set(C++)

C++のsetは要素の数が有限の集合である。また、setの中の要素はソートされて保持されており、順序づけされたオブジェクトの集合とかんがえることができる。つまり、数学の集合とは意味が異なる。

setの良い点は、findによって目的のオブジェクトがsetに含まれているかどうかすぐに判別できる点であり、ソートされて保持された性質を利用して、ソート用途としてsetを使ってはならない。vectorをalgorithm sortでソートするよりもオーバーヘッドが高いからである。オーバーヘッドは、setが指定した要素をfindですぐに見つけられるように要素をinsertする際にインデックスすることからも想像に難くない。

また、ソートされることからわかるように、setの要素となる型にはオペレータ < が定義されている必要がある。これはmapのキーと同じである。

//
// set.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/25.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <set>
using namespace std;
int main(int argc, char* argv[]){
set<int> s;
// insert
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(4);
s.insert(5);
// setの要素数
cout << "set cnt is " << s.size() << endl;
// 保持している要素は、iteratorを受け取ることができる
set<int>::iterator i = s.find(3);
if(i == s.end()){
cout << "can not find." << endl;
}else{
cout << "find " << *i << endl;
}
// 保持していない要素は、iterator end()を受け取ることができる
set<int>:: iterator i_c = s.find(10);
if(i_c == s.end()){
cout << "can not find 10" << endl;
}else{
cout << *i << endl;
}
// 要素の削除
s.erase(3);
set<int>:: iterator i_e = s.find(3);
if(i_e == s.end()){
cout << "can not find 3" << endl;
}else{
cout << *i << endl;
}
// setの要素数
cout << "set cnt is " << s.size() << endl;
}
view raw set.cpp hosted with ❤ by GitHub

マニピュレータ iomanip (C++)

C++の入出力で書式を設定するのに マニピュレータ を使うと便利である。iosヘッダまたはiomanipヘッダに定義された機能を利用できる。

//
// iomanip.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/25.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <iomanip>
using namespace std;
int main(int argc, char* argv[]){
// 8進数で表示
cout << oct << 10 << endl;
// 1度設定した値は引き継がれることに注意
cout << 10 << endl;
// 10進数表示に変更
cout << dec << 10 << endl;
// + をつける
cout << showpos << 10 << endl;
// -は通常どおりやればつく
cout << -10 << endl;
// フィールド幅を10桁に設定(上記では、マニピュレータに()がついていない。引数をとらない場合は()をつけない。なぜなら、オーバーロードされたオペレータ<<に渡されるのがマニピュレータのアドレスであるため。)
cout << setw(10) << 100 << endl;
// 16進数
cout << hex << 100 << endl;
// 基数をつける
cout << showbase << 100 << endl;
}
view raw iomanip.cpp hosted with ❤ by GitHub

stdexcept(C++)

stdexceptは標準的な例外クラスを提供する。

これらのクラス群に反映されているエラーモデルの種類
  • runtime error 実行時エラー
  • logic error 論理エラー
実行時エラーは、プログラムの制御の及ばない事象を起因とする。
論理エラーは、プログラムの内部的論理の誤りに起因する。

以下の様なクラスが定義されている。
  • exception
    • runtime error
      • range_error
      • overflow_error
      • underflow_error
    • logic error
      • domain_error
      • invalide_argument
      • length_error
      • out_of_range
これらのクラスは同じpublic関数が定義されており、ジェネリックな呼び出しが可能である。
explicit T(const string& what_arg){} 指定したメッセージをもつ例外オブジェクトの生成 
explicit T(const char* what_arg){} C++11 指定したメッセージをもつ例外オブジェクトの生成
virtual const char* what() const noexcept; メッセージの取得

//
// stdexcept.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/25.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <stdexcept>
using namespace std;
class processing{
public:
void function(){
throw std::logic_error("an logic error.");
}
};
int main(int argc, char* argv[]){
processing p;
try{
p.function();
}catch(const std::logic_error& e){
cout << e.what() <<endl;
}
}
view raw stdexcept.cpp hosted with ❤ by GitHub

2015年5月23日土曜日

enum(C++)

C++における列挙型enumは数種類のint型の値しかとることができない型を宣言する。
関数の引数や戻り値の値の意図を記述できる。

  • 値は明示しないと0から順に付けられる
  • サイズは環境依存であるため、通信プロトコルでの利用などでは注意すること

//
// enum.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/23.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
using namespace std;
enum Gender{
MALE,
FEMALE
};
enum FunctionType{
NORMAL = 1,
ACTIVATION = 2,
LOSS = 3
};
enum Type{
YES = 1,
NO = -1
};
class A{
public:
Type function(){
return NO;
}
};
int main(int argc, char* argv[]){
A a;
cout << a.function() << endl;
}
view raw enum.cpp hosted with ❤ by GitHub

explicit(C++)

explicitは引数を1つだけとる変換コンストラクタが暗黙的に呼ばれることを防ぐ。

よくあるケース
  • explicitを記述しない変換コンストラクタをもつクラスは、= で初期化(コンストラクタ呼び出し)を記述できる
  • クラスの参照を引数に受け取る場合、意図せずして暗黙的に変換コンストラクタが呼び出されることがある
//
// explicit.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/23.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
using namespace std;
class X {
public:
X(int x){}
};
class Y{
public:
Y(const X& x){}
};
class Str{
public:
Str(const char* str){str_ = str;}
~Str(){}
const char* toChar() const{
return str_;
};
private:
const char* str_;
};
class StrExplicit{
public:
explicit StrExplicit(const char* str){str_ = str;}
~StrExplicit(){}
const char* toChar() const{
return str_;
}
private:
const char* str_;
};
int main(int argc, char* argv[]){
// Yにintを指定しても、Xの変換コンストラクタが暗黙的に呼ばれ、X(3) を代入したことと同じになる
Y(3);
// 変換コンストラクタが暗黙的に呼ばれる(ただし、operator=とは異なる)
Str s = "abc";
cout << s.toChar() << endl;
//StrExplicit se = "efg"; // NG(暗黙的にコンストラクタを呼べないため、コンパイルエラー)
//cout << se.toChar() << endl;
StrExplicit se("efg");
cout << se.toChar() << endl;
}
view raw explicit.cpp hosted with ❤ by GitHub

2015年5月22日金曜日

関数宣言(C++)

関数の引数には型のみを指定することも可能
//
// function_argument.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/22.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
using namespace std;
class A {
public:
int function(int a, int /*index*/){
return a;
}
};
int main(int argc, char* argv[]){
A* obj = new A();
cout << obj->function(10, 4) << endl;
}

overrideキーワード(C++11)

overrideキーワードは、意図せずして正しいオーバーライドになっていない状態を防ぐものである。

派生クラスの関数が、基底クラスの仮想関数をオーバーライドしていることを示す。

//
// override_keyword.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/22.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
using namespace std;
struct A{
public:
virtual void function() = 0;
};
struct B : A{
public:
void function() override {
cout << "override" << endl;
}
};
int main(int argc, char* argv[]){
B obj;
obj.function();
}

transform(C++)

transformは変換を行うライブラリである。transformの処理内容は、関数オブジェクトやラムダ式を使って記述する。

//
// transform.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/22.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <vector>
using namespace std;
// 関数オブジェクトで記述するため構造体
struct FunctionObject{
int operator()(int value){
return value * 2;
}
};
int main(int argc, char* argv[]){
vector<int> v(3);
fill(v.begin(), v.end(), 1);
for(int i : v){
cout << i << endl;
}
// 関数オブジェクトで変換を記述
transform(v.begin(), v.end(), v.begin(), FunctionObject());
for(int i : v){
cout << i << endl;
}
// ラムダ式で変換を記述 []の中は処理する値を参照で受け取るかどうかを記述する。空の場合は値渡し、&で参照渡しとなる。今回はプリミティブ型なので空でも処理はうまくいく。
transform(v.begin(), v.end(), v.begin(), [&](int x) { return x * 10; });
for(int i : v){
cout << i << endl;
}
// 別のベクトルに入れる場合
vector<int> v2(v.size());
transform(v.begin(), v.end(), v2.begin(), [&](int x) { return x * 100; });
for(int i : v2){
cout << i << endl;
}
}
view raw transform.cpp hosted with ❤ by GitHub

関数オブジェクト(C++)

()は関数呼び出しの演算子である。クラス定義中に、()をoperatorとしてオーバーロードすると、オブジェクトを関数呼び出しの形で呼び出せる。これが、関数オブジェクトである。
//
// function_object.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/22.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
using namespace std;
// 10倍にして返す関数オブジェクト(このように定義すると、ヘッダーに処理内容も記述が可能)
class FunctionObject{
public:
int operator()(int value){
return value * 10;
}
};
struct FunctionStructObject{
int operator()(int value){
return value * 20;
}
};
int main(int argc, char* argv[]){
FunctionObject obj;
cout << obj(5) << endl;
FunctionStructObject structObj;
cout << structObj(5) << endl;
}

vector_array_for(C++)

配列、vectorforについて整理

配列中の要素を変更するには、参照を取得すること。

//
// vector_for.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/22.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[]){
vector<int> v(5);
fill(v.begin(), v.end(), 10);
// intのベクターをautoで取り出す
cout << "int auto" << endl;
for(auto a : v){
cout << a << endl;
}
// intのベクターをauto&で取り出しても同じ結果
cout << "int auto&" << endl;
for(auto& a : v){
cout << a << endl;
}
vector<string> v_str(5);
fill(v_str.begin(), v_str.end(), "abc");
// stringのベクターをautoで取り出しても読み出し可能だが、実体は変更できない
cout << "string auto" << endl;
for(auto b : v_str){
b = "change";
cout << b << endl;
}
cout << v_str[0] << endl;
// stringのベクターをauto&で取りだすと、配列内のstringの実体を変更できる
cout << "string auto&" << endl;
for(auto& b : v_str){
b = "change;";
cout << b << endl;
}
cout << v_str[0] << endl;
// vectorの配列ではどうか
vector<string> v_str1(2);
fill(v_str1.begin(), v_str1.end(), "abc1");
vector<string> v_str2(2);
fill(v_str2.begin(), v_str2.end(), "abc2");
vector<string> v_str3(2);
fill(v_str3.begin(), v_str3.end(), "abc3");
vector<string> v_array[3] = {v_str1, v_str2, v_str3};
// 配列からベクターをautoで取り出すと、&を付けないと実体が異なる
for(auto vs : v_array){
vs.resize(5);
cout << vs.size() << endl;
}
cout << v_array[0].size() << endl;
// 配列からベクターをauto&で取り出すと、配列内のvectorの実体を変更できる
for(auto& vs : v_array){
vs.resize(7);
cout << vs.size() << endl;
}
cout << v_array[0].size() << endl;
}

vector resize reserve(C++)

vectorresizereserveの動作についてまとめる。

//
// reserver_resize.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/22.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[]){
// デフォルトコンストラクタ
vector<int> vec_def;
cout << "vec_def size: " << vec_def.size() << ", capacity: " << vec_def.capacity() << endl;
// コンストラクタでサイズ指定
vector<int> vec_constructor(256);
cout << "vec_constructor size: " << vec_constructor.size() << ", capacity: " << vec_constructor.capacity() << endl;
// デフォルトコンストラクタで作成したvectorをreserveで変更
vec_def.reserve(128);
cout << "vec_def reserve size: " << vec_def.size() << ", capacity: " << vec_def.capacity() << endl;
// リサイズで変更
vec_def.resize(64);
cout << "vec_def resize size: " << vec_def.size() << ", capacity: " << vec_def.capacity() << endl;
// リサイズすると、size()も変更後と同じになる。出力すると、すべて0に初期化されていた。
for(auto& a : vec_def){
cout << a << " " ;
}
cout << endl;
// リサイズでは、初期化する値を決定することができる
vec_def.resize(128, 10);
cout << "vec_def resize size: " << vec_def.size() << ", capacity: " << vec_def.capacity() << endl;
for(auto& a : vec_def){
cout << a << " " ;
}
cout << endl;
}

fill(C++)

std::fillは配列やコンテナに対してレンジ指定してすべて同じ値を代入する関数である。

//
// fill.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/22.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> v(10);
fill(v.begin(), v.end(), 3);
for(auto i : v){
cout << i << endl;
}
}
view raw fill.cpp hosted with ❤ by GitHub

vector iterator(C++)

C++のvectorのイテレータを扱う関数はtemplateで型に依存しないようにしておこう。
//
// iterator.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/22.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <vector>
using namespace std;
template<typename Iter>
void func(Iter begin, Iter end){
// ++itでポインタを次へ進める
for (Iter it = begin; it != end; ++it){
// イテレータの要素へのアクセスはポインタの実体を指定
cout << *it << endl;
}
}
int main(){
// 配列の定義
vector<int> int_array;
// サンプルデータを入れる
int_array.push_back(2);
int_array.push_back(4);
int_array.push_back(6);
int_array.push_back(8);
// 要素の書き出し
func(int_array.begin(), int_array.end());
// 別の型の配列を定義
vector<double> double_array;
double_array.push_back(.3);
double_array.push_back(.4);
double_array.push_back(.5);
double_array.push_back(.6);
double_array.push_back(.7);
func(double_array.begin(), double_array.end());
}

nullptr(C++)

C++ではNULLは0でマクロ定義されており、プリミティブ型として扱われる。

nullptrはNULLをポインタ化したものであり、ポインタとして扱いたいときに利用する。

//
// nullptr.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/22.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
using namespace std;
void func(void* p){
cout << "void*" << endl;
}
void func(int a){
cout << "int" << endl;
}
void func(nullptr_t p){
cout << "nullptr_t" << endl;
}
int main(){
func(12);
func(nullptr);
}
view raw nullptr.cpp hosted with ❤ by GitHub

コンストラクタ初期化子(C++)

以下のように使用するコンストラクタのコロンは、後ろにメンバ変数や親クラスを初期化する処理を記述することができる。

コンストラクタの中に処理を記述する場合と異なるのは、変数の初期化を省略できることである。

1億回の繰り返し処理で比較した結果、初期化子(コロンを使用した初期化処理)のほうが高速であった(どのくらい高速化は環境によって異なる)。

ただし、プリミティブ型については初期化の必要がないため、初期化子と代入で効率の違いはでないが、記述方法の一貫性やconst対策、コードの可読性のために初期化子を使用するべきである。

 親クラスの初期化についても以下のサンプルに記述しておく。
//
// constructor.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/22.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <chrono>
#include <string>
class constructor_init{
public:
constructor_init() : m_int(0), m_double(.1), m_str("abc"){}
private:
int m_int;
double m_double;
std::string m_str;
};
class constructor_noninit{
public:
constructor_noninit(){
m_int = 0;
m_double = 0;
m_str = "abc";
}
private:
int m_int;
double m_double;
std::string m_str;
};
class parent {
public:
parent(int a){
m_int = a;
}
public:
int m_int;
};
class child : public parent{
public:
child() : parent(2){
}
};
void init(bool constinit){
const auto startTime = std::chrono::system_clock::now();
for(unsigned int i = 0; i < 100000000; ++i){
if(constinit){
constructor_init* c = new constructor_init();
}else{
constructor_noninit* c = new constructor_noninit();
}
}
const auto endTime = std::chrono::system_clock::now();
const auto duration = endTime - startTime;
const auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
std::cout << "duration: " << msec << std::endl;
}
int main(){
// 親クラスの初期化
child* obj = new child();
std:: cout << obj->m_int << std::endl;
// コンストラクタ初期を使用した場合と代入の速度比較
init(true);
init(false);
}
view raw constructor.cpp hosted with ❤ by GitHub

2015年5月21日木曜日

alignment(C++11)

アラインメントとは、オブジェクトのための領域をメモリ上に確保する際のアドレスの境界位置のこと。
intのsizeが4バイトの環境では、intのデータを4の倍数のアドレスに配置すると、より高速にアクセスできる場合がある。

alignofの返すアライメント要求は、その型のオブジェクトをアドレス上に配置するためのものである。alignofが4の場合、該当のオブジェクトは4の倍数のアドレスに配置する必要がある。

アラインメントを指定するには、alignasを使う。変数及びメンバ変数のアラインメント属性を指定する。alignas(型名) は alignas(alignof(型名)) と同じである。

複数のアラインメントを指定すると、最も大きなアラインメントが選択される。

//
// alignment.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/21.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
using namespace std;
// 構造体のすべてのメンバを4バイト単位で配置する例
struct S{
alignas(uint32_t) uint8_t a_;
alignas(uint32_t) uint16_t b_;
alignas(uint32_t) uint32_t c_;
};
int main(){
// int型のアライメント要求
cout << alignof(int) << endl;
cout << alignof(uint32_t) << endl;
}
view raw alignment.cpp hosted with ❤ by GitHub

size_t(C++)

size_t

長さ、大きさ、サイズ(メモリ量)を表現する型として用いるもので、sizeof演算子が返す符号なしの整数型(unsigned int)である。

//
// sizeof.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/21.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
using namespace std;
template<class ... T>
struct S{
static const size_t count = sizeof...(T);
};
int main(){
// int型で確保されるメモリサイズを出力
cout << sizeof 1 << endl;
int a = 2;
// sizeofに与えられた式は評価されないため、後に出力するaは2のまま
cout << sizeof ++a << endl;
cout << a << endl;
// 式でなく、型を与えても良い
cout << sizeof(int) << endl;
cout << sizeof(float) << endl;
cout << sizeof(double) << endl;
// 可変長引数の個数を取得する場合
S<int, char, double> t;
cout << t.count << endl;
}
view raw sizeof.cpp hosted with ❤ by GitHub

immintrin (C++)

immintrinはSIMD演算用の関数ヘッダーファイルである。

以下のようにすると、すべてのSIMD、AVX演算を利用することが可能である。
#include <immintrin.h>

SIMD -SIMDとは-

コンパイラ最適化入門 -明示的にベクトル化されたコードを記述する-

使いこなすの大変だなこれは。

Levenberg-Marquardt(レーベンバーグ・マーカート)

最適化(非線形最小化)手法の1つ。Deeplearning実装のために準備する。

非線形関数の最小値をみつける最適化を行うことが目的。
最も単純な方法は最急降下法であり、コスト関数を微分して小さくなる方向に進む。
最急降下法が大変遅いことを解決するのに、Gauss-Newton法(または単にニュートン法)を利用する。

Gauss-Newton法は、関数を2階微分して0になる箇所を探す。局所解に陥る危険はあるが高速に学習が進む。また、Gauss-Newton法が対象とする関数は2階微分を元の関数の1階微分の2乗で近似できる関数である。そのため、1階微分の2乗が0になる位置を探す。

上述の、Gauss-Newton法が局所解に陥る危険を減らしたものが、Levenberg-Marquardt法である。

コンピュータビジョン最先端ガイド3の岡谷先生によるバンドルアジャストメントの記述が丁寧である。

その他の最適化手法について、以下のスライドが詳しい。
- SGD、モーメンタム、etc・・・
http://www.slideshare.net/beam2d/deep-learningimplementation

unordered_map (C++11)

unordered_mapは連想配列(キーと値をセットで保持)を簡単に利用できるライブラリである。JavaではHashMapが使われる。

unordered_mapは名前のとおり、keyの順序に関係なくHashを使って格納する。
keyの順序によってソートしたい場合は、std::map を使えば良い。

mapへの操作は、unordered_map も std::map も基本的に同じである。

//
// unordered_map.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/20.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <unordered_map>
using namespace std;
int main(){
// keyとvalueの型を指定して初期化する
unordered_map<string, int> hash;
// key testの追加
hash["test"] = 10;
// key testのvalueを取得
cout << hash["test"] << endl;
// 存在しないkeyを指定しても、領域が確保される
cout << hash["test2"] << endl;
// at()では、存在するkey test が使える。
hash.at("test") = 20;
cout << hash.at("test") << endl;
// at()で、存在しないkey test2 を指定すると out_of_range例外が発生する
// hash.at("test2") = 30; NG
// keyとvalueをセットで追加したい場合、insertを使う
hash.insert(pair<string, int>("pair", 30));
cout << hash.at("pair") << endl;
// 状態を取得する
cout << hash.size() << endl;
cout << hash.empty() << endl;
// iterator
unordered_map<string, int>::iterator it = hash.begin();
while( it != hash.end() )
{
cout << (*it).first << ":" << (*it).second << endl;
++it;
}
return 0;
}
以下に他の機能も詳しく記載されている。

http://program.station.ez-net.jp/special/handbook/cpp/stl/map.asp

2015年5月20日水曜日

virtual function(C++)

virtual function(仮想関数)について

継承関係のあるクラスの関数をオーバーライドしたい場合にポリモーフィズム実現のために利用する 仮想関数 だが(実装を持たない場合、純粋仮想関数)、なぜ 仮想関数 を定義したクラスのデストラクタは virtualでなくてはならないのか。

 【復習】
仮想関数
//
// Stream.h
// CplusplusPractice
//
// Created by masai on 2015/05/20.
// Copyright (c) 2015年 masai. All rights reserved.
//
#ifndef __CplusplusPractice__Stream__
#define __CplusplusPractice__Stream__
class Stream{
public:
double Get() const;
bool Set();
protected: //派生クラスで使用可能
virtual void SetBase() = 0;
double m_n;
};
#endif /* defined(__CplusplusPractice__Stream__) */
view raw Stream.hpp hosted with ❤ by GitHub
//
// Stream.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/20.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include "Stream.hpp"
using namespace std;
double Stream::Get() const{
return m_n;
}
bool Stream::Set(){
cout << "Stream::Set" << endl;
SetBase();
return m_n >= 0;
}
// 必ず子供で実装するので実装が不要→純粋仮想関数
//void Stream::SetBase(){
// cout << "Stream::SetBase" << endl;
// m_n = -1;
//}
view raw Stream.cpp hosted with ❤ by GitHub
//
// ArrayStream.h
// CplusplusPractice
//
// Created by masai on 2015/05/20.
// Copyright (c) 2015年 masai. All rights reserved.
//
#ifndef __CplusplusPractice__ArrayStream__
#define __CplusplusPractice__ArrayStream__
#include "Stream.hpp"
class ArrayStream : public Stream{
public:
ArrayStream(const double* array); //コンストラクタ
protected:
virtual void SetBase();
private:
const double* m_array; //配列
int m_i; //現在のインデックス
};
#endif /* defined(__CplusplusPractice__ArrayStream__) */
view raw ArrayStream.hpp hosted with ❤ by GitHub
//
// ArrayStream.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/20.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include "ArrayStream.hpp"
using namespace std;
ArrayStream::ArrayStream(const double* array){
m_array = array;
m_i = 0;
}
void ArrayStream::SetBase(){
m_n = m_array[m_i];
++m_i;
}
view raw ArrayStream.cpp hosted with ❤ by GitHub
//
// InputStream.hpp
// CplusplusPractice
//
// Created by masai on 2015/05/20.
// Copyright (c) 2015年 masai. All rights reserved.
//
#ifndef CplusplusPractice_InputStream_hpp
#define CplusplusPractice_InputStream_hpp
#include "Stream.hpp"
class InputStream : public Stream{
protected:
virtual void SetBase();
};
#endif
view raw InputStream.hpp hosted with ❤ by GitHub
//
// InputStream.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/20.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include "InputStream.hpp"
using namespace std;
void InputStream::SetBase(){
cin >> m_n;
}
view raw InputStream.cpp hosted with ❤ by GitHub
//
// inheritance.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/20.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include "Stream.hpp"
#include "InputStream.hpp"
#include "ArrayStream.hpp"
using namespace std;
bool Average(Stream& stream){
int count;
double avr = 0;
for(count = 0; stream.Set(); ++count){
avr += stream.Get();
}
if(count == 0){
return false;
}
avr /= count;
cout << "average is " << avr << endl;
count = 0;
return true;
}
int main(){
// ArrayStream
static const double array1[] = {1, 2, 3, 4, 5, 6, -1};
static const double array2[] = {2, 4, 5, 6, 1, -1};
static const double* const array[] = {array1, array2};
// sizeは全体のメモリサイズ / 要素(最初の一つ目)のメモリサイズ
static const int size = sizeof array / sizeof *array;
for(int i = 0; i < size; ++i){
ArrayStream stream(array[i]);
if(! Average(stream)){
//break;
}
}
// InputStream
while(true){
InputStream stream;
if(! Average(stream)){
break;
}
}
}

仮想関数テーブル
virtual function table, vtable という隠しメンバ変数を使って実現される。
ある仮想関数を呼び出したとき、実装にはどの関数かを管理するテーブル 
仮想関数テーブルは実行時、コンストラクタで初期化されてデストラクタで破棄されるので、不要な場合はvirtualにしないほうが仮想関数テーブルの分だけメモリ使用量は節約できるし、効率もあがる。

仮想関数を定義したクラスのデストラクタ
仮想関数の利用シーンは、「子クラスのポインタ」を「親クラスのポインタ」にキャストして使って、仮想関数の実装だけ入れ替えるようにして利用(ポリモーフィズム)がほとんどのはずである。

このとき、親クラスのポインタ(実体は子クラス)に対して delete した際、親クラスのデストラクタがvirtualでない場合、子クラスのデストラクタが呼ばれず、メモリリークが発生する。

また、親クラスが暗黙的に作成するデストラクタはvirutalでは無いので、内容がなかったとしても以下のように明示的に宣言すること。
virtual ~ParentClazz() {}

座標系スケール変換関数(template)

座標系のスケール変換を行う関数をテンプレート使って記述する。
//
// rescale.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/20.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
template<typename T, typename U>
U rescale(T x, T src_min, T src_max, U dst_min, U dst_max) {
U value = static_cast<U>(((x - src_min) * (dst_max - dst_min)) / (src_max - src_min) + dst_min);
return std::min(dst_max, std::max(value, dst_min));
}
int main(int argc, const char * argv[]) {
int a = 10;
int b = 1;
int c = 100;
int d = 300;
int e = 500;
int result = rescale(a, b, c, d, e);
std::cout << result << std::endl;
}
view raw scale.cpp hosted with ❤ by GitHub


macro

引数つきのmacroについて

以下のように、macroに引数を定義することが可能。うけとった引数の処理は続けて()に記述できる。

//
// macro.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/20.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
#define CMACRO(x) (void)(x)
int main(int argc, const char * argv[]) {
std::cout << "con1.data = " << abi::__cxa_demangle(typeid(CMACRO(12)).name(), 0, 0, 0) << std::endl;
return 0;
}
view raw macro.cpp hosted with ❤ by GitHub

2015年5月19日火曜日

namespaceとoperator

namespaceとoperator
//
// namespace_operator.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/19.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
namespace namespace_op {
class Integer {
int value;
public:
int operator + (Integer obj) {
// biasの30が必ずプラスされるオペレータ+
return this->value + obj.value + 30;
}
Integer(int value) { this->value = value; }
};
}
using namespace namespace_op;
int main() {
Integer obj1(10) , obj2(100);
std::cout << obj1 + obj2 << std::endl;
return 0;
}

assert(C++)

assertでは、コードに開発者の意図を埋め込むことができる。

例えば、以下のコードはassertion failedとなる。

//
// assert.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/19.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <limits>
#include <cstdlib>
#include <assert.h>
typedef long long_type;
long base();
int main(int argc, const char * argv[]) {
long v = 32;
assert(v * base() > std::numeric_limits<long_type>::max());
return 0;
}
long base(){
return 200;
}
view raw assert.cpp hosted with ❤ by GitHub

static_cast (C++)

static_cast は 型変換(キャスト) の方法である

以下を満たす場合に使うことができる。

  • 暗黙的変換ができる
  • void * から他のポインターへの変換

汎用ポインタ(C++)

汎用ポインタ void* は、あらゆる型のポインタを代入できる。
void*型からのキャストはstatic_castが推奨される。

//
// genericpointer.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/19.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
// 構造体Container
struct Container{
void* data;
};
// 構造体Num
struct Num{
int n;
};
int main(int argc, const char * argv[]) {
const char* text = "text";
Container con1;
// Container構造体のdataにconst charのポインタを入れる(void*にキャストする)
con1.data = (void*)text;
std::cout << "con1.data = " << abi::__cxa_demangle(typeid(con1.data).name(), 0, 0, 0) << std::endl;
// Num構造体を動的確保
Num* numPointer = new Num();
numPointer->n = 42;
// Container構造体のdataにNum型のポインタを入れる
Container con2;
con2.data = (void*)numPointer;
std::cout << "con2.data = " << abi::__cxa_demangle(typeid(con1.data).name(), 0, 0, 0) << std::endl;
printf("%s\n", static_cast<const char*>(con1.data)); // 取り出す際にstatic_castする
printf("%d\n", ((Num*)con2.data)->n); //通常のキャストも可能
return 0;
}

cstdint(C++11)

cstdintには、bit数を指定できる整数が用意されている。


//
// cstdlib.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/19.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <cstdlib>
int main(int argc, const char * argv[]) {
std::cout << "HashValue(int8_t): " << std::numeric_limits<int8_t>::max() << std::endl;
std::cout << "HashValue(int16_t): " << std::numeric_limits<int16_t>::max() << std::endl;
std::cout << "HashValue(int32_t): " << std::numeric_limits<int32_t>::max() << std::endl;
std::cout << "HashValue(int64_t): " << std::numeric_limits<int64_t>::max() << std::endl;
std::cout << "HashValue(uint8_t): " << std::numeric_limits<uint8_t>::max() << std::endl;
std::cout << "HashValue(uint16_t): " << std::numeric_limits<uint16_t>::max() << std::endl;
std::cout << "HashValue(uint32_t): " << std::numeric_limits<uint32_t>::max() << std::endl;
std::cout << "HashValue(uint64_t): " << std::numeric_limits<uint64_t>::max() << std::endl;
return 0;
}
view raw cstdlib.cpp hosted with ❤ by GitHub

参考サイト
C++日本語リファレンス
http://cpprefjp.github.io/reference/cstdint.html

limits (C++)

プリミティブ型の最大値や最小値を取得する際、マクロ変数から取得することも可能だが、型安全な定数やメタ関数を利用して取得する。

 メタ関数は、こんな形式の関数

meta-function<type ...>::value()
typeに対してプリミティブ型でなく、typedefした型を入力すれば、型の変更に合わせてコードを書き換える必要なく値を取得できる。

//
// limits.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/19.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <limits>
typedef long HashValueLong;
typedef unsigned long HashValueULong;
int main(int argc, const char * argv[]) {
// マクロ定義による取得
std::cout << "int max: " << INT_MAX << std::endl;
std::cout << "int min: " << INT_MIN << std::endl;
// クラステンプレートによる取得
std::cout << "int max: " << std::numeric_limits<int>::max() << std::endl; //2147483647
std::cout << "long max: " << std::numeric_limits<long>::max() << std::endl; //2147483647
// 型に依存しない書き方
std::cout << "HashValue(long): " << std::numeric_limits<HashValueLong>::max() << std::endl;
std::cout << "HashValue(unsigned long): " << std::numeric_limits<HashValueULong>::max() << std::endl;
return 0;
}
view raw limits.cpp hosted with ❤ by GitHub

参考サイト
C++のプリミティブ型が取りうる最大値を取得する。
https://www.c3.club.kyutech.ac.jp/archives/1203

decltype と type traits (C++11)

decltype


decltype(expression) で式の型を得ることができる。

利用シーン


  • プロトタイプ宣言の型指定
  • 関数の戻り値の型を得る
typeinfoを併用して使い方を見てみる。typeinfoは実行時型情報(RTTI RunTimeTypeIdentification)を取得する機能である。

また、C++のコンパイラが名前マングルした(シンボルがuniqueな名前となるように)文字列を閲覧するのではなく、デマングルして宣言した型であることを確認する。

libstdc++cxxapi abi::__cxa_demangle()関数を利用する。

//
// decltype.cpp
// CplusplusPractice
//
// Created by masai on 2015/04/10.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <vector>
#include <typeinfo> //オブジェクトの型を知るためのライブラリ
#include <cxxabi.h>
using namespace std;
int methoz(int i);
double methoz(double d);
struct B {
virtual ~B(){}
};
struct D : B {
};
//戻り値型が引数aに合わせて変化させたい
//Bの子であるDの場合も存在する
auto test(const B& a) -> decltype(a) {
cout << "typeid(a)=" << abi::__cxa_demangle(typeid(a).name(), 0, 0, 0) << endl;
return a;
}
int main(int argc, const char * argv[]) {
// methoz(1)の戻り値の型をもつ変数nを定義する
decltype(methoz(1)) n = 3.4;
// int型として出力される
cout << n << endl;
decltype(methoz(2.3)) m = 3.4;
// double型として出力される
cout << m << endl;
// 型によって異なるvectorをつくる
auto a = 10;
vector<decltype(a)> vec;
// int型として挿入される
vec.push_back(3.3);
vec.push_back(10);
for(int i = 0; i < vec.size(); ++i){
cout << vec[i] << endl;
}
// 引数に合わせて戻り値が変化する関数
B b_instance;
D d_instance;
cout << abi::__cxa_demangle(typeid(test).name(), 0, 0, 0) << endl;
test(b_instance);
test(d_instance);
return 0;
}
view raw decltype.cpp hosted with ❤ by GitHub

type traits

型の特徴を調べたり、型の特徴を操作する関数
C++11では、type_traitsをインポートして enable_if が使える。
template <bool B, Class T = void>
struct enable_if;
enable_ifは、Bがtrueの時にtypedef T type;をもち、Bがfalseであればtypeをもたない。

SFINAE(Substitution Failure Is Not An Error)用途に使われる。
SFINAEは置き換え失敗はエラーにあらず、という意味で関数をオーバーライドする際、型変換がうまくいかなければオーバーライドの候補から自動ではずすことができる記述である。

ていうかいろんな書き方があってC++レベルが足りてない。以下の様な書き方があるってことを認識しておこう。

//
// typetraits.cpp
// CplusplusPractice
//
// Created by masai on 2015/05/19.
// Copyright (c) 2015年 masai. All rights reserved.
//
#include <iostream>
#include <type_traits>
// static_assertでコンパル時チェックを行うことが可能
// enable_ifにtrueのみ渡すと、デフォルトのvoidの型になる
static_assert(std::is_same<std::enable_if<true>::type, void>::value, "::type");
// enable_ifにtrueとintを渡すと、int型を返す
static_assert(std::is_same<std::enable_if<true, int>::type, int>::value, "::type");
// enable_ifにtrueとunsignedを渡すと、unsigned型を返す
static_assert(std::is_same<std::enable_if<true, unsigned>::type, unsigned>::value, "::type");
// enable_ifの第一引数にfalseを渡すと、type は無くなる
// **********************************************************************************
// is_integralはTがint型かどうかを確認する
// 以下の記述方法はTがintでない場合には、funcの呼び出しをエラーとする
template<typename T>
void func(T x, typename std::enable_if<std::is_integral<T>::value>::type* =0){
std::cout << "integral:" << x << std::endl;
}
// std::disable_if はないので、std::enable_if を使用する
template<typename T>
void func(T x, typename std::enable_if<!std::is_integral<T>::value>::type* =0){
std::cout << "other:" << x << std::endl;
}
// **********************************************************************************
// 以下は仮引数にenable_ifを記述しないタイプの書き方(enablerの利用)
// 条件無し。T は何型でもOKな関数f
template<class T>
void f(T const &){}
// T がint型と等しい時のみ有効な関数g
// is_integralはis_same<T, int>でも良い
extern void* enabler; // enabler
template<class T, typename std::enable_if<std::is_integral<T>::value>::type*& = enabler>
void g(T const &){
}
// **********************************************************************************
int main(int argc, const char * argv[]) {
// int型の変数a
int a = 0;
double d = 2.3;
// 構造体s
struct s{} b;
// func
func(a);
func(d);
f(a); // OK
f(b); // OK
g(a); // OK
//g(b); // gはint以外はエラーになる
return 0;
}
view raw typetraits.cpp hosted with ❤ by GitHub

2015年5月18日月曜日

3年計画の途中経過

以下の目標を実現できそうなところで仕事させてもらえそうなので、とても嬉しい。

  • 専門性(データマイニング・コンピュータビジョン)が活かせる、またはキャリア・スキルアップになる仕事をする。
  • 世界で仕事が出来る場所にいく

前のプロジェクトが死ぬレベルで忙しすぎてストップしてた英語を再開。
  • TOEIC 900点

DeepLearning 実装 準備編

DeepLearningの実装をスクラッチから行う。

まずは準備編として、3層多クラス分類のニューラルネットワークを実装した。

  • Androidアプリにも取り入れやすい
  • C++への書き換えも割と容易
ということでJavaで実装した。

動作確認用の可視化用クラスは、以下のものが使いやすかったので、多クラス分類用に修正して利用させていただいた。

NN法っていいよね-きしだのはてな

以下がコード。

ニューラルネットワーク


【課題】

  • 学習誤差を出力して、学習の進度を確認できるようにすること


2015年4月5日日曜日

リアクティブ(Rx)プログラミングについて自分なりに落とし込んだ

Rxを理解する切り口

サーバ、システム、インフラ

非同期アーキテクチャ、アクターモデル、メッセージ駆動

プログラミング

Push型、イベント駆動、データ構造のストリーム化(※Functional Reactive Programming)、データバインディング

※FRP
業務アプリ実装にFRPを使ってみた http://programplusgirl.tumblr.com/post/52698153869/frp
FRPについて理解するために参考にしたものhttp://qiita.com/busyoumono99/items/b355150fb69eae1584c2

リアクティブ

「反応」を意味する

リアクティブプログラミング

データの変更が流れるように自動的に伝搬していくプログラミング手法

時間変化する値や振る舞いを宣言的に行う(手順的な記述にならない)


プログラミングパラダイム

・オブジェクト指向→オブジェクトとメッセージの集まりを作成し、オブジェクト間のメッセージを定義して問題を解決する
・関数型→プログラムを関数評価の連続とみなす。副作用や状態から関数を切り離す。

宣言型

性質を満たす結果が得られれば、結果を得る方法は気にしない。

データを扱うということ

・データは入力される(最初に揃わない)
・レスポンスを待つ(データはすぐに揃わない)
・データの全体がmassiveなため、部分的にしか使えない

データを扱うということ(課題)

非同期である
→ 時間軸に一様に配置されないから順番を記述しないほうが良い

ざっくり言って

「いつ呼ばれるかに依存しない書き方」ではないか

Rxを実現するのに必要な概念

・ストリーム(データをもつ時間軸、データはユーザからの入力であったりする)
・ストリームをsubscribeするオブジェクト
・ストリーム上で起きるシグナル(シグナルに対する振る舞いを個別にプログラムする)
・Push型のデータバインディング(UIもしくはデータが変更されたときに、変更のイベントが自動で届く仕組み)

RxJava

分かった気になる初めてのRxJava
https://speakerdeck.com/kirimin/fen-katutaqi-ninaruhazimetefalserxjava

この辺りまでの概念を考えた上であれば、適切にEventBusを使えるのではと思う。

EventBus

Implementing an Event Bus With RxJava - RxBus
http://nerds.weddingpartyapp.com/tech/2014/12/24/implementing-an-event-bus-with-rxjava-rxbus/

EventBus library

EventBus
https://github.com/greenrobot/EventBus

JVM言語 Kotlin

JVM言語 Kotlinは、ScalaやGroovyのように、Javaバイトコードを生成することでJVM上で動作する言語である。

JavaScriptの生成も標準でサポートしており、さらにAndroidまでサポートする。Android開発が軽くなるととても嬉しいので注目している。

以下、設計思想と特徴を簡単にまとめた。

## Kotlinの設計ゴール
  • Java互換
  • Javaバイトコードへのコンパイル
  • JavaScriptコードへのコンパイル
  • Javaと同等以上のコンパイル速度
  • Javaより安全(NULL安全など)
  • Javaより簡潔
  • Scalaよりシンプルな方法
  • 表現力を実用レベルに維持

## 特徴

  • オブジェクト指向である
  • プリミティブ型がなく、すべてがオブジェクトである
  • プロパティ、トレイと、オブジェクト宣言
  • 関数は第一級オブジェクト

2015年1月11日日曜日

Swift言語の簡単な特徴メモ

Swift

ブロック
中括弧で表現{}

型の記述
スタイル:先頭は大文字
指定:変数の後ろにコロンと合わせて記述する。あくまで型推論の補助というポリシーだとわかる。

配列.array
宣言;大カッコ
空配列は型の指定が必要:Pythonよりは型安全だが、型の指定方法は[型]
配列の要素アクセス:大カッコとindex指定
配列の要素入れかえ:大カッコとindex指定
配列の要素挿入:insertとindex指定、+=で最後に要素もしくは配列を連結
配列の要素削除:removeAtIndex(atIndex:)とindex指定
配列の最後の要素を削除:removeLast(要素アクセスと併用でPythonのpop)
配列の要素全削除:removeAll
配列の要素選択:Pythonのrangeにあたる機能、[m...n]でmからn-1までの要素を取得などのrange演算子が使える
配列の代入は完全なlazyコピー
letはimmutable、varはmutable
lazyコピーの効率:2015/1/10時点ではまだissue状態だが、概ね効率的。ただし、大量の再代入は避けるべき。
functionへ参照を渡す処理の場合:inoutパラメータを使用する。再起処理を関数呼び出しで実行する場合には注意。関数の呼び出し側で参照を知らせる&を使用する。
Cocoaフレームワークへの変換:as

ハッシュテーブル.dictionary
宣言:大カッコにkeyとvalueを:で分離
ハッシュテーブルのvalueアクセス:大カッコとkey
ハッシュテーブルのレコードの削除:nil代入
順序:保証しない
Cocoaフレームワークへの変換:as

演算子
比較演算子:極めて一般的な記号
論理演算子:極めて一般的な記号(powを表現する記号は無し)
for-in:一般的、range演算子を使用可能
条件付きfor:小括弧を省略するスタイル、型推論可能
while:小括弧を省略するスタイル
if:小括弧を省略するスタイル
switch:小括弧を省略するスタイル、break不要

関数.function
宣言:func
引数:引数名: 型(代入時の型にも注意)
可変引数:型...で表現
戻り値の分離:-> 型
外部引数名:引数変数の前に名前を指定
外部引数名の関数呼び出し:呼び出し時は外部引数名の指定が必須
ネスト:可能。内側の関数は外側の関数ブロックがアクセス空間

クロージャ.closuer
存在:ある。functionはclosuerの特別な形式。
ボディの分離:-> 戻り値型 in
ボディの分離の省略:
よく使われるケース:コールバックするためのHandler

構造体.structure
宣言:struct
型:値型(value type)
プロパティの型推論:可能
プロパティへのアクセス:ドット
ARC(Auto Reference Count: 参照カウント型のメモリ管理機能)対象外

クラス.class
宣言;class
型:参照型(reference type)
継承:有り。宣言時に:(コロン)で区切ってsuper classを記述する
オーバーライド:継承後のメソッドではsuper必須。
型キャスト:有り
ARC(Auto Reference Count: 参照カウント型のメモリ管理機能)対象

メソッド.method
タイプ:インスタンス、static有り

包括型.Any
包括クラス型.AnyObject、Cocoaフレームワーク(主にNSArrayとNSMutableArray)への変換

ナル表現
nil

その他の表現
オプショナル型、ラップ状態の表現:?、nilチェックに使えるので楽

アンラップ表現:!

2015年1月7日水曜日

2015/01/11までの目標


  • ERFilter 論文
  • ERFilter Train
  • Playframework2.3 テンプレートエンジン、CSS、js周り
  • 英単語 + 1000
  • 英語漬け + 毎日
  • 英文法 2/6

playframework2.3 for Java (Macに移行)

play2.3 for javaの環境をMacに移行したのでメモ

今年はplay2.3 for javaでつくったWEBアプリをサイトに組み込む。

公式ドキュメント


参考にしたブログ


インストール

playは2.3からactivatorを利用する。
まずはactivatorをインストール。
以下からダウンロード。

適当な場所に展開する。
$ cd ~
$ mkdir app
$ cp activator-1.2.12-minimal.zip /User/masai/app
$ cd /User/masai/app
$ unzip activator-1.2.12-minimal.zip
$ ln -s activator-1.2.12-minimal activator
$ export PATH=$PATH:/User/masai/app/activator

activatorコマンドが使えるかどうか、以下で確認
$ activator -help

activatorを使って、playフレームワークのアプリケーションを作成する。
$ activator new my-first-app play-java
(scalaで開発する場合は、play-javaをplay-scalaにする)

ユーザのhomeディレクトリにアプリケーションディレクトリが出来る。
$ cd /User/masai/my-first-app
$ activator
ここで依存関係の解決にけっこう時間がかかるので途中でやめないように注意。

以下のコマンドでデフォルトのアプリケーションを起動することができる。
$ activator run

では、アプリケーションをEclipseに取り込んでみよう。

開発環境

Eclipse は Scala IDE for Eclipseを使う。

$ activator eclipse
[info] Loading project definition from /Users/masai/my-first-app/project
[info] Set current project to my-first-app (in build file:/Users/masai/my-first-app/)
[info] About to create Eclipse project files for your project(s).
[info] Successfully created Eclipse project files for project(s):
[info] my-first-app

処理が完了したら、Eclipseからmy-first-appのディレクトリをインポートする。

Eclipseでインポートしたら、Playアプリケーションのファイル構成を確認しよう。

routes

routesを使って、URLとコントローラをひもづける。
サンプル・アプリケーションには2つの設定が記述されている。
GET / controllers.Applications.index
これは、/に対してGETリクエストを受け取ると、controllers.Application.indexが呼び出されることを意味する。

controller

□Application.java
・index.renderがindex.scala.htmlの描画を担当する。
・index.renderの引数はmessageとして、index.scala.htmlへのパラメータになる。
・OkはHTTPステータスコード200を返す。

view

xxx.html.indexの形式で作成しておくと、コンパイル時にview.htmlパッケージ内に
xxxオブジェクトが作成される。この動作を前提として、コントローラのクラスを記述するため、
Application.javaではindex.renderを記述できる。

□index.scala.html
・変数の宣言
@(message: String)
これは、String型のmessageという変数を使用する、という宣言であり、とても安全である。

@main
main関数の呼び出し。main.scala.htmlの呼び出しである。
mainの引数はtitleとして、main.scala.htmlへのパラメータになる。

@mainアノテーション中の @play.weblcome もmain.scala.htmlに渡すパラメータである。
play20のwelcomeメソッドを呼び出す。
変数を渡すこともできるし、style = “Java” のように、styleという変数名で、Javaというvalueで
渡すことができる。

play20のwelcomeメソッドで様々なhtmlを生成して表示する。

□main.scala.html
本体のhtmlである。
・変数の宣言
@(title: String)(content: Html)
これは、String型のtitle、Html型のcontentという変数を使用する宣言。

@titleの部分で、index.scala.html のmainメソッドから渡された値が使用される。

@routes.Assets.at
routesは、conf.routesファイルで定義される。
routesには、/Assets.atが定義されている。/assetsから、GETでfileを取得するように記載している。

# Map static resources from the /public folder to the /assets URL path
GET     /assets/*file               controllers.Assets.at(path="/public", file)

assetsでアクセスするファイルは、パスpublicとしている。
実際、以下のディレクトリには、stylesheetsとimages、javascriptsディレクトリがある。
/Users/masai/my-first-app/public/main

@content
これは、index.scala.htmlのplay20.welcomeメソッドが生成したHtml型のオブジェクトが渡される。play29.welcomeはplayのライブラリに含まれる。

バージョン管理からはずすファイル

logs
project/project
project/target
target
tmp
dist

.cache

次回

テンプレートエンジン

2015年1月6日火曜日

2015年の目標


2015は目標をもって進んでいこう

今年の目標!!3年計画の1年目

  • 英語。6年間の復習、キクタン制覇、英文解釈読了。TOEIC受験。
    • 本腰いれて英語やる。世界で仕事したい。
  • 機械学習の入門資料準備。
    • 自分の復習も兼ねて、一緒にやれる人も増やしたいので。
  • ComputerVisionとObjectRecognitionで新たな研究の実装。
    • こちらは大学院。新しい研究を始めるので、とにかくアイデアと実装までいく。
  • 自分のホームページつくる
    • いままでブログだったけど、エンジニアとして発信するのに文字だけというのはどうかなと思ったのがきっかけ。
  • 自分のホームページに価値のあるコンテンツを置く(機械学習とそのコード、物体認識デモ)
    • ホームページつくるならコンテンツがほしい。価値が出せるのは恐らく機械学習とか画像処理とかで実装したところ。ライブラリみたいに出来れば一番いいけどまずは解説とかコードを公開するといったことを目標にする。

中期目標!!3年で実現すること

  • TOEIC 900点以上
  • 専門性が活かせる、またはキャリア・スキルアップになる仕事をする。
  • 世界で仕事が出来る場所にいく。
  • もう一本ComputerVision系の論文を発表する
  • ホームページをバイリンガル対応に(英語)