반응형

stackoverflow.com/questions/58538135/keras-methods-predict-and-predict-generator-with-different-result

 

Keras methods 'predict' and 'predict_generator' with different result

I have trained a basic CNN model for image classification. While training the model I have used ImageDataGenerator from keras api. After the model is being trained i used testdatagenerator and

stackoverflow.com

Keras에서 Image data generator 로 train 코드를 돌리고, Image data generator 로 test 코드도 돌리는 경우에 model.predict_generator(test_generator) 에서 나오는 예측값과 똑같은 모델 & 가중치 값으로 image를 불러와서 numpy array 로 model.predict() 한 예측값이 다른 문제가 발생했다.

 

열심히 구글링 한 결과,

Keras에서 Image data generator 는 PIL library 로 이미지를 불러오는데 이는 RGB로 불러온다.

근데 내가 쓴 OpenCV 는 이미지를 BGR로 불러와서 생긴 문제였다.

그래서 OpenCV로 이미지를 불러와서 예측하는 경우에는 BGR를 RGB로 바꿔줘야한다...

 

이런식으로 ...ㅎㅎ

img = cv2.imread(img_file)

img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

 

 

Image Data Generator 로 test.py 짠 코드

* 주의 - You need to reset the test_generator before whenever you call the predict_generator. This is important, if you forget to reset the test_generator you will get outputs in a weird order. (test_generator.reset() 해주기!!!!)

test_datagen = ImageDataGenerator(rescale=1./255)

test_generator = test_datagen.flow_from_directory(
    '데이터 경로',
    # seed=44,
    batch_size=32,
    class_mode='categorical',
    shuffle=False
    )

model_path = '../model/model.h5' # 저장된 모델 경로
model = tf.keras.models.load_model(model_path, custom_objects=customObjects)

test_generator.reset() # predict_generator 쓸 때 해줘야함
output = model.predict_generator(test_generator)

print(test_generator.class_indices) # 데이터 클래스 보기
# print(output)

y_predict = np.argmax(output, axis=1) # categorical class mode 임으로 softmax 거침
# print(y_predict)

loss, acc = model.evaluate_generator(test_generator)
print("Accuracy : ", str(np.round(acc,2)*100) + "%")

 

이미지 PIL로 불러와서 predict 하기

path = f'데이터 경로'

category_ls = os.listdir(path) # 카테고리 / y label
category_ls.sort()

model_path = '../model/model.h5' # 모델 저장된 경로
model = tf.keras.models.load_model(model_path, custom_objects=customObjects)

# 전체 클래스 평균 acc 계산 하기 위함
all_y_true = []
all_y_predict = []
all_output = []

# 클래스 별로 acc 계산함
for idx, name in enumerate(category_ls):
    images_ls = os.listdir(os.path.join(path,name))
    x_test = list()
    for image in images_ls:
    	# # cv2로 부른 경우
        # img = cv2.imread(os.path.join(path, name, image))
        # img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        #
        # img = cv2.resize(img, (256, 256))
        # x_test.append(img.tolist())
		
        # PIL로 부른 경우!!
        img = Image.open(os.path.join(path, name, image))
        img = np.array(img)
        x_test.append(img.tolist())
        
    # print("class : ", name)
    y_true = [idx for i in range(len(images_ls))]
    y_true= np.array(y_true)
    test_set = len(y_true)  # .next()[1]))
    
    # print("y_true",y_true)
    # x_test = np.array(x_test) / 255.0
    x_test = np.array(x_test) * 1./255

    output = model.predict_proba(x_test)

    y_predict = np.argmax(ensemble, axis=1)
    # print("y_predict",y_predict)

	acc = accuracy_score(y_true,y_predict)
    print('정확도 : {:.4f}'.format(acc))

    all_y_true.extend(y_true)
    all_y_predict.extend(y_predict)

print(all_y_predict)

all_acc = accuracy_score(all_y_true,all_y_predict) # 전체 평균 Acc 
print('정확도 : {:.4f}'.format(all_acc))
반응형