Алгоритмы неформально. Инструкция для начинающих питонистов - [19]
Рис. 3.2. Чтобы вычислить производную, нужно провести касательную к кривой в точке и определить ее угол наклона
Мы можем написать на Python функцию, которая задает производную следующим образом:
def revenue_derivative(tax):
return(100 * (1/(tax + 1) - 2 * (tax - 0.2)))
Для вычисления этой функции были использованы четыре правила. Во-первых, мы использовали правило о том, что производная log(x) равна 1 / x. Отсюда следует, что производная log(tax + 1) равна 1 / (tax + 1). Во-вторых, производная x2 равна 2x, поэтому производная (tax – 0,2)2 равна 2(tax – 0,2). Два последних правила — производная постоянного числа всегда равна 0, а производная 100f(x) равна 100 × производная f(x). Объединяя все эти правила, мы находим, что функция 100(log(tax + 1) – (tax – 0,2)2 + 0,04) имеет следующую производную, которая соответствует приведенной выше функции Python:
.Простая проверка показывает, что при текущей ставке налога производная действительно отрицательна:
print(revenue_derivative(0.7))
Команда выводит результат -41.17647.
Отрицательная производная означает, что увеличение ставки налога приведет к снижению поступлений. И наоборот, снижение ставки должно привести к их повышению. Хотя точное значение ставки, обеспечивающее максимум кривой, нам пока не известно, по крайней мере, можно утверждать, что при небольшом смещении в сторону уменьшения ставки налога поступления должны возрасти.
Чтобы сделать шаг в направлении максимальных поступлений, необходимо сначала выбрать его размер. Мы сохраним достаточно малый размер шага в переменной Python:
step_size = 0.001
Затем продвинемся в направлении максимума и вычислим новую ставку, находящуюся в одном шаге от текущей в направлении максимума:
current_rate = current_rate + step_size * revenue_derivative(current_rate)
На данный момент процесс поиска максимума выглядит так: мы начинаем с текущей ставки налога и продвигаемся к максимуму на величину, пропорциональную выбранному значению step_size, в направлении, определяемом производной функции «ставка налога-поступления» при текущем значении ставки.
Можно убедиться в том, что после этого шага новое значение current_rate составит 0.6588235 (ставка налога около 66 %), а поступления, соответствующие этой ставке, равны 33.55896. Но хотя мы сделали шаг в направлении максимума и увеличили поступления, по сути, оказываемся в той же ситуации, что и прежде: максимум еще не достигнут, но мы знаем производную функции и общее направление для дальнейшего перемещения. Таким образом, мы просто делаем еще один шаг — точно так же, как и прежде, но со значениями, соответствующими новой ставке. Снова выполняется присваивание:
current_rate = current_rate + step_size * revenue_derivative(current_rate)
После повторного присваивания новое значение current_rate равно 0.6273425, а поступления, соответствующие новой ставке, составят 34.43267. Мы сделали еще один шаг в правильном направлении. Тем не менее максимум еще не достигнут, и чтобы приблизиться к нему, нужно сделать еще один шаг.
Преобразование шагов в алгоритм
Нетрудно разглядеть постепенно проявляющуюся закономерность. Мы многократно выполняем действия, которые указаны ниже.
1. Начать с текущей ставки current_rate и размера шага step_size.
2. Вычислить производную максимизируемой функции в точке current_rate.
3. Прибавить к текущей ставке величину step_size*revenue_derivative(current_rate) для получения нового значения current_rate.
4. Повторять шаги 2 и 3.
В этой схеме не хватает только одного: правила остановки, то есть правила, срабатывающего при достижении максимума. На практике весьма вероятно, что мы будем приближаться к максимуму асимптотически, то есть подходить к нему все ближе и ближе, но всегда оставаясь на микроскопическом расстоянии от него. Итак, мы, возможно, никогда не достигнем максимума, но можем подойти достаточно близко к нему с точностью до 3-го, 4-го и даже 20-го знака в дробной части. Мы узнаем, что подошли достаточно близко к асимптоте, если размер приращения очень мал. Соответствующее значение можно задать в программе Python:
threshold = 0.0001
Процесс должен остановиться, когда ставка изменяется на величину, которая меньше порога threshold при каждой итерации процесса. Возможно и то, что процесс пошагового приближения вообще не сойдется к искомому максимуму, поэтому простой цикл может выполняться бесконечно. Чтобы подготовиться к этой возможности, мы зададим максимальное количество итераций, и если количество выполненных приближений достигнет этой величины, то программа просто отказывается от дальнейших попыток и останавливается.
Теперь все фрагменты можно собрать воедино (листинг 3.1).
Листинг 3.1. Реализация градиентного подъема
threshold = 0.0001
maximum_iterations = 100000
keep_going = True
iterations = 0
while(keep_going):
rate_change = step_size * revenue_derivative(current_rate)
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.