1
votes

Pourquoi j'obtiens une précision nulle dans le modèle de classification binaire Keras?

J'ai un modèle séquentiel Keras prenant des entrées à partir de fichiers csv. Lorsque je lance le modèle, sa précision reste nulle même après 20 époques.

J'ai parcouru ces deux threads de stackoverflow ( zéro-précision-formation et pourquoi-est-la-précision-pour-mon-modèle-keras-toujours-0 ) mais rien n'a résolu mon problème.

Comme mon modèle est une classification binaire, et je pense qu'il ne devrait pas fonctionner comme un modèle de régression pour rendre la métrique de précision inefficace. Voici le modèle

def preprocess(*fields):
    return tf.stack(fields[:-1]), tf.stack(fields[-1:]) # x, y


import tensorflow as tf
from tensorflow.keras import layers
from tensorflow import feature_column

import pathlib

csvs =  sorted(str(p) for p in pathlib.Path('.').glob("My_Dataset/*/*/*.csv"))

data_set=tf.data.experimental.CsvDataset(
    csvs, record_defaults=defaults, compression_type=None, buffer_size=None,
    header=True, field_delim=',', use_quote_delim=True, na_value=""
)
print(type(data_set))

#Output: <class 'tensorflow.python.data.experimental.ops.readers.CsvDatasetV2'>

data_set.take(1)

#Output: <TakeDataset shapes: ((), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()), types: (tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32, tf.float32)>

validate_ds = data_set.map(preprocess).take(10).batch(100).repeat()
train_ds = data_set.map(preprocess).skip(10).take(90).batch(100).repeat()

model = tf.keras.Sequential([
    layers.Dense(256,activation='elu'),  
    layers.Dense(128,activation='elu'),  
    layers.Dense(64,activation='elu'),  
    layers.Dense(1,activation='sigmoid') 
])


model.compile(optimizer='adam',
            loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
            metrics=['accuracy'])    #have to find the related evaluation metrics


model.fit(train_ds,
        validation_data=validate_ds,
        validation_steps=5,
        steps_per_epoch= 5,
        epochs=20,
        verbose=1
        )

Qu'est-ce que je fais mal?


1 commentaires

Votre réseau ne produit pas de logits car il a une activation sigmoïde en sortie, donc from_logits = True n'est pas correct.


3 Réponses :


1
votes

Êtes-vous sûr que la vôtre est une tâche de classification?

Parce que comme je peux le voir à partir de votre variable cible, celle que vous extrayez du csv, le type est un float

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

S'il s'agit d'une tâche de classification binaire, vérifiez également que les valeurs des valeurs cibles sont 0 et 1. Sinon, le modèle fonctionnera mal

Quelque chose comme ça:

#Output: <TakeDataset shapes: ((), (), ..., tf.float32)>

Parce que le crossentropy fonctionne avec 0 et 1

C'est la raison pour laquelle vous utilisez le sigmoïde comme fonction d'activation, qui affichera des valeurs dans la plage [0, 1]

Comme déjà suggéré, vous devez définir from_logits=False


3 commentaires

Ok Cher, Cela semble être une solution correcte pour vous et Timbus Calin. J'ai créé une prime pour le même problème il y a quelques jours. Vous voudrez peut-être y répondre également. stackoverflow.com/questions/64725275/...


Bonjour Nikaido, je train_ds = training_dataset.map(preprocess).skip(10).take(90).batch(100‌​).repeat() mon expérience en appelant la répétition sur l'ensemble de données en tant que train_ds = training_dataset.map(preprocess).skip(10).take(90).batch(100‌​).repeat() mais je suis confus quand Je supprime reapeat () de la fin, la formation prend beaucoup de temps. Et en cas de répétition (), l'entraînement s'est terminé en quelques secondes, ce qui ne va pas selon moi ...! Peux-tu aider s'il te plait?


@DevLoverUmar, il est assez difficile de comprendre pourquoi. Je vous suggère d'ouvrir une nouvelle question car c'est un autre problème. Quoi qu'il en soit, essayez si possible de partager un instantané de vos données, avant et après l'élaboration, pour vérifier ce qui se passe à l'intérieur



1
votes

Le problème est ici:

model = tf.keras.Sequential([
    layers.Dense(256,activation='elu'),  
    layers.Dense(128,activation='elu'),  
    layers.Dense(64,activation='elu'),  
    layers.Dense(1,activation='sigmoid') 
])


model.compile(optimizer='adam',
              #Here is the problem
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])    #Have to find the related evaluation metrics

Vous avez deux solutions:

  1. Soit défini from_logits=False

  2. Ou laissez les layers.Dense(1) and (from_logits=True)

C'est la raison pour laquelle vous rencontrez le problème, puisque from_logits = True implique qu'aucune fonction d'activation n'est utilisée.


0 commentaires

1
votes

Avec l'aide d'autres réponses de Nikaido et Timbus Calin, j'ai fait un changement mineur et c'est corrigé.

def preprocess(*fields):
    features=tf.stack(fields[:-1])
    labels=tf.stack([int(x) for x in fields[-1:]])
    return features,labels  # x, y

Je viens de changer le type de données de l'étiquette de classe en int dans le prétraitement, pour le faire fonctionner comme un classificateur.


0 commentaires