CNN架构:分类“优质”和“劣质”图像

我正在研究实现一个CNN来将图像分类为“优质”或“劣质”,但目前的架构似乎并不奏效。

表示“劣质”图像的特征包括:

  • overexposure(曝光过度)
  • oversaturation(饱和度过高)
  • incorrect white balance(白平衡错误)
  • blurriness(模糊)

基于这些特征,使用神经网络来分类图像是否可行,还是最好使用传统算法,仅通过检查图像中亮度/对比度的变化来进行分类?

我尝试使用VGGNet架构训练CNN,但无论是增加训练轮数还是步数,得到的模型总是有偏差且不可靠。

示例:

"优质" 照片"劣质" 照片

我的当前模型架构非常简单(因为我刚开始接触机器学习领域),在处理其他分类问题时表现良好,我已经对其进行了少许修改以更好地适应这个二元分类问题:

    # CONV => RELU => POOL 层设置    # 定义卷积层,使用“ReLU”激活函数    # 并通过池化层减小空间尺寸(宽度和高度)    model.add(Conv2D(32, (3, 3), padding="same", input_shape=input_shape)) # 32个3x3滤波器(高度,宽度,深度)    model.add(Activation("relu"))    model.add(BatchNormalization(axis=channel_dimension))    model.add(MaxPooling2D(pool_size=(2,2)))    model.add(Dropout(0.25)) # 帮助防止过拟合(随机断开25%的神经元)    # (CONV => RELU) * 2 => POOL 层设置(随着CNN深入,增加层数)    model.add(Conv2D(64, (3, 3), padding="same", input_shape=input_shape)) # 64个3x3滤波器    model.add(Activation("relu"))    model.add(BatchNormalization(axis=channel_dimension))    model.add(Conv2D(64, (3, 3), padding="same", input_shape=input_shape)) # 64个3x3滤波器    model.add(Activation("relu"))    model.add(BatchNormalization(axis=channel_dimension))    model.add(MaxPooling2D(pool_size=(2,2)))    model.add(Dropout(0.25)) # 帮助防止过拟合(随机断开25%的神经元)    # (CONV => RELU) * 3 => POOL 层设置(输入体积尺寸越来越小)    model.add(Conv2D(128, (3, 3), padding="same", input_shape=input_shape)) # 128个3x3滤波器    model.add(Activation("relu"))    model.add(BatchNormalization(axis=channel_dimension))    model.add(Conv2D(128, (3, 3), padding="same", input_shape=input_shape)) # 128个3x3滤波器    model.add(Activation("relu"))    model.add(BatchNormalization(axis=channel_dimension))    model.add(Conv2D(128, (3, 3), padding="same", input_shape=input_shape)) # 128个3x3滤波器    model.add(Activation("relu"))    model.add(BatchNormalization(axis=channel_dimension))    model.add(MaxPooling2D(pool_size=(2,2)))    model.add(Dropout(0.25)) # 帮助防止过拟合(随机断开25%的神经元)    # 仅一组FC => RELU 层    model.add(Flatten())    model.add(Dense(512))    model.add(Activation("relu"))    model.add(BatchNormalization())    model.add(Dropout(0.5))    # sigmoid 分类器(输出层)    model.add(Dense(classes))    model.add(Activation("sigmoid"))

这个模型是否存在明显的遗漏或错误,或者我是否无法使用深度学习(使用我的当前GPU,GTX 970)解决这个问题?

以下是我编译/训练模型的代码:

# 初始化模型和优化器print("[INFO] 正在训练网络...")opt = SGD(lr=initial_lr, decay=initial_lr / epochs)model.compile(loss="sparse_categorical_crossentropy", optimizer=opt, metrics=["accuracy"])# 设置检查点model_name = "output/50_epochs_{epoch:02d}_{val_acc:.2f}.model"checkpoint = ModelCheckpoint(model_name, monitor='val_acc', verbose=1, save_best_only=True, mode='max')reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2,                          patience=5, min_lr=0.001)tensorboard = TensorBoard(log_dir="logs/{}".format(time()))callbacks_list = [checkpoint, reduce_lr, tensorboard]# 训练网络H = model.fit_generator(training_set, steps_per_epoch=500, epochs=50, validation_data=test_set, validation_steps=150, callbacks=callbacks_list)

回答:

我建议你采用迁移学习而不是从头开始训练整个网络。使用在像ImageNet这样的大型数据集上训练的权重。

你可以使用Keras轻松实现这一点,只需导入带权重的模型,如xception,并删除表示ImageNet数据集1000个类别的最后一层,改为2个节点的密集层,因为你只有两个类别,并将基础层的trainable设置为False,而将自定义添加的层(如节点数为2的密集层)的trainable设置为True

然后你可以像往常一样训练模型。

演示代码 –

from keras.applications import *from keras.models import Modelbase_model = Xception(input_shape=(img_width, img_height, 3), weights='imagenet', include_top=Falsex = base_model.outputx = GlobalAveragePooling2D()(x)predictions = Dense(2, activation='softmax')(x)model = Model(base_model.input, predictions)# 冻结基础层权重for layer in base_model.layers:    layer.trainable = False

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注