ITエンジニア ノイのブログ

ITエンジニアのノイです。 YouTubeで ITエンジニアのお勉強という学習用の動画を公開しています。チャンネル登録お願いします!https://m.youtube.com/channel/UCBKfJIMVWXd3ReG_FDh31Aw/playlists

ミニバッチ学習のループ

復元抽出と非復元抽出

ミニバッチの学習には復元抽出と非復元抽出の2種類があります。 復元抽出(with replacement)と非復元抽出(without replacement)は、統計学機械学習においてデータをサンプリングする方法の違いを表しています。

復元抽出(with replacement)

サンプルを選択した後、元のデータセットに戻すことを許すサンプリング方法です。つまり、同じサンプルが複数回選ばれることがあります。この場合、サンプルの選択は独立であり、選ばれる確率は一定です。復元抽出は、ランダム性と確率の性質を維持しながら大規模なデータセットから比較的少数のサンプルを選ぶのに有用です。

非復元抽出(without replacement)

サンプルを選択した後、元のデータセットから取り除くサンプリング方法です。つまり、同じサンプルは一度しか選ばれません。この場合、選ばれるサンプルは前の選択に依存して変化します。非復元抽出は、データセット全体の特徴や分布を反映させるために使用されます。

  • コードの例(復元抽出) np.random.choice(train_size, batch_size)の部分で、train_sizeの範囲からbatch_size個のサンプルが重複を許してランダムに選ばれています。これにより、同じサンプルが複数回選ばれる可能性があります。

  • コードの例(非復元抽出) index = np.arange(train_size)でトレーニングデータのインデックスが生成され、np.random.shuffle(index)でそのインデックスがシャッフルされます。その後、ミニバッチを作成する際にシャッフルされたインデックスから部分配列を抽出することで、同じサンプルが複数回選ばれることはありません。

復元抽出の場合

コード

np.random.seed(1234)
train_size = train_labels.shape[0]
batch_size = 32
max_iter = 10  #ループの回数
network = None #ダミー

for i in range(max_iter):
    batch_mask = np.random.choice(train_size, batch_size) # 復元抽出
    print("i=%s, "%i, "batch_mask=%s"%batch_mask[:10])
    x_batch = train[batch_mask]
    y_batch = train_labels[batch_mask]

    trainer(network, x_batch, y_batch)

コード解説

このコードは、ニューラルネットワークのトレーニングループを実行しています。以下にコードの解説を示します。

  1. np.random.seed(1234): 乱数のシードを設定しています。これにより、再現性のあるランダムな動作が得られます。

  2. train_size = train_labels.shape[0]: train_labelsのサイズを取得し、train_sizeに代入しています。これはトレーニングデータのサンプル数を表します。

  3. batch_size = 32: バッチサイズを定義しています。バッチサイズとは、一度にネットワークに入力するサンプルの数です。

  4. max_iter = 10: ループの回数を定義しています。トレーニングデータ全体を何回繰り返して学習するかを表します。

  5. network = None: ネットワークモデルを表す変数networkを定義しています。このコードではダミーのままであり、実際のネットワークモデルは記述されていません。

  6. for i in range(max_iter):: ループをmax_iter回繰り返します。

  7. batch_mask = np.random.choice(train_size, batch_size): train_sizeの範囲から、バッチサイズの数だけ復元抽出(重複を許す抽出)を行い、batch_maskに代入します。これにより、ランダムに選択されたサンプルのインデックスが得られます。

  8. print("i=%s, "%i, "batch_mask=%s"%batch_mask[:10]): 現在のループ回数と選択されたバッチのインデックスを出力します。batch_mask[:10]は最初の10個のインデックスを表します。

  9. x_batch = train[batch_mask]: 選択されたバッチのインデックスを使って、トレーニングデータtrainから対応する部分配列を抽出し、x_batchに代入します。これにより、ネットワークへの入力データが得られます。

  10. y_batch = train_labels[batch_mask]: 選択されたバッチのインデックスを使って、トレーニングデータのラベルtrain_labelsから対応する部分配列を抽出し、y_batchに代入します。これにより、ネットワークへの正解データが得られます。

  11. trainer(network, x_batch, y_batch): trainer関数を呼び出し、ネットワークモデルnetworkとバッチデータx_batch、正解データy_batchを引数として渡しています。trainer関数は、ネットワークモデルを使用してバッチデータをトレーニングし、パラメータの更新を行う関数です。

  12. trainer(network, x_batch, y_batch): trainer関数を呼び出し、ネットワークモデルnetwork、バッチデータx_batch、正解データy_batchを渡しています。この関数は、ネットワークモデルに対してバッチデータを与えてトレーニングを行い、パラメータの更新を行います。

このコードは、与えられたトレーニングデータをバッチサイズごとにランダムに選択してミニバッチを作成し、それぞれのミニバッチを使ってネットワークモデルをトレーニングしています。ループはmax_iter回繰り返され、トレーニングデータ全体を複数回学習します。このようにランダムなミニバッチを用いることで、トレーニングデータ全体の特徴を反映しつつ、効率的にネットワークのパラメータを更新することができます。

非復元抽出の場合

コード

np.random.seed(1234)
train_size = train_labels.shape[0]
batch_size = 32
epochs = 10
network = None #ダミー
minibatch_num = np.ceil( train_size / batch_size).astype(int) #学習データをバッチ数で割ってミニバッチ数を求める
    
for epoch in range(epochs):
    index = np.arange(train_size)
    np.random.shuffle(index)
    
    for mn in range(minibatch_num):
        batch_mask = index[batch_size*mn:batch_size*(mn+1)]
        print("epoch=%s, "%epoch, "batch_mask=%s"%batch_mask[:10])
        x_batch = train[batch_mask]
        y_batch = train_labels[batch_mask]

        trainer(network, x_batch, y_batch)

コード解説

このコードは、ミニバッチ学習を行いながらニューラルネットワークのトレーニングを実行しています。以下にコードの解説を示します。

  1. np.random.seed(1234): 乱数のシードを設定しています。これにより、再現性のあるランダムな動作が得られます。

  2. train_size = train_labels.shape[0]: train_labelsのサイズを取得し、train_sizeに代入しています。これはトレーニングデータのサンプル数を表します。

  3. batch_size = 32: バッチサイズを定義しています。バッチサイズとは、一度にネットワークに入力するサンプルの数です。

  4. epochs = 10: エポック数を定義しています。エポック数は、トレーニングデータ全体を何回繰り返して学習するかを表します。

  5. network = None: ネットワークモデルを表す変数networkを定義しています。このコードではダミーのままであり、実際のネットワークモデルは記述されていません。

  6. minibatch_num = np.ceil(train_size / batch_size).astype(int): ミニバッチの個数を計算しています。トレーニングデータのサンプル数をバッチサイズで割り、小数点以下を切り上げて整数に変換しています。

  7. for epoch in range(epochs):: エポック数だけループを実行します。

  8. print(): 空行を出力します。

  9. index = np.arange(train_size): 0からtrain_size-1までの連番を生成し、indexに代入しています。これはトレーニングデータのインデックスを表します。

  10. np.random.shuffle(index): indexの要素をランダムにシャッフルします。これにより、トレーニングデータの順序がランダムになります。

  11. for mn in range(minibatch_num):: ミニバッチの個数だけループを実行します。

  12. batch_mask = index[batch_size*mn:batch_size*(mn+1)]: シャッフルされたインデックスから、ミニバッチに対応する部分配列を抽出し、batch_maskに代入します。これにより、ミニバッチ内のサンプルのインデックスが得られます。

  13. print("epoch=%s, "%epoch, "batch_mask=%s"%batch_mask[:10]): 現在のエポックとミニバッチのインデックスを出力します。batch_mask[:10]は最初の10個のインデックスを表します。

  14. x_batch = train[batch_mask]: 選択されたミニバッチのインデックスを使って、トレーニングデータtrainから対応する部分配列を抽出し、x_batchに代入します。これにより、ネットワークへの入力データが得られます。

  15. y_batch = train_labels[batch_mask]: 選択されたミニバッチのインデックスを使って、トレーニングデータのラベルtrain_labelsから対応する部分配列を抽出し、y_batchに代入します。これにより、ネットワークへの正解データが得られます。

  16. trainer(network, x_batch, y_batch): trainer関数を呼び出し、ネットワークモデルnetwork、バッチデータx_batch、正解データy_batchを渡しています。この関数は、ネットワークモデルに対してバッチデータを与えてトレーニングを行い、パラメータの更新を行います。

このコードは、与えられたトレーニングデータをエポックごとにシャッフルし、ミニバッチ学習を行いながらニューラルネットワークのトレーニングを実行します。各エポックでは、トレーニングデータをバッチサイズごとに非復元抽出(重複のない抽出)し、ミニバッチを作成します。これにより、トレーニングデータ全体を複数回学習し、ネットワークのパラメータを更新します。