2017年5月27日土曜日

Jupiter Notebook + Keras(Tensor Flow)でチュートリアルをしてみる2

Jupiter Notebook + Keras(Tensor Flow)でチュートリアルをしてみる1の続き。

前回は環境構築して、簡単なチュートリアルを試してみた。今回はそのコードをこまかく見ていく。

まず必要なライブラリ群のインポート

from keras.models import Sequential
from keras.layers import Dense
import numpy
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot

SVG, model_to_dotはモデルの可視化に使う。その他はKerasのプロジェクトではだいたいimportしないといけないはず。

次にランダムな数を生成した時に再現性を持たせるためにseedを設定。

# fix random seed for reproducibility
numpy.random.seed(7)

学習するデータを読み込みする。このチュートリアルでは糖尿病患者のデータをcsvから読み込み。X, Yの変数に読み込む、Xには全行の0から7の8列の2次元配列のデータ、Yには全行、8列目の1次元配列のデータが入る。
どうやらXには予想のためのデータ、Yにはその結果、0(陰性)、0(陽性)が入っているよう。

# load pima indians dataset
dataset = numpy.loadtxt("../tutorial/1/pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]



次はモデルを定義していく。

KerasではSequentialというモデルを作り、そこにNWの層を追加していく形が基本らしい。
1層目は通常の全結合NWレイヤーで、入力が8 個、出力が12個の物を積んでる。 activationは活性化関数をどうするかというところ、ここではrelu(ランプ関数)が指定されている。現在は一般的にランプ関数を指定した方が精度がいいとされているらしい。

2層目は入力12個で、出力が8個

3層目は入力8個で、出力1個、activationにsigmoid(シグモイド関数)を使って出力を0 or 1 の整数にしている。


# create model
model = Sequential()
model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

モデルの定義が終わったあと、モデルをコンパイルする。
引数は3つとり、optimizer(最適化手法)、loss(損失関数)、metrics(評価指標のリスト)が必要、詳しくはここ参照

最適化手法はadam
損失関数はbinary_crossentropy = logloss
metricsは一般的にはaccuracyを使うらしい。


# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])


コンパイル後、実際に学習を始める。
XはテストデータのNumpy配列、Yは教師データのNumpy配列を与える。
epoches(反復回数)とbatch(何サンプルでgradient disent の更新をするか)も指定する。

model.fit(X, Y, epochs=50, batch_size=10)

最後にモデルの評価を行う。
XはテストデータのNumpy配列、Yは教師データのNumpy配列を与える。

evaluate後モデルの評価スコアが帰ってくる。

# evaluate the model
scores = model.evaluate(X, Y)
print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))



非常に簡単に使えるので、ぜんぜんTensorFlowより敷居が低そう。ただ機械学習、ニューラルネットワークの基礎はしっている必要があるので、CourseraのMachine larning(とくに)week4 week5あたりをやっておくといいと思う。


2017年5月20日土曜日

Oauth 2.0 Mac Token

Oauth 2.0のMAC Tokenについて調べたのでまとめる


  • Message Authentification Codeの略
  • メッセージに署名をつけて、認証しようよということ
  • Bearer Tokenと MAC Tokenがある
  • Bearer Tokenの方がシンプルで見かけることが多い
  • Bearer か MACかはクライアントは決めれない。サーバが決める。
  • MAC Tokenでトークンが渡される時のレスポンス


HTTP/1.1 200 OK
  Content-Type: application/json
  Cache-Control: no-store
  {
  "access_token":"SlAV32hkKG",
  "token_type":"mac",
  "expires_in":3600,
  "refresh_token":"8xLOxBtZp8",
  "mac_key":"adijq39jdlaska9asud",
  "mac_algorithm":"hmac-sha-256"
  }

  • MAC Tokenではリソースへのアクセス時、以下情報をヘッダに付加する必要あり。

Authorization: MAC id="h480djs93hd8",  ts="1336363200",  nonce="dj83hs9s",  mac="bhCQXTVyfj5cmA9uKkPFx1zeOXM="

  • idはトークン取得時にもらった、Mac Key Identifireかaccess_token。
  • tsはクライアントで付け加えるタイムスタンプ 
  • nonceはクライアント側で生成し、付け加えるユニークな文字列、id, ts, nonceの組み合わせがユニークにならないといけない
  • macは以下方法で生成

ts + nonce + http method + uri + host + port + ext or Authorized(optional) の文字列を生成して、mac_algorithmで指定されているアルゴリズムでhashの生成したもの

参考

http://stackoverflow.com/questions/31209525/oauth-2-0-bearer-tokens-vs-mac-tokens-why-not-using-mac-tokens

https://dzone.com/articles/oauth-20-bearer-token-profile

https://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05

https://www.slideshare.net/ritou/oauth-20-mac-authentication 日本語

2017年5月13日土曜日

Jupiter Notebook + Keras(Tensor Flow)でチュートリアルをしてみる1

Tensorflowを昔やってみたのだが、挫折したのでもっと直感的と言われているKerasを試してみる。

インストール

pyenv

Pyhonデータ分析ライブラリたちが入る
Anaconda https://docs.continuum.io/anaconda/install-macos
pyenv使ってるのでこちらを参考にした
http://qiita.com/takehilo/items/1ffe5b266ed6a64690c8

jun-mac:keras jun-ishioka$ pyenv install -v anaconda3-4.2.0
jun-mac:keras jun-ishioka$ pyenv global anaconda3-4.2.0
jun-mac:keras jun-ishioka$ python --version
Python 3.5.2 :: Anaconda 4.2.0 (x86_64) 
source /Users/jun-ishioka/.pyenv/versions/anaconda3-4.2.0/bin/activate 
Tensorflow, KerasはAnacondaのパッケージ管理出あるcondaでインストール

Googleの機械学習ライブラリ
Tensorflow  https://www.tensorflow.org/install/install_mac

conda install -c conda-forge tensorflow

Tensorflowのラッパー、より直感的に操作できる
Keras https://keras.io/#installation

conda install -c conda-forge keras

もろもろインストール後、Jupiter Notebookという対話しきのPytyon GUIを起動(これはAnacondaにデフォルトで含まれているみたい)

jupyter notebook

ブラウザが立ち上がりファイラーが表示される。
 適当なフォルダを作って、NewからPython [conda root]を選択。
 そうすると、ノートブックが出来上がる。

このセルの中にはマークダウンでドキュメントを書いたり、コードを書いて実行したりできる。

ここのチュートリアルをやってみた。
http://machinelearningmastery.com/tutorial-first-neural-network-python-keras/
実行したいときはCell -> Run Cells
 無事実行完了、Jupyter Notebook素敵すぎる。コードの管理とかかなり楽になりそう。

Kerasのコードの内容まで踏み込みたいのだが、環境構築に手こずってしまったので今日はここまで。

2017年5月7日日曜日

サイトアクセスをどう伸ばしていくか?

Kindleセール情報サイトを作ったが、まあ作っただけではどんなサイトでもアクセスは増えない。

現状はこんな感じだが、今後の効果の備忘録のためにのせておく。


























自分たち以外のアクセスはほぼないと言っても良さそう。
Webマーケティングの知り合いにヒアリングしてやらなければいけないのは以下。
  • キーワード調査
    • そのキーワードのページを作る 例えばコミック セールなど
    • 被リンク
  • 有名人にメール、Twitterでツールの情報を宣伝してみる
    • 本当にいいツールだったら使ってもらえるかも?
  • 広告はあまりPayしないかも1クリック50円とかかかる
  • Life Hack
    • 2ちゃんまとめのライフハックなどに入るとバズる
これらをやりつつ効果を定期的に見ていく。

2017年5月1日月曜日

nginxによるアクセス制御に関して調べてみた

業務でアクセス制御する必要があったので、どのような解決策があるかを調べてみた。


要件

ある外部システムをWebAPIで叩いて連携する必要があるが、そのシステムはURLごとに2req/sしか叩かれないように制御したい。

例えば
/searchと/user はそれぞれに2req/sになるように制御したい。

この要件を聞いてみて使えそうかな?とおもったnginx調べてみた。

nginx

http limit req moduleでいけるか調べてみる。
ある$keyごとに1req/secondなど柔軟に処理できそうなので、URLごとにリクエストを制御できるかテストしてみる。

検証環境はmac
  • brew install nginx
  • sudo nginx
  • http://localhost:8080/にアクセスするとデフォルトページが表示された。
index.htmlを / と /testの2つに用意
mkdir /usr/local/var/www/test
cp /usr/local/var/www/index.html /usr/local/var/www/test
そこに$uriごとにアクセス制限をかける以下を追加

http {
    limit_req_zone $uri zone=one:10m rate=2r/s;

    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/access.log  main;

    sendfile        on;

    keepalive_timeout  65;

    server {
        limit_req zone=one burst=5;
        listen       8080;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }

設定完了したので、nginx再起動。

sudo nginx -s reload

そしてアクセスログを見守りつつ、/ と /testにpararel 4,  request数12で飛ばす。
ab -n 12 -c 4 http://127.0.0.1:8080/index.html & ab -n 12 -c 4 http://127.0.0.1:8080/test/index.html
するとアクセスログは以下のように同じ秒間にはuriごとに2リクエストしかさばいてないので、nginxの方でよしなに遅延させて処理してくれた模様。
[01/May/2017:00:31:23 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:23 +0900] "GET /index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:23 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:24 +0900] "GET /index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:24 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:24 +0900] "GET /index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:24 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:25 +0900] "GET /index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:25 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:25 +0900] "GET /index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:25 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" [01/May/2017:00:31:26 +0900] "GET /index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:26 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:26 +0900] "GET /index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:26 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:27 +0900] "GET /index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:27 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:27 +0900] "GET /index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:27 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:28 +0900] "GET /index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:28 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:28 +0900] "GET /index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
[01/May/2017:00:31:28 +0900] "GET /test/index.html HTTP/1.0" 200 612 "-" "ApacheBench/2.3" "-"
秒間をこえたリクエストを遅延して処理するかどうかはburstが決めているのでそれをいじってエラーにしてみる。

十分これで目的を達成できそうな気がするな。