Глубокое обучение Понимание процесса инициализации Caffe (установление потока данных)

глубокое обучение

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

Создание потока данных #Caffe FeatureMap ##Глоссарий

  • FeatureMap: информация о входном изображении или информация об изображении после многослойной обработки.
  • веса: весовые коэффициенты, которые существуют только для сверточных слоев.
  • caffe: Кофе, упомянутый в тексте, относится к caffed1.0, если вы используете caffe2.0, это будет специально указано.

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

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

Из вышеприведенного объяснения иерархических отношений нетрудно увидеть, что FeatureMap не принадлежит ни одному слою во всей структуре Caffe, поэтому она принадлежит самому верхнему сетевому слою. Слой сети должен иметь возможность вывести входные данные, от которых зависит каждый уровень, через файл модели caffe, чтобы можно было построить полную цепочку данных. В соответствии с этим требованием Caffe вводит два определения:

  • внизу: входные данные слоя.
  • вверху: выходные данные слоя. Конкретная форма выглядит следующим образом (ситуации с одним и несколькими входами):

stream_format.jpg

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

proto_example.jpg

Вышеупомянутая работа выполняется в Net Init (void Net::Init(const NetParameter& in_param)), основная реализация состоит в том, чтобы получить тип создаваемого слоя в соответствии с файлом модели в левой части рисунка выше и связать данные между слоями. Основные параметры функции следующие:

название Функции
in_param Сохраните файл модели, преобразованный protobuf
bottom_vecs_ Тип входных данных, хранящихся в каждом слое, следующий: vector >
top_vecs_ Тип выходных данных, хранящийся в каждом слое, следующий: vector >
available_blobs Тип выходных данных, хранящийся в каждом слое, следующий: vector >

##Традиционный процесс установления канала передачи данных (сценарий с одним входом и одним выходом):

  1. Свяжите нижние данные этого слоя (int Net::AppendBottom(const NetParameter& param, const int layer_id, const int bottom_id, set<string>* available_blobs, map<string, int>* blob_name_to_idx)), функция будет использовать имя слоя соответствующего дна из информации о дне, содержащейся в текущем слое, а затем использовать это имя для поиска соответствующего блоба и добавления его в bottom_vecs_.

  2. Свяжите верхние данные этого слоя (void Net::AppendTop(const NetParameter& param, const int layer_id,const int top_id, set<string>* available_blobs, map<string, int>* blob_name_to_idx)), эта операция состоит в том, чтобы добавить выходные данные этого слоя в top_vecs_ и объединить их с Layer_id связан, и он также отвечает за применение объекта Blob. Следует отметить, что в верхней части создается новый объект Blob, а в нижней добавляется только указатель верхней части верхнего слоя, при этом в этом процессе CAFFE также использует available_blobs для выполнения проверки исключений. . При добавлении верхнего уровня запишите соответствующее имя BLOB-объекта. После связывания верхнего слоя с нижним удалите соответствующее имя BLOB-объекта в available_blobs. Соответствующий псевдокод выглядит следующим образом:

     for (int layer_id = 0; layer_id < param.layer_size(); ++layer_id) {
     	AppendBottom();
     	AppendTop();
     }
    

##Установление мультивходной цепочки данных: Внимательные студенты должны были обнаружить, что когда данные вводятся с несколькими основаниями, поскольку данные available_blobs были удалены последним процессом связывания, когда одно и то же основание снова связывается, будет выдан ненормальный сигнал тревоги.В этом случае нам нужно Внедрить еще одну функцию обработки CAFFEvoid InsertSplits(const NetParameter& param, NetParameter* param_split), основная функция этой функции — разделить верхний вывод на несколько слоев. Вся функция делится на две части:

  1. Пройдитесь по всей сети, запишите максимальное использование каждого слоя и поместите структуру записи вtop_idx_to_bottom_countсередина.

  2. пройти через всю сеть, даtop_idx_to_bottom_count > 1случай, который необходимо обработать: А. Первый состоит в том, чтобы разделить верхний слой, используемый несколькими слоями. Основной метод заключается в создании нового слоя за слоем. Новый слой будетtop_idx_to_bottom_countКоличество и согласованное имя разделения (SplitBlobName) для создания новой вершины, а код для добавления слоя выглядит следующим образом (здесь показан только процесс создания ядра, пожалуйста, отслеживайте конкретный процесс вызова самостоятельно):

     //该函数执行新层的添加
     void ConfigureSplitLayer(const string& layer_name, const string& blob_name,
         const int blob_idx, const int split_count, const float loss_weight,
         LayerParameter* split_layer_param) {
       split_layer_param->Clear();
       split_layer_param->add_bottom(blob_name);
       split_layer_param->set_name(SplitLayerName(layer_name, blob_name, blob_idx));
       split_layer_param->set_type("Split");
       for (int k = 0; k < split_count; ++k) {//split_count就是该top被引用的个数
     	//添加了分割后的top
     	//命名由SplitBlobName生成		    
     	split_layer_param->add_top(
             SplitBlobName(layer_name, blob_name, blob_idx, k));
         if (loss_weight) {
           if (k == 0) {
             split_layer_param->add_loss_weight(loss_weight);
           } else {
             split_layer_param->add_loss_weight(0);
           }
         }
       }
     }
    

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

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

![Upload new_split_layer.jpg failed. Please try again.]

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

## Оставшаяся проблема Выше приведено установление связи данных FeatureMap на этапе инициализации, но заполнение весов и ввод исходной картинки не анализировались.