简体   繁体   English

使用python在机器学习中将未经训练的对象分类为未知对象

[英]Categorize a not trained object as unknown object in machine learning using python

I'm new in machine learning.我是机器学习的新手。 Currently I'm working on a fruit/vegetable classification project using deep learning with keras.目前我正在使用 keras 进行深度学习的水果/蔬菜分类项目。 I was able to train the model.我能够训练模型。 So far, it can detect already trained objects correctly but when I'm providing an other fruit/vegetable which was not trained, its predicts from the trained model whereas, It should recognize it as unknown fruit.到目前为止,它可以正确检测已经训练过的物体,但是当我提供其他未经训练的水果/蔬菜时,它会根据训练过的模型进行预测,而它应该将其识别为未知水果。

Suppose, I trained a model with Apple, Potato and Banana images.假设,我用 Apple、Potato 和 Banana 图像训练了一个模型。 As long as I provide the images of Apple/Potato/Banana its predicts correctly.只要我提供 Apple/Potato/Banana 的图像,它就会正确预测。 But the moment I provide a image of an Orange, it predicts as an Potato or lemon predicts as an Apple.但是当我提供一个橙子的图像时,它预测为土豆或柠檬预测为苹果。 Here is the code snippet that I'm using to train & predicts fruits:这是我用来训练和预测水果的代码片段:

import os.path
import numpy as np
np.random.seed(123)
from keras import applications
from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense
from keras.utils.np_utils import to_categorical
from keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img
from keras.layers.normalization import BatchNormalization
import matplotlib.pyplot as plt
import math
import cv2   

#dimensions of images
img_width, img_height = 224, 224  

#file paths & directories
top_model_weights_path = 'bottleneck_fc_model.h5'
bottleneck_train_path = 'bottleneck_features_train.npy'
bottleneck_validation_path = 'bottleneck_features_validation.npy'
train_data_dir = 'data/train'
validation_data_dir = 'data/validation/'

#hyperparameters
epochs = 10
batch_size = 16


def save_bottleneck_features():
    model = applications.VGG16(include_top=False, weights='imagenet')

    datagen = ImageDataGenerator(rescale=1./255,
                                 shear_range=0.2,
                                 zoom_range=0.2,
                                 horizontal_flip=True)

    generator = datagen.flow_from_directory(train_data_dir,
                                            target_size=(img_width, img_height),
                                            batch_size=batch_size,
                                            shuffle=False)

    no_train_samples = len(generator.filenames)

    predict_size_train = int(math.ceil(no_train_samples / batch_size))
    bottleneck_features_train = model.predict_generator(generator, predict_size_train)
    np.save(bottleneck_train_path, bottleneck_features_train)

    datagen = ImageDataGenerator(rescale=1./255)

    generator = datagen.flow_from_directory(validation_data_dir,
                                            target_size=(img_width, img_height),
                                            batch_size=batch_size,
                                            class_mode=None,
                                            shuffle=False)

    no_validation_samples = len(generator.filenames)

    predict_size_validation = int(math.ceil(no_validation_samples / batch_size))
    bottleneck_features_validation = model.predict_generator(generator, predict_size_validation)
    np.save(bottleneck_validation_path, bottleneck_features_validation)



def train_top_model():
    datagen_top = ImageDataGenerator(rescale=1./255)

    generator_top = datagen_top.flow_from_directory(train_data_dir, 
                                                    target_size=(img_width, img_height),
                                                    batch_size=batch_size,
                                                    class_mode='categorical',
                                                    shuffle=False)

    num_classes = len(generator_top.class_indices)

    # save the class indices to use later in predictions
    np.save('class_indices.npy', generator_top.class_indices)

    # get the class labels for the training data, in the original order
    train_labels = generator_top.classes
    # convert the training labels to categorical vectors
    train_labels = to_categorical(train_labels, num_classes=num_classes)

    generator_top = datagen_top.flow_from_directory(validation_data_dir,
                                                    target_size=(img_width, img_height),
                                                    batch_size=batch_size,
                                                    class_mode=None,
                                                    shuffle=False)

    validation_labels = generator_top.classes
    validation_labels = to_categorical(validation_labels, num_classes=num_classes)

    # load the bottleneck features saved earlier
    train_data = np.load('bottleneck_features_train.npy')
    validation_data = np.load('bottleneck_features_validation.npy')


    # build the model
    model = Sequential()
    model.add(Flatten(input_shape=train_data.shape[1:]))
    model.add(BatchNormalization())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(num_classes, activation='softmax'))

    model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

    history = model.fit(train_data, train_labels, epochs=epochs, batch_size=batch_size)

    model.save_weights(top_model_weights_path)


def predict(image_path):
    class_dictionary = np.load('class_indices.npy').item()
    #print("Values: ",class_dictionary)

    num_classes = len(class_dictionary)

    orig = cv2.imread(image_path)

    print('[INFO] loading and preprocessing image...')
    image = load_img(image_path, target_size=(224, 224))
    image = img_to_array(image)
    image = image / 255
    image = np.expand_dims(image, axis=0)

    model = applications.VGG16(include_top=False, weights='imagenet')

    bottleneck_prediction = model.predict(image)

    # build top model
    model = Sequential()
    model.add(Flatten(input_shape=bottleneck_prediction.shape[1:]))
    model.add(BatchNormalization())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(num_classes, activation='sigmoid'))

    model.load_weights(top_model_weights_path)

    # use the bottleneck prediction on the top model to get the final classification
    class_predicted = model.predict_classes(bottleneck_prediction)

    probabilities = model.predict_proba(bottleneck_prediction)

    inID = class_predicted[0]

    inv_map = {v: k for k, v in class_dictionary.items()}

    label = inv_map[inID]

    print("Image ID: {}, Label: {}".format(inID, label))

    cv2.putText(orig, "Predicted: {}".format(label), (10, 30),
                cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 0, 0), 2)

    cv2.imshow('Classification', orig)
    cv2.imwrite('predicted.jpg', orig)
    cv2.waitKey(0)


if __name__ == '__main__': 
    if not os.path.exists(bottleneck_train_path):
        save_bottleneck_features()
    if not os.path.exists(top_model_weights_path):
        train_top_model()

    image_path = 'fruits/orange.jpg'  
    predict(image_path)

How to overcome this situation?如何克服这种情况? Any help will be appreciated.任何帮助将不胜感激。

When training with loss='categorical_crossentropy' , and activation='softmax' at the last layer, each class is represented by 1 node in the graph at the last layer.在最后一层使用loss='categorical_crossentropy'activation='softmax'进行训练时,每个类在最后一层由图中的 1 个节点表示。 softmax ensures the value of all the nodes is summed to 1, by normalizing all the values. softmax 通过对所有值进行归一化,确保所有节点的值总和为 1。
categorial crossentropy assumes the node with the highest value is the predicted class, and compares it with the labels.分类交叉熵假设具有最高值的节点是预测类别,并将其与标签进行比较。

For example, after predicting a sample you might can have the following values for nodes: 0.33 banana, 0.33 apple, 0.34 potato , thus potato will be the class selected for the prediction.例如,在预测样本后,您可能会为节点设置以下值: 0.33 banana, 0.33 apple, 0.34 potato ,因此马铃薯将是为预测选择的类。

If you wish to have an 'unknown class' prediction, you should add it as another possible class, and have some samples labeled as unknown class during training.如果您希望进行“未知类别”预测,则应将其添加为另一个可能的类别,并在训练期间将一些样本标记为未知类别。

Edit:编辑:
Note that while what i suggested above can work for you, training it can be very difficulty, as it might require a larger number of samples, both known and unkown, as the 'unkown' features are harder to generalize, and might damage the other classes generalization.请注意,虽然我上面的建议可以为您工作,但训练它可能非常困难,因为它可能需要大量样本,已知和未知,因为“未知”特征更难概括,并且可能会损坏另一个类泛化。

A more practical way would be to define a threshold, as i mentioned earlier, after predicting you recieve some value for each one of the possible labels.更实用的方法是定义一个阈值,正如我之前提到的,在预测您收到每个可能标签的某个值之后。 When picking the label, this value is the 'confidence' score of the label.选择标签时,该值是标签的“置信度”分数。
Examining the example above, we will pick potato with 0.34 confidence.检查上面的示例,我们将以 0.34 的置信度选择马铃薯。
You could define some threshold, say 0.6, and when assuming the label for the image, check the different confidence score, if the highest (the 'chosen') label is lower then the threshold, you can mark it as 'unknown fruit'.您可以定义一些阈值,例如 0.6,并在假设图像的标签时,检查不同的置信度分数,如果最高(“选择”)标签低于阈值,您可以将其标记为“未知水果”。

Another Edit另一个编辑
Several good works on the subject as come up since that question, for future reference, this: https://github.com/hendrycks/outlier-exposure自从那个问题出现以来,关于这个主题的一些好作品,供将来参考,这个: https : //github.com/hendrycks/outlier-exposure

would be a good place to start.将是一个很好的起点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 这对于使用 Tensorflow Object Detection API 训练的机器学习模型是否正常? - Is this normal for machine learning model trained using Tensorflow Object Detection API 使用机器学习对大文本进行分类 - categorize large text using machine learning 在Python中使用dlib训练的对象检测器 - Using dlib trained object detector in Python 如何在python 3.5上训练的python 3.6中加载机器学习模型? - How to load machine learning model in python 3.6 that is trained on python 3.5? Python机器学习训练有素的分类器错误指数超出范围 - Python Machine Learning Trained Classifer Error index is out of bounds 是否可以在python中提取训练有素的机器学习模型的公式? - Is it possible to extract the formulas of the trained machine learning models in python? 在python中使用机器学习的笔法 - stylometry using machine learning in python 是否可以将 TensorFlow 中经过训练的模型转换为可用于迁移学习的对象? - Is it possible to convert a trained model in TensorFlow to an object that could be used for transfer learning? 在 javascript 中加载经过训练的机器学习 model - Load trained Machine Learning model in javascript 在机器学习中识别未经训练的项目的可能性 - Possibility of identification of non trained item in Machine Learning
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM