J'essaie de former un classificateur d'images keras pour prédire entre les mauvaises herbes (1) et les herbes (0) dans les images. Cependant, quelle que soit la méthode / le modèle que j'essaie de créer, la précision reste bloquée, et par là, je veux dire que la précision d'entraînement est comme si elle ne prédit que des 0. Je peux le confirmer, car lorsque j'ai changé mon tableau d'étiquettes pour ne contenir que des zéros, le modèle réclamait en quelque sorte une précision de 1,00, mais lorsque j'ai changé les étiquettes en un, la précision du modèle était de 0,00. Toutes mes images sont redimensionnées et converties en RVB. voici le code:
model = Sequential() model.add(Conv2D(32, kernel_size=3, input_shape=(530, 400, 1))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.2)) model.add(Conv2D(32, kernel_size=3)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.5)) model.add(Conv2D(64, kernel_size=3)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) model.add(Dense(64)) model.add(Activation('relu')) #model.add(Dropout(0.5)) model.add(Dense(2)) #or n_clasess model.add(Activation('softmax')) model.compile(optimizer=Adam(0.0001), loss='categorical_crossentropy', metrics=['accuracy'])
J'applique ensuite to_categorical (étiquettes) pour les encoder à chaud model:
def prep_image(filename): im = cv2.imread(filename, 0) new_im = cv2.resize(im, (400,530)) arr = np.array(new_im) arr = np.reshape(arr, (530, 400)) return arr image_files = [] #contains the file paths of the images images = [] # contains arrays/images labels = [] n_classes = 2 def add_image_data(root): global images global labels print("starting") delim = os.sep for dirpath, dirs, files in tqdm(os.walk(root)): for file in [f for f in files if (f.endswith(".jpg"))]: image_files.append(os.path.join(dirpath, file)) for file in tqdm(image_files): image_arr = prep_image(file) images.append(image_arr) #print("supposed added ", file) label = file.split(delim)[-2] if label == "Grass": label = 0; else: label = 1; labels.append(label) images = np.array(images) labels = np.array(labels)
il ne semble pas non plus y avoir d'apprentissage en cours, la perte et la précision semblent rester bloquées après la première époque. les étiquettes contiennent les deux classes. Merci d'avance
3 Réponses :
Votre ensemble de données est-il déséquilibré? C'est un problème courant lorsque vous avez un jeu de données fortement déséquilibré. Cela signifie qu'une ou plusieurs des classes et bien plus fréquentes que les autres. Votre modèle a découvert que le moyen le plus simple d'obtenir une précision considérable est de deviner la classe la plus fréquente. Cela peut rendre l'optimisation de l'apprentissage beaucoup plus difficile.
Il existe plusieurs façons de gérer les ensembles de données non équilibrés que vous pouvez essayer: https://machinelearningmastery.com/tactics-to-combat-imbalanced-classes-in-your-machine-learning-dataset/
70-30% seraient-ils considérés comme très déséquilibrés?, et comme je l'ai mentionné, même lorsque j'ai fait de mes étiquettes tous les zéros ou tous les uns, cela rendait l'acc 0 ou 1, donc je pense que le problème pourrait être autre chose
avez-vous regardé vos scores de pronostics? Si la métrique de précision est basée sur un score de prédiction> 0,5, il se peut qu'aucune de vos classes n'obtienne un score supérieur à 0,5. Cela est probablement dû au déséquilibre des classes. Vous pouvez ensuite modifier le seuil d'une prédiction "positive".
Essayez plutôt d'utiliser une métrique telle que l'AUC, ou imprimez simplement vos prédictions et examinez les scores.
Modifier à partir des commentaires: Avez-vous prétraité correctement vos entrées? Normalisation, etc. Si vos valeurs d'entrée sont trop grandes, les dégradés ne couleront pas correctement.
Le manque de normalisation arrêtera le flux de gradient. Cela est dû au fait que vous n'utiliserez pas la non-linéarité dans les fonctions d'activation si vos valeurs sont trop grandes / petites pour toutes les entrées.
Avez-vous prétraité correctement vos entrées? Normalisation, etc. Si vos valeurs d'entrée sont trop grandes, les dégradés ne couleront pas correctement.
Cela fonctionne, j'ai simplement supposé parce que c'était en niveaux de gris qu'il était normalisé, mais ce n'était pas le cas, maintenant c'est une formation, merci!
Je pense que le problème peut être que vous comparez une étiquette (0 ou 1) avec le résultat de softmax qui est deux valeurs représentant la probabilité que le sujet soit pour cette classe.
Vous devriez effectuer une conversion d'encodage à chaud comme ceci: 0 -> [1, 0] 1 -> [0, 1]
De cette façon, la sortie du réseau neuronal et les étiquettes sont dans le même format et peuvent être comparées.
mon mauvais, j'ai oublié d'ajouter le code pour cela, mais j'utilise to_categorical pour encoder à chaud mes étiquettes
Puisque vous n'avez que 2 classes, vous devez utiliser
loss = 'binary_crossentropy'
; Je suggérerais également de laisser votre dernière couche dense avec seulement 1 unité et l'activationsigmoïde
(est-ce que vous encodez actuellement vos étiquettes à chaud?)@desertnaut J'ai essayé cela aussi, mais même résultat, j'ai basculé entre les deux modèles et les deux donnent les mêmes sorties. J'ai également essayé la crossentropie binaire avec 1 unité et sigmoïde, mais cela n'a pas non plus fonctionné
De tels détails sont toujours utiles à inclure dans la question ...
Incluez également ce que vous appelez pour entraîner le modèle. Je suppose que
model.fit
mais je l'inclus pour être complet. De plus, par "toutes mes images sont mises à l'échelle", voulez-vous dire redimensionnées? Faites-vous une normalisation que nous ne voyons pas? Une certaine visualisation des données serait utile. Et, pour référence future, vous n'avez pas besoin de convertir une image en tableau puisquecv2
utilisera NumPy comme représentation des images.@LukeDeLuccia J'ai supposé que l'échelle de gris était une normalisation automatique, mais j'ai résolu le problème maintenant, en normalisant manuellement. Merci