簡體   English   中英

CNN架構:對“好”和“壞”圖像進行分類

[英]CNN architecture: classifying “good” and “bad” images

我正在研究實現CNN以便將圖像分類為“好”或“壞”的可能性,但是我目前的體系結構沒有運氣。

表示“不良”圖像的特征:

  • 過度曝光
  • 過飽和
  • 白平衡不正確
  • 模糊性

實現神經網絡基於這些特征對圖像進行分類是否可行,還是最好讓傳統算法簡單地查看整個圖像的亮度/對比度變化並以這種方式分類?

我曾嘗試使用VGGNet架構來訓練CNN,但無論歷元數或步驟數如何,我似乎總是有偏見且不可靠。

例子:

“好照片 “不良”照片

我當前模型的架構非常簡單(因為我是整個機器學習領域的新手),但似乎可以與其他分類問題配合使用,並且我對其進行了一些修改,以更好地解決此二進制分類問題:

    # CONV => RELU => POOL layer set
    # define convolutional layers, use "ReLU" activation function
    # and reduce the spatial size (width and height) with pool layers
    model.add(Conv2D(32, (3, 3), padding="same", input_shape=input_shape)) # 32 3x3 filters (height, width, depth)
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channel_dimension))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(Dropout(0.25)) # helps prevent overfitting (25% of neurons disconnected randomly)

    # (CONV => RELU) * 2 => POOL layer set (increasing number of layers as you go deeper into CNN)
    model.add(Conv2D(64, (3, 3), padding="same", input_shape=input_shape)) # 64 3x3 filters
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channel_dimension))
    model.add(Conv2D(64, (3, 3), padding="same", input_shape=input_shape)) # 64 3x3 filters
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channel_dimension))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(Dropout(0.25)) # helps prevent overfitting (25% of neurons disconnected randomly)

    # (CONV => RELU) * 3 => POOL layer set (input volume size becoming smaller and smaller)
    model.add(Conv2D(128, (3, 3), padding="same", input_shape=input_shape)) # 128 3x3 filters
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channel_dimension))
    model.add(Conv2D(128, (3, 3), padding="same", input_shape=input_shape)) # 128 3x3 filters
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channel_dimension))
    model.add(Conv2D(128, (3, 3), padding="same", input_shape=input_shape)) # 128 3x3 filters
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channel_dimension))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(Dropout(0.25)) # helps prevent overfitting (25% of neurons disconnected randomly)

    # only set of FC => RELU layers
    model.add(Flatten())
    model.add(Dense(512))
    model.add(Activation("relu"))
    model.add(BatchNormalization())
    model.add(Dropout(0.5))

    # sigmoid classifier (output layer)
    model.add(Dense(classes))
    model.add(Activation("sigmoid"))

該模型是否存在明顯的遺漏或錯誤,還是我不能使用深度學習(使用我當前的GPU,GTX 970)來解決此問題?

感謝您的時間和經驗,

喬希

編輯:這是我用於編譯/訓練模型的代碼:

# initialise the model and optimiser
print("[INFO] Training network...")
opt = SGD(lr=initial_lr, decay=initial_lr / epochs)
model.compile(loss="sparse_categorical_crossentropy", optimizer=opt, metrics=["accuracy"])

# set up checkpoints
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]

# train the network
H = model.fit_generator(training_set, steps_per_epoch=500, epochs=50, validation_data=test_set, validation_steps=150, callbacks=callbacks_list)

獨立於任何其他建議(包括已經提供的答案),並假設classes=2 (您沒有弄清楚-我們在這里要求提供MCVE的原因),您似乎在最后一層犯了一個基本錯誤,即:

# sigmoid classifier (output layer)
model.add(Dense(classes))
model.add(Activation("sigmoid"))

僅當您的最后一層由單個節點組成時,才適用S型激活。 如果我懷疑classes=2 ,也是基於您在評論中令人費解的陳述,

使用三個不同的圖像,我的結果是0.987不好,0.999很好

我以前給過你模型的預測

您應該使用softmax激活,即

model.add(Dense(classes))
model.add(Activation("softmax"))

或者,您可以使用sigmoid,但最后一層應包含一個節點,即

model.add(Dense(1))
model.add(Activation("sigmoid"))

后者通常在二進制分類設置中是首選,但是結果在原理上應該相同。

更新 (更新問題后):

sparse_categorical_crossentropy在這里也不是正確的損失。

總之,請嘗試以下更改:

model.compile(loss="binary_crossentropy", optimizer=Adam(), metrics=["accuracy"])

# final layer:
model.add(Dense(1))
model.add(Activation("sigmoid"))

使用Adam優化器(需要導入)。 另外, 默認情況下不應使用dropout-請參見此線程 從沒有它開始,僅在必要時添加(即,如果您看到過度擬合的跡象)。

我建議您去轉學而不是訓練整個網絡。 使用在像ImageNet這樣的龐大數據集上訓練的權重

您可以使用Keras輕松地做到這一點,您只需要導入權重如xception的模型並刪除代表1000個類別的imagenet數據集的最后一層到2個節點密集層,因為您只有2個類別,並且將基礎層和trainable=True設置為trainable=False trainable=True對於自定義添加的層trainable=True ,例如具有節點= 2的密集層。

您可以像往常一樣訓練模型。

演示代碼-

from keras.applications import *
from keras.models import Model

base_model = Xception(input_shape=(img_width, img_height, 3), weights='imagenet', include_top=False
x = base_model.output
x = GlobalAveragePooling2D()(x)
predictions = Dense(2, activation='softmax')(x)
model = Model(base_model.input, predictions)
# freezing the base layer weights
for layer in base_model.layers:
    layer.trainable = False

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM