Оптимизация
Давеча переписал имплементацию энималов. Ранее использовался IronPython с отрисовкой WPF. Аргументировал я это тем, что, во-первых, IronPython хорошо умеет работать с многопоточностью и он лишен тех недостатков, которыми обладает CPython со своим GIL. А во-вторых, тем что небольшие бенчмарки показывали существенное преимущество IronPython. В-третьих, удобство разработки UI.Однако, перенеся проект с IronPython на Python версии 3.5, с использованием Qt для UI и OpenGL для прорисовки сцены, однопоточное выполнение этого кода имело такую же производительность как многопоточный код на IronPython! И когда я воспользовался возможностью подключать сторонние библиотеки в проект, и оптимизировал критические части программы с использованием библиотек numpy и scipy, то производительность увеличилась в пять раз. А при помощи уловки, при которой прорисовка сцены происходит каждые 200 циклов мира, в тот момент, когда мы не следим за происходящим, производительность улучшается еще в два раза, в итоге давая десятикратное ускорение. Стоит учесть что вычисления происходят на одном ядре процессора, что позволяет лично мне запускать три экземпляра программы одновременно, т.к. имею три ядра.
![]() |
| интерфейс программы |
Изменения
Главным изменением стал отказ от гендерного различия. Теперь потомство могут создавать любые две особи, у которых достаточно для этого энергии. Количество сенсоров уменьшилось с 7 до 3, т.к. этого вполне достаточно, чтобы определить направление расположения пищи по ее запаху. И результирующая топология нейронной сети являет собой: 3 сенсора во входном слое, 2 в скрытом и 2 в итоговом.Рисуется агент синеватым цветом, а центре каждого агента рисуется круг, одним из оттенков серого, в зависимости от текущей наполненности энергией. Чем больший запас энергии в данный момент содержит агент - тем светлее будет этот круг.
Весь процесс эволюции можно посмотреть тут:
Код доступен на github.com в ветке only-food: https://github.com/zshimanchik/animals/tree/only-food
Цветная еда
Чтобы усложнить им жизнь, пища теперь появляется со случайным значением color в отрезке [0; 1]. Отображается на сцене она зелёным цветом (r=0, g=255, b=255), если color=0, и плавно перетекает в синий (r=0, g=0, b=255), когда color=1. Когда color=0.5, то пища рисуется цветом морской волны (r=0, g=255, b=255).И запах пищи теперь характеризуется двумя атрибутами: двумерным вектором запаха и силой. Сила запаха прямо пропорционально зависит от размера куска еды:
smell_size = size * 21.0
А вектор запаха (g, b) строится в зависимости от атрибута color:g = min(1.0, (1.0 - color) * 2) b = min(1.0, color * 2)
Так как теперь есть два типа запахов, то каждый сенсор воспринимает в два раза больше величин, а значит у входного слоя нейронной сети теперь 6 нейронов.
В то же время теперь энималы тоже имеют цвет, значение его также в отрезке [0; 1]. Его значение определяет нейронная сеть, а значит у неё уже 3 нейрона в выходном слое: 1- поворот по или против часовой стрелки; 2- движение вперед или назад; 3-цвет. И так как у нас появилось больше информации для обработки, то в скрытом слое также увеличилось количество нейронов с 2 до 3.
Фокус этих цветов в том, что теперь пища быстрее поглощается теми агентами, у которых цвет ближе к цвету пищи. То есть, если раньше каждый энимал за один цикл программы съедал количество пищи равное константе:
EATING_VALUE
то сейчас он съедает
EATING_VALUE * (1.0 - abs(animal.color - food.color))
Это становится стимулом для того, чтобы нейронная сеть вычисляла цвет близкий к цвету пищи, запах которой сенсоры сейчас воспринимают.
Результат эволюции можно посмотреть тут:
Код доступен на github.com в ветке colored-food: https://github.com/zshimanchik/animals/tree/colored-food

No comments:
Post a Comment