Позвольте мне сказать несколько слов предостережения, предваряя рассказ. Давным-давно я работал с парнем, когда только начинал. У него была проблема с оптимизацией, с довольно грязной целью. Его решением было генерировать аналитические производные для оптимизации.
Проблема, которую я увидел, заключалась в том, что эти производные были неприятными. Созданные с использованием Macsyma, преобразованные в код на языке Fortran, каждый из них представлял собой десятки операторов продолжения. Фактически, компилятор Фортрана расстроился из-за того, что он превысил максимальное количество операторов продолжения. Хотя мы нашли флаг, который позволил нам обойти эту проблему, были и другие проблемы.
В длинных выражениях, которые обычно генерируются системами CA, существует риск массивного вычитания. Вычислите много больших чисел, только чтобы найти, что все они взаимно компенсируют друг друга, чтобы получить небольшое число.
Часто аналитически сгенерированные производные на самом деле более дороги для оценки, чем численно сгенерированные производные с использованием конечных разностей. Градиент для n переменных может занять более чем в n раз дороже оценки вашей целевой функции. (Вы можете сэкономить некоторое время, потому что многие термины могут быть повторно использованы в различных производных, но это также заставит вас делать осторожное ручное кодирование вместо использования сгенерированных компьютером выражений. И каждый раз, когда вы кодируете неприятные математические В выражениях вероятность ошибки не тривиальна. Убедитесь, что вы проверяете эти производные на точность.)
Суть моей истории в том, что эти сгенерированные CA выражения имеют свои собственные проблемы. Самое смешное, что мой коллега на самом деле гордился сложностью проблемы, потому что он явно решал действительно сложную задачу, потому что алгебра была настолько противной. Я не думаю, что он думал о том, что эта алгебра действительно вычисляет правильную вещь, делает ли она это точно, и делает ли она это эффективно.
Если бы я был старшим человеком в то время в этом проекте, я бы прочитал его акт бунта. Его гордость заставила его использовать решение, которое, вероятно, было излишне сложным, даже не проверяя, что градиент на основе конечных разностей был адекватным. Могу поспорить, что мы потратили, возможно, человеческую неделю, чтобы запустить эту оптимизацию. По крайней мере, я бы посоветовал ему тщательно проверить полученный градиент. Было ли это точно? Насколько это было точно по сравнению с производными с конечной разностью? Фактически, сегодня существуют инструменты, которые также будут возвращать оценку ошибки в их производном прогнозе. Это, безусловно, верно для адаптивного дифференцирующего кода (производного), который я написал в MATLAB.
Протестируйте код. Проверьте производные.
Но прежде чем делать ЛЮБОЕ из этого, подумайте, есть ли другие, более эффективные схемы оптимизации. Например, если вы делаете экспоненциальную подгонку, то есть очень хороший шанс, что вы можете использовать разделенные нелинейные наименьшие квадраты (иногда называемые сепарабельными наименьшими квадратами. Я думаю, что именно этот термин использовали Себер и Уайлд в своей книге.) Идея состоит в том, чтобы разбить набор параметров на внутренне линейные и внутренне нелинейные множества. Используйте оптимизацию, которая работает только с нелинейными параметрами. Если эти параметры «известны», то линейно линейные параметры могут быть оценены с использованием простых линейных наименьших квадратов. Эта схема уменьшит пространство параметров при оптимизации. Это делает проблему более устойчивой, поскольку вам не нужно находить начальные значения для линейных параметров. Это уменьшает размерность вашего пространства поиска, поэтому проблема запускается быстрее. Я снова поставилинструмент для этой цели , но только в MATLAB.
Если вы используете аналитические производные, используйте их для повторного использования терминов. Это может быть серьезной экономией времени и может фактически уменьшить количество ошибок, экономя ваше собственное время. Но тогда проверь эти цифры!
codegen
пакет в нем, поскольку он может автоматически генерировать компактный и эффективный код на C или Fortran для каждого или всех выражений.