Генетический алгоритм для нахождения минимума из трех переменных функции


Я реализовал простой генетический алгоритм для непрерывного параметра с плавающей точкой пространства и без рекомбинации. Однако, способ, которым я передаю в параметры и приобретя результаты мультипроцессирование неправильно. Я должен быть с использованием concurrent.futures?

Код ниже использует генетический алгоритм для нахождения минимального уравнения x^2+y^2+z/10 за параметр пространства -2 < x < 0, 0 < y < 2 и 10 < z < 11но я бы хотел, чтобы держать код легко модифицировать для различных параметров пространства и функций оценки.

import numpy as np

import multiprocessing
from collections import OrderedDict
import os
import time


def eval_iter(arg_lst, l_lst):
    for c_i, args in enumerate(arg_lst):
        yield c_i, args, l_lst


def eval_func(c_i, args, l_lst):
    assert len(args) == 3
    x = args[0]
    y = args[1]
    z = args[2]
    res = x**2 + y**2 + z/10
    print(f"Eval {x}, {y}, {z}: {res}")
    l_lst[c_i] = res


if __name__ == '__main__':

    generation_num = 10
    child_num = 5

    space = OrderedDict((
        ('x', (-2., 0.)),
        ('y', (0., 2.)),
        ('z', (10., 11.))
    ))

    params = OrderedDict([(nm, []) for nm in space.keys()])
    for nm, v_range in space.items():
        params[nm] = np.random.uniform(v_range[0], v_range[1], size=child_num)

    arg_list = []
    for c_n in range(child_num):
        arg_list.append([val[c_n] for val in params.values()])

    manager = multiprocessing.Manager()
    loss_lst = manager.list([np.inf for i in range(child_num)])

    for r_n in range(generation_num):
        with multiprocessing.Pool(os.cpu_count()) as pool:
            pool.starmap(eval_func, eval_iter(arg_list, loss_lst))

        fittest_idx = int(np.argmin(loss_lst))
        base_args = arg_list[fittest_idx]
        print(f"Best {base_args}\n")

        # mutate offspring from fittest individual
        params = OrderedDict([(nm, []) for nm in space.keys()])
        for s_i, (nm, v_range) in enumerate(space.items()):
            std = (v_range[1] - v_range[0]) / 2
            noise = np.random.normal(0, std, size=child_num)
            new_param = base_args[s_i] + noise
            params[nm] = np.clip(new_param, v_range[0], v_range[1])

        arg_list = []
        for c_n in range(child_num):
            arg_list.append([val[c_n] for val in params.values()])

        loss_lst = manager.list([np.inf for i in range(child_num)])


Комментарии
1 ответ


  1. Лучше организация

    Программа в ее нынешнем состоянии-это один огромный кусок фрагмента с вся логика внутри него. Вам следует разбить ее на отдельные более мелкие функции. Ограничения на \$ х, у, Z \$ заданы. Рассмотреть их как GLOBAL_CONSTANT.


  2. Идеальный импорт заказа (согласно PEP8) является


    • стандартный импорт библиотеки

    • обзоры импорта третьим лицам

    • местного применения/специальная библиотека импорта

    os/collections и т. д. стандартные библиотеки, и должны быть импортированы первым, затем numpy.


  3. pythonify код

    x = args[0]
    y = args[1]
    z = args[2]

    может быть выражена как:

    x, y, z = args

    аналогично

    manager.list([np.inf for i in range(child_num)])

    может стать

    manager.list([np.inf] * child_num)

Я не уверен, о том, как numpy.argmin работает, но я думаю, что с помощью None вместо np.inf может быть лучше в том смысле, что вы можете расширить вашу программу, чтобы также найти локальных/глобальных максимумов с минимумами очков.

3
ответ дан 3 марта 2018 в 01:03 Источник Поделиться