...

суббота, 24 июня 2017 г.

Россия — Мексика: исторический футбольный матч роботов, управляемый болельщиками через Твиттер

image

Матч роботов, под управлением российских и мексиканских пользователей Твиттера начнётся сегодня, в 15:00 по московскому времени, за три часа до начала официального матча между сборными в рамках Кубка конфедераций. Твиттербол организован Университетом Иннополис и компанией Трик в рамках Всероссийской Робототехнической Олимпиады.

Для управления робота нужно написать сообщение с тегом #ConfedCup и через пробелы указать сборную (Rus / Mex) и команду для робота. Регистр и знаки препинания не учитываются. Пример: “Rus go! #ConfedCup

Список доступных команд:

go — движение вперед на 30 сантиметров
back — движение назад на 30 сантиметров
left — поворот влево на 90 градусов
right — поворот вправо на 90 градусов
turn — разворот на 180 градусов

Специальный алгоритм каждые 5 секунд анализирует сообщения в Твиттере и приказывает роботам выполнить самую популярную команду за этот интервал. Болельщикам придётся действовать коллективно и обдуманно.

Наблюдать за действиями роботов можно по веб-трансляции на сайте: http://ift.tt/2sMd8Ne

Поддержи своих!

Комментарии (0)

    Let's block ads! (Why?)

    [Из песочницы] Установка ArchLinux ARM рядом с Android без chroot

    Руководство: как использовать Python для алгоритмической торговли на бирже. Часть 1

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

    Среди наиболее популярных в сфере финансов языков программирования можно отметить R и Python, также часто используются C++, C# и Java. В опубликованном на сайте DataCamp руководстве речь идет о том, как начать использовать Python для создания финансовых приложений — мы представляем вам серию статей-адаптаций глав этого материала.

    Структура руководства:

    • Первая часть предназначена для новичков на рынке, в ней речь пойдет об устройстве финансовых рынков, акциях и торговых стратегиях, данных временных рядов, а также о том, что понадобится для начала разработки.
    • Во второй части будет представлено введение в работу с данными временных рядов и инструментами финансового анализа, вроде подсчета волатильности и скользящих средних, с помощью Python-библиотеки Pandas.
    • Затем мы перейдем к непосредственной разработке простой импульсной торговой стратегии.
    • В четвертой части речь пойдет о том, как проводить бэктест стратегии на исторических данных.
    • В завершение, будут затронуты вопросы оптимизации стратегии для повышения ее производительности, а также оценки ее работы и надежности.

    Введение: простым языком об устройстве сферы финансов


    Прежде чем окунуться в мир торговых стратегий, имеет смысл коснуться базовых понятий. Однако это не означает, что то, о чем пойдет речь ниже, рассчитано совсем на новичков. Будет здорово, если вы предварительно ознакомитесь с курсом по использованию Python для работы с данными, а также представляете себе, как работать со списками и пакетами Python, а также хотя бы на базовом уровне знакомы с NumPy и Pandas.

    Акции и торговля на бирже


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

    Цена, по которой конкретная акция будет продана или куплена, может постоянно меняться, вне зависимости от бизнес-показателей выпустившей акции компании: все определяется спросом и предложением. Важно понимать различие между акциями и, например, облигациями (бондами), которые используются для привлечения именно заемных средств.

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

    При покупке акций инвестор получает определенную долю в компании, из чего может в будущем извлечь финансовую выгоду, продав эту долю. Стратегии могут различаться: существуют длинные сделки (long), заключаемые в надежде на дальнейший рост акций, и короткие, когда инвестор предполагает, что акции будут дешеветь, поэтому продает акции в надежде в будущем «откупить» их обратно по более низкой цене.

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

    Торговые стратегии обычно проверяют с помощью бэктестинга: это подход, при которым стратегия «прогоняется» на исторических данных о торгах — на их основе программа генерирует сделки. Это позволяет понять, принесла бы такая стратегия доход при том развитии рыночной ситуации, что наблюдалось в прошлом. Таким образом, можно предварительно оценить перспективность стратегии в торгах в режиме реального времени. При этом, нет гарантий того, что хорошие показатели на исторических данных повторятся при работе на реальном рынке.

    Данные временных рядов


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

    По оcи X расположены даты, а цена — на оси Y. «Последовательные равные промежутки времени» в данном случае означает, что по временной оси даты расположены с двухнедельным интервалом: можно сравнить 3/7/2005 и 3/31/2005, а также 4/5/2005 и 4/19/2005 (здесь даты записаны в принятом в США формате, когда сначала идет месяц, а затем день).

    Однако финансовые данные обычно включают не два параметра (цена и дата), а пять — помимо величины торгового периода, это цена открытия торгового периода, наивысшая и низшая цена в его рамках, а также цена в момент закрытия периода. Это значит, что если мы рассматривает дневной период, то анализ данных даст нам информацию о том, на каком уровне находилась цена в момент старта и завершения торгов в выбранный день, а также какой была максимальная и минимальная цена в ходе торгов.

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

    Основы Python для сферы финансов: Pandas


    Одним из самых востребованных инструментов при использовании Python для разработки финансовых приложений является пакет Pandas. Он нужен уже в самом начале, но по мере углубления в процесс разработки понадобятся и такие пакеты как NumPy, SciPy, Matplotlib.

    Для начала сфокусируемся на Pandas и применении этого инструмента к анализу временных рядов. Ниже речь пойдет о том, как с помощью данного пакета импортировать данные, анализировать и манипулировать ими.

    Импорт финансовых данных


    Пакет pandas-datareader позволяет получать данные из таких источников, как Google, Yahoo! Finance или Всемирный банк — подробнее о доступных источниках данных написано в документации. В этом руководстве будет рассматриваться получение данных с сервиса Yahoo! Finance. Для начала работы необходимо установить последнюю версию пакета с помощью pip:
    pip install pandas-datareader
    

    Инструкции по установке версии в разработке представлены здесь.
    import pandas_datareader as pdr
    import datetime 
    aapl = pdr.get_data_yahoo('AAPL', 
                              start=datetime.datetime(2006, 10, 1), 
                              end=datetime.datetime(2012, 1, 1))
    

    Не так давно в Yahoo API произошли изменения, так что для начала самостоятельной работы с библиотекой нужно установить исправления, который позволит дождаться официального патча. Подробнее проблема описана здесь. Однако для этого руководства данные были скачаны заранее, так что проблем с его изучением не возникнет.

    Важно также понимать, что несмотря на то, что pandas-datareader — это удобный инструмент для загрузки данных, он далеко не единственный для Python. Также можно использовать библиотеки вроде Quandl, которая позволяет получать данные с сервиса Google Finance:

    import quandl 
    aapl = quandl.get("WIKI/AAPL", start_date="2006-10-01", end_date="2012-01-01")
    

    Также многим известно, что в сфере финансов для анализа данных очень популярен Excel. Для удобства будущей работы можно интегрировать этот инструмент с Python (подробнее по ссылке).

    Работа с данными временных рядов


    Для импортирования данных мы использовали pandas_datareader. В результате возник объект aapl — это DataFrame, то есть двумерная именованная структура данных со столбцами потенциально разных типов. Первое, что следует сделать при работе с таким фреймом — запустить функции head() и tail() для того, чтобы взглянуть на первый и последний столбцы датафрейма. Для получения полезной статистической сводки по скачанным данным можно воспользоваться функцией describe().

    Пример этого кода можно найти на странице исходного материала.

    Данные содержат четыре столбца с ценой открытия и закрытия торгового периода, а также максимальной и минимальной ценой — мы рассматриваем дневные интервалы и акции Apple. Также мы получаем два дополнительных столбца: Volume и Adj Close. Первый из них используется для того, чтобы зафиксировать количество акций, с которыми совершались сделки в торговый день. Второй столбец — это «отрегулированная» цена закрытия (adjusted closing price), это значит, что в цену закрытия периода были добавлены все действия с акциями, которые могли быть совершены до момента открытия следующего торгового дня.

    Если нужно сохранить данные в CSV-файл, это можно сделать с помощью функции to_csv(), а прочитать файл можно с помощью read_csv() — это полезно для ситуаций, когда источник данных меняется и доступ к ним временно теряется.

    import pandas as pd
    aapl.to_csv('data/aapl_ohlc.csv')
    df = pd.read_csv('data/aapl_ohlc.csv', header=0, index_col='Date', parse_dates=True)
    

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

    Для того, чтобы посмотреть на индекс и столбцы данных следует использовать атрибуты index и columns. Затем можно выделить подмножество из десяти последних наблюдений в столбце column. Для изолирования этих значений следует использовать квадратные скобки. Последнее значение помещается в переменную ts, а проверка ее типа осуществляется с помощью функции type().

    # Inspect the index 
    aapl.index
     
    # Inspect the columns
    aapl.columns
     
    # Select only the last 10 observations of `Close`
    ts = aapl['Close'][-10:]
     
    # Check the type of `ts` 
    type(ts)
    

    Использование квадратных скобок удобно, но это не самый характерный способ при работе с Pandas. Поэтому также стоит рассмотреть функции loc() и iloc(): первая из них используется для label-based индексирования, а последняя для позиционального индексирования.

    На практике, это значит, что можно передать ярлык ряда вроде 2007 или 2006-11-01 в функцию loc(), а целые числа вроде 22 или 43 передаются функции iloc().

    # Inspect the first rows of November-December 2006
    print(aapl.loc[pd.Timestamp('2006-11-01'):pd.Timestamp('2006-12-31')].head())
     
    # Inspect the first rows of 2007 
    print(aapl.loc['2007'].head())
     
    # Inspect November 2006
    print(aapl.iloc[22:43])
     
    # Inspect the 'Open' and 'Close' values at 2006-11-01 and 2006-12-01
    print(aapl.iloc[[22,43], [0, 3]])
    

    Если внимательно взглянуть на результаты процедуры разбиения, то станет видно, что в данных пропущены определенные дни. Дальнейший анализ паттерна покажет, что обычно не хватает двух или трех дней. Это выходные дни и государственные праздники, во время которых нет биржевых торгов.

    Помимо индексирования есть несколько способов узнать о данных больше. Можно, к примеру, попробовать создать семпл из 20 строк данных, а затем переформатировать их таким образом, чтобы appl стал не дневным значением и месячным. Сделать это можно с помощью функций sample() и resample():

    # Sample 20 rows
    sample = aapl.sample(20)
     
    # Print `sample`
    print(sample)
     
    # Resample to monthly level 
    monthly_aapl = aapl.resample('M').mean()
     
    # Print `monthly_aapl`
    print(monthly_aapl)
    

    Прежде чем перейти к визуализации данных и проведению финансового анализа, можно начать вычислять разницу между ценами открытия и закрытия торгового периода. Эту арифметическую операцию можно с помощью Pandas — нужно вычесть значения столбца Open данных appl из столбца Close. Или, другими словами, вычесть aapl.Close из aapl.Open. Получившийся результат будет храниться в новом столбце датафрейма aapl под названием diff, который можно удалить с помощью функции del:
    # Add a column `diff` to `aapl` 
    aapl['diff'] = aapl.Open - aapl.Close
     
    # Delete the new `diff` column
    del aapl['diff']
    

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

    Визуализация данных временных рядов


    Помимо анализа данных с помощью функций head(), tail() и индексирования, также возможна их визуализация. Благодаря интеграции Pandas с инструментом для создания графиков Matplotlib это можно сделать довольно легко. Нужно лишь использовать функцию plot() и передать ей релевантные параметры. Кроме того, если добавить параметр grid, то получившийся график будет наложен на сетку.
    # Import Matplotlib's `pyplot` module as `plt`
    import matplotlib.pyplot as plt
     
    # Plot the closing prices for `aapl`
    aapl['Close'].plot(grid=True)
     
    # Show the plot
    plt.show()
    

    Этот код дает вот такой график:

    В следующей части руководства речь пойдет о финансовом анализе данных временных рядов с помощью Python.

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

    Другие материалы по теме финансов и фондового рынка от ITinvest:


    Комментарии (0)

      Let's block ads! (Why?)

      Переносим оценки из Имхонет в Must App

      image

      Имхонет закрылся. И людей оставили просто с табличкой фильмов, которые они смотрели. Мы сделали возможным перенести все ваши оценки фильмов, которые вы так долго собирали, в наше удобнейшее приложение для коллекционирования просмотренных фильмов Must App!

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

      Как перенести свои оценки?


      Для начала зайдите на наш сайт.

      image

      Нажмите «Войти», и выберите удобный для вас способ входа.

      image

      Выберите адрес вашей странички.

      image

      Ваш профиль создан. Теперь осталось только перенести ваши оценки.

      image

      Скачайте ваши оценки с Имхонет. Нажмите на ссылку Import Movie Library to Must. И загрузите файл с вашими оценками перетащив или нажав на кнопку списка Watched (чтобы фильмы добавились в список просмотренного).

      image

      Когда фильмы загрузятся, мы сообщим вам об этом, и напишем сколько фильмов удалось загрузить.

      image

      Ваши фильмы добавлены!

      Что дальше?


      Скачайте наше прекрасное приложение для iPhone, и наслаждайтесь!

      image

      Комментарии (0)

        Let's block ads! (Why?)

        Интегрируем Copy-Paste-Detector для Swift в Xcode

        DRY Principle


        Одним из основных мета-принципов программирования является DRY (Don’t Repeat Yourself). Суть данного мета-принципа проста и должна являться негаснущим маяком для любого разработчика. Она гласит, что в разрабатываемой системе не должно быть кусков кода, имеющих одинаковый код. Выражаясь более простым языком, в программе не должно быть копипасты!
        Для начала, давайте точно определим, что будем считать за копипасту. Если в проекте если одинаковые файлы — это грубейшая копипаста. Если есть одинаковые классы с разным названием и выполняющие одно и тоже — грубейшая копипаста. Даже если 10 строк одинакового кода — это тоже является копипастой. Возможно вы возразите, что 10 строк кода продублировать иногда позволительно. Из моего опыта, проект в 100000 строк вполне реально писать без подобной копипасты.
        Какие же минусы несёт нам копипаста?


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

        Как избежать копипасты


        Одним из основных способов нахождения некачественного кода, к коему относится и нарушение принципа DRY, является code-review.
        Важно отметить, что у этого способа есть ряд существенных недостатков, что заставляет искать другие способы поиска некачественного кода.


        • Code-review проводится уже после того, как код написан, а фича доделана. Поэтому если дублирование найдено, то приходится переделывать этот код.
        • Ревьюер вообще может не обнаружить копипасту, особенно если старый кусок сделан давно, а в pull request это продублировано. Часто разработчики забывают написанный код крайне быстро, чтобы освободить память под новые задачи.
        • Тратится время на написание начального кода, на ревью проекта и на исправление. А также на повторное ревью. Временные затраты вы можете посчитать сами. А как известно время=деньги! Особенно в разработке.

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


        Установка CPD


        Для языка Swift было найдено всего 2 детектора дублирования кода.



        Второй является более кастомизируемым, поддерживаемым и в целом более стабильным.
        Для начала работы необходимо установить pmd путем выполнения команды в консоли “brew install pmd”.
        Важно заметить, что для других языков в пакете pmd содержатся и статические анализаторы кода. В пакете для языка Swift есть только CPD (copy paste detector). Поэтому анализаторы кода нужно ставить дополнительно. Лучшим выбором на данный момент будет: http://ift.tt/1bZmpap


        Интеграция с Xcode


        Как ранее было выяснено, самым удобным способом обнаружения ошибок и копипасты является этап прекомпиляции проекта. В Xcode можно добавлять свои скрипты во вкладке Build Phases, чтобы они также отрабатывали на этом этапе и не давали скомпилироваться проекту успешно, если был найден дублирующийся код.


        Для подключения в проект необходимо создать новый build script с именем “CopyPaste Detection” во вкладке Build Phases и добавить внутрь следующий скрипт:


        # Running CPD
        pmd cpd --files ${EXECUTABLE_NAME} --minimum-tokens 50 --language swift --encoding UTF-8 --format net.sourceforge.pmd.cpd.XMLRenderer > cpd-output.xml --failOnViolation true
        # Running script
        php ./cpd_script.php -cpd-xml cpd-output.xml
        

        Разберем подробнее, что означает эта магия. Первая часть скрипта означает, что мы запускаем CPD для файлов, лежащих в корневой папке нашего проекта.  minimum-tokens означает минимальное количество токенов, при нахождении которые скрипт будет помечать фрагмент кода как копипасту. Токеном является некая абстрактная единица, поэтому не нужно принимать это за букву, слово и конструкцию. Эмпирическим путём было выяснено, что цифра 50 является оптимальной для языка Swift. Если взять меньше, то можно найти то, что не является копипастой, если больше, то есть большой шанс пропустить дублирование. Следующий параметр — format означает, что вывод будет происходить в xml-файл. И последний — failOnViolation говорит о том, что приложение не соберется, если найден хоть 1 фрагмент дублирующегося кода.


        В результате выполнения первой части скрипта, у нас есть xml файл с логами анализа проекта. Теперь необходимо показать нашу копипасту прямо в Xcode в привычном для разработчика формате в виде warnings. Для этого добавим еще один скрипт прямо в корень проекта:


        duplication as $duplication) {
           $files = $duplication->xpath('file');
           foreach ($files as $file) {
               echo $file['path'].':'.$file['line'].':1: warning: '.$duplication['lines'].' copy-pasted lines from: '
                   .implode(', ', array_map(function ($otherFile) { return $otherFile['path'].':'.$otherFile['line']; },
                   array_filter($files, function ($f) use (&$file) { return $f != $file; }))).PHP_EOL;
           }
        }
        ?>
        

        Вторая часть нашего первого скрипта запустит второй скрипт и преобразует сгенерированный xml файл в warnings в Xcode. Подробнее о том, как можно самому генерировать warnings в Xcode можно прочитать здесь.


        Теперь запустим наш проект, cmd+B/R и убедимся, что наш скрипт работает. Получаем следующую картину после запуска.


        В Issue Navigator:


        Внутри файла:


        Сopypaste — зло


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


        Теперь у вас есть средство для борьбы с этим злом, интегрированное прямо в Xcode в качестве скрипта в билд фазу. Да поможет вам это перейти на светлую сторону!

        Комментарии (0)

          Let's block ads! (Why?)

          В сеть утекли исходные коды операционной системы Windows 10 [маленькая часть]

          Security Week 25: В *NIX реанимировали древнюю уязвимость, WannaCry оказался не доделан, ЦРУ прослушивает наши роутеры

          Грех администратора или восстановление данных из стучащего HDD Western Digital WD5000AAKX

          пятница, 23 июня 2017 г.

          Как держать 20 тысяч VPN клиентов на серверах за $5

          [Из песочницы] Symfony 4: структура приложения

          CocoaHeads Russia. Прямая трансляция

          image

          Привет, хабраюзеры!

          Сегодня в офисе Туту.ру пройдет очередной митап iOS разработчиков. Мы организуем прямую трансляцию митапа. Если вы не смогли к нам попасть, то у вас есть шанс увидеть все online.

          Программа


          • 19:00 Открытие
          • 19:15 Анимация как средство самовыражения.
            Александр Зимин
          • 20:00 Перерыв
          • 20:25 Team Lead. Структурирование мыслей.
            Николай Ашанин
          • 21:00 Перерыв
          • 21:15 Викторина
          • 21:35 Реактивный VIPER.
            Дмитрий Котенко
          • 22:00 Автепати (трансляция в личные соцсеточки)


          Ссылка на трансляцию


          Будет доступна за 10 минут до открытия

          Комментарии (0)

            Let's block ads! (Why?)

            Как нам помогают нейронные сети в технической поддержке

            ECS (Elastic Cloud Storage) ― облачная платформа хранения Dell EMC

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

            Однако эти проблемы ― далеко не единственные. Бюджеты ИТ остаются на том же уровне или незначительно увеличиваются (примерно на 5% в год), а капитальные расходы большинства организаций каждый год вырастают почти вдвое. К тому же компаниям необходимо сохранять и улучшать уровень обслуживания, затрачивая на это все меньше ресурсов.


            Рост объемов данных (и, соответственно, требований к инфраструктуре хранения) ― тенденция отнюдь не временная, и если компании не трансформируют вовремя свой бизнес, они столкнутся с очень серьезными проблемами. Но развитие технологий позволяет найти нужные решения. Так, компания Dell EMC — крупнейший в мире поставщик систем хранения данных ― создала экономически эффективную облачную платформу ECS.
             

            Что такое ECS?


            Сперва нужно отметить, что ECS ― не публичный Cloud Storage, когда пользователь не знает, где хранятся его данные. Напротив, Dell EMC (Elastic Cloud Storage) — физический массив хранения (хотя есть и версия в виде ПО), и клиент сам выбирает, где его разместить. А облачным хранилищем ECS называется, поскольку систему можно использовать именно с такой целью.  

            Программное обеспечение ECS позволяет хранить, администрировать и анализировать неструктурированные данные в масштабной инфраструктуре из типовых компонентов. Это комплексная многопользовательская облачная платформа хранения, которая позволяет учитывать потребление ресурсов и самостоятельно их выделять.

            Заказчики могут приобрести ECS как готовую программно-аппаратную систему (решение Dell EMC ECS Appliance) или в виде программного продукта (ПО ECS): он устанавливается на серверы заказчика и типовые диски, сертифицированные Dell EMC. В состав ECS входит модуль хранения неструктурированных данных, который поддерживает сервисы управления объектами и HDFS, а также поддержка файловых сервисов.

            Технически эта система представляет собой:

            • сервер Intel x86 с подключенными к нему полками JBOD (до 60 дисков на сервер),
            • сетевые адаптеры 10GbE для подключения узлов.

            Конфигурация системы включает 4/8 узлов. Емкость решения достигает 3840 Tбайт на стойку.
             
            ECS ― объектная система хранения данных третьего поколения. Она позволяет:
            • консолидировать ресурсы основного хранилища и повысить окупаемость инвестиций;
            • модернизировать традиционные и унаследованные приложения для более эффективного использования хранилища;
            • ускоренно внедрять облачные приложения с новыми функциями для бизнеса.

            Преимущества объектного хранилища:
            • Доступ к объектам предоставляется по специализированным протоколам. В отличие от блочных или файловых, они работают поверх HTTP и основаны на REST: S3, Swift, Atmos.
            • Ориентированность на хранение неструктурированной информации (любые файлы, которые являются статическим или динамическим контентом на стороне клиента).
            • Каждый объект обладает уникальным адресом.
            • Глобальное пространство имен объектов: любой объект доступен в любой момент из любого сегмента инфраструктуры.

            Чем удобна ECS?


            1. Экономичность. ECS ― многофункциональная платформа, которая предполагает множество сценариев использования и защищает инвестиции в инфраструктуру хранения Dell EMC. Она упрощает управление, повышает гибкость, а главное — снижает затраты. С точки зрения масштабирования, ECS ― одно из самых экономически эффективных решений на рынке. Согласно исследованию Enterprise Strategy Group (ESG), хранить файлы в ECS минимум на 60% выгоднее по сравнению с другими облачными сервисами.
            2. Интеграция с существующей средой хранения. ECS «расширяет» облако до основного хранилища и позволяет освободить инфраструктуру хранения при помощи решений Dell EMC для облачных вычислений (CloudPools, CloudBoost, CloudArray и т. д.). Заказчики могут выводить неактивные данные из первичного хранилища (Isilon, VMAX Series, VPLEX, VNX Series, Vx Series, Data Domain, Data Protection Suite и т. д.) в облако, перемещая их на ECS. Такая консолидация ресурсов позволяет не покупать дополнительные и более дорогие платформы и заметно повышает эффективность имеющейся среды хранения.
            3. Оперативный и повсеместный доступ к данным. Объектная платформа ECS способна радикально улучшить время отклика и повысить скорость доступа к данным по сравнению с традиционной NAS. Данные защищаются при помощи кодирования и распределяются по всем узлам системы, обеспечивая мгновенный доступ для чтения/записи из любого места. При этом доступна самая последняя копия данных, что упрощает разработку приложений. Поддержка геокэширования также делает доступ более оперативным благодаря интеллектуальному системному распознаванию шаблонов операций: оно минимизирует трафик глобальной сети и улучшает латентность.
            4. Простота разработки приложений. Единое глобальное пространство имен не требует от разработчиков обращаться к сложным файловым системам NFS. Они могут сосредоточиться на создании приложений, а не деталях операций. Модернизируя традиционные приложения в хранилище объектов, пользователи получают дополнительные ресурсы, доступ к контенту через интернет и глобальную доступность через единое пространство имен. Кроме того, они смогут оптимально использовать ресурсы хранения в центре обработки данных. Нативные облачные приложения в полной мере используют инфраструктуру облачной среды.
            5. Пользователю доступны все плюсы программно-определяемой СХД. Платформа ECS полностью использует программно-определяемую архитектуру, что позволяет независимо масштабировать вычислительные ресурсы и ресурсы хранения. Все данные в ECS контейнеризированы; нет аппаратной зависимости, необходимости перекодировать или перенастраивать приложения, поскольку ECS обеспечивает поддержку нескольких протоколов. Это позволяет разработчикам гораздо быстрее внедрять инновации и выводить свои приложения на рынок.

            Цифровая трансформация — это просто


            Предприятия и поставщики облачных сервисов могут использовать ECS как основу для «цифровой трансформации». Традиционные бизнес-приложения сейчас сменяются облачными — а ECS устраняет разрыв между приложениями «второй» и «третьей» платформы, позволяя им использовать единую систему хранения. ECS не только справляется с огромным объемом неструктурированных данных ― как многоцелевая платформа она принимает на себя самые разные нагрузки и способна подготовить компанию к любым вызовам.

            ECS совместима с HDFS, OpenStack Swift и Amazon S3, а также с API Centera и Atmos. По выбору заказчика ее можно развертывать как полностью интегрированное решение, которое масштабируется до 3,8 Пбайт на стойку, или как программное решение для хранения данных на сертифицированном оборудовании. Кроме того, ECS доступна по подписке с платой за использование. Благодаря этому система завоевывает популярность у корпоративных клиентов и поставщиков услуг.

            Производитель позиционирует ECS для случаев, когда требуется:
            • распределенная архитектура,
            • глобальное пространство имен (все центры данных с узлами active/active, геозащитой, многопротокольным доступом и поиском по метаданным).

            Сценарии использования ECS


            Платформа ECS применяется как:
            1. Глобальный репозиторий контента. Это сравнительно простое в реализации решение обеспечивает глобальный доступ к файлам и защиту данных корпоративного уровня.
            2. Масштабная реализация аналитики больших данных. Система обеспечивает глобальную аналитику данных из географически распределенных архивов. Это экономичное высокоплотное решение хранения для Hadoop.
            3. Современная платформа для приложений. ECS поддерживает множество API и протоколов, а ее архитектура active/active оптимизирована для хранения данных и доступа к ним.
            4. Система холодного архивирования неактивных данных. Позволяет создавать архивы, готовые к поддержке будущих приложений, а также оптимизирует существующие среды хранения.
            5. Развертывание платформы управления для Интернета вещей (IoT). Архитектура IoT эффективна для работы с большим объемом неструктурированных данных. А на недавнем форуме Dell EMC World 2017 было объявлено, что теперь в ECS возможна потоковая передача данных IoT.


            Вот несколько вариантов использования ECS вместе с другими системами хранения Dell EMC:

            Пример 1. Комбинация ECS с Dell EMC Cloud Array. Файловые службы и хранилища для удаленных офисов без развертывания массива хранения на удаленной площадке.


            Пример 2. Комбинация ECS с Isilon (облачные пулы). Isilon (горизонтально-масштабируемая NAS) с автоматическим перемещением файлов на недорогое хранилище по заданным правилам.

            Пример 3. Классическое архивирование. ECS используется в качестве архива.
             
            Пример 4. Комбинация с Dell EMC Cloud Boost. Долгосрочное хранение данных.

            Пример 5. Разработка с использованием объектного хранилища. Мобильные приложения стали настолько развитыми, что их сложно связать с известными протоколами хранения данных (FC, NAS) без «шлюза» ― например, веб-сервера. Благодаря ECS мобильные приложения получают прямой доступ к хранилищу при помощи HTTP/HTTPS и могут получать или сохранять нужные объекты.

            Платформа ECS была выпущена в июне 2015 года. Сейчас ею пользуются более 250 клиентов, и у многих из них емкости инсталляций превышают петабайт. ECS поддерживает объекты, NFS и распределенную файловую систему Hadoop (HDFS), что позволяет ей хранить миллиарды файлов для облачных приложений.

            Комментарии (0)

              Let's block ads! (Why?)

              Автоэнкодеры в Keras, Часть 2: Manifold learning и скрытые (latent) переменные

              Содержание


              • Часть 1: Введение
              • Часть 2: Manifold learning и скрытые (latent) переменные
              • Часть 3: Вариационные автоэнкодеры (VAE)
              • Часть 4: Conditional VAE
              • Часть 5: GAN (Generative Adversarial Networks) и tensorflow
              • Часть 6: VAE + GAN

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

              Manifold learning


              Изображения цифр mnist (на которых примеры в прошлой части) — это элементы 28*28=784-мерного пространства, как и вообще любое монохромное изображение 28 на 28.

              Однако среди всех изображений, изображения цифр занимают лишь ничтожную часть, абсолютное же большинство изображений — это просто шум.

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

              А если взять два произвольных изображения цифры, то в изначальном 784-мерном пространстве скорее всего, можно найти непрерывную кривую, все точки вдоль которой можно также считать цифрами (хотя бы для изображений цифр одного лейбла), а вкупе с предыдущим замечанием, то и все точки некоторой области вдоль этой кривой.

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

              Автоэнкодеры с размерностью кода k ищут k-мерное многообразие в пространстве объектов, которое наиболее полно передает все вариации в выборке. А сам код задает параметризацию этого многообразия. При этом энкодер сопоставляет объекту его параметр на многообразии, а декодер параметру сопоставляет точку в пространстве объектов.

              Чем больше размерность кодов, тем больше вариаций в данных автоэнкодер сможет передать. Если размерность кодов слишком мала, автоэнкодер запомнит нечто среднее по недостающим вариациям в заданной метрике (это одна из причин, почему mnist цифры все более размытые при снижении размерности кода в автоэнкодерах).

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

              Код и визуализация
              # Импорт необходимых библиотек
              import numpy as np
              import matplotlib.pyplot as plt
              %matplotlib inline
              import seaborn as sns
              
              # Создание датасета
              x1 = np.linspace(-2.2, 2.2, 1000)
              fx = np.sin(x1)
              dots = np.vstack([x1, fx]).T
              noise = 0.06 * np.random.randn(*dots.shape)
              dots += noise
              
              # Цветные точки для отдельной визуализации позже
              from itertools import cycle
              size = 25
              colors = ["r", "g", "c", "y", "m"]
              idxs = range(0, x1.shape[0], x1.shape[0]//size)
              vx1 = x1[idxs]
              vdots = dots[idxs]
              
              

              # Визуализация
              plt.figure(figsize=(12, 10))
              plt.xlim([-2.5, 2.5])
              plt.scatter(dots[:, 0], dots[:, 1])
              plt.plot(x1, fx,  color="red", linewidth=4)
              plt.grid(False)
              
              



              На картинке выше: синие точки — данные, а красная кривая – многообразие, определяющее наши данные.

              Линейный сжимающий автоэнкодер


              Самый простой автоэнкодер — это двухслойный сжимающий автоэнкодер с линейными функциями активации (больше слоев не имеет смысла при линейной активации).

              Такой автоэнкодер ищет аффинное (линейное со сдвигом) подпространство в пространстве объектов, которое описывает наибольшую вариацию в объектах, тоже самое делает и PCA (метод главных компонент) и оба они находят одно и тоже подпространство

              from keras.layers import Input, Dense
              from keras.models import Model
              from keras.optimizers import Adam
              
              def linear_ae():
                  input_dots = Input((2,))
                  code = Dense(1, activation='linear')(input_dots)
                  out  = Dense(2, activation='linear')(code)
              
                  ae = Model(input_dots, out)
                  return ae
              
              ae = linear_ae()
              ae.compile(Adam(0.01), 'mse')
              
              ae.fit(dots, dots, epochs=15, batch_size=30, verbose=0)
              
              
              # Применение линейного автоэнкодера
              pdots = ae.predict(dots, batch_size=30)
              vpdots = pdots[idxs]
              
              # Применение PCA
              from sklearn.decomposition import PCA
              pca = PCA(1)
              pdots_pca = pca.inverse_transform(pca.fit_transform(dots))
              
              

              Визуализация
              # Визуализация
              plt.figure(figsize=(12, 10))
              plt.xlim([-2.5, 2.5])
              plt.scatter(dots[:, 0], dots[:, 1], zorder=1)
              plt.plot(x1, fx,  color="red", linewidth=4, zorder=10)
              plt.plot(pdots[:,0], pdots[:,1], color='white', linewidth=12, zorder=3)
              plt.plot(pdots_pca[:,0], pdots_pca[:,1], color='orange', linewidth=4, zorder=4)
              plt.scatter(vpdots[:,0], vpdots[:,1], color=colors*5, marker='*', s=150, zorder=5)
              plt.scatter(vdots[:,0], vdots[:,1], color=colors*5, s=150, zorder=6)
              plt.grid(False)
              
              



              На картинке выше:
              • белая линия – многообразие, в которое переходят синие точки данных после автоэнкодера, то есть попытка автоэнкодера построить многообразие, определяющее больше всего вариаций в данных,
              • оранжевая линия – многообразие, в которое переходят синие точки данных после PCA,
              • разноцветные кружки — точки, которые переходят в звездочки соответствующего цвета после автоэнкодера,
              • разноцветные звездочки – соответственно, образы кружков после автоэнкодера.

              Автоэнкодер, ищущий линейные зависимости, может быть не так полезен, как автоэнкодер, который может находить произвольные зависимости в данных. Полезно было бы, если бы и энкодер, и декодер могли аппроксимизировать произвольные функции. Если добавить и в энкодер, и в декодер еще хотя бы по одному слою достаточного размера и нелинейную функцию активации между ними, то они смогут находить произвольные зависимости.

              Глубокий автоэнкодер


              У глубокого автоэнкодера больше число слоев и самое главное — нелинейная функция активации между ними (в нашем случае ELU — Exponential Linear Unit).
              def deep_ae():
                  input_dots = Input((2,))
                  x = Dense(64, activation='elu')(input_dots)
                  x = Dense(64, activation='elu')(x)
                  code = Dense(1, activation='linear')(x)
                  x = Dense(64, activation='elu')(code)
                  x = Dense(64, activation='elu')(x)
                  out = Dense(2, activation='linear')(x)
              
                  ae = Model(input_dots, out)
                  return ae
              
              dae = deep_ae()
              dae.compile(Adam(0.003), 'mse')
              
              dae.fit(dots, dots, epochs=200, batch_size=30, verbose=0)
              pdots_d = dae.predict(dots, batch_size=30)
              vpdots_d = pdots_d[idxs]
              
              

              Визуализация
              # Визуализация
              plt.figure(figsize=(12, 10))
              plt.xlim([-2.5, 2.5])
              plt.scatter(dots[:, 0], dots[:, 1], zorder=1)
              plt.plot(x1, fx,  color="red", linewidth=4, zorder=10)
              plt.plot(pdots_d[:,0], pdots_d[:,1], color='white', linewidth=12, zorder=3)
              plt.plot(pdots_pca[:,0], pdots_pca[:,1], color='orange', linewidth=4, zorder=4)
              plt.scatter(vpdots_d[:,0], vpdots_d[:,1], color=colors*5, marker='*', s=150, zorder=5)
              plt.scatter(vdots[:,0], vdots[:,1], color=colors*5, s=150, zorder=6)
              plt.grid(False)
              
              


              У такого автоэнкодера практически идеально получилось построить определяющее многообразие: белая кривая почти совпадает с красной.

              Глубокий автоэнкодер теоретически сможет найти многообразие произвольной сложности, например, такое, около которого лежат цифры в 784-мерном пространстве.

              Если взять два объекта и посмотреть на объекты, лежащие на произвольной кривой между ними, то скорее всего промежуточные объекты не будут принадлежать генеральной совокупности, т. к. многообразие на котором лежит генеральная совокупность может быть сильно искривленным и малоразмерным.

              Вернемся к датасету рукописных цифр из предыдущей части.

              Сначала двигаемся по прямой в пространстве цифр от одной 8-ки к другой:

              Код
              from keras.layers import Conv2D, MaxPooling2D, UpSampling2D
              from keras.datasets import mnist
              
              (x_train, y_train), (x_test, y_test) = mnist.load_data()
              
              x_train = x_train.astype('float32') / 255.
              x_test  = x_test .astype('float32') / 255.
              x_train = np.reshape(x_train, (len(x_train), 28, 28, 1))
              x_test  = np.reshape(x_test,  (len(x_test),  28, 28, 1))
              
              # Сверточный автоэнкодер
              def create_deep_conv_ae():
                  input_img = Input(shape=(28, 28, 1))
              
                  x = Conv2D(128, (7, 7), activation='relu', padding='same')(input_img)
                  x = MaxPooling2D((2, 2), padding='same')(x)
                  x = Conv2D(32, (2, 2), activation='relu', padding='same')(x)
                  x = MaxPooling2D((2, 2), padding='same')(x)
                  encoded = Conv2D(1, (7, 7), activation='relu', padding='same')(x)
              
                  # На этом моменте представление  (7, 7, 1) т.е. 49-размерное
              
                  input_encoded = Input(shape=(7, 7, 1))
                  x = Conv2D(32, (7, 7), activation='relu', padding='same')(input_encoded)
                  x = UpSampling2D((2, 2))(x)
                  x = Conv2D(128, (2, 2), activation='relu', padding='same')(x)
                  x = UpSampling2D((2, 2))(x)
                  decoded = Conv2D(1, (7, 7), activation='sigmoid', padding='same')(x)
              
                  # Модели
                  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()
              c_autoencoder.compile(optimizer='adam', loss='binary_crossentropy')
              c_autoencoder.fit(x_train, x_train,
                              epochs=50,
                              batch_size=256,
                              shuffle=True,
                              validation_data=(x_test, x_test))
              
              def plot_digits(*args):
                  args = [x.squeeze() for x in args]
                  n = min([x.shape[0] for x in args])
                  
                  plt.figure(figsize=(2*n, 2*len(args)))
                  for j in range(n):
                      for i in range(len(args)):
                          ax = plt.subplot(len(args), n, i*n + j + 1)
                          plt.imshow(args[i][j])
                          plt.gray()
                          ax.get_xaxis().set_visible(False)
                          ax.get_yaxis().set_visible(False)
              
                  plt.show()
              
              # Гомотопия по прямой между объектами или между кодами
              def plot_homotopy(frm, to, n=10, decoder=None):
                  z = np.zeros(([n] + list(frm.shape)))
                  for i, t in enumerate(np.linspace(0., 1., n)):
                      z[i] = frm * (1-t) + to * t
                  if decoder:
                      plot_digits(decoder.predict(z, batch_size=n))
                  else:
                      plot_digits(z)
              
              


              # Гомотопия между первыми двумя восьмерками
              frm, to = x_test[y_test == 8][1:3]
              plot_homotopy(frm, to)
              
              

              Если же двигаться по кривой между кодами (и если многообразие кодов хорошо параметризовано), то декодер переведет эту кривую из пространства кодов, в кривую, не покидающую определяющее многообразие в пространстве объектов. То есть промежуточные объекты на кривой будут принадлежать генеральной совокупности.

              codes = c_encoder.predict(x_test[y_test == 8][1:3])
              plot_homotopy(codes[0], codes[1], n=10, decoder=c_decoder)
              
              


              Промежуточные цифры — вполне себе хорошие восьмерки.

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

              Переобучение автоэнкодера


              Для того чтобы автоэнкодер мог научиться вычленять какие-то сложные закономерности, обобщающие способности энкодера и декодера должны быть ограничены, иначе даже автоэнкодер с одномерным кодом сможет просто провести одномерную кривую через каждую точку в обучающей выборке, т.е. просто запомнить каждый объект. Но это сложное многообразие, которое построит автоэнкодер, не будет иметь много общего с определяющим генеральную совокупность многообразием.

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

              Код
              dae = deep_ae()
              dae.compile(Adam(0.0003), 'mse')
              x_train_oft = np.vstack([dots[idxs]]*4000)
              
              
              dae.fit(x_train_oft, x_train_oft, epochs=200, batch_size=15, verbose=1)
              
              
              pdots_d = dae.predict(dots, batch_size=30)
              vpdots_d = pdots_d[idxs]
              
              plt.figure(figsize=(12, 10))
              plt.xlim([-2.5, 2.5])
              plt.scatter(dots[:, 0], dots[:, 1], zorder=1)
              plt.plot(x1, fx, color="red", linewidth=4, zorder=10)
              plt.plot(pdots_d[:,0], pdots_d[:,1], color='white', linewidth=6, zorder=3)
              plt.plot(pdots_pca[:,0], pdots_pca[:,1], color='orange', linewidth=4, zorder=4)
              plt.scatter(vpdots_d[:,0], vpdots_d[:,1], color=colors*5, marker='*', s=150, zorder=5)
              plt.scatter(vdots[:,0], vdots[:,1], color=colors*5, s=150, zorder=6)
              plt.grid(False)
              
              


              Видно, что белая кривая прошла через каждую точку данных и слабо похожа на определяющую данные красную кривую: на лицо типичное переобучение.

              Скрытые переменные


              Можно рассмотреть генеральную совокупность как некоторый процесс генерации данных X, который зависит от некоторого количества скрытых переменных Z (случайных величин). Размерность данных X может быть намного выше, чем размерность скрытых случайных величин Z, которые эти данные определяют. Рассмотрим процесс генерации очередной цифры: то, как будет выглядеть цифра, может зависеть от множества факторов:
              • желаемой цифры,
              • толщины штриха,
              • наклона цифры,
              • аккуратности,
              • и т.д.

              Каждый из этих факторов имеет свое априорное распределение, например, вероятность того, что будет нарисована восьмерка — это распределение Бернулли с вероятностью 1/10, толщина штриха тоже имеет некоторое свое распределение и может зависеть как от аккуратности, так и от своих скрытых переменных, таких как толщина ручки или темперамент человека (опять же со своими распределениями).

              Автоэнкодер сам в процессе обучения должен прийти к скрытым факторам, например, таким как перечисленные выше, каким-то их сложным комбинациям, или вообще к совсем другим. Однако, то совместное распределение, которое он выучит, вовсе не обязано быть простым, это может быть какая-то сложная кривая область. (Декодеру можно передать и значения извне этой области, вот только результаты уже не будут из определяющего многообразия, а из его случайного непрерывного продолжения).

              Именно поэтому мы не можем просто генерировать новые X из распределения этих скрытых переменных. Сложно оставаться в пределах области, а еще сложнее как-то интерпретировать значения скрытых переменных в этой кривой области.

              Для определенности введем некоторые обозначения на примере цифр:

              • X — случайная величина картинки 28х28,
              • Z — случайная величина скрытых факторов, определяющих цифру на картинке,
              • p(X) — вероятностное распределение изображений цифр на картинках, т.е. вероятность конкретного изображения цифры в принципе быть нарисованным (если картинка не похожа на цифру, то эта вероятность крайне мала),
              • p(Z) — вероятностное распределение скрытых факторов, например, распределение толщины штриха,
              • p(Z|X) — распределение вероятности скрытых факторов при заданной картинке (к одной и той же картинке могут привести различное сочетание скрытых переменных и шума),
              • p(X|Z) — распределение вероятности картинок при заданных скрытых факторах, одни и те же факторы могут привести к разным картинкам (один и тот же человек в одних и тех же условиях не рисует абсолютно одинаковые цифры),
              • p(X,Z) — совместное распределение X и Z, наиболее полное понимание данных, необходимое для генерации новых объектов.

              p(X,Z) = p(X|Z) p(Z)

              p(X|Z) нам приближает декодер, но p(Z) на данный момент мы пока еще не понимаем.

              Посмотрим, как распределены скрытые переменные в обычном автоэнкодере:

              Код
              from keras.layers import Flatten, Reshape
              from keras.regularizers import L1L2
              
              def create_deep_sparse_ae(lambda_l1):
                  # Размерность кодированного представления
                  encoding_dim = 16
              
                  # Энкодер
                  input_img = Input(shape=(28, 28, 1))
                  flat_img = Flatten()(input_img)
                  x = Dense(encoding_dim*4, activation='relu')(flat_img)
                  x = Dense(encoding_dim*3, activation='relu')(x)
                  x = Dense(encoding_dim*2, activation='relu')(x)
                  encoded = Dense(encoding_dim, activation='linear', activity_regularizer=L1L2(lambda_l1, 0))(x)
                  
                  # Декодер
                  input_encoded = Input(shape=(encoding_dim,))
                  x = Dense(encoding_dim*2, activation='relu')(input_encoded)
                  x = Dense(encoding_dim*3, activation='relu')(x)
                  x = Dense(encoding_dim*4, activation='relu')(x)
                  flat_decoded = Dense(28*28, activation='sigmoid')(x)
                  decoded = Reshape((28, 28, 1))(flat_decoded)
                  
                  # Модели
                  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
              
              encoder, decoder, autoencoder = create_deep_sparse_ae(0.)
              autoencoder.compile(optimizer=Adam(0.0003), loss='binary_crossentropy')
              
              

              autoencoder.fit(x_train, x_train,
                                    epochs=100,
                                    batch_size=64,
                                    shuffle=True,
                                    validation_data=(x_test, x_test))
              
              

              n = 10
              imgs = x_test[:n]
              decoded_imgs = autoencoder.predict(imgs, batch_size=n)
              
              plot_digits(imgs, decoded_imgs)
              
              


              Вот так выглядят восстановленные этим энкодером изображения:
              Изображения


              Совместное распределение скрытых переменных P(Z_1, Z_3)
              codes = encoder.predict(x_test)
              sns.jointplot(codes[:,1], codes[:,3])
              
              

              Видно, что совместное распределение P(Z_1,Z_3) имеет сложную форму; Z_1 и Z_3 зависимы друг от друга.

              Есть ли какой-то способ контролировать распределения скрытых переменных P(Z)?

              Самый простой способ — добавить регуляризатор L_1 или L_2 на значения Z, это добавит априорные предположения на распределения скрытых переменных, соответственно, лапласса или нормальное (похоже на априорное распределение, добавляемое на значения весов при регуляризации).

              Регуляризатор вынуждает автоэнкодер искать скрытые переменные, которые распределены по нужным законам, получится ли у него — другой вопрос. Однако это никак не заставляет делать их независимыми, т.е. P(Z_i) \neq P(Z_i|Z_j).

              Посмотрим на совместное распределение скрытых параметров в разреженом автоэнкодере.

              Код и визуализация
              s_encoder, s_decoder, s_autoencoder = create_deep_sparse_ae(0.00001)
              s_autoencoder.compile(optimizer=Adam(0.0003), loss='binary_crossentropy')
              
              

              s_autoencoder.fit(x_train, x_train, epochs=200, batch_size=256, shuffle=True, 
                                        validation_data=(x_test, x_test))
              
              

              imgs = x_test[:n]
              decoded_imgs = s_autoencoder.predict(imgs, batch_size=n)
              plot_digits(imgs, decoded_imgs)
              
              



              codes = s_encoder.predict(x_test)
              snt.jointplot(codes[:,1], codes[:,3])
              
              

              Z_1 и Z_3 все так же зависимы друг от друга, но теперь хотя бы распределены вокруг 0, и даже более или менее нормально.

              О том, как контролировать скрытое пространство, так, чтобы из него уже можно было осмысленно генерировать изображения — в следующей части про вариационные автоэнкодеры (VAE).

              Полезные ссылки и литература


              Этот пост основан на главе про автоэнкодеры (в частности подглавы Learning maifolds with autoencoders) в Deep Learning Book.

              Комментарии (0)

                Let's block ads! (Why?)