company_banner

Нейропластичность в искусственных нейронных сетях

    Привет, Хабр, давно не виделись. В этом посте мне хотелось бы рассказать о таком относительно новом понятии в машинном обучении, как transfer learning. Так как я не нашел какого-либо устоявшегося перевода этого термина, то и в названии поста фигурирует хоть и другой, но близкий по смыслу термин, который как бы является биологической предпосылкой к формализации теории передачи знаний от одной модели к другой. Итак, план такой: для начала рассмотрим биологические предпосылки; после коснемся отличия transfer learning от очень похожей идеи предобучения глубокой нейронной сети; а в конце обсудим реальную задачу семантического хеширования изображений. Для этого мы не будем скромничать и возьмем глубокую (19 слоев) сверточную нейросеть победителей конкурса imagenet 2014 года в разделе «локализация и классификация» (Visual Geometry Group, University of Oxford), сделаем ей небольшую трепанацию, извлечем часть слоев и используем их в своих целях. Поехали.

    Нейропластичность


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



    Чтобы действительно ощутить всю мощь нашего мозга, давайте взглянем на эксперимент нейрофизиолога Paul Bach-y-Rita, работы которого в значительной степени повлияли на признание нейропластичности научной общественностью. Важным фактором, влияющим на мотивацию ученого, являлось то, что его отец был парализован. Совместными усилиями с братом-физиком они смогли поднять отца на ноги к 68 годам, что позволило тому даже заниматься экстремальными видами спорта. Их история показала, что даже в позднем возрасте мозг человека способен к реабилитации. Но это совсем другая история, вернемся к опыту 1969 года. Цель была серьезная: дать слепым (даже от рождения) людям возможность видеть. Для этого было взято стоматологическое кресло и переоборудовано следующим образом: рядом с креслу поставили телевизионную камеру, а к креслу подвели манипулятор, который позволял изменять масштаб и положение камеры. В спинку кресла было вмонтировано 400 стимуляторов, которые образовывали сетку: изображение, поступавшее с камеры, сжималось до размера 20 на 20; стимуляторы располагались на расстоянии 12 мм друг от друга. К каждому стимулятору был прикреплен небольшой миллиметровый наконечник, который вибрировал пропорционально току, подаваемому на соленоид, расположенный внутри стимулятора.



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



    Годом позже Пол разработал мобильную версию своей системы:
    мобильный визор 1970-ого года
    Человек похож на Мавроди, но это не он.



    В наше время вместо тактильной передачи сигнала используют «короткий» путь через более чувствительный орган — язык. Как пишут в статьях, достаточно нескольких часов, чтобы начать воспринимать изображение рецепторами языка.
    современный вариант
    Думаете, он ест лапшу? А нет, он смотрит языком.





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


    Так как же это работает? Говоря на простом языке (не биологов и нейрофизиологов, а скорее на языке анализа данных), нейроны обучаются эффективно извлекать признаки и делать выводы на них. Подменяя привычный сигнал на некоторый другой, наша нейронная сеть все равно извлекает хорошие низкоуровневые признаки (на примере компьютерного зрения, приводимого ниже, это будут различные градиентные переходы или паттерны) на слоях, которые расположены близко к сенсору (глазу, языку, уху и т.д.). Более глубокие слои пытаются извлечь высокоуровневые признаки (колесо, окно). И вероятно, если искать в звуковом сигнале колесо от машины, скорее всего мы его не найдем. К сожалению, посмотреть, какие признаки извлекают нейроны, у нас не очень получится, но благодаря статье "Visualizing and Understanding Convolutional Networks" есть возможность взглянуть на низкоуровневые и высокоуровневые признаки, извлекаемые глубокой сверточной нейронной сетью. Это, конечно, не биологическая сеть, и возможно, все в реальности не так. Как минимум, это дает некое интуитивное понимание причин того, что видеть можно даже рецепторами языка.

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

    Visualization of features in a fully trained model
    Каждый серый квадрат соответствует визуализации фильтра (который применяется для свертки) или весов одного нейрона, а каждая цветная картинка — это та часть оригинального изображения, которая активирует соответствующий нейрон. Для наглядности нейроны внутри одного слоя сгруппированы в тематические группы.



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

    А теперь давайте вспомним, с чего начиналась история искусственных нейронных сетей. В 1949 году Дональд Хебб публикует книгу The Organization of Behavior, в которой описывает первые принципы обучений ИНС. Стоит заметить, что современные алгоритмы обучения недалеко ушли от этих принципов.
    • если рядом стоящие нейроны активируются синхронно, то связь между ними усиливается;
    • если рядом стоящие нейроны активируются асинхронно, то связь между ними ослабевает (на самом деле, этого правила не было у Хебба, его дописали как дополнение уже позже).

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

    New York Time, July 8, 1958




    В персептроне были реализованы правила обучения Хебба. Как мы видим, синаптическая пластичность в правилах уже учтена в какой-то степени. И в принципе, online learning дает нам некоторую пластичность — нейросеть может постоянно дообучаться на непрерывном потоке данных, а ее прогнозы в связи с этим будут со временем меняться, постоянно учитывая изменения в данных. Но нет никаких рекомендаций по другим аспектам нейропластичности, таким как сенсорная заменяемость или нейрогенез. Но это и неудивительно, до принятия нейропластичности еще остается чуть более 20 лет. Учитывая последующую историю ИНС, ученым было не до имитации нейропластичности, вопрос был о выживаемости теории в принципе. Только после очередного ренессанса нейросетей в двухтысячных годах, благодаря таким людям, как Хинтон, ЛеКун, Бенджио и Шмидтхубер, у других ученых появилась возможность всесторонне подойти к машинному обучению и прийти к понятию transfer learning.

    Transfer learning


    Определим цели transfer learning. Авторы публикации 2009 года с одноименным названием выделяют три основные цели:
    • higher start — улучшение качества обучения уже на начальных итерациях за счет более тщательной подборки начальных параметров модели или какой-либо другой априорной информации;
    • higher slope — ускорение сходимости алгоритма обучения;
    • higher asymptote — улучшение верхней достижимой границы качества.



    Если вы знакомы с предобучением глубоких сетей с помощью автоенкодеров или ограниченных машин Больцмана, то вы сразу подумаете: «Так вот оно, я уже, оказывается, практиковал transfer learning или, как минимум, знаю, как это сделать». А вот, оказывается, нет. Авторы проводят четкую границу между стандартным машинным обучением и transfer learning. В стандартном подходе у вас есть только цель и набор данных, а задача заключается в том, чтобы какими-либо методами достичь этой цели. В рамках решения задачи вы можете построить глубокую сеть, предобучить ее жадным алгоритмом, построить еще с десяток таких же и каким-либо образом сделать ансамбль из них. Но все это будет в рамках решения какой-то одной проблемы, и время, потраченное на решение такой проблемы, будет сравнимо с суммарным временем, потраченным на обучение каждой модели, и ее предобучение.

    А теперь представьте, что есть две задачи, и решали их, возможно, даже разные люди. Один из них использует часть модели другого (source task) для уменьшения временных затрат на создание модели с нуля и улучшения производительности своей модели (target task). Процесс передачи знаний от одной проблемы к другой и есть transfer learning. А наш мозг, вероятно, так и поступает. Как в примере выше, его реальная задача почувствовать вкус рецепторами языка и видеть глазами. Встает задача — воспринимать визуальную информацию рецепторами языка. И вместо того, чтобы вырастить новые нейроны или же сбросить веса старых и обучить их заново, мозг просто слегка корректирует имеющуюся нейронную сеть для достижения результата.



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



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

    Итак, обучение с учителем является обучением на размеченных примерах, в то время как сам процесс обучения на примерах иногда называется индуктивным обучением (переход от частного к общему), а обобщающая способность называется inductive bias. Отсюда и второе название transfer learning — inductive transfer. Тогда можно сказать, что задача трансфера знаний в индуктивном обучении — позволить знаниям, накопленным в процессе обучения старой модели, повлиять на обобщающую способность новой модели (даже при решении другой задачи).

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



    Практика


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

    Для начала сформулируем проблему. Допустим, у вас есть очень большой набор изображений. Необходимо организовать поиск похожих изображений. Тут возникает две проблемы. Во-первых, мера схожести между изображениями неочевидна, и если просто брать евклидово расстояние от n*m-мерного вектора, результат получится не очень удовлетворительным. Во-вторых, даже если есть качественная мера, то она не позволит нам избежать полного сканирования базы, а база может содержать миллиарды изображений.

    Для решения этой задачи можно использовать семантическое хеширование, один из таких способов описан у Салакхудинова и Хинтона в статье Semantic Hashing. Их идея заключается в том, что исходный вектор данных кодируется бинарным вектором малой размерности (в нашем случае это изображение, а в оригинальной статье это бинарный вектор bag of words). При таком кодировании можно осуществлять поиск похожих изображений за линейное от длины кода время, используя расстояние Хэмминга. Такое кодирование называется семантическим, так как близкие по смыслу и содержанию изображения (тексты, музыка и т.д.) в новом пространстве признаков располагаются близко друг к другу. Для реализации этой идеи они использовали глубокую сеть доверия, алгоритм обучения которой был разработан Хинтоном и компанией еще в 2006 году:
    • сеть на вход принимает в общем случае действительные значения (gaussian-bernoulli rbm) и кодирует их в длинный бинарный вектор, каждый следующий слой старается уменьшить длину бинарного кода (berboulli-bernoulli rbm);
    • такая сеть предобучается последовательно снизу вверх своей собственной ограниченной машиной Больцмана, где каждая следующая использует выход предыдущей в качестве своих входных данных;
    • затем сеть разворачивается в обратном порядке и обучается как глубокий автоенкодер, которому на вход подается немного зашумленный вектор, и он пытается восстановить оригинальный не зашумленный образ; этот шаг называется fine turning;
    • в конце концов, бинарный образ в середине автоенкодера будет искомым бинарным хэшем от входного образа.



    Мне кажется, что это гениальная модель, и я решил, что в принципе задача решена, спасибо Хинтону. Я запустил предобучение на NVIDIA Tesla K20, подождал пару дней, и оказалось, что все не так радужно, как описывает Хинтон. То ли из-за того, что картинки большого размера, то ли потому, что я использовал gaussian-bernoulli rbm, а в статье используется poisson-bernoulli rbm, то ли из-за специфичности данных, а может быть, вообще, я мало обучал. Но дальше ждать мне как-то не хотелось. И тут я вспомнил совет Максима Милакова — юзай сверточные сети, а также термин transfer learning из одной его презентации. Были, конечно, и другие варианты, начиная от сжатия размерности картинок и квантификации цветов, до классических признаков компьютерного зрения и объединения их в bag of visual words. Но раз вступив на тропу глубокого обучения, не так-то просто с нее свернуть, да и бонусы, которые обещает transfer learning (особенно экономия времени), меня прельстили.

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

    Вообще, ImageNet — это не только конкурс, но и база изображений, которая содержит в себе немногим более одного миллиона реальных изображений. Каждое изображение отнесено к одному из 1000 классов. Набор сбалансирован по классам, то есть чуть более 1000 изображений на один класс. Парни из Оксфорда выиграли в номинации локализация и классификация. Так как объектов на изображениях может быть более одного, то и оценивание происходит по тому, находится ли правильный ответ в топ-5 наиболее вероятных вариантов по версии модели. На изображении ниже вы можете увидеть пример работы одной из моделей на картинках из imagenet. Обратите внимание на забавную ошибку с далматинцем, модель, к сожалению, не нашла там вишню.



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

    Нейросеть VGG обучена и сохранена в формате Caffe. Очень крутая библиотека для глубокого обучения, а главное — легкая в освоении, рекомендую ознакомиться. Прежде чем трепанировать сеть VGG, используя caffe, предлагаю мельком ознакомиться с самой сетью. Если интересны подробности, то рекомендую оригинальную статью — Very Deep Convolutional Networks for Large-Scale Image Recognition (название уже как бы намекает на глубину сети). А тем, кто вообще не знаком со сверточными сетями, необходимо как минимум почитать русскую википедию, прежде чем двигаться дальше, это не займет более 5-10 минут (или же есть небольшое описание на Хабре).

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



    На своей странице они выложили варианты D и E. Мы для эксперимента возьмем 19-слойный вариант E, в котором первые 16 слоев сверточные, а последние три — полносвязные. Последние три слоя чувствительны к размеру изображений, так что для эксперимента, недолго думая, я выкинул их и оставил первые 16 слоев, посчитав, что высокоуровневые признаки я удалил.

    В библиотеке caffe для описание моделей используется гугловский Protocol Buffers, и полное описание сети выглядит следующим образом.

    19-layer model
    name: "VGG_ILSVRC_19_layers"
    input: "data"
    input_dim: 10
    input_dim: 3
    input_dim: 224
    input_dim: 224
    layers {
      bottom: "data"
      top: "conv1_1"
      name: "conv1_1"
      type: CONVOLUTION
      convolution_param {
        num_output: 64
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv1_1"
      top: "conv1_1"
      name: "relu1_1"
      type: RELU
    }
    layers {
      bottom: "conv1_1"
      top: "conv1_2"
      name: "conv1_2"
      type: CONVOLUTION
      convolution_param {
        num_output: 64
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv1_2"
      top: "conv1_2"
      name: "relu1_2"
      type: RELU
    }
    layers {
      bottom: "conv1_2"
      top: "pool1"
      name: "pool1"
      type: POOLING
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layers {
      bottom: "pool1"
      top: "conv2_1"
      name: "conv2_1"
      type: CONVOLUTION
      convolution_param {
        num_output: 128
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv2_1"
      top: "conv2_1"
      name: "relu2_1"
      type: RELU
    }
    layers {
      bottom: "conv2_1"
      top: "conv2_2"
      name: "conv2_2"
      type: CONVOLUTION
      convolution_param {
        num_output: 128
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv2_2"
      top: "conv2_2"
      name: "relu2_2"
      type: RELU
    }
    layers {
      bottom: "conv2_2"
      top: "pool2"
      name: "pool2"
      type: POOLING
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layers {
      bottom: "pool2"
      top: "conv3_1"
      name: "conv3_1"
      type: CONVOLUTION
      convolution_param {
        num_output: 256
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv3_1"
      top: "conv3_1"
      name: "relu3_1"
      type: RELU
    }
    layers {
      bottom: "conv3_1"
      top: "conv3_2"
      name: "conv3_2"
      type: CONVOLUTION
      convolution_param {
        num_output: 256
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv3_2"
      top: "conv3_2"
      name: "relu3_2"
      type: RELU
    }
    layers {
      bottom: "conv3_2"
      top: "conv3_3"
      name: "conv3_3"
      type: CONVOLUTION
      convolution_param {
        num_output: 256
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv3_3"
      top: "conv3_3"
      name: "relu3_3"
      type: RELU
    }
    layers {
      bottom: "conv3_3"
      top: "conv3_4"
      name: "conv3_4"
      type: CONVOLUTION
      convolution_param {
        num_output: 256
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv3_4"
      top: "conv3_4"
      name: "relu3_4"
      type: RELU
    }
    layers {
      bottom: "conv3_4"
      top: "pool3"
      name: "pool3"
      type: POOLING
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layers {
      bottom: "pool3"
      top: "conv4_1"
      name: "conv4_1"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv4_1"
      top: "conv4_1"
      name: "relu4_1"
      type: RELU
    }
    layers {
      bottom: "conv4_1"
      top: "conv4_2"
      name: "conv4_2"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv4_2"
      top: "conv4_2"
      name: "relu4_2"
      type: RELU
    }
    layers {
      bottom: "conv4_2"
      top: "conv4_3"
      name: "conv4_3"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv4_3"
      top: "conv4_3"
      name: "relu4_3"
      type: RELU
    }
    layers {
      bottom: "conv4_3"
      top: "conv4_4"
      name: "conv4_4"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv4_4"
      top: "conv4_4"
      name: "relu4_4"
      type: RELU
    }
    layers {
      bottom: "conv4_4"
      top: "pool4"
      name: "pool4"
      type: POOLING
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layers {
      bottom: "pool4"
      top: "conv5_1"
      name: "conv5_1"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv5_1"
      top: "conv5_1"
      name: "relu5_1"
      type: RELU
    }
    layers {
      bottom: "conv5_1"
      top: "conv5_2"
      name: "conv5_2"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv5_2"
      top: "conv5_2"
      name: "relu5_2"
      type: RELU
    }
    layers {
      bottom: "conv5_2"
      top: "conv5_3"
      name: "conv5_3"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv5_3"
      top: "conv5_3"
      name: "relu5_3"
      type: RELU
    }
    layers {
      bottom: "conv5_3"
      top: "conv5_4"
      name: "conv5_4"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv5_4"
      top: "conv5_4"
      name: "relu5_4"
      type: RELU
    }
    layers {
      bottom: "conv5_4"
      top: "pool5"
      name: "pool5"
      type: POOLING
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layers {
      bottom: "pool5"
      top: "fc6"
      name: "fc6"
      type: INNER_PRODUCT
      inner_product_param {
        num_output: 4096
      }
    }
    layers {
      bottom: "fc6"
      top: "fc6"
      name: "relu6"
      type: RELU
    }
    layers {
      bottom: "fc6"
      top: "fc6"
      name: "drop6"
      type: DROPOUT
      dropout_param {
        dropout_ratio: 0.5
      }
    }
    layers {
      bottom: "fc6"
      top: "fc7"
      name: "fc7"
      type: INNER_PRODUCT
      inner_product_param {
        num_output: 4096
      }
    }
    layers {
      bottom: "fc7"
      top: "fc7"
      name: "relu7"
      type: RELU
    }
    layers {
      bottom: "fc7"
      top: "fc7"
      name: "drop7"
      type: DROPOUT
      dropout_param {
        dropout_ratio: 0.5
      }
    }
    layers {
      bottom: "fc7"
      top: "fc8"
      name: "fc8"
      type: INNER_PRODUCT
      inner_product_param {
        num_output: 1000
      }
    }
    layers {
      bottom: "fc8"
      top: "prob"
      name: "prob"
      type: SOFTMAX
    }
    



    Для того чтобы сделать описанную трепанацию, достаточно в описании модели удалить все слои, начиная от fc6 (full connected слой). Но стоит заметить, что тогда выход сети будет неограничен сверху, т.к. функцией активации является rectified linear unit:



    Такой вопрос удобно решается взятием сигмойда от выхода сети. Мы можем надеяться, что многие нейроны будут либо 0, либо какое-либо большое число. Тогда после взятия сигмоида у нас получится много единиц и 0.5 (сигмоид от 0 равен 0.5). Если нормировать полученные значения в промежуток от 0 до 1, то их можно интерпретировать как вероятности активации нейронов, и почти все из них будут в районе нуля либо единицы. Вероятность активации нейрона трактуется как вероятность наличия признака на изображении (например, есть ли на нем человеческий глаз).



    Вот типичный ответ такой сети в моем случае:

    нормированный сигмоид от последнего сверточного слоя
    0.0
    0.0
    0.0
    0.0
    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.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.994934
    0.0
    0.0
    0.999047
    0.829219
    0.0
    0.0
    0.0
    0.0
    0.0
    0.0
    0.0
    0.0
    0.0
    0.0
    0.0
    0.997255
    0.0
    0.0
    0.0
    0.0
    0.0
    0.0
    0.0
    1.0
    1.0
    0.0
    0.999382
    0.0
    0.0
    0.0
    0.0
    0.988762
    0.0
    0.0
    1.0
    1.0
    0.0
    1.0
    1.0
    0.0
    1.0
    1.0
    1.0
    1.0
    1.0
    0.0
    1.0
    1.0
    0.0
    0.0
    1.0
    1.0
    0.0
    1.0
    1.0
    0.0
    0.0
    0.0
    0.0
    0.0
    0.847886
    0.0
    0.0
    0.0
    0.0
    0.957379
    0.0
    0.0
    0.0
    0.0
    0.0
    1.0
    0.999998
    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
    1.0
    0.999999
    0.0
    0.54814
    0.739735
    0.0
    0.0
    0.0
    0.912179
    0.0
    0.0
    0.78984
    0.0
    0.0
    0.0
    0.0
    0.0
    0.0
    0.0
    0.681776
    0.0
    0.0
    0.991501
    0.0
    0.999999
    0.999152
    0.0
    0.0
    1.0
    0.0
    0.0
    0.0
    0.0
    0.999996
    1.0
    0.0
    1.0
    1.0
    0.0
    0.880588
    0.0
    0.0
    0.0
    0.0
    0.0
    0.0
    0.836756
    0.995515
    0.0
    0.999354
    0.0
    1.0
    1.0
    0.0
    1.0
    1.0
    0.0
    0.999897
    0.0
    0.953126
    0.0
    0.0
    0.999857
    0.0
    0.0
    0.937695
    0.999983
    1.0
    0.0
    0.0
    0.0
    0.0
    0.0
    1.0
    0.0
    0.0
    0.0


    В caffe такой вопрос решается следующим образом:

     layers {
       bottom: "pool5"
       top: "sigmoid1"
       name: "sigmoid1"
       type: SIGMOID
    }
    


    В caffe реализована обертка на питоне, и следующий код инициализирует сеть и делает нормировку:

    caffe.set_mode_gpu()
    net = caffe.Classifier('deploy.prototxt', 'VGG_ILSVRC_19_layers.caffemodel',
                           channel_swap=(2,1,0),
                           raw_scale=255,
                           image_dims=(options.width, options.height))
    
    #..................
    
    out = net.forward_all(**{net.inputs[0]: caffe_in})
    out = out['sigmoid1'].reshape(out['sigmoid1'].shape[0], np.prod(out['sigmoid1'].shape[1:]))
    out = (out - 0.5)/0.5
    


    Итак, на данный момент у нас на руках есть бинарное (ну или почти) представление изображений векторами высокой размерности, в моем случае 4608, осталось обучить Deep Befief Network для сжатия этих представлений. Итоговая модель стала еще более глубокой сетью. Не дожидаясь, пока несколько дней будет обучаться DBN, давайте проведем эксперимент на поиск: будем выбирать случайное изображение и для него искать несколько ближайших, в смысле расстояния Хэмминга. Заметьте, это все на сырых фичах, на векторе высокой размерности, без всякого взвешивания признаков.

    Пояснения: первая картинка — это картинка запрос, случайное изображение из базы; остальные — это ближайшие к ней.



    остальные примеры в спойлере

































    Заключение и ссылки


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



    А если попробовать что-то более близкое к эксперименту, описанному в первой части? Пожалуйста: вот пример статьи, где используется convolutional deep belief networks для извлечения признаков из аудиосигналов. Почему бы не использовать обученные свертки для инициализации весов cDBN? Чем такая вот спектрограма не изображение, и почему бы низкоуровневым признакам не работать на ней:



    Если хотите поэкспериментировать с обработкой естественного языка и попробовать transfer learning, то вот подходящая статья ЛеКуна для старта. И да, там тоже текст представляется в виде изображения.

    В общем, transfer learning — отличная штука, а caffe — крутая библиотека для глубокого обучения.

    Ссылок много в тексте, приведу некоторые из них тут:
    Mail.Ru Group 777,93
    Строим Интернет
    Поделиться публикацией
    Комментарии 38
    • +3
      Эх, эту бы статью да месяц назад. Я бы всех в Каггле порвал про планктон!

      А если серьёзно — спасибо большое, очень интересно.
      • +3
        думаю на планктонах бы это не прокатило, тк там серые изображения; у меня коллега участвовал в том конкурсе, он брал топологию VGG и обучал с нуля все, занял где то 30 (±) место

        а для того что бы использовать трансфер лернинг, он пробовал аугментировать изображения, преобразовывая их различными способами в трехканальные
        • 0
          А где вы, кстати, узнаёте про все эти весёлые челленджи? Интересно было бы поучаствовать.
          • +1
            Так www.kaggle.com/competitions же
        • 0
          А вы тренировали сверточную сеть с нуля, без претренировки? Хотелось бы понять, насколько здесь заметен вклад именно transfer learning. Статья вроде как об этом. По моему опыту иногда проще и лучше тренировать под задачу, чем использовать претренированную модель. Хотя, я слышал у некоторых получалось лучше с претренингом.

          На счет активации — не очень понятно зачем вы накручивали сигмоид на relu, если можно просто убрать relu слой.
          • 0
            А вы тренировали сверточную сеть с нуля, без претренировки?

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

            думаю позже я еще попробую такую штуку — Stacks of Convolutional Restricted Boltzmann Machines for Shift-Invariant Feature Learning, с нее не начал так тут придется код писать, не нашел нормальных реализаций

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

            еще лучше претренировать, а потом делать fine turning -) вот тут, на днях, Эндрю Нг на конфе nvidia GTC рассказал, что они в байду для модели генерации описания изображений использовали трансфер из обученной модели для классификации изображений

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

            моя мотивация следующая, хотя не претендует на абсолютную истину: релу придает спарсность выходу сети, скажем сигмоид от -1 будет равен 0.2689, а в моем случае это будет ноль
            • +1
              Про второй пункт статья в тему с последнего нипса — papers.nips.cc/paper/5347-how-transferable-are-features-in-deep-neural-networks
              Клун в разговоре обещал, что у них будет продолжение, где они будут более внимательно оценивать переносимость фичей на датасеты совсем иной природы.
          • +1
            Осталось дождаться «библиотеки» натренированных под разные задачи шаблоны нейронных сетей и использовать их при разработке своей нейронной сети.

            Вопрос к автору: а может уже существуют эти «библиотеки»? Вы случайно не искали?
            • +2
              я не видел, но думаю не исключено что когда-нибудь будет не только библиотека, то и что то типа Transfer Learning Market, все таки тренировка сети дело не дешевое, VGG пишут что тренировали сеть 3 недели

              а если скажем кто то соберет качественны датасет (что действительно не тривиально), затем месяцок потренит сеть на кластере, то пожно и продавать -)
              • +1
                <минутка_футурологии>Пока бесплатно раздают. Но скоро появится профессия «тренер искуственного интеллекта» и такие пакеты будут для него рабочими инструментами.</минутка футурологии>
                • 0
                  так обратите внимание что VGG раздает как бы бесплатно, но только для не коммерческого использования, совпадение? -)
                • 0
                  все таки тренировка сети дело не дешевое


                  Не согласен. Есть ряд частных случаев, когда обучение нейронной сети можно распараллелить.
                  Распределенные вычисления можно «накрутить» :)
                  • 0
                    да можно параллелить, но зависимость прироста скорости от количества гпу не линейная, вот к примеру слайд и недавнего выступления Нг на GTC conf



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

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

                  По крайней мере если я создам фирму, которая будет производить мозговитые станки у меня в контракте такой пункт будет. :)
                • 0
                  Жесть, нейропластичность для нейронных сетей!
                  В целях самообразования интересуюсь темой нейропластичности и вообще работы мозга (в разрезе использования знания, для понимания как научить ребенка с ЗПР говорить).
                  После прочтения появилась мысль организовать некий девайс с парой кнопок, типа, хочу пить, гулять и т.д.
                  Может это окажется эффективным (хотя и не научит говорить) для изъяснения мыслей.
                  • +1
                    Статья актуальная и интересная!

                    Я так и не понял, а где же transfer learning?
                    Из того что я видел:
                    Self-taught Learning: Transfer Learning from Unlabeled Data
                    Еще во второй части лекции от яндекса, где сетка похожая на рогатину

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

                    Как вы в итоге сравниваете качество работы алгоритма? на глаз?
                    • 0
                      Я так и не понял, а где же transfer learning?

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

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

                      именно сверточную сеть я взял готовую, тк мои данные не размечены, и как я упоминал в коменте выше, в принципе есть вариант unsupervised pretraining'а для сверточной сети, но это будет следующий эксперимент

                      а можем еще и дообучить на нашем датасете(некий такой finetuning).

                      ага, это и делается на извлеченных фичал, но уже используя deep belief network; в этом случае конечно веса сверток не дообучаются, происходит семантик хэшинг, их статьи Хинтона

                      Как вы в итоге сравниваете качество работы алгоритма? на глаз?

                      ага -) это все эксперименты без какой то конкретной задачи, как появится более четкая задача, то и будет более точная мера оценки качества; если до этого дойдет, то вероятно запилю еще один пост
                    • 0
                      Спасибо. Очень интересная статья. Трансфер, правда, грубоват если слоями дёргать, но идея крайне перспективная если даже в таком варианте получается. :)

                      В процессе вы ссылаетесь на вот эту статью про предобучение.
                      habrahabr.ru/post/163819/
                      Там фигурирует предположение, что в процессе обучения происходит затухание примерно так выглядящее:
                      image
                      Однако так грустно и однообразно веса изменяются только если их округлять тысячами. Если посмотреть визуализацию подчёркивающую изменения отдельных весов при слабо меняющихся остальных становится видно, что изменения в сети предельно далеки от постепенно затухающего приближения к оптимуму:
                      habrahabr.ru/post/221049/
                      • +2
                        Там фигурирует предположение

                        вообще это не предположение, а математика

                        наглядно легко увидеть это если решить простую задачку вычисления градиентов для такой вот сети
                        image

                        а формально можно почитать тут например



                        или погуглить saturation vanishing and exploding gradients
                        • 0
                          И если мы знаем, что теоретически должно быть так, а в эксперименте видим, что всё совсем не так, это говорит о чём? О том, что мы где-то неправильно применили математику или смотрим на плохую визуализацию. Или и то и другое одновременно.

                          В случае простой задачки существует прямой градиентный путь от точки начала до точки конца. Если вы сделаете хотя бы по два нейрона в слое уже возникнет ситуация, когда глобальный минимум из выбранного начала простым спуском вообще недостижим, то есть уже не так всё просто. Однако в реальной практике ландшафт эффективности на много более пересечённый. Точка достижимая из начального состояния по не слишком кривой траектории, как правило, является очень убогим минимумом. Реальной сети приходится пробираться по очень пересечённому рельефу, грубо говоря, не первому, а второму:
                          image
                          Картинка, кстати, из очень хорошей статьи по биологии, где рассмотрели ту же проблему: elementy.ru/news/432406

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

                          А невидите вы этого потому что визуализация плохая. Если вам моя визуализация не нравится вы можете сделать по другому. Это же, теоретически, степенная зависимость? Так вот нарисуёте на графике не значение скорости изменения, а степень графика приближающего на локальном участке эту скорости. Понятно, что её изменине даже процентов на 40 будет на исходном степенном графике почти незаметным. Вы обнаружите что она не только сильно скачет, но и скачет не случайно. Тоесть пока сеть идёт по аврагу в бок степень может сильно упасть. Через 20-30 эпох когда она из оврага выйдет степень может скакнуть вверх и долго оставаться большей. ПРичём не у всех синапсов, а только у некоторых.

                          Чрезвычайно интересное зрелище. Поразгладывайте его — не пожалеете.
                          • +1
                            И если мы знаем, что теоретически должно быть так, а в эксперименте видим, что всё совсем не так, это говорит о чём? О том, что мы где-то неправильно применили математику или смотрим на плохую визуализацию. Или и то и другое одновременно.


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

                            Мы возьмём сеть, состоящую из 3 слоёв по 15 нейронов в каждом

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

                            а вот возьмите архитектуру такого вот автоэнкодера как в статье Хинтона

                            DBN
                            image


                            и попробуем подсчитать количество параметров для небольшой картинки 256 на 256, получится 264 819 136 связей, против вашего эксперимента в котором 604 (вроде как) параметра
                            • 0
                              Сдаётся мне, что и на двухстах миллиардах связей закономерности были бы те же, вопрос только в том, что соотношение «сигнал-шум» было бы сильно хуже. В своих экспериментах я видел как значения скорости меняются на три порядка в норме, и до 7-8 порядков в пределе. Я экспериментировал и с большими сетями, но всё же не на столько большими. При числе синапсов на 6 порядков больше такой сигнал действительно может утонуть в шуме.

                              Но тут уж, как говорится. Я наблюдением, которое, как мне кажется, связано, вы на него посмотрели. Встретится оно вам или нет, и есть ли оно всегда или только в малых сетях — кто знает.
                              • +1
                                3 слоя по 15 нейронов это только для статьи было. Так то я занимаюсь сетями в которых слоёв десятки. В сети из третьей статьи если подходить формально, слоёв 28. Но нейронов действительно не много по сравнению с этими монстрами. Явление присутствует.
                              • +1
                                Чем больше размерность — тем «лучше» ландшафт. В одномерном случае градиентный спуск вообще сразу же увязнет, в двумерном тоже всё сложно.
                                Ваша картинка — двухмерная, от неё у вас возникает иллюзия понимания.
                                «Локальные минимумы» в сильно-многомерном ландшафте возникают около глобальных минимумов, причём, чем ближе к глобальному минимуму, тем больше локальных минимумов, и наоборот.
                                Проблемы, конечно, есть, поэтому и придумывают всякие Dropout, RMSProp и улучшают начальную оптимизацию.
                                Вообще, я бы сравнил это со знанием языков: в одном языке одну вещь можно сказать точнее, чем в другом, поэтому сеть застревает на одном понятии, а для выучивания одновременно двух понятий нейронов ей уже не хватает — понятий очень много, а нейронов слишком мало.
                                И именно поэтому сеть, обученная без учителя и одним и тем же количеством нейронов, будет лучше доучиваться, чем сеть, обученная с учителем, которую потом перенесли в другую предметную область.
                                • 0
                                  Хороший комментарий. Приятно комментировать.

                                  Чем больше размерность — тем «лучше» ландшафт.

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

                                  Ваша картинка — двухмерная, от неё у вас возникает иллюзия понимания.

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

                                  «Локальные минимумы» в сильно-многомерном ландшафте возникают около глобальных минимумов
                                  А вот далеко не всегда. У вам может быть в одной части пространства огромная трещётка из локальных минимумов с высотой 0.45, а гораздо более серьёзный минимум дающий в ошибку в 0,2 находится далеко от этого места, и рядом с ним локальных минимумов сильно меньше. Такая картинка у меня в третей птице, например. Такое очень часто возникает когда какой-то один нейрон из первого слоя обучается какому-нибудь хорошему полезному преобразованию координат. Вокруг такого состояния сети отдельных пиков мало, потому что его преобразование легко сломать, а искания соседей влияют на результат несопоставимо слабее чем он. Напротив ситуация, когда локальных минимумов много и они близко к глобальному — типична для неглубоких сетей, для которых роль одиночного нейрона не может быть велика.

                                  Алгоритмы Dropout, RMSProp гляну, сходу не прокомментирую, но я боле чем уверен, то что начальная оптимизация решает дело даже не на четверть. Например посмотрите на вот такое видео обучения: www.youtube.com/watch?v=09wHERJnnEA, вы увидите, что изучать строение второго крыла (ближе к концу видео) сеть начала только после того, как освоила форму первого. Чтобы конечное состояние сети из этого примера стало доступно по схеме «предобучение плюс тонкая подстройка» нужно было бы, чтобы предобучение успешно научило сеть рисовать тушку и первое крыло. Сдаётся мне, что алгоритмы предобучения такого не умеют.

                                  Обучение без учителя я, впрочем, пока, ещё только начал изучать, так что возможно вы в чём-то абсолютно правы.
                                  • 0
                                    Такая картинка у меня в третей птице, например
                                    Извините, ещё раз напомню: у вас, кажется, 50 нейронов в птице. Это ближе к одномерному и двумерному случаю, чем к 500-мерному пространству.
                                    Представьте, что у вас всего 50 понятий(нейронов), и вам нужно ими описать любую точку на птице. Много вы сможете описать? Безусловно, в такой ситуации всё зависит от особенностей функции ошибок и её гладкости.
                                    Но дело в том, что если у вас 50 нейронов, проще решить задачу аналитически, чем напрягать компьютер.
                                    А вот 10 миллионов нейронов и 1 миллиард связей — более типично для существующих практически полезных систем, нежели ваши 50 нейронов.

                                    Чем многомернее ландшафт тем больше шансов что путь существует.
                                    Можно считать, что пути до цели нет никогда — просто данные не идеальны и противоречивы в мелочах (обращать ли внимание на желто-коричневый цвет льва — и тогда лев похож на пчелу — или на зубы — и тогда не похож?).
                                    Но в многомерном случае вы приблизитесь к цели гораздо ближе, прежде чем эта противоречивость отдельных примеров начнёт существено влиять.

                                    Обучение без учителя я, впрочем, пока, ещё только начал изучать, так что возможно вы в чём-то абсолютно правы.
                                    Я вам ещё рекомендую ознакомиться с методом переноса знаний от одной (большей) сети к другой (меньшей) — мне кажется, данный способ даст больше результатов, чем обучение непосредственно маленькой сети.
                                    Во всяком случае, применение этого метода для работы с изображениями даёт всего небольшое (несколько процентов) ухудшение качества при переносе в десятки и сотни раз меньшую сеть, на десятки процентов превышая результаты обучения маленькой сети «с нуля».
                                    Я думаю, это одновременно соответствует передаче символьного «дистиллированного знания» между людьми, и процессу стирания запомненных деталей в мозгу во время сна (стирается до 99% полученной информации — можно считать это своеобразным «сжатием»).
                                    Ключевая работа в данной области — Dark Knowledge by Geoff Hinton, www.ttic.edu/dl/dark14.pdf
                                    • 0
                                      Но в многомерном случае вы приблизитесь к цели гораздо ближе, прежде чем эта противоречивость отдельных примеров начнёт существено влиять.


                                      Кстати теорема Ковера, 1965 год:

                                      A complex pattern-classification problem, cast in a high-dimensional space nonlinearly, is more likely to be linearly separable than in a low-dimensional space, provided that the space is not densely populated.

                                      У Хайкина в книге приведено доказательство, а так же формула, на сколько вероятнее будет линейная разделимость в пространстве высокой размерности n, по сравнению с пространством размерности m, где n > m.
                                      • 0
                                        Строго говоря у меня пространство чуть больше чем 460-мерное, по количеству синапсов. А 50 нейронов это не пятьдесят понятий. При применении эффективных алгоритмов — больше. Но в остальном вы, конечно, правы.

                                        С нетерпением жду когда появится время обучить что-нибудь большое на каких нибудь типовых общеизвестных данных. А то мне часто поминают, что я работаю с малюсенькими сетями, а мне и возразить то толком нечего. К сожалению, не раньше чем через пару месяцев.
                                    • 0
                                      Вспомнил, что такое Дропаут. Ну да, в частности.
                                  • 0
                                    Не успел до конца отредактировать.

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

                                    Но собственно вопрос в том, получилось ли обученную VGG использовать для улучшения результатов в другой задаче?
                                    Или может при её подключении результаты неожиданно ухудшились.
                                    Например это может произойти из-за того, что датасет ImageNet существенно не похож на датасет новой задачи. А VGG натренировала внутри себя какие-нибудь шумящие признаки, которые будут мешать, а не помогать новой нейронной сети.
                                    • 0
                                      пока рано сравнивать тк нет реальной задачи, это все делается в рамках исследования; пробовали вставлять такие признаки, вместе с другими имеющимися, в классификатор, результат уже не хуже

                                      Но собственно вопрос в том, получилось ли обученную VGG использовать для улучшения результатов в другой задаче?

                                      в реальную задачу я попробую вставить не те признаки что вернула VGG, а результат сжимания этого вектора многотысячной размерности в вектор размерности 50-100 с помощью DBN

                                      например на нашем датасете есть фичи которые на всех картинках нули, т.е. это значит, что в том датасете присутствовал какой то объект, которого в нашем нет, как раз все это ДБН должна и почистить
                                      • 0
                                        > например на нашем датасете есть фичи которые на всех картинках нули, т.е. это значит, что в том датасете присутствовал какой то объект, которого в нашем нет, как раз все это ДБН должна и почистить

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

                                        Например, если у нас 1000 объектов, то было бы неплохо разбить датасет по объектам 500 + 500 и посмотреть, как обученная VGG на первых 500 объектах (после сжатия до размерности 50-100 с помощью DBN) помогает улучшать классификацию других 500 объектов (считаем это новым датасетом). Будут ли там фичи, которые выдержат чистку и будут ли эти фичи вредить или улучшать.

                                        • 0
                                          ну так для этого и проводится приведенный эксперимент с поиском, я беру готовую VGG, которая никогда не видела мой датасет и вычисляю признаки, бинаризирую для простоты по порогу 0.95, и затем выбираю рандомную картинку, и ищу для нее близжайших соседей, в смысле расстояния Хэмминга

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

                                          тут уже не будет никаких оценок на глаз, а четкая функция стоимости
                                    • 0
                                      Caffe комманда прикольные, интересно, а что если брать не DAG архитектуру, а, наоборот, петель обратно на уровень выше навешать.
                                      • 0
                                        а ну так вы не обучите, все равно рекуррентную структуру придется развернуть в глубокую сеть прямого распространения
                                      • 0
                                        Оказывается это еще domain adaptation называется.
                                        sites.skoltech.ru/compvision/projects/grl

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

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