Подтвердить что ты не робот

Параллельная многомерная оптимизация

Я создаю script, который генерирует входные данные [параметры] для вычисления другой программы. Я хотел бы оптимизировать полученные данные. Раньше я использовал оптимизацию Powies numpy. Код psuedo выглядит примерно так.

def value(param):
     run_program(param)
     #Parse output
     return value

scipy.optimize.fmin_powell(value,param) 

Это отлично работает; однако это невероятно медленно, так как каждая итерация программы может занять несколько дней. То, что я хотел бы сделать, это грубое зерно, распараллеливающее это. Поэтому вместо запуска одной итерации за один раз она будет работать (количество параметров) * 2 за раз. Например:

Initial guess: param=[1,2,3,4,5]

#Modify guess by plus minus another matrix that is changeable at each iteration
jump=[1,1,1,1,1]
#Modify each variable plus/minus jump.
for num,a in enumerate(param):
    new_param1=param[:]
    new_param1[num]=new_param1[num]+jump[num]
    run_program(new_param1)
    new_param2=param[:]
    new_param2[num]=new_param2[num]-jump[num]
    run_program(new_param2)

#Wait until all programs are complete -> Parse Output
Output=[[value,param],...]
#Create new guess
#Repeat

Число переменных может варьироваться от 3-12, поэтому что-то вроде этого может потенциально ускорить выполнение кода от года до недели. Все переменные зависят друг от друга, и я только ищу локальные минимумы из первоначального предположения. Я начал реализацию с использованием гессианных матриц; однако это довольно активно. Есть ли что-то, что делает это, есть ли более простой способ или какие-либо предложения для начала?

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

Спасибо за ваше время.

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

Текущая лучшая реализация - это параллелизация внутреннего цикла метода powell.

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

4b9b3361

Ответ 1

У меня была такая же проблема, пока я был в университете, у нас был алгоритм fortran для вычисления эффективности движка, основанного на группе переменных. В то время, когда мы используем modeFRONTIER, и если я правильно помню, ни один из алгоритмов не мог генерировать несколько догадок.

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

Примечание: если у вас нет кластера и требуется больше вычислительной мощности, то HTCondor может вам помочь.

Ответ 2

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

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

Ответ 3

Существует два способа оценки градиентов, один из которых легко распараллеливается, а не:

  • вокруг одной точки, например. (f (x + h direction i) - f (x))/h; это легко распараллеливается до Ndim
  • "ходячий" градиент: перейти от x 0 в направлении e 0 к x 1, затем от x 1 в направлении e 1 до x 2...; это последовательное.

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

Я предлагаю scipy fmin_tnc с оценкой параллельного градиента, возможно, используя центральные, а не односторонние различия.
(FWIW, this сравнивает некоторые из scipy оптимизаторов без производных на двух 10-D-функциях; YMMV.)

Ответ 4

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

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

Ответ 5

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

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

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

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

задана функция

energy(*args) -> value

вы создаете предположение и функцию:

guess = [1,1,1,1]
funcs = [ lambda x,i=i: energy( guess[:i]+[x]+guess[i+1:] ) for i in range(len(guess)) ]

чем вы помещаете их в цикл while для оптимизации

while convergence_condition:
    for func in funcs:
        optimize fot func
        update the guess
    check for convergence

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

Ответ 6

Вы можете выполнить параллель в двух частях: 1) параллельный расчет одиночной итерации или 2) параллельный запуск N начального угадывания.

В 2) вам нужен контроллер заданий для управления N начальными потоками обнаружения.

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

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

Ответ 7

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

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

Некоторые алгоритмы могут также использовать больше parallelism по скромной алгоритмической стоимости. Например, квази-ньютоновские методы пытаются построить приближение матрицы Гессиана, часто обновляя это, оценивая градиент. Затем они делают шаг к минимуму и оценивают новый градиент, чтобы обновить гессиан. Если у вас достаточно процессоров, так что оценка Hessian так же быстро, как и оценка функции один раз, вы, вероятно, можете улучшить их, оценив гессиан на каждом шагу.

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