sklearn LabelEncoderクラス
LabelEncoderクラス
LabelEncoder は、全てのカテゴリに対して数値によるIDを割り当てることができるクラスです。
タイタニックのデータにおけるsex、class、who列におけるカテゴリを数値に変換した例が下記になります。
参考
【読書メモ】ゼロから作るDeep Learning 6章
ゼロから作るDeep Learningの読書メモとしてまとめました。
本を読む目的
Coursera Machine Learningを受講してニューラルネットワークを理解したので、次はディープラーニングについて深く理解をしたいため。
前章までのまとめ
- 【読書メモ】ゼロから作るDeep Learning 1章
- 【読書メモ】ゼロから作るDeep Learning 2章
- 【読書メモ】ゼロから作るDeep Learning 3章
- 【読書メモ】ゼロから作るDeep Learning 4章
- 【読書メモ】ゼロから作るDeep Learning 5章
本記事で利用しているソースコードは GitHub - oreilly-japan/deep-learning-from-scratch: 『ゼロから作る Deep Learning』のリポジトリを参考にしています。
最適化とは
最適化とは、損失関数の値を出来るだけ小さくするパラメータを見つけるような問題を解くこと。前章まではパラメータの勾配(微分)を使って勾配方向にパラメータを更新するステップを何回も繰り返す、確率的勾配降下法(Stochastic Gradient Descent:SGD)を最適化の手法として利用していたが、ここではSGDの欠点を改善する手法について説明。
SGDの欠点
目的とする関数の形状が等方的でないと、非効率な経路で探索してしまうため、学習に時間がかかってしまう。
SGDに代わる手法
Momentum
ボールがお椀を転がるように物理法則に準ずる動き。
class Momentum: def __init__(self, lr=0.01, momentum=0.9): self.lr = lr self.momentum = momentum self.v = None def update(self, params, grads): if self.v is None: self.v = {} for key, val in params.items(): self.v[key] = np.zeros_like(val) for key in params.keys(): self.v[key] = self.momentum*self.v[key] - self.lr*grads[key] params[key] += self.v[key]
AdaGrad
パラメータの要素の中で大きく更新された要素は学習係数が小さくなるような更新方法。
class AdaGrad: def __init__(self, lr=0.01): self.lr = lr self.h = None def update(self, params, grads): if self.h is None: self.h = {} for key, val in params.items(): self.h[key] = np.zeros_like(val) for key in params.keys(): self.h[key] += grads[key] * grads[key] params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)
Adam
MomentumとAdaGradの融合。ソースコードは割愛。
どの更新手法を用いるか
多くの研究では今でもSGDを使っている。最近はAdamを好んで使っている人も増えた。全ての問題で優れた手法は無いので、色々試す必要がある。
重みの初期値
重みの初期値によって、ニューラルネットワークの学習がうまくいくかが決定することが多い。 結論からいうと、活性化関数にsigmoid、tanhなどのS字カーブを用いる場合はXavierの初期値、ReLUを用いる場合は、Heの初期値を用いるとよい。
Weight decay(荷重減衰)
重みパラメータの値が小さくなるように学習を行うことを目的とした手法。重みパラメータを小さくするのに小さい初期値から始める。単純に初期値を0(均一な値)にすればいいのではと思うが、それはダメ。理由としては、すべての重みの値が均一に更新されてしまい、ニューラルネットワークの表現力がなくなるため。よって、ランダムな初期値が必要。
勾配消失問題
重みの初期値に標準偏差が1のガウス分布を用いると、活性化関数がシグモイド関数の場合、各層のアクティベーションの結果は0と1に偏った分布になってしまう。こうなると、逆伝播で微分(勾配)の値が0に近くため、勾配の値が伝播するにつれ小さくなってしまい、層が深いほど0に近づいてしまうこと。よって、初期値を適切な値にして上げる必要があり、XavierやHeの初期値が考えられた。
Xavierの初期値
Xaivierの初期値は一般的なディープラーニングのフレームワークで使われている。各層のアクティベーションを同じ広がりのある分布にすることを目的として、前層のノードの個数をnとして、の標準偏差をもつ分布を使う。Xavierの初期値は活性化関数が線形の場合に有効。
num = 100 # random.randn(num, num):標準正規(ガウシアン)分布による num × num の行列 w = np.random.randn(num, num) / np.sqrt(1.0 / num)
Heの初期値
活性化関数がReLUの場合に推奨されるのがHeの初期値。前層のノードの個数をnとして、の標準偏差をもつ分布を使う。
num = 100 w = np.random.randn(num, num) / np.sqrt(2.0 / num)
コード
初期値や活性化関数を変えて動かしてみる。
# coding: utf-8 import numpy as np import matplotlib.pyplot as plt def sigmoid(x): return 1 / (1 + np.exp(-x)) def ReLU(x): return np.maximum(0, x) def tanh(x): return np.tanh(x) input_data = np.random.randn(1000, 100) node_num = 100 hidden_layer_size = 5 activations = {} x = input_data for i in range(hidden_layer_size): if i != 0: x = activations[i-1] # 初期値の値を変える w = np.random.randn(node_num, node_num) * 1 # w = np.random.randn(node_num, node_num) * 0.01 # w = np.random.randn(node_num, node_num) * np.sqrt(1.0 / node_num) # # w = np.random.randn(node_num, node_num) * np.sqrt(2.0 / node_num) a = np.dot(x, w) # 活性化関数 z = sigmoid(a) # z = ReLU(a) # z = tanh(a) activations[i] = z for i, a in activations.items(): plt.subplot(1, len(activations), i+1) plt.title(str(i+1) + "-layer") if i != 0: plt.yticks([], []) # plt.xlim(0.1, 1) # plt.ylim(0, 7000) plt.hist(a.flatten(), 30, range=(0,1)) plt.show()
Batch Normalization
重みの初期値によって、各層のアクティベーションの結果が変わり適切な重みの初期値を設定することで各層のアクティベーションの分布は適度な広がりを持ち、学習がスムーズに進んだことを確認した。Batch Normalizationは、アクティベーションの分布を強制的に適度な広がりを持つように調整しようというアイディアのこと。アクティベーションの分布が適度な広がりを持たないと、ニューラルネットワークが表現力を無くす、つまりたくさんのニューロンを使用している意味がなくなる。
Batch Normalizationのメリット
- 学習を早くできる
- 初期値にあまり依存しない
- Overfitしない
Batch Normalizationレイヤの挿入
活性化関数レイヤの前(or後)にBatch Normalizationレイヤを挿入する。
Batch Normalizationの詳細
ミニバッチを単位として、ミニバッチごとにaデータの分布が平均が0で分散が1になるように正規化すること。
Batch Normalizationの評価
重みの初期値の標準偏差を様々な値に変えた時の学習経過が下記。Batch Normalizationを使用することで、重みの初期値にロバストになる。
過学習(Overfitting)
過学習とは訓練データだけに適応しすぎて、他のデータに適応できない状態のこと。過学習の原因としては、下記の2つが考えられる。
- パラメータをたくさん持っている
- 訓練データが少ない
Weight decay
過学習は重みパラメータが大きな値を取ることで起こることがしばしばある。そこで学習において大きな重みを取ることにペナルティを与えることで過学習を抑制することができる。この手法をWeight decay(荷重減衰)という。 具体的には損失関数に重みの二乗ノルム(L2ノルム)を加算する。 (ノルムとはベクトル空間における長さを示すもの。二乗ノルムはベクトルの長さ)
Dropout
過学習を抑制するためにニューロンを削除しながら学習する手法。訓練時にデータが流れるたびに消去するニューロンをランダムに選択する。 テスト時には全てのニューロンの信号を伝達するが、各ニューロンの出力に対して訓練時に削除した割合を乗算して出力。 Dropoutは学習時にランダムにニューロンを削除することによって、毎回別のモデルを学習させていることになるので、アンサンブル学習に近い発想。
ハイパーパラメータの検証
ハイパーパラメータとは、重みやバイアスといった訓練の結果取得できるパラメータとは異なり、人が試行錯誤をして決定しなければいけないパラメータのこと。例えば下記のパラメータがハイパーパラメータ
- ニューロンの数
- バッチサイズ
- 学習率
- Weight decay
検証データ(Validation data)
テストデータを使ってハイパーパラメータを調整するとテストデータに対して過学習してしまう。よって別途、検証データを用意してハイパーパラメータの調整を行う。まとめると下記になる。
- 訓練データは重みやバイアスの学習に使用
- 検証データはハイパーパラメータの性能評価のため使用
- テストデータは汎化性能をチェックするために使用
ハイパーパラメータの最適化
ハイパーパラメータの最適化のポイントは、いい値が存在する範囲を徐々に絞り込んでいくこと。
# coding: utf-8 import sys, os sys.path.append(os.pardir) # 親ディレクトリのファイルをインポートするための設定 import numpy as np import matplotlib.pyplot as plt from dataset.mnist import load_mnist from common.multi_layer_net import MultiLayerNet from common.util import shuffle_dataset from common.trainer import Trainer (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True) # 高速化のため訓練データの削減 x_train = x_train[:500] t_train = t_train[:500] # 検証データの分離 validation_rate = 0.20 validation_num = int(x_train.shape[0] * validation_rate) x_train, t_train = shuffle_dataset(x_train, t_train) x_val = x_train[:validation_num] t_val = t_train[:validation_num] x_train = x_train[validation_num:] t_train = t_train[validation_num:] def __train(lr, weight_decay, epocs=50): network = MultiLayerNet(input_size=784, hidden_size_list=[100, 100, 100, 100, 100, 100], output_size=10, weight_decay_lambda=weight_decay) trainer = Trainer(network, x_train, t_train, x_val, t_val, epochs=epocs, mini_batch_size=100, optimizer='sgd', optimizer_param={'lr': lr}, verbose=False) trainer.train() return trainer.test_acc_list, trainer.train_acc_list # ハイパーパラメータのランダム探索====================================== optimization_trial = 100 results_val = {} results_train = {} for _ in range(optimization_trial): # 探索したハイパーパラメータの範囲を指定=============== weight_decay = 10 ** np.random.uniform(-8, -4) lr = 10 ** np.random.uniform(-6, -2) # ================================================ val_acc_list, train_acc_list = __train(lr, weight_decay) print("val acc:" + str(val_acc_list[-1]) + " | lr:" + str(lr) + ", weight decay:" + str(weight_decay)) key = "lr:" + str(lr) + ", weight decay:" + str(weight_decay) results_val[key] = val_acc_list results_train[key] = train_acc_list # グラフの描画======================================================== print("=========== Hyper-Parameter Optimization Result ===========") graph_draw_num = 20 col_num = 5 row_num = int(np.ceil(graph_draw_num / col_num)) i = 0 for key, val_acc_list in sorted(results_val.items(), key=lambda x:x[1][-1], reverse=True): print("Best-" + str(i+1) + "(val acc:" + str(val_acc_list[-1]) + ") | " + key) plt.subplot(row_num, col_num, i+1) plt.title("Best-" + str(i+1)) plt.ylim(0.0, 1.0) if i % 5: plt.yticks([]) plt.xticks([]) x = np.arange(len(val_acc_list)) plt.plot(x, val_acc_list) plt.plot(x, results_train[key], "--") i += 1 if i >= graph_draw_num: break plt.show()
AWS スポットインスタンスでJupyterを起動するまで
背景
Kaggleの Microsoft Malware Prediction に参加しています。分析にはローカルPCを使用していましたが、リソースが足りなくなることが多いため、パブリッククラウドで1番慣れているAWSのスポットインスタンスを使ってみたので、Jupyterを起動するまでの手順について書こうと思います。
AWS スポットインスタンスとは
スポットインスタンスはオンデマンド価格より低価で利用できる未使用の EC2 インスタンスで、需要と供給によって利用料金が変動します。オンデマンドに比べて大幅に割引されますが、いくつかの理由によりインスタンスを中断されることがあります。
手順
スポットインスタンスのリクエスト
EC2のページのスポットインスタンスからスポットインスタンスのリクエストを選択します。まずどんなタスクに使用するかの選択をします。ここではBig data workloadsを選択します。
AMIやコンピュートユニットを選択します。ここでは、既存のインスタンスタイプからr3.xlargeを選択します。様々なインスタンスタイプがあるので、Amazon EC2 料金表などを参考に決めるといいでしょう。
その他もろもろの設定をしてリクエストの作成をする時に割引率が提示されます。この時は81%offの価格で利用できることが分かります。
少し時間がたつとインスタンスが作成されるので、ターミナル(Macの場合)などからsshします。インスタンスにsshするには、インスタンスのセキュリティグループ(ファイアウォールのようなもの)の設定が必要です。
セキュリティグループの設定
インスタンスのセキュリティグループが下記赤枠から確認できます。
対象のセキュリティグループのインバウンドルールにクライアントのIPを設定します。 個々の環境によって異なるかと思いますが、下記のようにMy IPを選択すれば今使っている端末のグローバルIPが自動で設定されるようです。
SSH接続する
作成したインスタンスにSSH接続します。SSH接続するためのコマンドは接続をクリックすると表示されます。
$ chmod 400 spot-instance-key.pem $ ssh -i "spot-instance-key.pem" root@ec2-54-248-31-178.ap-northeast-1.compute.amazonaws.com # SSH完了 [ec2-user@ip-172-31-14-83 ~]$
ここからは各自自由にJupyterを起動するまでの手順を進めてください。
今回自分の場合は、ローカル環境でDockerを使って環境構築して開発していたものをGithubリポジトリで管理していたので、git cloneをして、docker runをしました。
Dockerのインストールは Get Docker CE for Ubuntu を参考に進めます(Ubuntuの場合)。
AMI作成
スポットインスタンスは停止をすることができないため、計算が完了したら削除をしないといけません。よって、2度目以降に同じ環境を構築するためにAMIを作成しておきます。
AMIを作成しておけば、再度スポットインスタンスを作成するときに、テンプレートとしてそのAMIを指定することで同じ環境を構築することができます。
参考:インスタンスと AMI
Pythonの内包表記について
Pythonには内包表記という、リストなどの iterableな オブジェクトのループ処理をシンプルに記述できる記法があります。今回は基本的な内包表記についてまとめてみました。
通常のリスト
Pythonでリストに追加するには下記のように下記のが一般的ですが、内包表記というものもあります。
squares = [] for x in range(10): squares.append(x**2) print(squares)
# 結果 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
内包表記
内包表記の場合、下記のように1行で書くことができます。
squares = [x**2 for x in range(10)] print(squares)
# 結果 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
map()
リストの各要素に関数を適用するmap関数を用いて書くこともできます。
# map(関数, リスト) squares = list(map(lambda x: x**2, range(10)))
# 結果 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
【読書メモ】ゼロから作るDeep Learning 5章
ゼロから作るDeep Learningの読書メモとしてまとめました。
本を読む目的
Coursera Machine Learningを受講してニューラルネットワークを理解したので、次はディープラーニングについて深く理解をしたいため。
前章までのまとめ
- 【読書メモ】ゼロから作るDeep Learning 1章
- 【読書メモ】ゼロから作るDeep Learning 2章
- 【読書メモ】ゼロから作るDeep Learning 3章
- 【読書メモ】ゼロから作るDeep Learning 4章
はじめに
本章では、重みパラメータの勾配の計算を高速に行う手法である 誤差逆伝播法 について学ぶ。4章のニューラルネットワークの学習では、重みパラメータの勾配は数値微分で求めたが、時間がかかるので効率的に計算を行う方法として誤差逆伝播法が編み出されました。
2層のニューラルネットワーク
# coding: utf-8 import sys, os sys.path.append(os.pardir) # 親ディレクトリのファイルをインポートするための設定 import numpy as np from common.layers import * from common.gradient import numerical_gradient from collections import OrderedDict class TwoLayerNet: def __init__(self, input_size, hidden_size, output_size, weight_init_std = 0.01): # 重みの初期化 self.params = {} self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size) self.params['b1'] = np.zeros(hidden_size) self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size) self.params['b2'] = np.zeros(output_size) # レイヤの生成 self.layers = OrderedDict() self.layers['Affine1'] = Affine(self.params['W1'], self.params['b1']) self.layers['Relu1'] = Relu() self.layers['Affine2'] = Affine(self.params['W2'], self.params['b2']) self.lastLayer = SoftmaxWithLoss() def predict(self, x): for layer in self.layers.values(): x = layer.forward(x) return x def loss(self, x, t): y = self.predict(x) return self.lastLayer.forward(y, t) def accuracy(self, x, t): y = self.predict(x) y = np.argmax(y, axis=1) if t.ndim != 1 : t = np.argmax(t, axis=1) accuracy = np.sum(y == t) / float(x.shape[0]) return accuracy def gradient(self, x, t): # forward self.loss(x, t) # backward dout = 1 dout = self.lastLayer.backward(dout) layers = list(self.layers.values()) layers.reverse() for layer in layers: dout = layer.backward(dout) # 設定 grads = {} grads['W1'], grads['b1'] = self.layers['Affine1'].dW, self.layers['Affine1'].db grads['W2'], grads['b2'] = self.layers['Affine2'].dW, self.layers['Affine2'].db return grads
誤差逆伝播法を使った学習
# coding: utf-8 import sys, os sys.path.append(os.pardir) import numpy as np from dataset.mnist import load_mnist from two_layer_net import TwoLayerNet # データの読み込み (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True) network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10) iters_num = 10000 train_size = x_train.shape[0] batch_size = 100 learning_rate = 0.1 train_loss_list = [] train_acc_list = [] test_acc_list = [] iter_per_epoch = max(train_size / batch_size, 1) for i in range(iters_num): batch_mask = np.random.choice(train_size, batch_size) x_batch = x_train[batch_mask] t_batch = t_train[batch_mask] # 勾配 grad = network.gradient(x_batch, t_batch) # 更新 for key in ('W1', 'b1', 'W2', 'b2'): network.params[key] -= learning_rate * grad[key] loss = network.loss(x_batch, t_batch) train_loss_list.append(loss) if i % iter_per_epoch == 0: train_acc = network.accuracy(x_train, t_train) test_acc = network.accuracy(x_test, t_test) train_acc_list.append(train_acc) test_acc_list.append(test_acc) print(train_acc, test_acc)
【読書メモ】ゼロから作るDeep Learning 4章
ゼロから作るDeep Learningの読書メモとしてまとめました。
本を読む目的
Coursera Machine Learningを受講してニューラルネットワークを理解したので、次はディープラーニングについて深く理解をしたいため。
前章までのまとめ
ニューラルネットワークの学習
- ニューラルネットワークでいう学習とは、訓練データから最適な重みパラメータの値を自動で獲得すること
- 特徴量とはデータから本質的なデータを的確に抽出できるように設計された変換器のこと
- SVN, KNN等の機械学習では特徴量自体は人が設計するが、ニューラルネットワークの場合はデータをそのまま学習する
損失関数
最適なパラメータを探索(学習)するための指標。一般的にはニューラルネットワークの損失関数は二乗和誤差か交差エントロピーを用いる。損失関数の値をもっとも小さくする重みパラメータを探し出すことを学習という。
二乗和誤差
ニューラルネットワークの出力と教師データの各要素の差の二乗の総和
def mean_squared_error(y, t): return 0.5 * np.sum((y - t) ** 2 ) t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0] # 教師データ y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0] # ニューラルネットワークの出力 mean_squared_error(np.array(y), np.array(t))
結果
0.097500000000000031
交差エントロピー誤差
正解ラベルのインデックスのみ1となるので、それに対応するニューラルネットワークの出力の自然対数を計算。deltaを使っているのは、log(0)となった時にマイナス無限大となってしまうのを防ぐため。
def cross_entropy_error(y, t): delta = 1e - 7 return -np.sum(t * np.log(y + delta)) t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0] # 教師データ y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0] # ニューラルネットワークの出力 cross_entropy_error(np.array(y), np.array(t))
結果
2.3025840929945458
ミニバッチ学習
全てのデータを対象に損失関数の和を求めるのは時間がかかるため、データの中から一部を取り出して学習させることをミニバッチ学習という。
勾配
全ての変数の偏微分をベクトルとしてまとめたもので、各地点において低くなる方向のこと。勾配が指す方向は、各場所において関数の値を最も減らす方向。勾配法とは、勾配方向へ進むことを繰り返すことで関数の値を減らして行くこと。
勾配降下法
import numpy as np # 勾配 def numerical_gradient(f, x): h = 0.0001 grad = np.zeros_like(x) for idx in range(x.size): tmp_val = x[idx] x[idx] = tmp_val + h fxh1 = f(x) x[idx] = tmp_val -h fxh2 = f(x) grad[idx] = (fxh1 - fxh2) / (2*h) x[idx] = tmp_val return grad # 勾配法 def gradient_descent(f, init_x, lr=0.01, step_num=100): x = init_x for i in range(step_num): grad = numerical_gradient(f, x) x = x - lr * grad return x # 関数 def function_2(x): return x[0]**2 + x[1]**2
# 適切な学習率は最小値に近い値が取得できる >>> init_x = np.array([-3.0, 4.0]) >>> gradient_descent(function_2, init_x=init_x, lr=0.1, step_num=100) [-6.11110793e-10 8.14814391e-10] # 学習率が大きすぎる大きな値に発散してしまう >>> init_x = np.array([-3.0, 4.0]) >>> gradient_descent(function_2, init_x=init_x, lr=10, step_num=100) [-2.58983747e+13 -1.29524862e+12] # 学習率が小さすぎるとほとんど更新されずに終わる >>> init_x = np.array([-3.0, 4.0]) >>> gradient_descent(function_2, init_x=init_x, lr=le-10, step_num=100) [-2.999999994, 3.99999992]
二層ニューラルネットワーク
# coding: utf-8 import sys, os sys.path.append(os.pardir) # 親ディレクトリのファイルをインポートするための設定 from common.functions import * from common.gradient import numerical_gradient class TwoLayerNet: def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01): # 重みの初期化 self.params = {} self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size) self.params['b1'] = np.zeros(hidden_size) self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size) self.params['b2'] = np.zeros(output_size) def predict(self, x): W1, W2 = self.params['W1'], self.params['W2'] b1, b2 = self.params['b1'], self.params['b2'] a1 = np.dot(x, W1) + b1 z1 = sigmoid(a1) a2 = np.dot(z1, W2) + b2 y = softmax(a2) return y # x:入力データ, t:教師データ def loss(self, x, t): y = self.predict(x) return cross_entropy_error(y, t) def accuracy(self, x, t): y = self.predict(x) y = np.argmax(y, axis=1) t = np.argmax(t, axis=1) accuracy = np.sum(y == t) / float(x.shape[0]) return accuracy # x:入力データ, t:教師データ def numerical_gradient(self, x, t): loss_W = lambda W: self.loss(x, t) grads = {} grads['W1'] = numerical_gradient(loss_W, self.params['W1']) grads['b1'] = numerical_gradient(loss_W, self.params['b1']) grads['W2'] = numerical_gradient(loss_W, self.params['W2']) grads['b2'] = numerical_gradient(loss_W, self.params['b2']) return grads def gradient(self, x, t): W1, W2 = self.params['W1'], self.params['W2'] b1, b2 = self.params['b1'], self.params['b2'] grads = {} batch_num = x.shape[0] # forward a1 = np.dot(x, W1) + b1 z1 = sigmoid(a1) a2 = np.dot(z1, W2) + b2 y = softmax(a2) # backward dy = (y - t) / batch_num grads['W2'] = np.dot(z1.T, dy) grads['b2'] = np.sum(dy, axis=0) dz1 = np.dot(dy, W2.T) da1 = sigmoid_grad(a1) * dz1 grads['W1'] = np.dot(x.T, da1) grads['b1'] = np.sum(da1, axis=0) return grads
# coding: utf-8 import sys, os sys.path.append(os.pardir) # 親ディレクトリのファイルをインポートするための設定 import numpy as np import matplotlib.pyplot as plt from dataset.mnist import load_mnist from two_layer_net import TwoLayerNet # データの読み込み (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True) network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10) iters_num = 10000 # 繰り返しの回数を適宜設定する train_size = x_train.shape[0] batch_size = 100 learning_rate = 0.1 train_loss_list = [] train_acc_list = [] test_acc_list = [] iter_per_epoch = max(train_size / batch_size, 1) for i in range(iters_num): batch_mask = np.random.choice(train_size, batch_size) x_batch = x_train[batch_mask] t_batch = t_train[batch_mask] # 勾配の計算 #grad = network.numerical_gradient(x_batch, t_batch) grad = network.gradient(x_batch, t_batch) # パラメータの更新 for key in ('W1', 'b1', 'W2', 'b2'): network.params[key] -= learning_rate * grad[key] loss = network.loss(x_batch, t_batch) train_loss_list.append(loss) if i % iter_per_epoch == 0: train_acc = network.accuracy(x_train, t_train) test_acc = network.accuracy(x_test, t_test) train_acc_list.append(train_acc) test_acc_list.append(test_acc) print("train acc, test acc | " + str(train_acc) + ", " + str(test_acc)) # グラフの描画 markers = {'train': 'o', 'test': 's'} x = np.arange(len(train_acc_list)) plt.plot(x, train_acc_list, label='train acc') plt.plot(x, test_acc_list, label='test acc', linestyle='--') plt.xlabel("epochs") plt.ylabel("accuracy") plt.ylim(0, 1.0) plt.legend(loc='lower right') plt.show()
まとめ
ニューラルネットワークの学習手順は下記。
ミニバッチ
訓練データからランダムに一部のデータを選び(ミニバッチ)、そのミニバッチの損失関数の値を減らすことを目的とする。勾配
ミニバッチの損失関数を減らすために、重みパラメータの勾配を求める。パラメータの更新
重みパラメータを勾配方向に更新する。更新量はハイパーパラメータの学習率で設定する。1~3を繰り返す
DockerコンテナでPython3、Jupyterの入ったデータ分析環境を作成
背景
データ分析コンペに参加した時に、爆速で Docker コンテナにデータ分析環境を生成するテンプレート を作りましたを参考に、DockerコンテナにJupyter notebookが使える環境構築をしたのでその手順についてまとめました。めちゃくちゃ早く環境構築ができるのと、Dockerコンテナを利用することで環境の再現性が出る等のメリットがあります。
プロジェクトディレクトリ作成
cookiecutterのインストール
$ pip install cookiecutter
プロジェクトディレクトリの作成
$ cookiecutter git@github.com:docker-science/cookiecutter-docker-science.git project_name [project_name]: xxxxxxxxxx project_slug [national_park_prediction]: national_park_prediction jupyter_host_port [8888]: 8888 description [Please Input a short description]: This repository is for predicting the number of accumdation in national park Select data_source_type: 1 - s3 2 - nfs 3 - url Choose from 1, 2, 3 [1]: 1 # AWSのS3を使用する data_source [Please Input data source]: s3://project/national_park_prediction/data # S3のデータ格納ディレクトリ Select use_nvidia_docker: 1 - no 2 - yes Choose from 1, 2 [1]: 1 # GPUは使用しない
プロジェクトディレクトリが作成されていることを確認
$ ls Makefile config docker national_park_prediction requirements.txt tests README.md data model notebook scripts
イメージ作成・コンテナ起動・修正
作成されたディレクトリでDockerfileからimageの作成、コンテナの起動を行います。 requirements.txtをみるとわかるように、デフォルトでは必要最低限のPythonモジュールをインストールする設定なので必要に応じて追記を行ってimageを作成する必要がありそうです。
イメージの作成
$ make init-docker docker build -t national_park_prediction-image -f docker/Dockerfile --build-arg UID=501 . Sending build context to Docker daemon 20.48kB Step 1/10 : FROM ubuntu:16.04 ... ... ... Successfully built ade3fb3ef298 Successfully tagged national_park_prediction-image:latest
イメージが作成されていることを確認
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE national_park_prediction-image latest 2e8a7ad94a6a 9 seconds ago 797MB
# コンテナ起動・自動ログイン $ make create-container docker run -it -v `pwd`:/work -p 8888:8888 --name national_park_prediction-container national_park_prediction-image docker@187ca128cd75:/work$
コンテナ内にプロジェクトディレクトリがマウントされている
$ ls Makefile README.md config data docker forecast_tourist_accomdation_in_national_park model notebook requirements.txt scripts tests
コンテナ内でPythonモジュールをインストールした場合、Dockerfileにも反映をさせて、再度イメージファイルを作成して環境の再現性を保つようにしましょう。例えば、モデル作成に利用したxgboostをコンテナ上でインストールした場合、下記のようにrequirements.txtに追記してビルドを行い、そのイメージファイルを元に再度コンテナを起動します。
awscli click matplotlib jupyter notebook Sphinx flake8 xgboost
起動中のコンテナを表示
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 187ca128cd75 national_park_prediction-image "/bin/bash" 8 days ago Up 8 days 0.0.0.0:8888->8888/tcp national_park_prediction-container
対象のコンテナを停止
$ docker stop 187ca128cd75
187ca128cd75
イメージの削除
$ make clean-docker docker rm national_park_prediction-container national_park_prediction-container docker image rm national_park_prediction-image Untagged: national_park_prediction-image:latest Deleted: sha256:2e8a7ad94a6a4e75cbd3c67d6a87327108c356bd5add3e5851a9221f45231ad5 ・・・ ・・・ ・・・
ビルド
$ make init-docker
Jupyter notebookの起動
コンテナ上でJupyter notebookの起動を行います。起動後は http://localhost:8888/?token=xxxxxxxxxxxxxxxx にアクセスするとJupyter notebookに入ることができます。 xxxxxの部分はmake jupyterコマンド時に表示されており、下記の例でいうと 7fa9347363b180321b65bac24b900b31d0df6e12a6504fb7 になります。
$ make jupyter jupyter-notebook --ip=0.0.0.0 --port=8888 [I 01:04:36.114 NotebookApp] Writing notebook server cookie secret to /home/docker/.local/share/jupyter/runtime/notebook_cookie_secret [I 01:04:36.435 NotebookApp] Serving notebooks from local directory: /work [I 01:04:36.435 NotebookApp] The Jupyter Notebook is running at: [I 01:04:36.436 NotebookApp] http://(187ca128cd75 or 127.0.0.1):8888/?token=7fa9347363b180321b65bac24b900b31d0df6e12a6504fb7 [I 01:04:36.436 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). [W 01:04:36.437 NotebookApp] No web browser found: could not locate runnable browser. [C 01:04:36.438 NotebookApp] Copy/paste this URL into your browser when you connect for the first time, to login with a token: http://(187ca128cd75 or 127.0.0.1):8888/?token=7fa9347363b180321b65bac24b900b31d0df6e12a6504fb7
AWS Redshiftを使ってデータをロードしてクエリを実行するまで
AWS Redshiftとは
完全マネージド型、ペタバイトスケールのAWSデータウェアハウスサービス。
AWS Athenaとの違い
「Amazon Athena よくある質問」には下記記載あり。大きな違いは、課金体系でRedshiftはクラスタの起動時間課金に対して、Athenaの場合はデータ使用量に対する課金になります。
Amazon Redshift のクエリエンジンは、非常に大規模なデータベーステーブルを多数結合する複雑なクエリを実行する必要がある場合のユースケースで、パフォーマンスを特に発揮するように最適化されています。非常に大規模な多数のテーブル間で多数の結合がある、高度に構造化されたデータに対してクエリを実行する必要がある場合は、Amazon Redshift をお勧めします。
これに対して、Amazon Athena のようなクエリサービスを使用すると、データの形式化やインフラストラクチャの管理について心配することなく、Amazon S3 のデータに対して直接インタラクティブにクエリを実行できます。例えば、Athena は、一部のウェブログですばやくクエリを実行し、サイトのパフォーマンス問題のトラブルシューティングのみが必要とされる場合に適しています。クエリサービスを使用すると、迅速に開始できます。データのテーブルを定義し、標準 SQL を使用してクエリを開始するのみです。
課金体系
Redshiftはオンデマンドの場合、クラスタの起動時間課金になります。Redshift Spectrumの場合、スキャンされたバイト数に対して課金されます。Athenaの場合、スキャンされたデータ 1TB あたり 5USDがかかります。
準備
入門ガイドである Amazon Redshift の使用開始 を参考に進めます。 ガイド通りにSQL Workbench/JというSQL クライアントツールをインストールをしました。
Amazon S3 のサンプルデータをロードする
CREATE TABLE
CREATE TABLE を参考に、Workbench/Jから下記DDL(Data Definition Language)を実行して、新しいテーブルを作成します。
create table users( userid integer not null distkey sortkey, username char(8), firstname varchar(30), lastname varchar(30), city varchar(30), state char(2), email varchar(100), phone char(14), likesports boolean, liketheatre boolean, likeconcerts boolean, likejazz boolean, likeclassical boolean, likeopera boolean, likerock boolean, likevegas boolean, likebroadway boolean, likemusicals boolean); create table venue( venueid smallint not null distkey sortkey, venuename varchar(100), venuecity varchar(30), venuestate char(2), venueseats integer); create table category( catid smallint not null distkey sortkey, catgroup varchar(10), catname varchar(10), catdesc varchar(50)); create table date( dateid smallint not null distkey sortkey, caldate date not null, day character(3) not null, week smallint not null, month character(5) not null, qtr character(5) not null, year smallint not null, holiday boolean default('N')); create table event( eventid integer not null distkey, venueid smallint not null, catid smallint not null, dateid smallint not null sortkey, eventname varchar(200), starttime timestamp); create table listing( listid integer not null distkey, sellerid integer not null, eventid integer not null, dateid smallint not null sortkey, numtickets smallint not null, priceperticket decimal(8,2), totalprice decimal(8,2), listtime timestamp); create table sales( salesid integer not null, listid integer not null distkey, sellerid integer not null, buyerid integer not null, eventid integer not null, dateid smallint not null sortkey, qtysold smallint not null, pricepaid decimal(8,2), commission decimal(8,2), saletime timestamp);
s3にあるサンプルデータをロード
copy users from 's3://awssampledbuswest2/tickit/allusers_pipe.txt' credentials 'aws_iam_role=<iam-role-arn>' delimiter '|' region 'us-west-2'; copy venue from 's3://awssampledbuswest2/tickit/venue_pipe.txt' credentials 'aws_iam_role=<iam-role-arn>' delimiter '|' region 'us-west-2'; copy category from 's3://awssampledbuswest2/tickit/category_pipe.txt' credentials 'aws_iam_role=<iam-role-arn>' delimiter '|' region 'us-west-2'; copy date from 's3://awssampledbuswest2/tickit/date2008_pipe.txt' credentials 'aws_iam_role=<iam-role-arn>' delimiter '|' region 'us-west-2'; copy event from 's3://awssampledbuswest2/tickit/allevents_pipe.txt' credentials 'aws_iam_role=<iam-role-arn>' delimiter '|' timeformat 'YYYY-MM-DD HH:MI:SS' region 'us-west-2'; copy listing from 's3://awssampledbuswest2/tickit/listings_pipe.txt' credentials 'aws_iam_role=<iam-role-arn>' delimiter '|' region 'us-west-2'; copy sales from 's3://awssampledbuswest2/tickit/sales_tab.txt' credentials 'aws_iam_role=<iam-role-arn>' delimiter '\t' timeformat 'MM/DD/YYYY HH:MI:SS' region 'us-west-2';
クエリ実行
SELECT * FROM pg_table_def WHERE tablename = 'sales';
public sales salesid integer delta32k false 0 true public sales listid integer delta32k true 0 true public sales sellerid integer delta32k false 0 true public sales buyerid integer delta32k false 0 true public sales eventid integer delta32k false 0 true public sales dateid smallint lzo false 1 true public sales qtysold smallint lzo false 0 true public sales pricepaid numeric(8,2) lzo false 0 false public sales commission numeric(8,2) delta32k false 0 false public sales saletime timestamp without time zone lzo false 0 false
クラスターのリセット
ステップ 7: 他のリソースの検索と環境のリセットを参考にクラスターを削除します。クラスターをするまで、そのクラスターについて Amazon Redshift サービスの使用料が継続して発生するので注意しましょう。
pandasのread_csv時にdtypeを指定してメモリの節約
Kaggleで大きいデータの取り扱い
Microsoft Malware Predictionというコンペに参加しています。 このコンペでは与えられたデータが大きく、普通にread_csvだとローカルPCではメモリに乗りきりません。 こんな時いくつか方法がありますが、今回はread_csvのdtype指定についてまとめます。データは4.08 GBです。
pandasのread_csv時にdtypeを指定
pandasの仕様上、read_csv時にdtypeを指定しないと、整数はint64 、小数はfloat64 が勝手に割り当てられるようです。なので、必要最低限の型を割り当てる必要があります。
dtypes = { 'MachineIdentifier': 'category', 'ProductName': 'category', ・ ・ ・ 'OsSuite': 'int16', 'OsPlatformSubRelease': 'category', 'Census_IsVirtualDevice': 'float16', 'Census_IsTouchEnabled': 'int8', 'Census_IsPenCapable': 'int8', 'Wdft_IsGamer': 'float16', 'Wdft_RegionIdentifier': 'float16', 'HasDetections': 'int8' }
df_train = pd.read_csv('../input/train.csv', dtype=dtypes)
ではそもそもメモリに乗らないデータのカラムごとの型をどう見極めればいいでしょうか。方法としてはいくつかあると思いますが、read_csv時に読み込む行数を少なくしてデータを確認して必要なデータ型を調べる方法です。
df_train = pd.read_csv('../input/train.csv', nrows=10000) df_train.head(10000)
参考
初コンペ SIGNATE 国立公園の観光宿泊者数予測で18位でした
参加の背景
国立公園の観光宿泊者数予測というデータ分析コンペに初めて参加しました。目的としてはデータ分析の一通りの流れを試行錯誤しながら学びたかったためです。データ分析コンペは初参加で、このコンペ後にMicrosoft Malware Predictionに参加予定です。
コンペ概要
タスク
前日以前のデータを元に翌日以降の宿泊者数が予測可能なモデルを作成することです。
予測対象は8つの国立公園付近の1年間(2017/1/1~2017/12/31)の宿泊者数になります。
データ
- SNSデータ
- ロケーション付SNSデータ
- メッシュ型流動人口データ
- 公共交通検索ログデータ
- 国別月別来訪者数集計データ
- 気象データ
- 積雪気象観測データ
- 地域経済分析システム(RESAS)
最終順位の決定
コンペ最終日までの評価(暫定評価)は評価用データセットの一部で評価し、コンペ終了後の評価(最終評価)は評価用データセットの残りの部分で評価します。
これは特定のデータに過学習(Overfitting)するのを防ぐためで、暫定評価用のデータセットに最適化したモデルを作成するとコンペ終了後の評価用データセットに適合しないモデルになってしまいます。つまりモデルが汎化していないといけないということになります。この辺りの話は Machine Learning | Courseraで学びました。
また、順位確定の際に下記の情報を提出する必要があります。予測結果の再現の為の手順書は、コメントかJupyter NotebookのセルにMarkdownで記載すれば良さそうです。
- 予測モデルのソースコード
- 学習済モデル
- 予測結果の再現の為の手順書(前処理部分、学習部分、予測部分が分かるよう明記)
- 実行環境(OSのバージョン、使用ソフトウェア及び解析手法)
- 乱数シード(Random Forest等の乱数を利用した手法の場合)
- 各説明変数の予測モデルへの寄与度(寄与度の算出が可能な手法を用いた場合)
- データの解釈、工夫点、モデリングから得られる示唆等
評価
精度評価は、評価関数「Mean Absolute Error(MAE)」です。
MAEは平均絶対誤差ともいい、外れ値をより大きな誤差として扱う傾向があるそうです。
また、Pythonの代表的な機械学習のライブラリであるscikit-learn には MAE を計算する関数が実装されています。
モデル作成までの流れ
データのDL
国立公園の観光宿泊者数予測のデータページからデータをダウンロードしました。
分析環境作成
プロジェクトフォルダの作成
ディレクトリ構成を作るためのライブラリである Cookiecutter を使用して、機械学習用のプロジェクトディレクトリを作成しました。ディレクトリ作成後、ダウンロードしたデータを data/raw ディレクトリに格納しました。
参考:DockerコンテナでPython3、Jupyterの入ったデータ分析環境を作成する
初めはローカル環境(Macbook Pro)で分析を進めていましたが、リソースが足りない時が時々あったため、途中からはソース管理していたGitHubから読み込んでGoogle Colabrataryを使用して進めました。
Google Colabのスペックは下記になります。
- n1-highmem-2 instance
- 2vCPU @ 2.2GHz
- 13GB RAM
- 33GB Free Space
- idle cut-off 90 minutes
- maximum 12 hours
ソース管理
ソース管理はgitを使いました。リポジトリの作成方法は、https://github.com/new において New Reposotryを作成し、下記コマンドを対象ディレクトリで行えばいいでしょう。これ以降は適宜commit, pushをしていきます。(コンペ開催期間でのPublicリポジトリでの管理は有りなのでしょうか。)
$ pwd /Users/username/national_park_prediction $ git init # ワーキングディレクトリにgitリポジトリ作成 $ git add . # 全ファイル、全ディレクトリをインデックスに追加 $ git commit -m "first commit" # インデックスにあるファイル・ディレクトリをローカルリポジトリに記録 # リモートリポジトリ(national_park_prediction.git)をoriginという名前で登録 $ git remote add origin git@github.com:TaigoKuriyama/national_park_prediction.git $ git push -u origin master # リモートリポジトリにアップロード
issue管理
issue管理もGithub上で行いました。issueとは例えば、モデル作成中や環境構築時に出たエラーなどをあげて、どうやって解消したかを記載していきます。 今後似たようなことが起きた時に参考にできます。
ToDo管理
ToDo管理もGithubのProjects機能を使い、Inbox, In Progress, Doneと分けてタスクを管理しました。
コンペへの取り組み方理解
kaggleのチュートリアル。機械学習の入門に最適!に取り組み、コンペへどう取り組むかについて理解しました。こちらのnoteはkaggle(データ分析コンペプラットフォーム)を対象としたチュートリアルになりますが、コンペの取り組み方という意味ではとても参考になります。有料ですので詳細については書くことができませんがコンペに取り組んでみたいが、どうすればいいかわからないという方は購入してみてもいいかもしれません。
有料が厳しい場合は、こちら 一から始める機械学習(Kaggleで学ぶ機械学習) で学ぶのがいいかもしれません。
分析は主に下記の流れを繰り返すことと理解しました。
- データ前処理
- アルゴリズム選択
- パラメータ選択
- モデルの学習
- 評価
- 提出
データ概要理解
データ説明
コンペページのデータ説明に内容が書かれているのでまずはそれを読みつつ、実際のデータを確認しました。
データ詳細
データ分析のライブラリであるpandasを使って各データの詳細について理解を深めました。read_csv時には ファイル形式はcsv ( 項目間をカンマで区切ったデータ ) ではなく、tsv形式 ( 項目間をタブで区切ったデータ )なので、read_csvには sep='\t' というオプションが必要です。
# データの確認(観光宿泊者学習データの場合) import pandas as pd df_train = pd.read_csv('../data/raw/train.tsv',sep='\t') df_train.head()
# データ確認 df.head(n) # データフレームの上からn行を表示 df.shape # データフレームの行数と列数 df.columns # カラム df.info() # データの概要 df.isnull().sum() # 欠損値の数 df.describe() # 要約統計量
日付ごとの平均visitor数を降順に並べると、当たり前ですがGWや年末年始が多いことがわかります。よって祝日フラグデータがあればいいと考えました。
ネットで見つからなかったのでGoogle SpreadSheetで休日データの作成をしました。 まずは、土日フラグを下記の式で立てます。
=IF(( WEEKDAY(A2, 2) >= 6 ),1,0)
祝日のリストはこちらいただきました。土日リストと祝日リストからholiday.csvを作成しました。
特徴量について
最終的に使用した特徴量は下記になります。
仮説を立ててデータから試行錯誤して特徴量を作成し、モデルを作成、Cross Validationの結果を見てSubmitを繰り返すという流れを続けましたが最終的に使用したのは気象データ(気象庁)のみでした。
- 日
- 月
- 曜日
- 公園
- 休日
- sin, cos, tan
- 気温
- 降水量
- 降雪量
結果
最終結果は18位/124人となりました。
学び・反省・疑問
自分の足りないスキル、知識が明確になったのでとてもいい機会になりました。具体的には下記が学び・反省・疑問になります。
- データ探索のスキルが浅く与えられたデータから有益な特徴量が発見できなかった
- フォーラムのようなものが無く、完全に個人で進める感じだったので周りから勉強をする機会が無く残念だった
- モデルのアンサンブルをする時間が無かった
- 特徴量、モデル、提出ファイルの管理をどうすればいいか分からなかった
- 時系列データへの取り組み方が正しいのか分かっていない
- コンペ中はずっと Jupyter Notebookでコーディングするのだろうか?
当該Gitリポジトリ
全然まとまっていませんが、下記がコンペのリポジトリになります。 https://github.com/TaigoKuriyama/national_park_prediction
参考
【読書メモ】ゼロから作るDeep Learning 3章
ゼロから作るDeep Learning
ゼロから作るDeep Learningの読書メモとしてまとめました。
本を読む目的
Coursera Machine Learningを受講してニューラルネットワークを理解したので、次はディープラーニングについて深く理解をしたいため。
前章までのまとめ
内容
ステップ関数
# coding: utf-8 import numpy as np import matplotlib.pylab as plt def step_function(x): return np.array(x > 0, dtype=np.int) X = np.arange(-5.0, 5.0, 0.1) Y = step_function(X) plt.plot(X, Y) plt.ylim(-0.1, 1.1) # 図で描画するy軸の範囲を指定 plt.show()
シグモイド関数
# coding: utf-8 import numpy as np import matplotlib.pylab as plt def sigmoid(x): return 1 / (1 + np.exp(-x)) X = np.arange(-5.0, 5.0, 0.1) Y = sigmoid(X) plt.plot(X, Y) plt.ylim(-0.1, 1.1) plt.show()
ステップ関数・シグモイド関数の共通点
- 入力が小さい時に出力は0に近く、入力が大きい時に出力は1に近づく
- 出力信号は0から1の間
- 非線形関数
Relu関数
最近のニューラルネットワークはRelu(Rectified Linear Unit)関数を主に用いている。
# coding: utf-8 import numpy as np import matplotlib.pylab as plt def relu(x): return np.maximum(0, x) x = np.arange(-5.0, 5.0, 0.1) y = relu(x) plt.plot(x, y) plt.ylim(-1.0, 5.5) plt.show()
ニューラルネットワークのnumpy実装
- 回帰問題の場合、出力層の活性化関数を恒等関数(入力をそのまま出力する関数)として利用する
- 分類問題の場合、ソフトマックス関数を利用する
## Neural Network import numpy as np def sigmoid(x): return 1 / (1 + np.exp(-x)) def indentity_function(x): return x def init_network(): network = {} network['W1'] = np.array([[0.1,0.3,0.5], [0.2,0.4,0.6]]) network['b1'] = np.array([0.1,0.2,0.3]) network['W2'] = np.array([[0.1,0.4], [0.2,0.5], [0.3,0.6]]) network['b2'] = np.array([0.1,0.2]) network['W3'] = np.array([[0.1,0.3], [0.2,0.4]]) network['b3'] = np.array([0.1,0.2]) return network def forward(network, x): W1, W2, W3 = network['W1'], network['W2'], network['W3'] b1, b2, b3 = network['b1'], network['b2'], network['b3'] a1 = np.dot(x, W1) + b1 z1 = sigmoid(a1) a2 = np.dot(z1, W2) + b2 z2 = sigmoid(a2) a3 = np.dot(z2, W3) + b3 y = indentity_function(a3) return y network = init_network() x = np.array([1.0, 0.5]) y = forward(network, x) print(y)
$ python nn.py [0.31682708 0.69627909]
ソフトマックス関数
- ソフトマックス関数の出力は0〜1
- 出力の総和は1になる
- よって、ソフトマックス関数の出力を確率として解釈できる
import numpy as np # softmax function def softmax(a): exp_a = np.exp(a) # 指数関数 sum_exp_a = np.sum(exp_a) y = exp_a / sum_exp_a return y a = np.array([0.3,2.9,4.0]) y = softmax(a) print(y)
$ python softmax.py [0.01821127 0.24519181 0.73659691]
【読書メモ】ゼロから作るDeep Learning 2章
ゼロから作るDeep Learning
ゼロから作るDeep Learningの読書メモとしてまとめました。
本を読む目的
Coursera Machine Learningを受講してニューラルネットワークを理解したので、次はディープラーニングについて深く理解をしたいため。
前章までのまとめ
内容
パーセプトロンとは
- パーセプトロンとは複数の信号を入力として受け取り、一つの信号を出力するアルゴリズム
- ニューラルネットワーク(ディープラーニング)の起源となるもの
- パーセプトロンの信号は1or0の二値
パーセプトロンの実装
ANDゲート
# coding: utf-8 import numpy as np def AND(x1, x2): x = np.array([x1, x2]) w = np.array([0.5, 0.5]) b = -0.7 tmp = np.sum(w*x) + b if tmp <= 0: return 0 else: return 1 if __name__ == '__main__': for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]: y = AND(xs[0], xs[1]) print(str(xs) + " -> " + str(y))
$ python and_gate.py (0, 0) -> 0 (1, 0) -> 0 (0, 1) -> 0 (1, 1) -> 1
NANDゲート
# coding: utf-8 import numpy as np def NAND(x1, x2): x = np.array([x1, x2]) w = np.array([-0.5, -0.5]) b = 0.7 tmp = np.sum(w*x) + b if tmp <= 0: return 0 else: return 1 if __name__ == '__main__': for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]: y = NAND(xs[0], xs[1]) print(str(xs) + " -> " + str(y))
$ python nand_gate.py (0, 0) -> 1 (1, 0) -> 1 (0, 1) -> 1 (1, 1) -> 0
ORゲート
# coding: utf-8 import numpy as np def OR(x1, x2): x = np.array([x1, x2]) w = np.array([0.5, 0.5]) b = -0.2 tmp = np.sum(w*x) + b if tmp <= 0: return 0 else: return 1 if __name__ == '__main__': for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]: y = OR(xs[0], xs[1]) print(str(xs) + " -> " + str(y))
python or_gate.py (0, 0) -> 0 (1, 0) -> 1 (0, 1) -> 1 (1, 1) -> 1
XORゲート
XORゲートは第一層にNANDとORゲート、第二層にAND。
# coding: utf-8 from and_gate import AND from or_gate import OR from nand_gate import NAND def XOR(x1, x2): s1 = NAND(x1, x2) s2 = OR(x1, x2) y = AND(s1, s2) return y if __name__ == '__main__': for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]: y = XOR(xs[0], xs[1]) print(str(xs) + " -> " + str(y))
【読書メモ】ゼロから作るDeep Learning 1章
ゼロから作るDeep Learning
ゼロから作るDeep Learningの読書メモとしてまとめました。
本を読む目的
Coursera Machine Learningを受講してニューラルネットワークを理解したので、次はディープラーニングについて深く理解をしたいため。
内容
プログラムのダウンロード
本を内容のプログラムはgit clone してダウンロードしました。
$ git clone https://github.com/oreilly-japan/deep-learning-from-scratch
Pythonのクラス
- initメソッドはコンストラクタ。
- メソッドの第一引数に自身のインスタンスを表すselfを明示的に書く
- Manクラスからmというインスタンスを生成
- コンストラクタによって、self.name(インスタンス変数)を初期化
# man.py # coding: utf-8 class Man: def __init__(self, name): self.name = name print("Initilized!") def hello(self): print("Hello " + self.name + "!") def goodbye(self): print("Good-bye " + self.name + "!") m = Man("David") m.hello() m.goodbye()
$ python man.py Initilized! Hello David! Good-bye David!