Учим робота готовить пиццу. Часть 1: Получаем данные


    Автор изображения: Chuchilko


    Не так давно, после завершения очередного конкурса на Kaggle — вдруг возникла идея попробовать сделать тестовое ML-приложение.
    Например, такое: "помоги роботу сделать пиццу".


    Разумеется, основная цель этого ровно та же — изучение нового.


    Захотелось разобраться, как работают генеративные нейронные сети (Generative Adversarial Networks — GAN).


    Ключевой идеей было обучить GAN, который по выбранным ингредиентам сам собирает картинку пиццы.


    Ну что ж, приступим.


    Начало


    Разумеется, для тренировки любого алгоритма машинного обучения, нам первым делом нужны данные.
    В нашем случае, вариантов не так много — либо находить готовый датасет, либо вытаскивать данные из интернета самостоятельно.


    И тут я подумал — а почему бы не дёрнуть данные с сайта Додо-пиццы.


    Disclaimer

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


    Итак, в первом пункте плана действий появилось:


    1. получить с сайта нужные данные

    Загрузка данных


    Так как вся нужная нам информация доступна на сайте Додо-пиццы, применим так называемый парсинг сайтов (он же — Web Scraping).


    Здесь нам поможет статья: Web Scraping с помощью python.


    И всего две библиотеки:


    import requests
    import bs4

    Открываем сайт додо-пиццы, щелкаем в браузере "Просмотреть код" и находим элемент с нужными данными.


    На заглавной странице можно получить только базовый список пицц и их состав.
    Более подробную информацию можно получить, кликнув на понравившийся товар. Тогда появится всплывающее окошко, с подробной информацией и красивыми картинками о пицце.

    Это окошко появляется в результате GET-запроса, который можно эмулировать, передав нужные заголовки:


    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36',
        'Referer': siteurl,
        'x-requested-with': 'XMLHttpRequest'
    }
    res = requests.get(siteurl, headers = headers)

    в ответ получаем кусок html-кода, который уже можно распарсить.


    Сразу же можно обратить внимание, что статический контент распространяется через CDN akamaihd.net


    После непродолжительных эспериментов — получился скрипт dodo_scrapping.py, который получает с сайта додо-пиццы название пицц, их состав, а так же сохраняет в отдельные директории по три фотографии пицц.


    На выходе работы скрипта получается несколько csv-файлов и директорий с фотографиями.
    Для этого выполняются следующие действия:


    • получение списка городов (на тот момент — 146)
    • получение списка пицц (для Города)
    • получение информации о пицце
    • загрузка фотографий пиццы

    Информацию о пицце сохраняется в табличку вида:
    город, URL города, название, названиеENG, URL пиццы, содержимое, цена, калории, углеводы, белки, жиры, диаметр, вес


    Что хорошо в программировании скриптов автоматизации — их можно запустить и откинувшись на списку кресла наблюдать за их работой...


    На выходе получилось всего 20 пицц.
    На каждую пиццу получается по 3 картинки. Нас интересует только третья картинка, на которой есть вид пиццы сверху.


    Разумеется, после получения картинок, их нужно дополнительно обработать — вырезать и отцентровать пиццу.
    Думаю, это не должно составить особых проблем, так как все картинки одинаковые — 710х380.


    Обработка данных


    После scraping-а сайта, получили привычные по kaggle — csv-файл с данными (и директории с картинками).
    Настала пора изучить пиццы.


    Подключаем необходимые библиотеки.


    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    %matplotlib inline 
    
    import seaborn as sns
    
    np.random.seed(42)
    
    import cv2
    import os
    import sys

    df = pd.read_csv('pizzas.csv', encoding='cp1251')
    print(df.shape)

    (20, 13)

    df.info()

    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 20 entries, 0 to 19
    Data columns (total 13 columns):
    city_name         20 non-null object
    city_url          20 non-null object
    pizza_name        20 non-null object
    pizza_eng_name    20 non-null object
    pizza_url         20 non-null object
    pizza_contain     20 non-null object
    pizza_price       20 non-null int64
    kiloCalories      20 non-null object
    carbohydrates     20 non-null object
    proteins          20 non-null object
    fats              20 non-null object
    size              20 non-null int64
    weight            20 non-null object
    dtypes: int64(2), object(11)
    memory usage: 2.1+ KB

    df.head()


    city_name city_url pizza_name pizza_eng_name pizza_url pizza_contain pizza_price kiloCalories carbohydrates proteins fats size weight
    0 Калининград /Kaliningrad Двойная пепперони double-pepperoni https://dodopizza.ru/Kaliningrad/Product/doubl... Томатный соус, двойная порция пепперони и увел... 395 257,52 26,04 10,77 12,11 25 470±50
    1 Калининград /Kaliningrad Крэйзи пицца crazy-pizza https://dodopizza.ru/Kaliningrad/Product/crazy... Томатный соус, увеличенные порции цыпленка и п... 395 232,37 31,33 9,08 7,64 25 410±50
    2 Калининград /Kaliningrad Дон Бекон pizza-don-bekon https://dodopizza.ru/Kaliningrad/Product/pizza... Томатный соус, бекон, пепперони, цыпленок, кра... 395 274 25,2 9,8 14,8 25 454±50
    3 Калининград /Kaliningrad Грибы и ветчина gribvetchina https://dodopizza.ru/Kaliningrad/Product/gribv... Томатный соус, ветчина, шампиньоны, моцарелла 315 189 23,9 9,3 6,1 25 370±50
    4 Калининград /Kaliningrad Пицца-пирог pizza-pirog https://dodopizza.ru/Kaliningrad/Product/pizza... Сгущенное молоко, брусника, ананасы 315 144,9 29,8 2,9 2,7 25 420±50


    Приведём данные к более удобному виду.


    df['kiloCalories'] = df.kiloCalories.apply(lambda x: x.replace(',','.'))
    df['carbohydrates'] = df.carbohydrates.apply(lambda x: x.replace(',','.'))
    df['proteins'] = df.proteins.apply(lambda x: x.replace(',','.'))
    df['fats'] = df.fats.apply(lambda x: x.replace(',','.'))
    df['weight'], df['weight_err'] = df['weight'].str.split('±', 1).str

    df['kiloCalories'] = df.kiloCalories.astype('float32')
    df['carbohydrates'] = df.carbohydrates.astype('float32')
    df['proteins'] = df.proteins.astype('float32')
    df['fats'] = df.fats.astype('float32')
    df['weight'] = df.weight.astype('int64')
    df['weight_err'] = df.weight_err.astype('int64')

    df.head()


    city_name city_url pizza_name pizza_eng_name pizza_url pizza_contain pizza_price kiloCalories carbohydrates proteins fats size weight weight_err
    0 Калининград /Kaliningrad Двойная пепперони double-pepperoni https://dodopizza.ru/Kaliningrad/Product/doubl... Томатный соус, двойная порция пепперони и увел... 395 257.519989 26.040001 10.77 12.11 25 470 50
    1 Калининград /Kaliningrad Крэйзи пицца crazy-pizza https://dodopizza.ru/Kaliningrad/Product/crazy... Томатный соус, увеличенные порции цыпленка и п... 395 232.369995 31.330000 9.08 7.64 25 410 50
    2 Калининград /Kaliningrad Дон Бекон pizza-don-bekon https://dodopizza.ru/Kaliningrad/Product/pizza... Томатный соус, бекон, пепперони, цыпленок, кра... 395 274.000000 25.200001 9.80 14.80 25 454 50
    3 Калининград /Kaliningrad Грибы и ветчина gribvetchina https://dodopizza.ru/Kaliningrad/Product/gribv... Томатный соус, ветчина, шампиньоны, моцарелла 315 189.000000 23.900000 9.30 6.10 25 370 50
    4 Калининград /Kaliningrad Пицца-пирог pizza-pirog https://dodopizza.ru/Kaliningrad/Product/pizza... Сгущенное молоко, брусника, ананасы 315 144.899994 29.799999 2.90 2.70 25 420 50


    Учитывая, что пищевая ценность продукта приводится в расчёте на 100 грамм, то для лучшего понимания — домножим их на массу пиццы.


    df['pizza_kiloCalories'] = df.kiloCalories * df.weight / 100
    df['pizza_carbohydrates'] = df.carbohydrates * df.weight / 100
    df['pizza_proteins'] = df.proteins * df.weight / 100
    df['pizza_fats'] = df.fats * df.weight / 100

    df.describe()


    pizza_price kiloCalories carbohydrates proteins fats size weight weight_err pizza_kiloCalories pizza_carbohydrates pizza_proteins pizza_fats
    count 20.00000 20.000000 20.000000 20.000000 20.00000 20.0 20.000000 20.0 20.000000 20.000000 20.000000 20.000000
    mean 370.50000 212.134491 25.443501 8.692500 8.44250 25.0 457.700000 50.0 969.942043 115.867950 39.857950 38.736650
    std 33.16228 34.959122 2.204143 1.976283 3.20358 0.0 43.727746 0.0 175.835991 8.295421 9.989803 15.206275
    min 315.00000 144.899994 22.100000 2.900000 2.70000 25.0 370.000000 50.0 608.579974 88.429999 12.180000 11.340000
    25% 367.50000 188.250000 23.975000 7.975000 6.05000 25.0 420.000000 50.0 858.525000 113.010003 35.625000 28.159999
    50% 385.00000 212.500000 24.950000 9.090000 8.20000 25.0 460.000000 50.0 966.358490 114.779002 39.580000 35.930001
    75% 395.00000 235.527496 26.280001 9.800000 9.77500 25.0 485.000000 50.0 1095.459991 120.597001 45.707500 47.020001
    max 395.00000 274.000000 31.330000 12.200000 14.80000 25.0 560.000000 50.0 1243.960000 128.453000 60.999999 68.080001


    Настала пора узнать, какие же пиццы самые-самые...


    Итак, самая калорийная пицца


    df[df.pizza_kiloCalories == np.max(df.pizza_kiloCalories)]


    city_name city_url pizza_name pizza_eng_name pizza_url pizza_contain pizza_price kiloCalories carbohydrates proteins fats size weight weight_err pizza_kiloCalories pizza_carbohydrates pizza_proteins pizza_fats
    2 Калининград /Kaliningrad Дон Бекон pizza-don-bekon https://dodopizza.ru/Kaliningrad/Product/pizza... Томатный соус, бекон, пепперони, цыпленок, кра... 395 274.0 25.200001 9.8 14.8 25 454 50 1243.96 114.408003 44.492001 67.192001


    Самая жирная пицца:


    df[df.pizza_fats == np.max(df.pizza_fats)]


    city_name city_url pizza_name pizza_eng_name pizza_url pizza_contain pizza_price kiloCalories carbohydrates proteins fats size weight weight_err pizza_kiloCalories pizza_carbohydrates pizza_proteins pizza_fats
    14 Калининград /Kaliningrad Мясная myasnaya-pizza https://dodopizza.ru/Kaliningrad/Product/myasn... Томатный соус, охотничьи колбаски, бекон, ветч... 395 268.0 24.200001 9.1 14.8 25 460 50 1232.8 111.320004 41.860002 68.080001


    Самая богатая углеводами:


    df[df.pizza_carbohydrates == np.max(df.pizza_carbohydrates)]


    city_name city_url pizza_name pizza_eng_name pizza_url pizza_contain pizza_price kiloCalories carbohydrates proteins fats size weight weight_err pizza_kiloCalories pizza_carbohydrates pizza_proteins pizza_fats
    1 Калининград /Kaliningrad Крэйзи пицца crazy-pizza https://dodopizza.ru/Kaliningrad/Product/crazy... Томатный соус, увеличенные порции цыпленка и п... 395 232.369995 31.33 9.08 7.64 25 410 50 952.71698 128.453 37.228 31.323999


    Самая богатая белками:


    df[df.pizza_proteins == np.max(df.pizza_proteins)]


    city_name city_url pizza_name pizza_eng_name pizza_url pizza_contain pizza_price kiloCalories carbohydrates proteins fats size weight weight_err pizza_kiloCalories pizza_carbohydrates pizza_proteins pizza_fats
    7 Калининград /Kaliningrad Гавайская gavayskaya-pizza https://dodopizza.ru/Kaliningrad/Product/gavay... Томатный соус, ананасы, цыпленок, моцарелла 315 216.0 25.0 12.2 7.4 25 500 50 1080.0 125.0 60.999999 37.0


    Самая тяжёлая по весу пицца:


    df[df.weight == np.max(df.weight)]


    city_name city_url pizza_name pizza_eng_name pizza_url pizza_contain pizza_price kiloCalories carbohydrates proteins fats size weight weight_err pizza_kiloCalories pizza_carbohydrates pizza_proteins pizza_fats
    8 Калининград /Kaliningrad Додо pizza-dodo https://dodopizza.ru/Kaliningrad/Product/pizza... Томатный соус, говядина (фарш), ветчина, пеппе... 395 203.899994 22.1 8.6 8.9 25 560 50 1141.839966 123.760002 48.160002 49.839998


    Самая лёгкая по весу пицца:


    df[df.weight == np.min(df.weight)]


    city_name city_url pizza_name pizza_eng_name pizza_url pizza_contain pizza_price kiloCalories carbohydrates proteins fats size weight weight_err pizza_kiloCalories pizza_carbohydrates pizza_proteins pizza_fats
    3 Калининград /Kaliningrad Грибы и ветчина gribvetchina https://dodopizza.ru/Kaliningrad/Product/gribv... Томатный соус, ветчина, шампиньоны, моцарелла 315 189.0 23.9 9.3 6.1 25 370 50 699.3 88.429999 34.410001 22.57


    Получаем названия пицц


    pizza_names = df['pizza_name'].tolist()
    pizza_eng_names = df['pizza_eng_name'].tolist()
    print( pizza_eng_names )

    ['double-pepperoni', 'crazy-pizza', 'pizza-don-bekon', 'gribvetchina', 'pizza-pirog', 'pizza-margarita', 'syrnaya-pizza', 'gavayskaya-pizza', 'pizza-dodo', 'pizza-chetyre-sezona', 'ovoshi-i-griby', 'italyanskaya-pizza', 'meksikanskaya-pizza', 'morskaya-pizza', 'myasnaya-pizza', 'pizza-pepperoni', 'ranch-pizza', 'pizza-syrnyi-cyplenok', 'pizza-cyplenok-barbekyu', 'chizburger-pizza']

    Получаем путь до картинок — нас интересует 3-я картинка (вид сверху)


    image_paths = []
    for name in pizza_eng_names:
        path = os.path.join(name, name+'3.jpg')
        image_paths.append(path)
    print(image_paths)

    ['double-pepperoni\\double-pepperoni3.jpg', 'crazy-pizza\\crazy-pizza3.jpg', 'pizza-don-bekon\\pizza-don-bekon3.jpg', 'gribvetchina\\gribvetchina3.jpg', 'pizza-pirog\\pizza-pirog3.jpg', 'pizza-margarita\\pizza-margarita3.jpg', 'syrnaya-pizza\\syrnaya-pizza3.jpg', 'gavayskaya-pizza\\gavayskaya-pizza3.jpg', 'pizza-dodo\\pizza-dodo3.jpg', 'pizza-chetyre-sezona\\pizza-chetyre-sezona3.jpg', 'ovoshi-i-griby\\ovoshi-i-griby3.jpg', 'italyanskaya-pizza\\italyanskaya-pizza3.jpg', 'meksikanskaya-pizza\\meksikanskaya-pizza3.jpg', 'morskaya-pizza\\morskaya-pizza3.jpg', 'myasnaya-pizza\\myasnaya-pizza3.jpg', 'pizza-pepperoni\\pizza-pepperoni3.jpg', 'ranch-pizza\\ranch-pizza3.jpg', 'pizza-syrnyi-cyplenok\\pizza-syrnyi-cyplenok3.jpg', 'pizza-cyplenok-barbekyu\\pizza-cyplenok-barbekyu3.jpg', 'chizburger-pizza\\chizburger-pizza3.jpg']

    Загружаем картинки


    images = []
    for path in image_paths:
        print('Load image:', path)
        image = cv2.imread(path)
        if image is not None:
            images.append(image)
        else:
            print('Error read image:', path)

    Load image: double-pepperoni\double-pepperoni3.jpg
    Load image: crazy-pizza\crazy-pizza3.jpg
    Load image: pizza-don-bekon\pizza-don-bekon3.jpg
    Load image: gribvetchina\gribvetchina3.jpg
    Load image: pizza-pirog\pizza-pirog3.jpg
    Load image: pizza-margarita\pizza-margarita3.jpg
    Load image: syrnaya-pizza\syrnaya-pizza3.jpg
    Load image: gavayskaya-pizza\gavayskaya-pizza3.jpg
    Load image: pizza-dodo\pizza-dodo3.jpg
    Load image: pizza-chetyre-sezona\pizza-chetyre-sezona3.jpg
    Load image: ovoshi-i-griby\ovoshi-i-griby3.jpg
    Load image: italyanskaya-pizza\italyanskaya-pizza3.jpg
    Load image: meksikanskaya-pizza\meksikanskaya-pizza3.jpg
    Load image: morskaya-pizza\morskaya-pizza3.jpg
    Load image: myasnaya-pizza\myasnaya-pizza3.jpg
    Load image: pizza-pepperoni\pizza-pepperoni3.jpg
    Load image: ranch-pizza\ranch-pizza3.jpg
    Load image: pizza-syrnyi-cyplenok\pizza-syrnyi-cyplenok3.jpg
    Load image: pizza-cyplenok-barbekyu\pizza-cyplenok-barbekyu3.jpg
    Load image: chizburger-pizza\chizburger-pizza3.jpg

    Посмотрим на картинку


    def plot_img(img):
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        plt.imshow(img_rgb)
    
    print(images[0].shape)
    plot_img(images[0])

    (380, 710, 3)


    Пиццы располагаются в одной и той же области — вырезаем


    pizza_imgs = []
    for img in images:
        y, x, height, width = 0, 165, 380, 380
        pizza_crop = img[y:y+height, x:x+width]
        pizza_imgs.append(pizza_crop)
    print(pizza_imgs[0].shape)
    print(len(pizza_imgs))
    plot_img(pizza_imgs[0])

    (380, 380, 3)
    20


    Посмотрим все фотографии


    fig = plt.figure(figsize=(12,15))
    for i in range(0, len(pizza_imgs)):
        fig.add_subplot(4,5,i+1)
        plot_img(pizza_imgs[i])
    


    Пицца четыре сезона явно выбивается по своей структуре, так как, по сути, состоит из четырёх разных пицц.


    Изучим ингредиенты


    def split_contain(contain):
        lst = contain.split(',')
        print(len(lst),':', lst)
    
    for i, row in df.iterrows():
        split_contain(row.pizza_contain)

    2 : ['Томатный соус', ' двойная порция пепперони и увеличенная порция моцареллы']
    4 : ['Томатный соус', ' увеличенные порции цыпленка и пепперони', ' моцарелла', ' кисло-сладкий соус']
    6 : ['Томатный соус', ' бекон', ' пепперони', ' цыпленок', ' красный лук', ' моцарелла']
    4 : ['Томатный соус', ' ветчина', ' шампиньоны', ' моцарелла']
    3 : ['Сгущенное молоко', ' брусника', ' ананасы']
    4 : ['Томатный соус', ' томаты', ' увеличенная порция моцареллы', ' орегано']
    4 : ['Томатный соус', ' брынза', ' увеличенная порция сыра моцарелла', ' орегано']
    4 : ['Томатный соус', ' ананасы', ' цыпленок', ' моцарелла']
    9 : ['Томатный соус', ' говядина (фарш)', ' ветчина', ' пепперони', ' красный лук', ' маслины', ' сладкий перец', ' шампиньоны', ' моцарелла']
    8 : ['Томатный соус', ' пепперони', ' ветчина', ' брынза', ' томаты', ' шампиньоны', ' моцарелла', ' орегано']
    9 : ['Томатный соус', ' брынза', ' маслины', ' сладкий перец', ' томаты', ' шампиньоны', ' красный лук', ' моцарелла', ' базилик']
    6 : ['Томатный соус', ' пепперони', ' маслины', ' шампиньоны', ' моцарелла', ' орегано']
    8 : ['Томатный соус', ' халапеньо', ' сладкий перец', ' цыпленок', ' томаты', ' шампиньоны', ' красный лук', ' моцарелла']
    6 : ['Томатный соус', ' креветки', ' маслины', ' сладкий перец', ' красный лук', ' моцарелла']
    5 : ['Томатный соус', ' охотничьи колбаски', ' бекон', ' ветчина', ' моцарелла']
    3 : ['Томатный соус', ' пепперони', ' увеличенная порция моцареллы']
    6 : ['Соус Ранч', ' цыпленок', ' ветчина', ' томаты', ' чеснок', ' моцарелла']
    4 : ['Сырный соус', ' цыпленок', ' томаты', ' моцарелла']
    6 : ['Томатный соус', ' цыпленок', ' бекон', ' красный лук', ' моцарелла', ' соус Барбекю']
    7 : ['Сырный соус', ' говядина', ' бекон', ' соленые огурцы', ' томаты', ' красный лук', ' моцарелла']

    Проблема, что в нескольких пиццах указываются модификаторы вида:


    • "двойная порция"
    • "увеличенная порция"

    При этом, после модификаторов может идти перечисление ингредиетов через союз И.


    Гипотезы:


    • модификатор двойная порция можно заменить указав нужный ингредиент два раза.
    • модификатор увеличенная порция пока можно опустить (так как на фотографиях разница не заметна)

    Видим, что модификатор "увеличенная порция", относится только к сыру моцарелла.
    Так же один раз встречается:
    "увеличенная порция сыра моцарелла"


    Кстати, сразу же бросается в глаза, что основной используемый соус — томатный, а сыр — моцарелла.


    Почистим ингедиенты, чтобы привести к нормальному виду


    def split_contain2(contain):
        lst = contain.split(',')
        #print(len(lst),':', lst)
        for i in range(len(lst)):
            item = lst[i]
            item = item.replace('увеличенная порция', '')
            item = item.replace('увеличенные порции', '')
            item = item.replace('сыра моцарелла', 'моцарелла')
            item = item.replace('моцареллы', 'моцарелла')
            item = item.replace('цыпленка', 'цыпленок')
            and_pl = item.find(' и ')
            if and_pl != -1:
                item1 = item[0:and_pl]
                item2 = item[and_pl+3:]
                item = item1
                lst.insert(i+1, item2.strip())
            double_pl = item.find('двойная порция ')
            if double_pl != -1:
                item = item[double_pl+15:]
                lst.insert(i+1, item.strip())
            lst[i] = item.strip()
        # last one
        for i in range(len(lst)):
            lst[i] = lst[i].strip()
        print(len(lst),':', lst)
        return lst
    
    ingredients = []
    ingredients_count = []
    for i, row in df.iterrows():
        print(row.pizza_name)
        lst = split_contain2(row.pizza_contain)
        ingredients.append(lst)
        ingredients_count.append(len(lst))
    ingredients_count

    Двойная пепперони
    4 : ['Томатный соус', 'пепперони', 'пепперони', 'моцарелла']
    Крэйзи пицца 
    5 : ['Томатный соус', 'цыпленок', 'пепперони', 'моцарелла', 'кисло-сладкий соус']
    Дон Бекон
    6 : ['Томатный соус', 'бекон', 'пепперони', 'цыпленок', 'красный лук', 'моцарелла']
    Грибы и ветчина
    4 : ['Томатный соус', 'ветчина', 'шампиньоны', 'моцарелла']
    Пицца-пирог
    3 : ['Сгущенное молоко', 'брусника', 'ананасы']
    Маргарита
    4 : ['Томатный соус', 'томаты', 'моцарелла', 'орегано']
    Сырная
    4 : ['Томатный соус', 'брынза', 'моцарелла', 'орегано']
    Гавайская
    4 : ['Томатный соус', 'ананасы', 'цыпленок', 'моцарелла']
    Додо
    9 : ['Томатный соус', 'говядина (фарш)', 'ветчина', 'пепперони', 'красный лук', 'маслины', 'сладкий перец', 'шампиньоны', 'моцарелла']
    Четыре сезона
    8 : ['Томатный соус', 'пепперони', 'ветчина', 'брынза', 'томаты', 'шампиньоны', 'моцарелла', 'орегано']
    Овощи и грибы
    9 : ['Томатный соус', 'брынза', 'маслины', 'сладкий перец', 'томаты', 'шампиньоны', 'красный лук', 'моцарелла', 'базилик']
    Итальянская
    6 : ['Томатный соус', 'пепперони', 'маслины', 'шампиньоны', 'моцарелла', 'орегано']
    Мексиканская
    8 : ['Томатный соус', 'халапеньо', 'сладкий перец', 'цыпленок', 'томаты', 'шампиньоны', 'красный лук', 'моцарелла']
    Морская
    6 : ['Томатный соус', 'креветки', 'маслины', 'сладкий перец', 'красный лук', 'моцарелла']
    Мясная
    5 : ['Томатный соус', 'охотничьи колбаски', 'бекон', 'ветчина', 'моцарелла']
    Пепперони
    3 : ['Томатный соус', 'пепперони', 'моцарелла']
    Ранч пицца
    6 : ['Соус Ранч', 'цыпленок', 'ветчина', 'томаты', 'чеснок', 'моцарелла']
    Сырный цыплёнок
    4 : ['Сырный соус', 'цыпленок', 'томаты', 'моцарелла']
    Цыплёнок барбекю
    6 : ['Томатный соус', 'цыпленок', 'бекон', 'красный лук', 'моцарелла', 'соус Барбекю']
    Чизбургер-пицца
    7 : ['Сырный соус', 'говядина', 'бекон', 'соленые огурцы', 'томаты', 'красный лук', 'моцарелла']
    
    [4, 5, 6, 4, 3, 4, 4, 4, 9, 8, 9, 6, 8, 6, 5, 3, 6, 4, 6, 7]

    Посмотрим минимальное и максимальное количество ингредиентов


    min_count = np.min(ingredients_count)
    print('min:', min_count)
    max_count = np.max(ingredients_count)
    print('max:', max_count)

    min: 3
    max: 9

    print('min:', np.array(pizza_names)[ingredients_count == min_count] )
    print('max:', np.array(pizza_names)[ingredients_count == max_count] )

    min: ['Пицца-пирог' 'Пепперони']
    max: ['Додо' 'Овощи и грибы']

    Интересно, больше всего ингредиентов (9 штук) в пиццах: Додо и Овощи и грибы.


    Заполним табличку ингредиентов.


    df_ingredients = pd.DataFrame(ingredients)
    df_ingredients.fillna(value='0', inplace=True)
    df_ingredients


    0 1 2 3 4 5 6 7 8
    0 Томатный соус пепперони пепперони моцарелла 0 0 0 0 0
    1 Томатный соус цыпленок пепперони моцарелла кисло-сладкий соус 0 0 0 0
    2 Томатный соус бекон пепперони цыпленок красный лук моцарелла 0 0 0
    3 Томатный соус ветчина шампиньоны моцарелла 0 0 0 0 0
    4 Сгущенное молоко брусника ананасы 0 0 0 0 0 0
    5 Томатный соус томаты моцарелла орегано 0 0 0 0 0
    6 Томатный соус брынза моцарелла орегано 0 0 0 0 0
    7 Томатный соус ананасы цыпленок моцарелла 0 0 0 0 0
    8 Томатный соус говядина (фарш) ветчина пепперони красный лук маслины сладкий перец шампиньоны моцарелла
    9 Томатный соус пепперони ветчина брынза томаты шампиньоны моцарелла орегано 0
    10 Томатный соус брынза маслины сладкий перец томаты шампиньоны красный лук моцарелла базилик
    11 Томатный соус пепперони маслины шампиньоны моцарелла орегано 0 0 0
    12 Томатный соус халапеньо сладкий перец цыпленок томаты шампиньоны красный лук моцарелла 0
    13 Томатный соус креветки маслины сладкий перец красный лук моцарелла 0 0 0
    14 Томатный соус охотничьи колбаски бекон ветчина моцарелла 0 0 0 0
    15 Томатный соус пепперони моцарелла 0 0 0 0 0 0
    16 Соус Ранч цыпленок ветчина томаты чеснок моцарелла 0 0 0
    17 Сырный соус цыпленок томаты моцарелла 0 0 0 0 0
    18 Томатный соус цыпленок бекон красный лук моцарелла соус Барбекю 0 0 0
    19 Сырный соус говядина бекон соленые огурцы томаты красный лук моцарелла 0 0


    df_ingredients.describe()


    0 1 2 3 4 5 6 7 8
    count 20 20 20 20 20 20 20 20 20
    unique 4 13 10 12 6 7 4 4 3
    top Томатный соус пепперони пепперони моцарелла 0 0 0 0 0
    freq 16 4 3 5 8 10 15 16 18


    Как и ожидалось — самый используемый соус — томатный. Стандартный рецепт — состоит из 4 ингредиентов.


    Забавно, что образовался новый рецепт для пиццы.


    Посмотрим сколько раз встречается тот или иной ингредиент:


    df_ingredients.stack().value_counts()

    0                     69
    моцарелла             19
    Томатный соус         16
    пепперони              8
    томаты                 7
    цыпленок               7
    красный лук            7
    шампиньоны             6
    ветчина                5
    сладкий перец          4
    бекон                  4
    орегано                4
    маслины                4
    брынза                 3
    ананасы                2
    Сырный соус            2
    чеснок                 1
    кисло-сладкий соус     1
    базилик                1
    соус Барбекю           1
    креветки               1
    халапеньо              1
    Сгущенное молоко       1
    соленые огурцы         1
    говядина (фарш)        1
    охотничьи колбаски     1
    брусника               1
    говядина               1
    Соус Ранч              1
    dtype: int64

    Опять же: моцарелла, Томатный соус, пепперони.


    df_ingredients.stack().value_counts().drop('0').plot.pie()

    <matplotlib.axes._subplots.AxesSubplot at 0xea8d358>


    Теперь закодируем ингредиенты.


    from sklearn.preprocessing import LabelEncoder
    from sklearn.preprocessing import OneHotEncoder
    
    ingredients_full = df_ingredients.values.tolist()
    
    # flatten lists
    flat_ingredients = [item for sublist in ingredients_full for item in sublist]
    print(flat_ingredients)
    print(len(flat_ingredients))
    
    np_ingredients = np.array(flat_ingredients)
    #print(np_ingredients)
    
    labelencoder = LabelEncoder()
    ingredients_encoded = labelencoder.fit_transform(np_ingredients)
    print(ingredients_encoded)
    
    label_max = np.max(ingredients_encoded)
    print('max:', label_max)

    ['Томатный соус', 'пепперони', 'пепперони', 'моцарелла', '0', '0', '0', '0', '0', 'Томатный соус', 'цыпленок', 'пепперони', 'моцарелла', 'кисло-сладкий соус', '0', '0', '0', '0', 'Томатный соус', 'бекон', 'пепперони', 'цыпленок', 'красный лук', 'моцарелла', '0', '0', '0', 'Томатный соус', 'ветчина', 'шампиньоны', 'моцарелла', '0', '0', '0', '0', '0', 'Сгущенное молоко', 'брусника', 'ананасы', '0', '0', '0', '0', '0', '0', 'Томатный соус', 'томаты', 'моцарелла', 'орегано', '0', '0', '0', '0', '0', 'Томатный соус', 'брынза', 'моцарелла', 'орегано', '0', '0', '0', '0', '0', 'Томатный соус', 'ананасы', 'цыпленок', 'моцарелла', '0', '0', '0', '0', '0', 'Томатный соус', 'говядина (фарш)', 'ветчина', 'пепперони', 'красный лук', 'маслины', 'сладкий перец', 'шампиньоны', 'моцарелла', 'Томатный соус', 'пепперони', 'ветчина', 'брынза', 'томаты', 'шампиньоны', 'моцарелла', 'орегано', '0', 'Томатный соус', 'брынза', 'маслины', 'сладкий перец', 'томаты', 'шампиньоны', 'красный лук', 'моцарелла', 'базилик', 'Томатный соус', 'пепперони', 'маслины', 'шампиньоны', 'моцарелла', 'орегано', '0', '0', '0', 'Томатный соус', 'халапеньо', 'сладкий перец', 'цыпленок', 'томаты', 'шампиньоны', 'красный лук', 'моцарелла', '0', 'Томатный соус', 'креветки', 'маслины', 'сладкий перец', 'красный лук', 'моцарелла', '0', '0', '0', 'Томатный соус', 'охотничьи колбаски', 'бекон', 'ветчина', 'моцарелла', '0', '0', '0', '0', 'Томатный соус', 'пепперони', 'моцарелла', '0', '0', '0', '0', '0', '0', 'Соус Ранч', 'цыпленок', 'ветчина', 'томаты', 'чеснок', 'моцарелла', '0', '0', '0', 'Сырный соус', 'цыпленок', 'томаты', 'моцарелла', '0', '0', '0', '0', '0', 'Томатный соус', 'цыпленок', 'бекон', 'красный лук', 'моцарелла', 'соус Барбекю', '0', '0', '0', 'Сырный соус', 'говядина', 'бекон', 'соленые огурцы', 'томаты', 'красный лук', 'моцарелла', '0', '0']
    180
    [ 4 20 20 17  0  0  0  0  0  4 26 20 17 13  0  0  0  0  4  7 20 26 14 17  0
      0  0  4 10 28 17  0  0  0  0  0  1  8  5  0  0  0  0  0  0  4 24 17 18  0
      0  0  0  0  4  9 17 18  0  0  0  0  0  4  5 26 17  0  0  0  0  0  4 12 10
     20 14 16 21 28 17  4 20 10  9 24 28 17 18  0  4  9 16 21 24 28 14 17  6  4
     20 16 28 17 18  0  0  0  4 25 21 26 24 28 14 17  0  4 15 16 21 14 17  0  0
      0  4 19  7 10 17  0  0  0  0  4 20 17  0  0  0  0  0  0  2 26 10 24 27 17
      0  0  0  3 26 24 17  0  0  0  0  0  4 26  7 14 17 23  0  0  0  3 11  7 22
     24 14 17  0  0]
    max: 28

    Получается, что для приготовления, используется целых 27 ингредиентов.


    for label in range(label_max):
        print(label, labelencoder.inverse_transform(label))

    0 0
    1 Сгущенное молоко
    2 Соус Ранч
    3 Сырный соус
    4 Томатный соус
    5 ананасы
    6 базилик
    7 бекон
    8 брусника
    9 брынза
    10 ветчина
    11 говядина
    12 говядина (фарш)
    13 кисло-сладкий соус
    14 красный лук
    15 креветки
    16 маслины
    17 моцарелла
    18 орегано
    19 охотничьи колбаски
    20 пепперони
    21 сладкий перец
    22 соленые огурцы
    23 соус Барбекю
    24 томаты
    25 халапеньо
    26 цыпленок
    27 чеснок

    lb_ingredients = []
    for lst in ingredients_full:
        lb_ingredients.append(labelencoder.transform(lst).tolist())
    #lb_ingredients = np.array(lb_ingredients)
    lb_ingredients

    [[4, 20, 20, 17, 0, 0, 0, 0, 0],
     [4, 26, 20, 17, 13, 0, 0, 0, 0],
     [4, 7, 20, 26, 14, 17, 0, 0, 0],
     [4, 10, 28, 17, 0, 0, 0, 0, 0],
     [1, 8, 5, 0, 0, 0, 0, 0, 0],
     [4, 24, 17, 18, 0, 0, 0, 0, 0],
     [4, 9, 17, 18, 0, 0, 0, 0, 0],
     [4, 5, 26, 17, 0, 0, 0, 0, 0],
     [4, 12, 10, 20, 14, 16, 21, 28, 17],
     [4, 20, 10, 9, 24, 28, 17, 18, 0],
     [4, 9, 16, 21, 24, 28, 14, 17, 6],
     [4, 20, 16, 28, 17, 18, 0, 0, 0],
     [4, 25, 21, 26, 24, 28, 14, 17, 0],
     [4, 15, 16, 21, 14, 17, 0, 0, 0],
     [4, 19, 7, 10, 17, 0, 0, 0, 0],
     [4, 20, 17, 0, 0, 0, 0, 0, 0],
     [2, 26, 10, 24, 27, 17, 0, 0, 0],
     [3, 26, 24, 17, 0, 0, 0, 0, 0],
     [4, 26, 7, 14, 17, 23, 0, 0, 0],
     [3, 11, 7, 22, 24, 14, 17, 0, 0]]

    onehotencoder = OneHotEncoder(sparse=False)
    ingredients_onehotencoded = onehotencoder.fit_transform(ingredients_encoded.reshape(-1, 1))
    print(ingredients_onehotencoded.shape)
    ingredients_onehotencoded[0]

    (180, 29)
    
    array([ 0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
            0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
            0.,  0.,  0.])

    Теперь у нас есть данные с которыми мы можем работать.


    Автоэнкодер


    Попробуем загрузить фотографии пиц (вид сверху) и попробуем натренировать простой сжимающий автоэнкодер.


    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    %matplotlib inline 
    
    import seaborn as sns
    
    np.random.seed(42)
    
    import cv2
    import os
    import sys
    
    import load_data
    import prepare_images

    Загружаем фотографии пицц


    pizza_eng_names, pizza_imgs = prepare_images.load_photos()

    Read csv...
    (20, 13)
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 20 entries, 0 to 19
    Data columns (total 13 columns):
    city_name         20 non-null object
    city_url          20 non-null object
    pizza_name        20 non-null object
    pizza_eng_name    20 non-null object
    pizza_url         20 non-null object
    pizza_contain     20 non-null object
    pizza_price       20 non-null int64
    kiloCalories      20 non-null object
    carbohydrates     20 non-null object
    proteins          20 non-null object
    fats              20 non-null object
    size              20 non-null int64
    weight            20 non-null object
    dtypes: int64(2), object(11)
    memory usage: 2.1+ KB
    None
    ['double-pepperoni', 'crazy-pizza', 'pizza-don-bekon', 'gribvetchina', 'pizza-pirog', 'pizza-margarita', 'syrnaya-pizza', 'gavayskaya-pizza', 'pizza-dodo', 'pizza-chetyre-sezona', 'ovoshi-i-griby', 'italyanskaya-pizza', 'meksikanskaya-pizza', 'morskaya-pizza', 'myasnaya-pizza', 'pizza-pepperoni', 'ranch-pizza', 'pizza-syrnyi-cyplenok', 'pizza-cyplenok-barbekyu', 'chizburger-pizza']
    ['double-pepperoni\\double-pepperoni3.jpg', 'crazy-pizza\\crazy-pizza3.jpg', 'pizza-don-bekon\\pizza-don-bekon3.jpg', 'gribvetchina\\gribvetchina3.jpg', 'pizza-pirog\\pizza-pirog3.jpg', 'pizza-margarita\\pizza-margarita3.jpg', 'syrnaya-pizza\\syrnaya-pizza3.jpg', 'gavayskaya-pizza\\gavayskaya-pizza3.jpg', 'pizza-dodo\\pizza-dodo3.jpg', 'pizza-chetyre-sezona\\pizza-chetyre-sezona3.jpg', 'ovoshi-i-griby\\ovoshi-i-griby3.jpg', 'italyanskaya-pizza\\italyanskaya-pizza3.jpg', 'meksikanskaya-pizza\\meksikanskaya-pizza3.jpg', 'morskaya-pizza\\morskaya-pizza3.jpg', 'myasnaya-pizza\\myasnaya-pizza3.jpg', 'pizza-pepperoni\\pizza-pepperoni3.jpg', 'ranch-pizza\\ranch-pizza3.jpg', 'pizza-syrnyi-cyplenok\\pizza-syrnyi-cyplenok3.jpg', 'pizza-cyplenok-barbekyu\\pizza-cyplenok-barbekyu3.jpg', 'chizburger-pizza\\chizburger-pizza3.jpg']
    Load images...
    Load image: double-pepperoni\double-pepperoni3.jpg
    Load image: crazy-pizza\crazy-pizza3.jpg
    Load image: pizza-don-bekon\pizza-don-bekon3.jpg
    Load image: gribvetchina\gribvetchina3.jpg
    Load image: pizza-pirog\pizza-pirog3.jpg
    Load image: pizza-margarita\pizza-margarita3.jpg
    Load image: syrnaya-pizza\syrnaya-pizza3.jpg
    Load image: gavayskaya-pizza\gavayskaya-pizza3.jpg
    Load image: pizza-dodo\pizza-dodo3.jpg
    Load image: pizza-chetyre-sezona\pizza-chetyre-sezona3.jpg
    Load image: ovoshi-i-griby\ovoshi-i-griby3.jpg
    Load image: italyanskaya-pizza\italyanskaya-pizza3.jpg
    Load image: meksikanskaya-pizza\meksikanskaya-pizza3.jpg
    Load image: morskaya-pizza\morskaya-pizza3.jpg
    Load image: myasnaya-pizza\myasnaya-pizza3.jpg
    Load image: pizza-pepperoni\pizza-pepperoni3.jpg
    Load image: ranch-pizza\ranch-pizza3.jpg
    Load image: pizza-syrnyi-cyplenok\pizza-syrnyi-cyplenok3.jpg
    Load image: pizza-cyplenok-barbekyu\pizza-cyplenok-barbekyu3.jpg
    Load image: chizburger-pizza\chizburger-pizza3.jpg
    Cut pizza from images...
    (380, 380, 3)
    20

    def plot_img(img):
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        plt.imshow(img_rgb)
    
    plot_img(pizza_imgs[0])


    Замечательно, что пицца обладает осевой симметрией — для аугментации, её можно будет вращать вокруг центра, а так же отражать по вертикали.


    img_flipy = cv2.flip(pizza_imgs[0], 1)
    plot_img(img_flipy)


    Результат поворота вокруг центра на 15 градусов:


    img_rot15 = load_data.rotate(pizza_imgs[0], 15)
    plot_img(img_rot15)


    Сделаем аугментацию для первой пиццы в списке (предварительно уменьшив до размеров: 56 на 56) — вращение вокруг оси на 360 градусов с шагом в 1 градус и отражением по вертикали.


    channels, height, width = 3, 56, 56
    
    lst0 = load_data.resize_rotate_flip(pizza_imgs[0], (height, width))
    print(len(lst0))

    720

    plot_img(lst0[0])


    Попробуем автоэнкодер


    Преобразуем список с картинками к нужному виду и разобьём его на тренировочную и тестовую выборки.


    image_list = lst0
    image_list = np.array(image_list, dtype=np.float32)
    image_list = image_list.transpose((0, 3, 1, 2))
    image_list /= 255.0
    print(image_list.shape)

    (720, 3, 56, 56)

    x_train = image_list[:600]
    x_test = image_list[600:]
    print(x_train.shape, x_test.shape)

    (600, 3, 56, 56) (120, 3, 56, 56)

    from keras.models import Model
    from keras.layers import Input, Dense, Flatten, Reshape
    from keras.layers import Conv2D, MaxPooling2D, UpSampling2D
    
    from keras import backend as K
    #For 2D data (e.g. image), "channels_last" assumes (rows, cols, channels) while "channels_first" assumes  (channels, rows, cols).
    K.set_image_data_format('channels_first')

    Using Theano backend.

    Создаём автоэнкодер


    def create_deep_conv_ae(channels, height, width):
        input_img = Input(shape=(channels, height, width))
    
        x = Conv2D(16, (3, 3), activation='relu', padding='same')(input_img)
        x = MaxPooling2D(pool_size=(2, 2), padding='same')(x)
        x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
        encoded = MaxPooling2D(pool_size=(2, 2), padding='same')(x)
    
        # at this point the representation is (8, 14, 14)
    
        input_encoded = Input(shape=(8, 14, 14))
        x = Conv2D(8, (3, 3), activation='relu', padding='same')(input_encoded)
        x = UpSampling2D((2, 2))(x)
        x = Conv2D(16, (3, 3), activation='relu', padding='same')(x)
        x = UpSampling2D((2, 2))(x)
        decoded = Conv2D(channels, (3, 3), activation='sigmoid', padding='same')(x)
    
        # Models
        encoder = Model(input_img, encoded, name="encoder")
        decoder = Model(input_encoded, decoded, name="decoder")
        autoencoder = Model(input_img, decoder(encoder(input_img)), name="autoencoder")
        return encoder, decoder, autoencoder
    
    c_encoder, c_decoder, c_autoencoder = create_deep_conv_ae(channels, height, width)
    c_autoencoder.compile(optimizer='adam', loss='binary_crossentropy')
    
    c_encoder.summary()
    c_decoder.summary()
    c_autoencoder.summary()

    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_1 (InputLayer)         (None, 3, 56, 56)         0         
    _________________________________________________________________
    conv2d_1 (Conv2D)            (None, 16, 56, 56)        448       
    _________________________________________________________________
    max_pooling2d_1 (MaxPooling2 (None, 16, 28, 28)        0         
    _________________________________________________________________
    conv2d_2 (Conv2D)            (None, 8, 28, 28)         1160      
    _________________________________________________________________
    max_pooling2d_2 (MaxPooling2 (None, 8, 14, 14)         0         
    =================================================================
    Total params: 1,608
    Trainable params: 1,608
    Non-trainable params: 0
    _________________________________________________________________
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_2 (InputLayer)         (None, 8, 14, 14)         0         
    _________________________________________________________________
    conv2d_3 (Conv2D)            (None, 8, 14, 14)         584       
    _________________________________________________________________
    up_sampling2d_1 (UpSampling2 (None, 8, 28, 28)         0         
    _________________________________________________________________
    conv2d_4 (Conv2D)            (None, 16, 28, 28)        1168      
    _________________________________________________________________
    up_sampling2d_2 (UpSampling2 (None, 16, 56, 56)        0         
    _________________________________________________________________
    conv2d_5 (Conv2D)            (None, 3, 56, 56)         435       
    =================================================================
    Total params: 2,187
    Trainable params: 2,187
    Non-trainable params: 0
    _________________________________________________________________
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_1 (InputLayer)         (None, 3, 56, 56)         0         
    _________________________________________________________________
    encoder (Model)              (None, 8, 14, 14)         1608      
    _________________________________________________________________
    decoder (Model)              (None, 3, 56, 56)         2187      
    =================================================================
    Total params: 3,795
    Trainable params: 3,795
    Non-trainable params: 0
    _________________________________________________________________

    c_autoencoder.fit(x_train, x_train,
                    epochs=20,
                    batch_size=16,
                    shuffle=True,
                    verbose=2,
                    validation_data=(x_test, x_test))

    Train on 600 samples, validate on 120 samples
    Epoch 1/20
    10s - loss: 0.5840 - val_loss: 0.5305
    Epoch 2/20
    10s - loss: 0.4571 - val_loss: 0.4162
    Epoch 3/20
    9s - loss: 0.4032 - val_loss: 0.3956
    Epoch 4/20
    8s - loss: 0.3884 - val_loss: 0.3855
    Epoch 5/20
    10s - loss: 0.3829 - val_loss: 0.3829
    Epoch 6/20
    11s - loss: 0.3808 - val_loss: 0.3815
    Epoch 7/20
    9s - loss: 0.3795 - val_loss: 0.3804
    Epoch 8/20
    8s - loss: 0.3785 - val_loss: 0.3797
    Epoch 9/20
    10s - loss: 0.3778 - val_loss: 0.3787
    Epoch 10/20
    10s - loss: 0.3771 - val_loss: 0.3781
    Epoch 11/20
    9s - loss: 0.3764 - val_loss: 0.3779
    Epoch 12/20
    8s - loss: 0.3760 - val_loss: 0.3773
    Epoch 13/20
    9s - loss: 0.3756 - val_loss: 0.3768
    Epoch 14/20
    10s - loss: 0.3751 - val_loss: 0.3766
    Epoch 15/20
    10s - loss: 0.3748 - val_loss: 0.3768
    Epoch 16/20
    9s - loss: 0.3745 - val_loss: 0.3762
    Epoch 17/20
    10s - loss: 0.3741 - val_loss: 0.3755
    Epoch 18/20
    9s - loss: 0.3738 - val_loss: 0.3754
    Epoch 19/20
    11s - loss: 0.3735 - val_loss: 0.3752
    Epoch 20/20
    8s - loss: 0.3733 - val_loss: 0.3748
    
    <keras.callbacks.History at 0x262db6a0>

    #c_autoencoder.save_weights('c_autoencoder_weights.h5')
    #c_autoencoder.load_weights('c_autoencoder_weights.h5')

    Посмотрим на результаты работы автоэнкодера


    n = 5
    imgs = x_test[:n]
    encoded_imgs = c_encoder.predict(imgs, batch_size=n)
    decoded_imgs = c_decoder.predict(encoded_imgs, batch_size=n)
    
    def get_image_from_net_data(data):
        res = data.transpose((1, 2, 0))
        res *= 255.0
        res = np.array(res, dtype=np.uint8)
        return res
    
    #image0 = get_image_from_net_data(decoded_imgs[0])
    #plot_img(image0)

    fig = plt.figure()
    j = 0
    for i in range(0, len(imgs)):
        j += 1
        fig.add_subplot(n,2,j)
        plot_img( get_image_from_net_data(imgs[i]) )
        j += 1
        fig.add_subplot(n,2,j)
        plot_img( get_image_from_net_data(decoded_imgs[i]) )


    Продолжение следует...


    Ссылки


    Метки:
    • +20
    • 4,9k
    • 4
    Поделиться публикацией
    Похожие публикации
    Комментарии 4
    • +1
      Эмм… а где робот который будет готовить пиццу?
      • +1
        Имеется в виду виртуальный робот.
        Разумеется, сделать железного робота было бы крайне интересно, но для этого одного энтузиазма не достаточно.
        • 0
          Пятница ведь, еще и конец рабочего дня, проголодался, а тут вижу робот, да который пиццу готовить будет… да так… эх…
          (sarcasm off)
        • 0
          https://www.youtube.com/watch?v=U03mCq_cpac

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