TensorFlowバックエンドでkerasを使用して、画像の特徴を予測しようとしています。具体的には、keras ImageDataGenerator
を使用しようとしています。モデルは4エポックで実行するように設定されており、MemoryErrorで失敗する4エポックまで正常に動作します。
このモデルをAWSで実行しています g2.2xlarge Ubuntu Server 16.04 LTS(HVM)、SSD Volume Typeを実行しているインスタンス。
トレーニング画像は256x256 RGBピクセルタイル(8ビット符号なし)であり、トレーニングマスクは256x256シングルバンド(8ビット符号なし)タイルデータです。ここで、255 ==対象の特徴、0 ==その他すべてです。
次の3つの関数は、このエラーに関連するものです。
このMemoryErrorを解決するにはどうすればよいですか?
def train_model():
batch_size = 1
training_imgs = np.lib.format.open_memmap(filename=os.path.join(data_path, 'data.npy'),mode='r+')
training_masks = np.lib.format.open_memmap(filename=os.path.join(data_path, 'mask.npy'),mode='r+')
dl_model = create_model()
print(dl_model.summary())
model_checkpoint = ModelCheckpoint(os.path.join(data_path,'mod_weight.hdf5'), monitor='loss',verbose=1, save_best_only=True)
dl_model.fit_generator(generator(training_imgs, training_masks, batch_size), steps_per_Epoch=(len(training_imgs)/batch_size), epochs=4,verbose=1,callbacks=[model_checkpoint])
def generator(train_imgs, train_masks=None, batch_size=None):
# Create empty arrays to contain batch of features and labels#
if train_masks is not None:
train_imgs_batch = np.zeros((batch_size,y_to_res,x_to_res,bands))
train_masks_batch = np.zeros((batch_size,y_to_res,x_to_res,1))
while True:
for i in range(batch_size):
# choose random index in features
index= random.choice(range(len(train_imgs)))
train_imgs_batch[i] = train_imgs[index]
train_masks_batch[i] = train_masks[index]
yield train_imgs_batch, train_masks_batch
else:
rec_imgs_batch = np.zeros((batch_size,y_to_res,x_to_res,bands))
while True:
for i in range(batch_size):
# choose random index in features
index= random.choice(range(len(train_imgs)))
rec_imgs_batch[i] = train_imgs[index]
yield rec_imgs_batch
def train_generator(train_images,train_masks,batch_size):
data_gen_args=dict(rotation_range=90.,horizontal_flip=True,vertical_flip=True,rescale=1./255)
image_datagen = ImageDataGenerator()
mask_datagen = ImageDataGenerator()
# # Provide the same seed and keyword arguments to the fit and flow methods
seed = 1
image_datagen.fit(train_images, augment=True, seed=seed)
mask_datagen.fit(train_masks, augment=True, seed=seed)
image_generator = image_datagen.flow(train_images,batch_size=batch_size)
mask_generator = mask_datagen.flow(train_masks,batch_size=batch_size)
return Zip(image_generator, mask_generator)
以下は、エポックとエラーメッセージを詳述するモデルからの出力です。
Epoch 00001: loss improved from inf to 0.01683, saving model to /home/ubuntu/deep_learn/client_data/mod_weight.hdf5
Epoch 2/4
7569/7569 [==============================] - 3394s 448ms/step - loss: 0.0049 - binary_crossentropy: 0.0027 - jaccard_coef_int: 0.9983
Epoch 00002: loss improved from 0.01683 to 0.00492, saving model to /home/ubuntu/deep_learn/client_data/mod_weight.hdf5
Epoch 3/4
7569/7569 [==============================] - 3394s 448ms/step - loss: 0.0049 - binary_crossentropy: 0.0026 - jaccard_coef_int: 0.9982
Epoch 00003: loss improved from 0.00492 to 0.00488, saving model to /home/ubuntu/deep_learn/client_data/mod_weight.hdf5
Epoch 4/4
7569/7569 [==============================] - 3394s 448ms/step - loss: 0.0074 - binary_crossentropy: 0.0042 - jaccard_coef_int: 0.9975
Epoch 00004: loss did not improve
Traceback (most recent call last):
File "image_rec.py", line 291, in <module>
train_model()
File "image_rec.py", line 208, in train_model
dl_model.fit_generator(train_generator(training_imgs,training_masks,batch_size),steps_per_Epoch=1,epochs=1,workers=1)
File "image_rec.py", line 274, in train_generator
image_datagen.fit(train_images, augment=True, seed=seed)
File "/home/ubuntu/pyvirt_test/local/lib/python2.7/site-packages/keras/preprocessing/image.py", line 753, in fit
x = np.copy(x)
File "/home/ubuntu/pyvirt_test/local/lib/python2.7/site-packages/numpy/lib/function_base.py", line 1505, in copy
return array(a, order=order, copy=True)
MemoryError
あなたの問題はデータが大きすぎるためであるようです。私は2つの解決策を見ることができます。最初の方法は、sparkを使用して分散システムでコードを実行することです。このサポートはないので、もう一方に進みましょう。
2つ目は実行可能だと思います。データをスライスし、モデルにインクリメンタルにフィードしてみます。 Daskでこれを行うことができます。このライブラリは、データをスライスしてオブジェクトに保存し、必要な部分でのみディスクから読み取り値を取得できます。
サイズが100x100のマトリックスであるイメージがある場合、100個の配列をメモリにロードする必要なく各配列を取得できます。メモリ内の配列ごとに配列をロードできます(前のものを解放します)。これがニューラルネットワークの入力になります。
これを行うには、np.arrayをdask arrayに変換し、パーティションを割り当てることができます。例えば:
>>> k = np.random.randn(10,10) # Matrix 10x10
>>> import dask.array as da
>>> k2 = da.from_array(k,chunks = 3)
dask.array<array, shape=(10, 10), dtype=float64, chunksize=(3, 3)>
>>> k2.to_delayed()
array([[Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 0, 0)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 0, 1)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 0, 2)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 0, 3))],
[Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 1, 0)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 1, 1)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 1, 2)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 1, 3))],
[Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 2, 0)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 2, 1)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 2, 2)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 2, 3))],
[Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 3, 0)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 3, 1)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 3, 2)),
Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 3, 3))]],
dtype=object)
ここで、データがオブジェクトにどのように保存されているかを確認し、モデルにフィードするために部分的に取得できます。
このソリューションを実装するには、関数にループを導入して、各パーティションを呼び出し、NNにフィードして増分トレーニングを取得する必要があります。
詳細については、Dask documentationを参照してください
これは、浮動小数点の精度が高すぎる場合に32ビットを実行するときに一般的です。 32ビットを実行していますか?配列のキャストまたは丸めを検討することもできます。
一般に、Keras/Tensorflowはリソースの使用に関して非常に優れていますが、過去に問題を引き起こしたことが知られているメモリリークがあります。それが問題の原因ではないことを確認するには、次の2行のコードをトレーニングスクリプトに含めてみてください。
# load the backend
from keras import backend as K
# prevent Tensorflow memory leakage
K.clear_session()
最近、同じ問題に出会いました。どういうわけか、FCN-8コードはtensorflow1.2 + keras2.0.9 + 8G RAM +1060コンピューターで正常に実行できますが、tf1.4 + keras2でmodelcheckpointを使用するとメモリエラーが発生しました。 1.5 + 16g RAM + 1080tiコンピューター。