【読書メモ】Deep Learningを学ぶ〜推論の実装をバッチ処理化する〜Part 15
最初に
本記事は以下の本から得た知見を自分用のメモも兼ねてまとめた記事となります。ただし本の内容をそのまま書き写ししているわけではなく、ある程度自身で調べたものや感想が混じっています。ご了承ください。
ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装
また、本記事は株式会社よむネコのプロジェクトの業務内のお時間を頂いて蓄積した知見となります。
以下会社URLです。
今回は、前回作成した、MNISTの手描き文字の推論をバッチ処理にしつつ、バッチ処理自体がどういったものかを学んでいきます。
バッチ処理とは?
n個のデータをまとめて計算したいと考えた場合に、入力の数値をnxにすると行列の積の計算を一度で行うことができます。例えば、100個のデータを一気に計算したい場合は、前回の例だとX=784, N=100, N×Xを入力として与えることでまとめて計算ができます。この場合、出力データの形状はYが10クラスだとするとN×Yとなります。与えたデータ分が一度に出力されます。
全ての訓練データ(n個)を1回で学習することを、1エポック(epoch)と数えます。
また、まとまりのある入力データの束をバッチと呼び、バッチをまとめて処理することをバッチ処理と呼びます。バッチに含まれるサンプル数のことをバッチサイズと呼びます。このバッチサイズは基本的に学習中ずっと一定です。
どのようなタイプの処理を行うかはバッチサイズに寄ります。これは追々確認していこうと思います。
なぜバッチ処理?
バッチ単位で推論処理を行うと計算が高速化できる。これは、NumPyなどの数値計算を扱うライブラリの殆どが大きな配列の計算を効率よく処理できるように最適化しているからです。
実際に前回の内容をバッチ処理に置き換える
前回の実装内容が以下の通りです。
x, t = get_data() network = init_network() # ニューラルネットワークが正解したカウント変数 accuracy_cnt = 0 for i in range(len(x)): y = predict(network, x[i]) # 最も確率の高い要素のインデックスを取得 p = np.argmax(y) # ニューラルネットワークが予測した答えと正解ラベルを比較 if p == t[i]: accuracy_cnt += 1 # 一致していれば正解数をインクリメント # 正解数 / xの要素数 = 正解率 print("Accuracy:" + str(float(accuracy_cnt) / len(x)) # 結果:0.9352 つまり93.52%
これをバッチ処理にすると以下のようになります。
x, t = get_data() network = init_network() accuracy_cnt = 0 # バッチサイズ batch_size = 100 # range(start, end, step=1ループ当たりstepの値分足されていく) for i in range(0, len(x), batch_size): # xのデータのi番目からi+batch_size番目までを取り出す. x_batch = x[i:i+batch_size] y_batch = predict(network, x_batch) # axis=1 とすると100*10の配列の中で1次元の要素ごとに # 最大値のインデックスを見つける. # [[0.1, 0.5, 0.4], [0.7, 0.2, 0.1], [0.8, 0.1, 0.1]] なら # [1 0 0] p = np.argmax(y_batch, axis=1) # p = [1, 0, 0], t = [1, 1, 0] なら [True, False, True] # cnt += np.sum(p == t) accuracy_cnt += np.sum(p == t[i:i+batch_size]) # 正解数 / xの要素数 = 正解率 print("Accuracy:" + str(float(accuracy_cnt) / len(x))
最後に
これでバッチ処理として高速に処理が行えるようになりました。次はニューラルネットワークの学習に関する章となります。頑張って進めていこうと思います。