Search on the blog

2016年2月20日土曜日

S3のファイルを一般公開する

 AWSのS3のファイルを一般公開する方法について説明します。
  • S3でWeb Hostingを行う
  • S3でファイル共有を行う
の2つの場合に分けて説明します。

S3でWeb Hosting

まずは静的なHTMLを公開して、S3でWeb Hostingする場合を考えます。
手順は以下のとおりです。
  1. S3のバケットを作成
  2. インデックスドキュメントの作成/アップロード
  3. 静的ウェブホスティングの設定
  4. アクセス許可
  5. ブラウザで確認
1. S3のバケットを作成
AWS Management Consoleでバケットを作成します。
S3のバケット名はそのままURLになるため、他のユーザのバケット名とかぶらないようなユニークな名前をつける必要があります。名前がかぶると登録エラーになります。

今回の例ではバケット名は、
sample.s3.kenjih.com
とします。

2. インデックスドキュメントの作成/アップロード
Webページのインデックスドキュメントを作成します。
以下のようなファイルを作って、index.htmlという名前で作成したバケットにアップロードします。

<html>
  <head>
    <title>S3 Hosting Sample</title>
  </head>
  <body>
    Hello, S3 Hosting!
  </body>
</html>

3. 静的ウェブホスティングの設定
AWS Management ConsoleのS3のプロパティ-静的ウェブサイトホスティングで
「ウェブサイトのホスティングを有効にする」を選択します。
インデックスドキュメントには、index.htmlと入力します。


4. アクセス許可
次にS3のオブジェクトのアクセス許可設定を行います。
この設定を行っていないと、ブラウザからリソースを参照したときに403エラーになります。

AWS Management ConsoleのS3のプロパティ-アクセス許可-バケットポリシーの追加を選択し、以下のポリシー言語を入力し保存します。


{
 "Version": "2012-10-17",
 "Statement": [
  {
   "Sid": "AddPerm",
   "Effect": "Allow",
   "Principal": "*",
   "Action": [
    "s3:GetObject"
   ],
   "Resource": [
    "arn:aws:s3:::sample.s3.kenjih.com/*"
   ]
  }
 ]
}

上の設定で、任意のユーザがバケットのオブジェクトを参照できるようになります。
より詳細な設定方法については以下のページを参照してください。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/example-bucket-policies.html

ここで注意しないといけないのは、Versionの日付です。
この日付はポリシーを作成した日付ではなく、ポリシー言語のVersionを指定する日付です。

ポリシーを作成した日付を入力すると
Document is invalid: Invalid Version 2016-02-20 - undefined
のようなエラーになるので、注意してください。

5. ブラウザで確認
ブラウザで確認すると、以下のように表示されます。
リソースのURLはAWS Management ConsoleのS3のプロパティ-静的ウェブサイトホスティング-エンドポイントで確認できます。

S3でファイルを共有

次に、Web Hostingではなく単にファイルを共有する場合を考えます。
手順は以下のとおりです。

  1. バケットの作成
  2. ファイルのアップロード
  3. ファイルの公開
  4. 確認
1. バケットの作成

AWS Management Consoleでバケットを作成します。
S3のバケット名はそのままURLになるため、他のユーザのバケット名とかぶらないようなユニークな名前をつける必要があります。名前がかぶると登録エラーになります。

今回の例ではバケット名は、
share.s3.kenjih.com
とします。

2. ファイルのアップロード
公開したいファイルを作成したバケットにアップロードします。
今回の例ではhoge.zipというファイルをアップロードします。

3. ファイルの公開
公開したいファイルを右クリックし、「公開する」を選択します。

4. 確認
公開したファイルを選択し、アクション-プロパティ-リンクを参照すると、ファイルのリンクが表示されます。
このリンクをブラウザに入力し、ファイルをダウンロードできることを確認します。

2016年2月13日土曜日

pyenv-virtualenvでPythonの環境構築

pyenv-virtualenvとは?
virtualenv環境を管理するためのpyenvプラグイン。

pyenvを使うと異なったバージョンをPythonを使い分けることができるが、virtualenvを使うと同じバージョンのPythonで異なる環境(依存するライブラリが異なる環境など)を使い分けることができる。
pyenv-virtualenvはvirtualenvの機能をpyenvから使うことができる便利なプラグイン。

インストール
pyenvはインストール済みであるとする。

Mac OSの場合はhomebrewでインストール。
$ brew install pyenv-virtualenv

インストール後、以下を.bash_profileに追記。
if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi

サンプル
シチュエーション
projectXというプロジェクトをPython 3.5.1で開発したい。
システムにインストールされているPythonのバージョンは変えたくない。
pyenvで3.5.1の環境は作れるが別のプロジェクトでも3.5.1を使う可能性があり、依存するライブラリを共有したくない。

解決策
pyenv-virtualenvの出番だ!
$ mkdir projectX
$ cd projectX/
$ pyenv local 3.5.1
$ pyenv version
3.5.1 (set by /Users/kenjih/work/projectX/.python-version)
$ pyenv virtualenv projectX
$ pyenv local projectX 
$ pyenv version
projectX (set by /Users/kenjih/work/projectX/.python-version)

上記のようにpyenv virtualenv projectXprojectXという名前の環境を作成できる。
仮想環境のPythonのバージョンは環境作成時のpyenv versionのものが使われる。(上の例では3.5.1)
pyenv local projectXとすることで、カレントディレクトリ以下がprojectX環境となり、独立したPythonの環境を構築できる。

作成した環境一覧の表示、作成した環境の削除は以下のコマンドで行う。
$ pyenv virtualenvs
  3.5.1/envs/projectX (created from /Users/kenjih/.pyenv/versions/3.5.1)
  projectX (created from /Users/kenjih/.pyenv/versions/3.5.1)
$ pyenv virtualenv-delete projectX

pyenvでPythonの環境構築

やりたいこと
  • いろいろなバージョンのPythonを使いたい
  • あるアプリはPython2系で、別のアプリはPython3系で開発したい
pyenvを使うと上記のやりたいことを実現できる。

インストール
Macの場合はhomebrewでインストールできる。
brew install pyenv

インストール後、~/.bash_profileに以下を追加する。
if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi

使ってみる
まずはシステムにインストールされているPythonの情報を確認。
$ python -V
Python 2.7.10
$ pip -V
pip 7.1.2 from /usr/local/lib/python2.7/site-packages (python 2.7)

pyenvを使って別のバージョンのPythonを入れてみる。
pyenv installで指定したバージョンのPythonをインストールできる。
新しいバージョンのPythonを入れた時やバイナリを提供するパッケージをインストールしたときはpyenv rehashを実行。
$ pyenv version
system (set by /Users/kenjih/.pyenv/version)
$ pyenv install 3.5.1
$ pyenv rehash
$ pyenv shell 3.5.1
$ pyenv version
3.5.1 (set by PYENV_VERSION environment variable)

Python 3.5.1が入ったっぽい。
現在のPythonのバージョンを確認してみる。
$ python -V
Python 3.5.1
$ pip -V
pip 7.1.2 from /Users/kenjih/.pyenv/versions/3.5.1/lib/python3.5/site-packages (python 3.5)

Pythonのバージョンの設定方法
pyenvは、以下の3つの単位でバージョンを設定できる。

設定単位 設定コマンド 設定が記述される場所
シェルセッション pyenv shell x.x.x 環境変数 PYENV_VERSION
アプリケーション pyenv local x.x.x カレントディレクトリの.python-version
グローバル pyenv global x.x.x ~/.pyenv/version

pyenvは上の設定内容に従って以下のようにPythonのバージョンを決める。
  1. 環境変数PYENV_VERSIONが定義されていればそれを使う
  2. カレントディレクトリに.python-versionファイルがあればそれを使う
  3. カレントディレクトリに.python-versionファイルがあればそれを使う
  4. rootディレクトリまで親を辿っていって.python-versionファイルがあればそれを使う
  5. ~/.pyenv/versionファイルを使う
シンプルで分かりやすい。

アプリケーションごとの設定を試してみる
おそらく最もよく使うのはこの設定かなと思うので試してみた。

$ mkdir py2 && cd py2 && pyenv local 2.7.11 && cd ..
$ mkdir py3 && cd py3 && pyenv local 3.5.1 && cd ..
$ cd py2 && python -V && cd ..
Python 2.7.11
$ cd py3 && python -V && cd ..
Python 3.5.1

これは便利だ。

2016年2月12日金曜日

TensorFlow入門(2)Deep MNIST for Experts

 TensorFlowのtutorialをやってみた。MNISTをDeep Learningで学習させる回。識別率99%を超えるモデルを作ることが出来る。重要そうなところをメモしておく。

元ネタ
Deep MNIST for Experts

TensorFlowについて
重い計算はC++のバックエンドで行う。
バックエンドとのコネクションを"セッション"と呼ぶ。

ソースコード
import tensorflow as tf
import input_data

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

def conv2d(x, W):
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], 
                      padding='SAME')

def max_pool_2x2(x):
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')

mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

sess = tf.InteractiveSession()
x = tf.placeholder("float", shape=[None, 784])
y_ = tf.placeholder("float", shape=[None, 10])

x_image = tf.reshape(x, [-1,28,28,1])
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

sess.run(tf.initialize_all_variables())
for i in range(20000):
  batch = mnist.train.next_batch(50)
  if i%100 == 0:
    train_accuracy = accuracy.eval(feed_dict={
        x:batch[0], y_: batch[1], keep_prob: 1.0})
    print "step %d, training accuracy %g"%(i, train_accuracy)
  train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

print "test accuracy %g"%accuracy.eval(feed_dict={
    x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0})

以下、上記ソースコードで記述したモデルについて説明。

Weight Initialization
wはtruncated normal distributionの乱数。
bは定数。

Convolution and Pooling
Convolutionのstrideは1*1。padding='SAME'とすることで、入力と出力のサイズが同じになる。
Poolingは2*2のブロックのMax Pooling。

First Convolutional Layer
28 * 28 * 1チャネルの入力を
5*5のパッチでconvolutionして28 * 28 * 32 チャネルにした後、
Max Poolingして、14 * 14 * 32チャネルにする。

Second Convolutional Layer
14 * 14 * 32チャネルの入力を
5*5のパッチでconvolutionして14 * 14 * 64チャネルにした後、
Max Poolingして、7 * 7 * 64チャネルにする。

Densely Connected Layer
7 * 7 * 64チャネルの入力をflattenしてベクトルにした後、
1024次元のベクトルにする。

Dropout
オーバーフィッティング対策のために出力層の前にdropoutを入れる。
keepするneuronの割合をplaceholderにしておくことで、学習時と識別時でdropoutのあり/なしを切り替えることが出来る。

Readout Layer
softmaxする。

2016年2月11日木曜日

TensorFlow入門(1)MNIST For ML Beginners

 TensorFlowのtutorialをやってみた。
機械学習入門者向けのtutorialでMNISTを例題にNNを学習させるやり方が記載されていた。
NNはnum of hidden layer=0、activation function=softmaxというシンプルなモデルを使っていた。自分用にメモを残しておく。

元ネタ
MNIST For ML Beginners

softmaxについて
  • 対象がそれぞれのクラスに属する確率を求めたいときに使う
  • NNの最終レイヤーはsoftmaxを使うことが多い
TensorFlowについて
numpyは重い数値計算をpythonの外で行う
=> 結果をpythonに戻すときにオーバーヘッドがある
=>TensorFlowはpythonの外で実行したい計算処理の相互作用をグラフで記述できる

placeholder: 計算開始時に入力として渡す値 (データの特徴ベクトル、教師信号用)
Variable: 計算中時に利用する変更可能な変数(学習させるパラメータ用)

ソースコード
import input_data
import tensorflow as tf

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x, W) + b)

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

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

sess = tf.Session()
sess.run(init)
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})

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})

AWS勉強記(5)SSHのログインユーザ名

 普段はAmazon Linux AMIを使っているが、Ubuntu AMIに変えたときにSSHでログインできなくなってツマってしまった。

 AMIごとにデフォルトのユーザ名が異なるらしく、SSHするときは各AMIのデフォルトユーザ名を使わないといけないらしい。

 例えばUbuntuの場合は、以下のようにユーザ名ubuntuでSSHする。
ssh ubuntu@xx.xx.xx.xx -i ~/.ssh/yyyy.pem

よく使われるAMIとデフォルトユーザは以下のとおり。
AMI デフォルトユーザ名
Amazon Linux c2-user
Ubuntu ubuntu
RHEL5 root