首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Tensorflow NIH胸部X光CNN验证准确性即使使用正则化也不会提高

Tensorflow NIH胸部X光CNN验证准确性即使使用正则化也不会提高
EN

Stack Overflow用户
提问于 2021-05-02 07:46:33
回答 1查看 74关注 0票数 0

我一直在研究一种CNN,它接收224x224灰度x射线图像,并根据是否检测到异常输出0或1。

This是我正在使用的数据集。我将数据集分成两部分,其中106496张图像用于训练,其余的5624张用于验证。因为它们都来自相同的数据集,所以它们应该都来自相同的分布。

我尝试使用预先训练好的InceptionV3和VGG19架构来训练我上面描述的模型,但没有成功。然后,我尝试使我自己的模型类似于VGG19架构。

我尽可能地简化了模型,使训练准确率达到90%以上,并添加了各种正则化器,如dropout和l2。我还尝试了不同的超参数和图像增强,但在5-10个时期后,验证准确率不会超过70%。验证损失似乎也丝毫没有下降。

这是我的准确率与历元和损失与历元曲线(粉红色是列车,绿色在验证中):

下面是我的代码:

代码语言:javascript
运行
复制
def create_model(settings):
    """
    Create a basic model
    """
    # create model
    model = tf.keras.models.Sequential()
    model.add(layers.Input((224, 224, 1)))
    # block 1
    model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', use_bias=True, name='block1_conv'))
    model.add(layers.MaxPool2D((2, 2), strides=(2, 2), name='block1_pool'))
    # block 2
    model.add(layers.Conv2D(96, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', use_bias=True, name='block2_conv'))
    model.add(layers.MaxPool2D((2, 2), strides=(2, 2), name='block2_pool'))
    # block 3
    model.add(layers.Conv2D(192, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', use_bias=True, name='block3_conv1'))
    model.add(layers.Conv2D(192, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', use_bias=True, name='block3_conv2'))
    model.add(layers.MaxPool2D((2, 2), strides=(2, 2), name='block3_pool'))
    # block 4
    model.add(layers.Conv2D(384, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', use_bias=True, name='block4_conv1'))
    model.add(layers.Conv2D(384, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', use_bias=True, name='block4_conv2'))
    model.add(layers.Conv2D(384, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', use_bias=True, name='block4_conv3'))
    model.add(layers.MaxPool2D((2, 2), strides=(2, 2), name='block4_pool'))
    # block 5
    model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', use_bias=True, name='block5_conv1'))
    model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', use_bias=True, name='block5_conv2'))
    model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', use_bias=True, name='block5_conv3'))
    model.add(layers.MaxPool2D((2, 2), strides=(2, 2), name='block5_pool'))
    # fully connected
    model.add(layers.GlobalAveragePooling2D(name='fc_pool'))   
    model.add(layers.Dropout(0.3, name='fc_dropout'))
    model.add(layers.Dense(1, activation='sigmoid', name='fc_output'))
    
    # compile model
    model.compile(
        optimizers.SGD(
            learning_rate=settings["lr_init"],
            momentum=settings["momentum"],
        ),
        loss='binary_crossentropy',
        metrics=[
            'accuracy',
            metrics.Precision(),
            metrics.Recall(),
            metrics.AUC()
        ]
    )
    model.summary()
    return model



def configure_callbacks(settings):
    """
    Create a list of callback objects
    """
    # tensorboard
    log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
    tensorboard_callback = callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)
    
    # learning rate reduction on plateau
    lrreduce_callback = callbacks.ReduceLROnPlateau(
        monitor='val_loss',
        factor=settings["lr_factor"],
        patience=settings["lr_patience"],
        min_lr=settings["lr_min"],
        verbose=1,
    )
    
    # save model
    checkpoint_callback = callbacks.ModelCheckpoint(
        filepath="saves/" + settings["modelname"] + "/cp-{epoch:03d}",
        monitor='val_accuracy',
        mode='max',
        save_weights_only=True,
        save_best_only=True,
        verbose=1,
    )
    return [tensorboard_callback, lrreduce_callback, checkpoint_callback]



def get_data(settings):
    """ 
    Create a generator that will be used for training
    """
    df=pd.read_csv("dataset/y_train_binary.csv")
    columns = [
        "Abnormal"
    ]
    datagen = ImageDataGenerator(
        rescale=1./255.,
        rotation_range=5,
        brightness_range=(0.9, 1.1),
        zoom_range=(1,  1.1),
    )
    # 94.983% for training (106496 = 64*6656)
    traindata = datagen.flow_from_dataframe(
        dataframe=df[:NTRAIN],
        directory="dataset/images",
        x_col="Image Index",
        y_col=columns,
        color_mode='grayscale',
        batch_size=settings["batchsize"],
        class_mode="raw",
        target_size=(224,224),
        shuffle=True,
    )
    # 5.017% for testing (5624)
    testdata = datagen.flow_from_dataframe(
        dataframe=df[NTRAIN:],
        directory="dataset/images",
        x_col="Image Index",
        y_col=columns,
        color_mode='grayscale',
        batch_size=settings["batchsize"],
        class_mode="raw",
        target_size=(224,224),
        shuffle=True,
    )
    return (traindata, testdata)



def newtrain(settings):
    """
    Create a new model "(modelname)" and train for (epoch) epochs
    """
    model = create_model(settings)
    callbacks = configure_callbacks(settings)
    traindata, testdata = get_data(settings)
    
    # train
    model.fit(
        x=traindata,
        epochs=settings["epoch"],
        validation_data=testdata,
        callbacks=callbacks,
        verbose=1,
    )
    model.save_weights(f"saves/{settings['modelname']}/cp-{settings['epoch']:03d}")

我的想法快用完了,训练50个时代需要半天的时间,所以如果有人知道我如何解决这个问题,我将不胜感激。谢谢。

EN

回答 1

Stack Overflow用户

发布于 2021-05-02 08:25:28

如果您在NIH Chest X-rays上执行一些EDA,您可能还会看到14个类之间存在严重的类不平衡问题。根据你的模型定义,我可以假设你把一个正常的图像放在一边,把一个异常的(13情况)放在另一边。首先,如果这是真的,我会说,最好对所有病例进行分类-所有病例在临床实践中都很重要。

  • 转移到14 cases classification

您正在使用自己的设计模型,但您应该首先从预先训练好的模型开始。这样会更好,接下来你可以逐渐整合你自己的想法。

  • 使用预端模型,例如DenseNetEfficientNetNFNet

在您的数据生成器中,您为测试集使用了shuffle=True,这是错误的,而应该是False

代码语言:javascript
运行
复制
 testdata = datagen.flow_from_dataframe(
        ....
        target_size=(224,224),
         shuffle=False

为了更好地控制您的输入管道,IMO,您应该编写自己的自定义数据生成器,并试验高级增强以防止过拟合。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67351810

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档