Делаем нейронную сеть, которая сможет отличить борщ от пельмешек

    Как то раз смотря видос про достижения Поднебесной, я увидел прикольную штуку. Столовую будущего, точнее для Китая настоящего, а для нас будущего. Суть заключалась в полном самообслуживание клиента. Он брал блюда на поднос и подносил поднос к видео камере где нейросетка детектировала и распознавала еду, выставляла ему счет и он через еще одну нейронную сеть, которая распознавала его лицо, оплачивал свою покупку. Мне тоже захотелось сделать что то подобное. Размечать датасет под YOLO, что бы можно было детектировать блюда мне было совсем не охото. Готово размеченного с борщами и пельмешками я не нашел, поэтому решил сделать только классификацию.



    Картинки борща, пельменей и кофе я спарсил из гугла и яндекса. Далее разложил их по папкам train и data. Засада оказалась в керасе, а именно в модуле image generator. Я не хотел что бы датасет занимал всю оперативку, но почему то когда программа доходила до этого модуля, то она зависала. Ну тогда я решил идти простым пу тем и просто забил весь датасет в оперативку.

    def data_load_image(folder, y, z):
        imagePath = folder + '/'
        jpg1 = ".jpg"
        y = int(y)
        global number
        global dataset_X
        global dataset_Y
        global dataval_X
        global dataval_Y
        for file in glob.glob(folder +"/*"):
            identify = os.path.splitext(os.path.basename(file))[0]
            #print (identify)
            cv = imagePath + identify + jpg1
            #print (cv)
            img = (cv2.imread(cv))
            img = cv2.resize(img,(224,224))
            #img = np.reshape(img,(3,224,224))
            if z == 1:
                dataset_X[number, :, : , :] = img/255.0
                dataset_Y[number, y] = 1
            else:
                dataval_X[number, :, :, :] = img/255.0
                dataval_Y[number, y] = 1
            number = number + 1
    

    Далее скачиваем библиотеку Resnet-50 без подключенных верхних слоев и замораживаем их. Обучение наиважнейшей задаче по рапознованию пельмешек было опробованно так же на VGG-19 и MobileNet, но они с задачей не справлялись от слова совсем.

    model = applications.ResNet50(
        weights = 'imagenet',include_top = False,
        input_tensor = img, input_shape = None, pooling = 'avg')
    for layer in model.layers:
        layer.trainable = False
    

    Добавляем слои для transfer learning

    #Adding custom Layers 
    x = model.layers[-1].output
    #x = Flatten()(x)
    #x = Dense(128, activation="relu")(x)
    x = Dropout(0.1)(x)
    x = Dense(256, activation="relu")(x)
    
    predictions = Dense(4, activation="sigmoid")(x)
    
    # creating the final model 
    model_final = Model(input = model.input, output = predictions)

    Функция для перемешивания наших картинок, что бы нейросети было сложнее обучаться. Хочу заметить что я не задавал конкретного значения для функции рандома. Модель обучалась несколько раз с разным значением рандома и каждый раз результат был более 90 процентов.

    Похоже правило счастливого билета действует только для больших нейронных сетей.

    def unison_shuffled_copies(a, b):
        assert len(a) == len(b)
        z = np.arange(a.shape[0])
        np.random.shuffle(z)
        print(z.shape)
        return a[z,:], b[z,:]

    Для обучения я использовал категориальную кросэнтропию, а оптимизатор — адам.

    model_final.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    model.summary()

    Ну и сам процесс обучения. Здесь я перемешивал картинки каждую эпоху

    for i in range(30):
    	print('STEP ' + str(i))
    	model_final.fit(dataset_X, dataset_Y, epochs=1, batch_size=15)
    	dataset_X, dataset_Y = unison_shuffled_copies(dataset_X,dataset_Y)

    Результат на видео.


    Ссылка на исходники.

    Для запуска нейронки запустите файл opencv-camera.py
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 6

      +2
      А как нейросеть опознаёт это?
      image
      (на фото не прикол, а реально существующее блюдо)
        +1
        Это чучвара, узбекское блюдо. По русски суп с пельменями.
        0

        Зачем так было усложнять имхо coreML справиться с этим.

          0

          Я занимался лет 10 назад задачей распознавания типа блюда по его фото для определения состава и калорийности. Там все не так просто, ибо отличить блин с мясом от блина с творогом физически невозможно, апельсин от мандарина — в общем случае (при произвольном освещении) тоже, равно как сметану от майонеза. Размер порции же можно определить только в определенной посуде определенного ресторана. Кроме того, нужно отстраиваться от подносов, тарелок и скатертей, на которых тоже может быть изображена еда ;)


          Есть ещё гомогенные блюда (каша), и гетерогенные — английский завтрак. Для последних хорошие результаты даёт анализ по предварительно определённым кластерам — омлет, горошек, сосиска — и выбор блюда из наиболее вероятного исходя из определенных компонентов и их пропорций

            0
            10 лет назад эта задача была много сложнее.
            Какой подход использовали?
            0

            «Не ХотДог.» ©


            image

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое