728x90
반응형

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))
728x90
반응형