我正在 numpy 中实现遗传算法,并且试图弄清楚如何通过轮盘赌和随机通用采样正确实现选择。我在 stackoverflow 或其他地方看到的示例使用 python 循环而不是矢量化的 numpy 代码。
例如,以下是 DEAP 中两种算法的实现。
def selRoulette(individuals, k, fit_attr="fitness"):
"""Select *k* individuals from the input *individuals* using *k*
spins of a roulette. The selection is made by looking only at the first
objective of each individual. The list returned contains references to
the input *individuals*.
:param individuals: A list of individuals to select from.
:param k: The number of individuals to select.
:param fit_attr: The attribute of individuals to use as selection criterion
:returns: A list of selected individuals.
This function uses the :func:`~random.random` function from the python base
"""
s_inds = sorted(individuals, key=attrgetter(fit_attr), reverse=True)
sum_fits = sum(getattr(ind, fit_attr).values[0] for ind in individuals)
chosen = []
for i in xrange(k):
u = random.random() * sum_fits
sum_ = 0
for ind in s_inds:
sum_ += getattr(ind, fit_attr).values[0]
if sum_ > u:
chosen.append(ind)
break
return chosen
def selStochasticUniversalSampling(individuals, k, fit_attr="fitness"):
"""Select the *k* individuals among the input *individuals*.
The selection is made by using a single random value to sample all of the
individuals by choosing them at evenly spaced intervals. The list returned
contains references to the input *individuals*.
:param individuals: A list of individuals to select from.
:param k: The number of individuals to select.
:param fit_attr: The attribute of individuals to use as selection criterion
:return: A list of selected individuals.
"""
s_inds = sorted(individuals, key=attrgetter(fit_attr), reverse=True)
sum_fits = sum(getattr(ind, fit_attr).values[0] for ind in individuals)
distance = sum_fits / float(k)
start = random.uniform(0, distance)
points = [start + i*distance for i in xrange(k)]
chosen = []
for p in points:
i = 0
sum_ = getattr(s_inds[i], fit_attr).values[0]
while sum_ < p:
i += 1
sum_ += getattr(s_inds[i], fit_attr).values[0]
chosen.append(s_inds[i])
return chosen
这是我的轮盘赌实现,它似乎是带替换的加权采样,但我不确定替换参数。
# population is a 2D array of integers
# population_fitness is a 1D array of float of same length as population
weights = population_fitness / population_fitness.sum()
selected = population[np.random.choice(len(population), size=n, replace=True, p=weights)]
这是我对SUS选择的实现。我是否正确,当在 numpy 中实施时,我唯一需要改变的是采样是没有替换的,还是我也应该删除权重?
weights = population_fitness / population_fitness.sum()
selected = population[np.random.choice(len(population), size=n, replace=False, p=weights)]
感谢您的任何建议!