Keras val_acc和model.evaluate acc不匹配

时间:2019-11-03 19:16:03

标签: machine-learning keras deep-learning

我正在使用Python 3.6.9(Anaconda),keras 2.2.4和tensorflow 1.10.0来使用celebA数据集中的部分数据进行二进制分类。我的文件划分如下:

                  dataset
           __________|_________
          |                    |
    training_set        validation_set
     _____|_____          _____|_____
    |           |        |           |
   men        women     men         women
    |           |        |           |
   40k         40k       4k          4k

运行我得到的代码(以2个时期为例):

Using TensorFlow backend. 
Found 80000 images belonging to 2 classes.
Found 8000 images belonging to 2 classes.
Class weights:  {0: 1.0, 1: 1.0}

Epoch 1/2
1250/1250 [==============================] - 341s 273ms/step - loss: 0.3103 - acc: 0.8662 - val_loss: 0.2502 - val_acc: 0.9005

Epoch 2/2
1250/1250 [==============================] - 346s 276ms/step - loss: 0.2094 - acc: 0.9152 - val_loss: 0.2133 - val_acc: 0.9129

8000/8000 [==============================] - 9s 1ms/step
[8.048886075259292, 0.500625]

问题是,val_acc达到0.9,而acc我只有0.5(可理解)。用于验证的集合,模型和权重与用于评估的相同,但它们给出的值却完全不同,为什么?

通过类似这样一个非常简单的网络的其他事情,火车acc真的真的可以达到一个时期的0.86吗?这个值可靠吗?

这是我的代码:

import os
import numpy as np
import keras
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.layers import Dense, Flatten
from keras.preprocessing.image import ImageDataGenerator
from keras.preprocessing import image
from keras.applications.mobilenet import preprocess_input
from keras.optimizers import Adam
from keras.layers.normalization import BatchNormalization
from keras.models import Sequential
import cv2
from keras.models import model_from_json
import psutil

p = psutil.Process(os.getpid())

try:

    p.nice(19) #Ubuntu

except:

    p.nice(psutil.HIGH_PRIORITY_CLASS) #Windows

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'

HEIGHT = 128
WIDTH = 128

def prepare_image(file):
    img_path = ''
    img = image.load_img(img_path + file, target_size=(HEIGHT, WIDTH))
    img_array = image.img_to_array(img)
    img_array_expanded_dims = np.expand_dims(img_array, axis=0)
    return keras.applications.mobilenet.preprocess_input(img_array_expanded_dims)


model = Sequential()
model.add(Conv2D(32, (3, 3) , padding='same', activation='relu', input_shape=(HEIGHT,WIDTH,3)))
model.add(Conv2D(64, (3, 3) , padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(BatchNormalization())

model.add(Dense(128, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

opt = Adam(lr = 0.0001)

train_datagen=ImageDataGenerator(preprocessing_function=preprocess_input,
    rotation_range=20,
    zoom_range=0.2,
    shear_range=0.2,
    horizontal_flip=True,
    rescale=1./255
    )

valid_datagen=ImageDataGenerator(preprocessing_function=preprocess_input,
    rescale=1./255)

train_generator=train_datagen.flow_from_directory('dataset/training_set',
    target_size=(HEIGHT,WIDTH),
    color_mode='rgb',
    batch_size=64,
    class_mode='binary',
    )

valid_generator=valid_datagen.flow_from_directory('dataset/validation_set',
    target_size=(HEIGHT,WIDTH),
    color_mode='rgb',
    batch_size=64,
    class_mode='binary'
    )

step_size_train=train_generator.n//train_generator.batch_size
step_size_valid=valid_generator.n//valid_generator.batch_size

model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])

from collections import Counter
itemCt = Counter(train_generator.classes)
maxCt = float(max(itemCt.values()))
cw = {clsID : maxCt/numImg for clsID, numImg in itemCt.items()}

print("Class weights: ", cw)

model.fit_generator(
    train_generator,
    steps_per_epoch = step_size_train,
    validation_data = valid_generator,
    validation_steps = step_size_valid,
    epochs=2,
    verbose = 1,
    class_weight=cw
    )


model_json = model.to_json()
with open("model.json", "w") as json_file:
    json_file.write(model_json)

model.save_weights("model.h5")

def load_data():

    path = os.getcwd() + "\\dataset\\validation_set\\"
    lista = os.listdir(path)
    lista.sort()

    data = []
    pred = []

    for i in range(len(lista)):

        listb = os.listdir(path+lista[i])
        listb.sort()

        for j in listb:

            pic = cv2.imread(path+lista[i]+"/"+j)
            pic = cv2.resize(pic, (HEIGHT,WIDTH)) / 255.
            data.append(pic)

            pred.append(i)


    data = np.asarray(data)
    pred = np.asarray(pred)

    return data, pred

data, pred = load_data()

def load_model():

    json_file = open('model.json', 'r')
    loaded_model_json = json_file.read()
    json_file.close()

    loaded_model = model_from_json(loaded_model_json)
    loaded_model.load_weights("model.h5")
    loaded_model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])

    return loaded_model

loaded_model = load_model()

result = loaded_model.evaluate(data, pred)
print(result)

我按照建议的更正进行了编辑,但仍然存在相同的问题。我是否以正确的方式加载模型?

1 个答案:

答案 0 :(得分:0)

在您的代码中

valid_generator=train_datagen.flow_from_directory('dataset/validation_set',
    target_size=(HEIGHT,WIDTH),
    color_mode='rgb',
    batch_size=64,
    class_mode='binary'
    )

valid_datagen 应该放在这里,而不是 train_datagen

另外,我认为在调用 load_data()时,您不会在训练和验证时通过1./255重新缩放数据。
这应该可以解决您的问题。