簡體   English   中英

使用CNN對圖片進行兩類分類,但始終可以將所有內容預測為一類

[英]Image two-classification with CNN, but it always predicts everything into one class

介紹

我有一個基於tensorflow的普通CNN網絡,我的目標是訓練它,然后使用它將圖像分類為2類。

關於火車數據集

X:圖像(健康,不健康),128 * 128

標簽:[1,0](不健康)或[0,1](健康)

我使用TFrecords制作數據集。

關於CNN模型

def weight_variable(shape):

    initial = tf.truncated_normal(shape, stddev = 0.1, dtype = tf.float32)
    return tf.Variable(initial)


def bias_variable(shape):

    initial = tf.constant(0.1, shape = shape, dtype = tf.float32)
    return tf.Variable(initial)


def conv2d(x, W):

    #(input, filter, strides, padding)
    #[batch, height, width, in_channels]
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')


def max_pool_2x2(x):

    #(value, ksize, strides, padding)
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

def cnn_model():

    epochs = 1
    batch_size = 200
    learning_rate = 0.001
    hidden = 1024
    cap_c = 498
    cap_h = 478
    num = cap_c + cap_h # the sum number of the training x
    image_size = 128
    label_size = 2
    ex = 2

    #train_loss = np.empty((num//(batch_size * ex)) * epochs)
    #train_acc = np.empty((num//(batch_size * ex)) * epochs)

    x = tf.placeholder(tf.float32, shape = [None, image_size * image_size])
    y = tf.placeholder(tf.float32, shape = [None, label_size])

    X_train_ = tf.reshape(x, [-1, image_size, image_size, 1])

    #First layer
    W_conv1 = weight_variable([5, 5, 1, 32])
    b_conv1 = bias_variable([32])

    h_conv1 = tf.nn.relu(conv2d(X_train_, W_conv1) + b_conv1)
    h_pool1 = max_pool_2x2(h_conv1)

    #Second layer
    W_conv2 = weight_variable([5, 5, 32, 64])
    b_conv2 = bias_variable([64])

    h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
    h_pool2 = max_pool_2x2(h_conv2)

    #Third layer
    #W_conv3 = weight_variable([5, 5, 64, 128])
    #b_conv3 = bias_variable([128])

    #h_conv3 = tf.nn.relu(conv2d(h_pool2, W_conv3) + b_conv3)
    #h_pool3 = max_pool_2x2(h_conv3)

    #Full connect layer
    W_fc1 = weight_variable([64 * 64 * 32, hidden])
    b_fc1 = bias_variable([hidden])

    h_pool2_flat = tf.reshape(h_pool2, [-1, 64 * 64 * 32])
    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

    #Output_Softmax

    W_fc2 = weight_variable([hidden, label_size])
    b_fc2 = bias_variable([label_size])

    y_conv = tf.nn.softmax(tf.matmul(h_fc1, W_fc2) + b_fc2)

    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels = y, logits = y_conv))
    optimize = tf.train.AdamOptimizer(learning_rate).minimize(loss)
    correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y, 1)) 
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

然后是數據讀取或處理部分。

關於形狀

作為占位符的形狀,如果批量為200

X形:[200,128 * 128]

標簽形狀:[200,2]

輸出形狀:[200,2]

關於輸出結果

我認為預測值應訓練為[1,0]或[0,1],但是經過大約5個步驟,預測值都是[1,0]或[0,1]。 例如,如果批次大小為5,則結果將為

[[1, 0],
[1, 0],
[1, 0],
[1, 0],
[1, 0]] 

或完全相反。 但是,有時結果會有所不同,像這樣

[[1, 0],
[0, 1],
[1, 0],
[0, 1],
[1, 0]] 

但這僅持續約5步,那么結果將完全相同。

關於損失和准確性

由於預測結果不正確,因此損失無法收斂。 換句話說,損失和准確性完全取決於訓練數據集的X,這是沒有意義的。

我的想法

我認為數據集TFrecords沒有問題,因為我已經打印了圖像矩陣和標簽,它們沒問題。 因此,我認為問題出在模型上。

我沒有從Google搜索中獲得可以解決我的問題的答案以及SO中的其他問題,非常感謝您能為我提供幫助。 如果您需要更多結果或代碼以供參考,請告訴我。

我認為您的數據可能不平衡,即兩個課程的訓練樣本數量都不大。 在您的示例中,您的健康目標可能比不健康的目標要多得多。 在這種情況下,通過將所有樣本分類到同一類別中,損失函數會大大降低,但是此后,經過一段時間分類的樣本不太可能再次正確分類。

您可以嘗試對數據重新采樣,以使兩個類的數據大致相等。

另一種方法是使用加權交叉熵(例如,您可以計算每個樣本的交叉熵,然后將其乘以權重(確切地說,是每個樣本的權重張量);僅在此之后才應應用tf.reduce_mean例如,您可以對包含更少樣本的類施加更大的權重,從而迫使優化器更加關注這些樣本。

看起來應該像這樣:

weights = tf.placeholder(tf.float32, shape=[None])
loss = tf.reduce_mean(tf.multiply(tf.nn.softmax_cross_entropy_with_logits(labels = y, logits = y_conv), weights))

當然,您需要在某些時候用值填充weights

暫無
暫無

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

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