2017-12-28 3 views
2

이것이 스택 오버플로의 첫 번째 질문이라고 생각합니다. 모든 지침을 따르지 않으면 사전에 사과드립니다. 최근 Kerr을 심화 학습에 사용하기 시작했으며 h5py를 사용하여 HD5 파일을 사용하여 대규모 데이터 세트를 관리하기 때문에 매우 큰 HDF5 파일에서 케라를 사용하여 모델을 학습하는 방법을 모색했습니다. 가장 일반적인 방법은 keras.utils.io_utils에있는 HDF5Matrix를 사용하는 것입니다. Keras를 레이블이있는 HDF5Matrix와 함께 사용

나는 다음과 같은 Keras 예 ( mnist.cnn) 중 하나 수정 :

'''Trains a simple convnet on the MNIST dataset. 

Gets to 99.25% test accuracy after 12 epochs 
(there is still a lot of margin for parameter tuning). 
16 seconds per epoch on a GRID K520 GPU. 
''' 

from __future__ import print_function 
import keras 
from keras.datasets import mnist 
from keras.models import Sequential 
from keras.layers import Dense, Dropout, Flatten 
from keras.layers import Conv2D, MaxPooling2D 
from keras import backend as K 

# My Imports 
from os.path import exists 
import h5py 
from keras.utils.io_utils import HDF5Matrix 
batch_size = 128 
num_classes = 10 
epochs = 12 

# input image dimensions 
img_rows, img_cols = 28, 28 

# the data, shuffled and split between train and test sets 
(x_train, y_train), (x_test, y_test) = mnist.load_data() 

if K.image_data_format() == 'channels_first': 
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols) 
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols) 
    input_shape = (1, img_rows, img_cols) 
else: 
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1) 
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1) 
    input_shape = (img_rows, img_cols, 1) 

x_train = x_train.astype('float32') 
x_test = x_test.astype('float32') 
x_train /= 255 
x_test /= 255 
print('x_train shape:', x_train.shape) 
print(x_train.shape[0], 'train samples') 
print(x_test.shape[0], 'test samples') 

# convert class vectors to binary class matrices 
y_train = keras.utils.to_categorical(y_train, num_classes) 
y_test = keras.utils.to_categorical(y_test, num_classes) 

#-----------------------------------HDF5 files creation--------------------------------------- 
sample_file_name = "x.hdf5" 
solution_file_name = "y.hdf5" 
train_name = "train" 
test_name = "test" 

#Create dataset 
if (not exists(sample_file_name)) and (not exists(solution_file_name)): 
    samples_file = h5py.File(sample_file_name,mode='a') 
    solutions_file = h5py.File(solution_file_name,mode='a') 
    samples_train = samples_file.create_dataset(train_name,data=x_train) 
    samples_test = samples_file.create_dataset(test_name, data=x_test) 
    solution_train = solutions_file.create_dataset(train_name, data=y_train) 
    solution_test = solutions_file.create_dataset(test_name, data=y_test) 
    samples_file.flush() 
    samples_file.close() 
    solutions_file.flush() 
    solutions_file.close() 

x_train = HDF5Matrix(sample_file_name,train_name) 
x_test = HDF5Matrix(sample_file_name,test_name) 
y_train = HDF5Matrix(solution_file_name,train_name) 
y_test = HDF5Matrix(solution_file_name,test_name) 
#--------------------------------------------------------------------------------------------- 

model = Sequential() 
model.add(Conv2D(32, kernel_size=(3, 3), 
       activation='relu', 
       input_shape=input_shape)) 
model.add(Conv2D(64, (3, 3), activation='relu')) 
model.add(MaxPooling2D(pool_size=(2, 2))) 
model.add(Dropout(0.25)) 
model.add(Flatten()) 
model.add(Dense(128, activation='relu')) 
model.add(Dropout(0.5)) 
model.add(Dense(num_classes, activation='softmax')) 

model.compile(loss=keras.losses.categorical_crossentropy, 
       optimizer=keras.optimizers.Adadelta(), 
       metrics=['accuracy']) 

# If using HDF5Matrix one needs to disable shuffle 
model.fit(x_train, y_train, 
      batch_size=batch_size, 
      epochs=epochs, 
      verbose=1, 
      validation_data=(x_test, y_test), 
      shuffle=False) 

score = model.evaluate(x_test, y_test, verbose=0) 
print('Test loss:', score[0]) 
print('Test accuracy:', score[1]) 

것은 그러나, 나에 관한 것이 있습니다. 세분화 문제 \ 클래스의 수가 매우 많은 다중 클래스 문제에서 솔루션을 범주 형식으로 저장하는 것은 매우 낭비입니다. 또한, 일단 새로운 클래스를 추가하면 전체 데이터 세트가 그에 따라 변경되어야한다는 것을 의미합니다. 나는 다음과 같은 HDF5Matrix의 정규화 기능을 사용하여 생각하는 이유입니다 :

'''Trains a simple convnet on the MNIST dataset. 

Gets to 99.25% test accuracy after 12 epochs 
(there is still a lot of margin for parameter tuning). 
16 seconds per epoch on a GRID K520 GPU. 
''' 

from __future__ import print_function 
import keras 
from keras.datasets import mnist 
from keras.models import Sequential 
from keras.layers import Dense, Dropout, Flatten 
from keras.layers import Conv2D, MaxPooling2D 
from keras import backend as K 

# My Imports 
from os.path import exists 
import h5py 
from keras.utils.io_utils import HDF5Matrix 
batch_size = 128 
num_classes = 10 
epochs = 12 

# input image dimensions 
img_rows, img_cols = 28, 28 

# the data, shuffled and split between train and test sets 
(x_train, y_train), (x_test, y_test) = mnist.load_data() 

if K.image_data_format() == 'channels_first': 
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols) 
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols) 
    input_shape = (1, img_rows, img_cols) 
else: 
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1) 
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1) 
    input_shape = (img_rows, img_cols, 1) 

x_train = x_train.astype('float32') 
x_test = x_test.astype('float32') 
x_train /= 255 
x_test /= 255 
print('x_train shape:', x_train.shape) 
print(x_train.shape[0], 'train samples') 
print(x_test.shape[0], 'test samples') 

#-----------------------------------HDF5 files creation--------------------------------------- 
sample_file_name = "x.hdf5" 
solution_file_name = "y.hdf5" 
train_name = "train" 
test_name = "test" 

#Create dataset 
if (not exists(sample_file_name)) and (not exists(solution_file_name)): 
    samples_file = h5py.File(sample_file_name,mode='a') 
    solutions_file = h5py.File(solution_file_name,mode='a') 
    samples_train = samples_file.create_dataset(train_name,data=x_train) 
    samples_test = samples_file.create_dataset(test_name, data=x_test) 
    solution_train = solutions_file.create_dataset(train_name, data=y_train) 
    solution_test = solutions_file.create_dataset(test_name, data=y_test) 
    samples_file.flush() 
    samples_file.close() 
    solutions_file.flush() 
    solutions_file.close() 

x_train = HDF5Matrix(sample_file_name,train_name) 
x_test = HDF5Matrix(sample_file_name,test_name) 
y_train = HDF5Matrix(solution_file_name,train_name,normalizer=lambda solution: keras.utils.to_categorical(solution,num_classes)) 
y_test = HDF5Matrix(solution_file_name,test_name,normalizer=lambda solution: keras.utils.to_categorical(solution,num_classes)) 
#--------------------------------------------------------------------------------------------- 

model = Sequential() 
model.add(Conv2D(32, kernel_size=(3, 3), 
       activation='relu', 
       input_shape=input_shape)) 
model.add(Conv2D(64, (3, 3), activation='relu')) 
model.add(MaxPooling2D(pool_size=(2, 2))) 
model.add(Dropout(0.25)) 
model.add(Flatten()) 
model.add(Dense(128, activation='relu')) 
model.add(Dropout(0.5)) 
model.add(Dense(num_classes, activation='softmax')) 

model.compile(loss=keras.losses.categorical_crossentropy, 
       optimizer=keras.optimizers.Adadelta(), 
       metrics=['accuracy']) 

# If using HDF5Matrix one needs to disable shuffle 
model.fit(x_train, y_train, 
      batch_size=batch_size, 
      epochs=epochs, 
      verbose=1, 
      validation_data=(x_test, y_test), 
      shuffle=False) 

score = model.evaluate(x_test, y_test, verbose=0) 
print('Test loss:', score[0]) 
print('Test accuracy:', score[1]) 

그러나,이 솔루션의 형태가 일치해야한다는 의미 오류를 산출하고, 정규화는 그런 식으로 사용할 수 없습니다 :

ValueError: Error when checking target: expected dense_2 to have 2, but got array with shape (60000, 1, 10) 

그래서 데이터를 HDF5에 저장하고 (가능한 경우 다른 형식을 사용하여) 데이터를 저장하지 않고 레이블을 저장하는 방식으로 Keras를 사용하는 방법이 있습니까? 회귀 문제?

답변

1

these 행 때문에이 오류가 발생합니다.

Keras는 훈련 전에 입력 모양을 확인합니다. 문제는 당신이 .shape를 호출하는 경우 HDF5Matrix이 사전에 표준화 된 형태를 돌려주는 것입니다, 다음 Keras는 y_test에 대한 y_train과 (10000)에 대한 (60000) 배열을 믿을 것이다.

그러나 행렬의 슬라이스를 액세스 할 때 normalizer가 적용되어 예를 들어 y_train[5:7].shape이 최종 예상 모양을 갖도록합니다. (2, 10).

이것은 주로 노멀 라이저가 실제로 모양을 변경할 것으로 예상되지는 않지만 Keras가 실제로이 경우를 처리 할 수 ​​있기 때문입니다. 당신이 발전기 함수 내에서 정상화의 어떤 종류를 할 수

def generator(features, labels, size): 
    while True: 
     start, end = 0, size 
     while end < len(features): 
      s = slice(start, end) 
      # you can actually do the normalization here if you want 
      yield features[s], labels[s] 
      start, end = end, end + size 

model.fit_generator(
    generator(x_train, y_train, batch_size), 
    steps_per_epoch=len(x_train) // batch_size, 
    epochs=1, 
    verbose=1, 
    validation_data=generator(x_test, y_test, batch_size), 
    validation_steps=len(x_test) // batch_size, 
    shuffle=False) 

주와 그 Keras에 투명하게됩니다

당신은 그래서 교육은 정상화 본다 데이터를 fit_generator를 사용하는 대신 fit하여 문제를 해결할 수 있습니다. 기차와 검증을 위해 다른 배치 크기를 사용할 수 있습니다.

또한, 같은 방법으로 평가를 변경해야합니다 :

score = model.evaluate_generator(
    generator(x_test, y_test, batch_size), 
    steps=len(x_test) // batch_size) 

나는 정규화와 솔루션 그런데, 좋은 아이디어라고 생각합니다.

+1

내 질문에 너무 빨리 답변 해 주셔서 감사합니다. 불행히도이 솔루션에는 작은 문제가 있습니다. 매우 큰 데이터 세트로 작업하고 있으며 세그먼트 코드 문제를 해결하기 위해 코드의 상당 부분을 마이그레이션 할 계획입니다. y 데이터 세트는 이미지이므로 많은 메모리를 사용합니다.당신이 제안한 솔루션이 전체 y 데이터 세트를 메모리로로드하게 만들지 않을까요? –

+0

@DolevShapira 실제로 참으로 두려웠습니다. 이 문제가 발생하지 않도록 발전기를 사용하기 위해 솔루션을 편집했습니다. – grovina

+0

도움을 주셔서 대단히 감사합니다! 나는 그것이 HDF5Matrix만으로 소개하는 복잡성 때문에 fit_generator를 회피 할 수있을 것이라고 생각했습니다. Apparantly, 결국 불가피했다. –