Обсуждение статьи "Глубокие нейросети (Часть VI). Ансамбль нейросетевых классификаторов: bagging"

 

Опубликована статья Глубокие нейросети (Часть VI). Ансамбль нейросетевых классификаторов: bagging:

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

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

Просуммируем все изложенное выше. Схематически весь процесс создания и тестирования ансамбля нейросетей можно условно разделить на 4 этапа:


Рис.3 Структурная схема обучения и тестирования ансамбля нейросетей с объединителем averaging/voting

Автор: Vladimir Perervenko

 

Спасибо, интересно, elmNN похоже достойная замена nnet, особенно в ансамбле. Заодно познакомился с rBayesianOptimization, попробую применить в будущем.

 

Интересная статья!
Неожиданным было обучение сразу 500 сетей. Не думал, что это можно делать так быстро. С DNN это будут часы...

1) Вместо дополнительного генератора случ. чисел setRNG(rng[[k]]) можно было использовать встроенный holdout(Ytrain, ratio = r/10, mode = "random", seed = i ) # где  i - номер итерации цикла.
Так мы тоже получим на каждой итерации новый перемешанный набор вх. данных, и повторяемый при перезапусках.

2) А вообще holdout - замечательная функция, очень хорошо перемешивает данные, гораздо лучше самописной в МТ5 с заменой каждой строки на случайную другую строку.
Именно при смене seed можно наткнуться на очень хороший результат обучения. Пробовал вручную менять с darch - получал ошибку от 50% до 30% и кол-во сделок от единиц до сотен - и это всего лишь после смены ключа для перемешивания. Автоматически проверять в цикле пожалуй понадежнее будет.

3) elmNN - напоминает обычную НС с одной эпохой обучения. Беря 500 штук (из которых выбираем лучшую) получим аналог 1 НС с 500 эпохами обучения ( из которых тоже выбираем по лучшей эпохе). Впрочем это всего лишь ассоциация, а не утверждение.

Хотя усреднение из нескольких лучших сетей думаю лучше чем 1 лучший результат после 500 эпох. Хотелось бы сделать ансамбль с DNN, но боюсь это будет очень долго обучаться. Буду экспериментировать)
Спасибо за статью!

 
elibrarius:

Интересная статья!
Неожиданным было обучение сразу 500 сетей. Не думал, что это можно делать так быстро. С DNN это будут часы...

1) Вместо дополнительного генератора случ. чисел setRNG(rng[[k]]) можно было использовать встроенный holdout(Ytrain, ratio = r/10, mode = "random", seed = i ) # где  i - номер итерации цикла.
Так мы тоже получим на каждой итерации новый перемешанный набор вх. данных, и повторяемый при перезапусках.

2) А вообще holdout - замечательная функция, очень хорошо перемешивает данные, гораздо лучше самописной в МТ5 с заменой каждой строки на случайную другую строку.
Именно при смене seed можно наткнуться на очень хороший результат обучения. Пробовал вручную менять с darch - получал ошибку от 50% до 30% и кол-во сделок от единиц до сотен - и это всего лишь после смены ключа для перемешивания. Автоматически проверять в цикле пожалуй понадежнее будет.

3) elmNN - напоминает обычную НС с одной эпохой обучения. Беря 500 штук (из которых выбираем лучшую) получим аналог 1 НС с 500 эпохами обучения ( из которых тоже выбираем по лучшей эпохе). Впрочем это всего лишь ассоциация, а не утверждение.

Хотя усреднение из нескольких лучших сетей думаю лучше чем 1 лучший результат после 500 эпох. Хотелось бы сделать ансамбль с DNN, но боюсь это будет очень долго обучаться. Буду экспериментировать)
Спасибо за статью!

1. Нельзя. Основная задача RNG обеспечить инициализацию весов нейросетей в ансамбле постоянными случайными величинами. Для оптимизации гиперпараметров необходим постоянный по качеству ансамбль.

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

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

Удачи

 
Vladimir Perervenko:

1. Нельзя. Основная задача RNG обеспечить инициализацию весов нейросетей в ансамбле постоянными случайными величинами. Для оптимизации гиперпараметров необходим постоянный по качеству ансамбль.

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

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

Удачи

1) Понял. Кроме инициализации перемешивания делаете еще и инициализацию весов сети.
А просто set.seed(i); не даст тот же эффект?

 
elibrarius:

1) Понял. Кроме инициализации перемешивания делаете еще и инициализацию весов сети.
А просто set.seed(i); не даст тот же эффект?

Нет не даст. Он установит ГСЧ в состояние один раз, а у нас 500 итераций foreach и на каждой нам нужно свое различное состояние ГСЧ. Посмотрите описание пакета doRNG.

Удачи

 
Vladimir Perervenko:

Нет не даст. Он установит ГСЧ в состояние один раз, а у нас 500 итераций foreach и на каждой нам нужно свое различное состояние ГСЧ. Посмотрите описание пакета doRNG.

Удачи

Это внутри цикла будет

  Ens <- foreach(i = 1:n, .packages = "elmNN") %do% {
    set.seed(i);
    idx <- rminer::holdout(Ytrain, ratio = r/10, mode = "random")$tr
    elmtrain(x = Xtrain[idx, ], y = Ytrain[idx], 
             nhid = nh, actfun = "sin")
  }
т.е. будет  set.seed(1); потом  set.seed(2);  set.seed(3); .....  set.seed(500);
 
elibrarius:

Это внутри цикла будет

Попробуйте. Может и получится.

 
Vladimir Perervenko:

Попробуйте. Может и получится.

Должно.

И думаю можно не выключать многопоточность при таком варианте.

 
elibrarius:

Должно.

И думаю можно не выключать многопоточность при таком варианте.

Просто проверьте практически. Если получите тот же результат или лучше, значит можно и так. Язык R позволяет одно и то же действие выполнять разными способами.

Удачи

 
Vladimir Perervenko:

Просто проверьте практически. Если получите тот же результат или лучше, значит можно и так. Язык R позволяет одно и то же действие выполнять разными способами.

Удачи

Версия

  Ens <- foreach(i = 1:n, .packages = "elmNN") %do% {
    set.seed(i);
    idx <- rminer::holdout(Ytrain, ratio = r/10, mode = "random")$tr
    elmtrain(x = Xtrain[idx, ], y = Ytrain[idx], 
             nhid = nh, actfun = "sin")
  }

работает. При каждом запуске выдает одинаковые веса сети. Сравнивал по второй сети. Выводил env$Ens[2], а потом плагином в notepad++ сравнивал.

С многопоточностью не получилось:

Ошибка в setMKLthreads(2) :не могу найти функцию "setMKLthreads"

Что за функция такая? В коде 4 и 6 статей ее нет. Как ее подключить?

ПС: Удобнее было если бы Вы сессию R со всеми функциями и исходными данными выложили.