簡體   English   中英

ValueError:`logits` 和 `labels` 必須具有相同的形狀

[英]ValueError: `logits` and `labels` must have the same shape

我正在嘗試將 Imag.net V2 與遷移學習一起用於多類分類(6 類),但出現以下錯誤。 有人可以幫忙嗎?

ValueError: `logits` and `labels` must have the same shape, received ((None, 6) vs (None, 1)).

我從 Andrew Ng 的 CNN 課程中借用了這段代碼,但原始代碼用於二進制分類。 我試圖修改它以進行多類分類,但出現了這個錯誤。 這是我的代碼:

import matplotlib.pyplot as plt
import numpy as np
import os
import tensorflow as tf
import tensorflow.keras.layers as tfl
import datetime

from tensorflow.keras.preprocessing import image_dataset_from_directory
from tensorflow.keras.layers.experimental.preprocessing import RandomFlip, RandomRotation

BATCH_SIZE = 16
IMG_SIZE = (160, 160)
training_directory = "/content/drive/MyDrive/Microscopy Data/04112028_multiclass_maiden/Training/Actin"
validation_directory = "/content/drive/MyDrive/Microscopy Data/04112028_multiclass_maiden/Validation/Actin"
train_dataset = image_dataset_from_directory(training_directory,
                                             shuffle=True,
                                             batch_size=BATCH_SIZE,
                                             image_size=IMG_SIZE,
                                             seed=42)
validation_dataset = image_dataset_from_directory(validation_directory,
                                             shuffle=True,
                                             batch_size=BATCH_SIZE,
                                             image_size=IMG_SIZE,
                                             seed=42)

Output:找到屬於 6 個類的 600 個文件。 找到屬於 6 個類的 600 個文件。 代碼續...

class_names = train_dataset.class_names

AUTOTUNE = tf.data.experimental.AUTOTUNE
train_dataset = train_dataset.prefetch(buffer_size=AUTOTUNE)

preprocess_input = tf.keras.applications.mobilenet_v2.preprocess_input

IMG_SHAPE = IMG_SIZE + (3,)
base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
                                               include_top=True,
                                               weights='imagenet')

def huvec_model (image_shape=IMG_SIZE, data_augmentation=data_augmenter()):
    ''' Define a tf.keras model for binary classification out of the MobileNetV2 model
    Arguments:
        image_shape -- Image width and height
        data_augmentation -- data augmentation function
    Returns:
    Returns:
        tf.keras.model
    '''
    
    
    input_shape = image_shape + (3,)
    
    # Freeze the base model by making it non trainable
    # base_model.trainable = None 

    # create the input layer (Same as the imageNetv2 input size)
    # inputs = tf.keras.Input(shape=None) 
    
    # apply data augmentation to the inputs
    # x = None
    
    # data preprocessing using the same weights the model was trained on
    # x = preprocess_input(None) 
    
    # set training to False to avoid keeping track of statistics in the batch norm layer
    # x = base_model(None, training=None) 
    
    # Add the new Binary classification layers
    # use global avg pooling to summarize the info in each channel
    # x = None()(x) 
    #include dropout with probability of 0.2 to avoid overfitting
    # x = None(None)(x)
        
    # create a prediction layer with one neuron (as a classifier only needs one)
    # prediction_layer = None
    
    base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
                                               include_top=False,
                                               weights='imagenet')
    base_model.trainable = False
    inputs = tf.keras.Input(shape=input_shape)
    x = data_augmentation(inputs)
    x = preprocess_input(x)
    x = base_model(x, training=False)
    x = tf.keras.layers.GlobalAveragePooling2D()(x)
    x = tfl.Dropout(.2)(x)
    prediction_layer = tf.keras.layers.Dense(units = len(class_names), activation='softmax')
    # YOUR CODE ENDS HERE
    
    outputs = prediction_layer(x) 
    model = tf.keras.Model(inputs, outputs)
    
    return model

model2 = huvec_model(IMG_SIZE)

base_model.trainable = True
# Let's take a look to see how many layers are in the base model
print("Number of layers in the base model: ", len(base_model.layers))

# Fine-tune from this layer onwards
fine_tune_at = 120

# Freeze all the layers before the `fine_tune_at` layer
# for layer in base_model.layers[:fine_tune_at]:
#    layer.trainable = None
    
# Define a BinaryCrossentropy loss function. Use from_logits=True
# loss_function=None
# Define an Adam optimizer with a learning rate of 0.1 * base_learning_rate
# optimizer = None
# Use accuracy as evaluation metric
# metrics=None
base_learning_rate = 0.01
# YOUR CODE STARTS HERE
for layer in base_model.layers[:fine_tune_at]:
    layer.trainable = False
loss_function=tf.keras.losses.BinaryCrossentropy(from_logits=True)
optimizer= tf.keras.optimizers.Adam(learning_rate=0.1*base_learning_rate)
metrics=['accuracy']

# YOUR CODE ENDS HERE
model2.compile(loss=loss_function,
              optimizer = optimizer,
              metrics=metrics)

initial_epochs = 5
history = model2.fit(train_dataset, validation_data=validation_dataset, epochs=initial_epochs)

看起來您還必須對標簽進行單熱編碼,即對於屬於i i class 的圖像的 label,其形狀為(None, 1) ,提供除索引 i 處的 1 之外全為 0 的數組,其形狀為(None, 6) 然后labels具有與logits相同的形狀。

您很容易需要匹配 logits output,或者您需要刪除 model 末尾的 softmax 或分布。

幾乎正確,我對未定義的 data_augmentation 進行了一些更改。

它將具有 output 但計算基於 output 期望嘗試使用 meanquears 你會看到錯誤或使用 class 熵將提供不同的行為。

有人告訴它提高了准確性 output 因為他們使用二進制交叉熵但不是這樣,當使用二進制序列時它會大大提高參見 ALE 游戲示例(街頭霸王)

[ 樣本 ]:

import os
from os.path import exists

import tensorflow as tf

import matplotlib.pyplot as plt

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Variables
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
BATCH_SIZE = 16
IMG_SIZE = (160, 160)
PATH = 'F:\\datasets\\downloads\\sample\\cats_dogs\\training'
training_directory = os.path.join(PATH, 'train')
validation_directory = os.path.join(PATH, 'validation')

train_dataset = tf.keras.utils.image_dataset_from_directory(training_directory,
            shuffle=True,
            batch_size=BATCH_SIZE,
            image_size=IMG_SIZE,
            seed=42)
validation_dataset = tf.keras.utils.image_dataset_from_directory(validation_directory,
            shuffle=True,
            batch_size=BATCH_SIZE,
            image_size=IMG_SIZE,
            seed=42)
    
class_names = train_dataset.class_names
print( "class_names: " + str( class_names ) )

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Functions
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
def huvec_model (image_shape=IMG_SIZE, data_augmentation = tf.keras.Sequential([ tf.keras.layers.RandomFlip('horizontal'), tf.keras.layers.RandomRotation(0.2), ])):
# def huvec_model (image_shape=IMG_SIZE, data_augmentation=data_augmenter()):
    ''' Define a tf.keras model for binary classification out of the MobileNetV2 model
    Arguments:
    image_shape -- Image width and height
    data_augmentation -- data augmentation function
    Returns:
    Returns:
    tf.keras.model
    '''

    input_shape = image_shape + (3,)
    
    base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
        include_top=False,
        weights='imagenet')
    base_model.trainable = False
    inputs = tf.keras.Input(shape=input_shape)
    x = data_augmentation(inputs)
    x = preprocess_input(x)
    x = base_model(x, training=False)
    x = tf.keras.layers.GlobalAveragePooling2D()(x)
    x = tf.keras.layers.Dropout(.2)(x)
    prediction_layer = tf.keras.layers.Dense(units = len(class_names), activation='softmax')

    outputs = prediction_layer(x) 
    model = tf.keras.Model(inputs, outputs)

    return model

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
DataSet
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_dataset = train_dataset.prefetch(buffer_size=AUTOTUNE)
preprocess_input = tf.keras.applications.mobilenet_v2.preprocess_input

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Model Initialize
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
IMG_SHAPE = IMG_SIZE + (3,)
base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
            include_top=True,
            weights='imagenet')

base_model.summary()

model2 = huvec_model(IMG_SIZE)

base_model.trainable = True
# Let's take a look to see how many layers are in the base model
print("Number of layers in the base model: ", len(base_model.layers))

# Fine-tune from this layer onwards
fine_tune_at = 120
base_learning_rate = 0.01

for layer in base_model.layers[:fine_tune_at]:
    layer.trainable = False
    
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Optimizer
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
optimizer = tf.keras.optimizers.Adam(learning_rate=0.1*base_learning_rate)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Loss Fn
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""                               
lossfn = tf.keras.losses.BinaryCrossentropy(from_logits=False)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Model Summary
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
model2.compile(optimizer=optimizer, loss=lossfn, metrics=[ 'accuracy' ])

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Training
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
history = model2.fit(train_dataset, validation_data=validation_dataset, epochs=5)

input('...')

[ Output ] 樣本 ...

發現錯誤:

我不得不在 model 編譯器中將 loss 重新定義為loss='sparse_categorical_crossentropy' ,它最初定義為loss=tf.keras.losses.BinaryCrossentropy(from_logits=True)

有關更多詳細信息,請參閱 SO 線程將 Keras Model 從二進制分類更改為多分類

暫無
暫無

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

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