Xception(图像分类)中的损失和准确性没有提高

Posted

技术标签:

【中文标题】Xception(图像分类)中的损失和准确性没有提高【英文标题】:Loss & accuracy don't improve in Xception (image classification) 【发布时间】:2021-10-23 17:03:30 【问题描述】:

作为一项试验,我正在实施 Xception 对图像进行分类,而不使用 Tensorflow 中的预训练权重。 但是,与原始论文相比,准确性太低了。 有人可以分享任何建议来解决这个问题吗?

我从 ImageNet 准备了 1000 个课程中的 500 个,并使用从头开始的这些数据训练 ready-Xception model。 我尝试了与the original paper 中使用的相同的学习率和优化器。

– 优化器:SGD – 动量:0.9 – 初始学习率:0.045 – 学习率衰减:每 2 个 epochs 衰减 0.94

但是,这并没有那么好。

我知道最好使用所有 1000 个类而不是只使用 500 个,但是,我无法为它准备存储。 它是否影响了我的代码的性能?

这是我的代码。

import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras import layers, losses, models, optimizers, callbacks, applications, preprocessing

# scheduler
def scheduler(epoch, lr):
    return 0.045*0.94**(epoch/2.0)
lr_decay = callbacks.LearningRateScheduler(scheduler)

# early stopping
EarlyStopping = callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=500, verbose=0, mode='auto', restore_best_weights=True)

# build xception
inputs = tf.keras.Input(shape=(224, 224, 3))
x = tf.cast(inputs, tf.float32)
x = tf.keras.applications.xception.preprocess_input(x) #preprocess image
x = applications.xception.Xception(weights=None, include_top=False,)(x, training=True)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(nb_class)(x)
outputs = layers.Softmax()(x)
model = tf.keras.Model(inputs, outputs)

model.compile(optimizer=optimizers.SGD(momentum=0.9, nesterov=True), 
            loss = 'categorical_crossentropy', 
            metrics= ['accuracy'])

# fitting data
history = model.fit(image_gen(df_train_chunk, 224, 224, ), #feed images with a generator
                    batch_size = 32,
                    steps_per_epoch = 64,
                    epochs=1000000000,
                    validation_data = image_gen(df_valid_chunk, 224, 224, ),  #feed images with a generator
                    validation_steps = 64,
                    callbacks = [lr_decay, EarlyStopping],
                    )

我的结果如下。在原始论文中,它的准确率达到了 0.8 左右。 相比之下,我的代码性能太差了。

附言

有些人可能会怀疑我的生成器是不是出错了,所以我把我的生成器代码和结果放在下面。

from PIL import Image, ImageEnhance, ImageOps

def image_gen(df_data, h, w, shuffle=True):
    nb_class = len(np.unique(df_data['Class']))
    while True:
        if shuffle:
            df_data = df_data.sample(frac=1) 
        for i in range(len(df_data)):
            X = Image.open((df_data.iloc[i]).loc['Path'])
            X = X.convert('RGB')
            X = X.resize((w,h))
            X = preprocessing.image.img_to_array(X)
            X = np.expand_dims(X, axis=0)
            
            klass = (df_data.iloc[i]).loc['Class']
            y = np.zeros(nb_class)
            y[klass] = 1
            y = np.expand_dims(y, axis=0)

            yield X, y

train_gen = image_gen(df_train_chunk, 224, 224, )

for i in range(5):
    X, y = next(train_gen)
    print('\n\n class: ', y.argmax(-1))
    display(Image.fromarray(X.squeeze(0).astype(np.uint8)))

结果如下。

【问题讨论】:

【参考方案1】:

当您只选择 500 个标签时,您会选择前 500 个吗? softmax 输出从 0 开始,因此请确保您的标签也是从 0 到 499。

【讨论】:

我检查了提供图像和标签的生成器是否正常工作。每个图像对应每个标签。

以上是关于Xception(图像分类)中的损失和准确性没有提高的主要内容,如果未能解决你的问题,请参考以下文章

图像分类。验证损失在初始训练期间卡住(v1)

MNIST 分类:准确率低(10%),损失没有变化

Pytorch CIFAR10图像分类 DenseNet篇

Pytorch CIFAR10图像分类 GoogLeNet篇

Pytorch CIFAR10图像分类 AlexNet篇

Pytorch CIFAR10图像分类 MobileNetv2篇