我正在使用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)
我按照建议的更正进行了编辑,但仍然存在相同的问题。我是否以正确的方式加载模型?
答案 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重新缩放数据。
这应该可以解决您的问题。