Tensorflow,Keras:在多类别分类中,准确度很高,但大多数类别的准确度、召回率和f1分数为零



一般解释:我的代码运行良好,但结果是有线的。我不知道有问题

  • 网络结构
  • 或者我将数据馈送到网络的方式
  • 或其他任何东西

几个星期以来,我一直在与这个错误作斗争,到目前为止,我已经更改了损失函数、优化器、数据生成器等,但我无法解决它。我感谢您的帮助。如果以下信息不够,请告诉我。

研究领域:我使用tensorflow,keras进行多类别分类。该数据集具有36个二进制人类属性。我使用了resnet50,然后对于身体的每个部位(头部、上身、下身、鞋子、配饰(,我在网络中添加了一个单独的分支。该网络具有1个具有36个标签的输入图像和36个输出节点(具有S形激活的36个denes层(。

问题:问题是keras报告的准确性很高,但对于大多数输出,f1分数非常低或为零(即使我在编译网络时使用f1分数作为度量标准,用于验证的f1 socre也非常糟糕(。

a训练后,当我在预测模式下使用网络时,对于某些类,它总是返回一/零。这意味着网络无法学习(即使我使用加权损失函数或焦点损失函数(

为什么这很奇怪?因为,最先进的方法即使在第一个历元之后也会报告高f1分数(例如。https://github.com/chufengt/iccv19_attribute,我已经在我的电脑上运行了它,并在一个时代后获得了良好的结果(。

部分代码:

print("setup model ...")
input_image = KL.Input(args.img_input_shape, name= "input_1")
C1, C2, C3, C4, C5 = resnet_graph(input_image, architecture="resnet50", stage5=False, train_bn=True)
output_layers = merged_model (input_features=C4)
model = Model(inputs=input_image, outputs=output_layers, name='SoftBiometrics_Model')
...
print("model compiling ...")
OPTIM = optimizers.Adadelta(lr=args.learning_rate, rho=0.95)
model.compile(optimizer=OPTIM, loss=binary_focal_loss(alpha=.25, gamma=2), metrics=['acc',get_f1])
plot_model(model, to_file='model.png')
...
img_datagen = ImageDataGenerator(rotation_range=6, width_shift_range=0.03, height_shift_range=0.03, brightness_range=[0.85,1.15], shear_range=0.06, zoom_range=0.09, horizontal_flip=True, preprocessing_function=preprocess_input_resnet, rescale=1/255.)
img_datagen_test = ImageDataGenerator(preprocessing_function=preprocess_input_resnet, rescale=1/255.)
def multiple_outputs(generator, dataframe, batch_size, x_col):
Gen = generator.flow_from_dataframe(dataframe=dataframe,
directory=None,
x_col = x_col,
y_col = args.Categories,
target_size = (args.img_input_shape[0],args.img_input_shape[1]),
class_mode = "multi_output",
classes=None,
batch_size = batch_size,
shuffle = True)
while True:
gnext = Gen.next()
# return image batch and 36 sets of lables
labels = gnext[1]
output_dict = {"{}_output".format(Category): np.array(labels[index]) for index, Category in enumerate(args.Categories)}
yield {'input_1':gnext[0]}, output_dict
trainGen = multiple_outputs (generator = img_datagen, dataframe=Train_df_img, batch_size=args.BATCH_SIZE, x_col="Train_Filenames")
testGen = multiple_outputs (generator = img_datagen_test, dataframe=Test_df_img, batch_size=args.BATCH_SIZE, x_col="Test_Filenames")
STEP_SIZE_TRAIN = len(Train_df_img["Train_Filenames"]) // args.BATCH_SIZE
STEP_SIZE_VALID = len(Test_df_img["Test_Filenames"]) // args.BATCH_SIZE
...
print("Fitting the model to the data ...")
history = model.fit_generator(generator=trainGen,
epochs=args.Number_of_epochs,
steps_per_epoch=STEP_SIZE_TRAIN,
validation_data=testGen,
validation_steps=STEP_SIZE_VALID,
callbacks= [chekpont],
verbose=1)

有可能将二进制f1分数传递给compile函数。这应该可以解决问题-

pip install tensorflow-addons
...
import tensorflow_addons as tfa 
f1 = tfa.metrics.F1Score(36,'micro' or 'macro')
model.compile(...,metrics=[f1])

你可以在这里阅读更多关于f1微观和f1宏观是如何计算的,以及哪些是有用的。

不知怎么的,Keras模型的predict_generator((没有按预期工作。我宁愿一个接一个地循环浏览所有测试图像,并在每次迭代中获得每个图像的预测。我使用Plaid ML Keras作为我的后端,为了获得预测,我使用以下代码。

import os
from PIL import Image
import keras
import numpy
print("Prediction result:")
dir = "/path/to/test/images"
files = os.listdir(dir)
correct = 0
total = 0
#dictionary to label all traffic signs class.
classes = {
0:'This is Cat',
1:'This is Dog',
}
for file_name in files:
total += 1
image = Image.open(dir + "/" + file_name).convert('RGB')
image = image.resize((100,100))
image = numpy.expand_dims(image, axis=0)
image = numpy.array(image)
image = image/255
pred = model.predict_classes([image])[0]
sign = classes[pred]
if ("cat" in file_name) and ("cat" in sign):
print(correct,". ", file_name, sign)
correct+=1
elif ("dog" in file_name) and ("dog" in sign):
print(correct,". ", file_name, sign)
correct+=1
print("accuracy: ", (correct/total))

最新更新