首页 > 解决方案 > How do I do something like numpy where(2darray ==0, 1darray, 1darray)

问题描述

I'm working on a mutation function for a genetic algorithm, but I'm pretty new to numpy.

The default mutation method looks like this:

whereMutate = np.random.rand(np.shape(population)[0],np.shape(population)[1])
population[np.where(whereMutate < self.mutationProb)] = 1 - population[np.where(whereMutate < self.mutationProb)]

The default mutationprob is set to 1/chromosome length. Population contains a different chromosome on each row and chromosomes are 561 long, with a 0 or 1 at each position.

What I was trying to do is to set the probability of mutation based upon the frequency of 0s and 1s for that chromosome, so that when a chromosome with very few 1s mutates it is just as likely to switch a 0 to a 1 as it is to go the other way.

Currently I have something like this:

mProbOne = 0.5/np.count_nonzero(population, axis=1)
mProbZero = 0.5/np.count_nonzero(population == 0, axis=1)
probs = np.where(population == 0, mProbZero, mProbOne)
# Something like the above ought to give me a 2d array 
# with probability of mutation for each position in the chromosome,
# separately for each chromosome
whereMutate = np.random.rand(np.shape(population)[0],np.shape(population)[1]
population[np.where(whereMutate < probs)] = 1-population[np.where(whereMutate < self.mutationProb)]

The last two lines are just the same as the currently existing two lines for the case where mutation probability is fixed. My issue is line 3 above. mProbZero and mProbOne are 1d numpy arrays. I am getting a

ValueError: operands could not be broadcast together with shapes (2,5) (2,) (2,)

Follow-up: the following code seems to work, though it's probably about 4 lines more than necessary... is there any way to do this better?

mProbZero = 0.5/np.count_nonzero(population == 0, axis=1)
mProbOne = 0.5/np.count_nonzero(population, axis=1)
probs = np.zeros(np.shape(population))
probs[np.where(population == 0)] = mProbZero[np.where(population == 0)[0]]
probs[np.where(population == 1)] = mProbOne[np.where(population == 1)[0]]
whereMutate = np.random.rand(np.shape(population)[0],np.shape(population)[1])
population[np.where(whereMutate < self.mutationProb)] = 1 - population[np.where(whereMutate < self.mutationProb)]

标签: pythonnumpygenetic-algorithmmutation

解决方案


我相信您正在使用二进制遗传算法。这意味着在您的突变中,您需要将 1 转换为 0 并将 0 转换为 1。我不知道您的人口是什么样的。对于一个简单的方法,您可以修改此代码。这里我使用选择随机位置,您可以更改为突变概率。

   def binary_mutation(parent1):
        posi = random.randint(0, len(parent1)-1)
        if parent1[posi] == 1:
            parent1[posi] = 0
        elif parent1[posi] == 0:
            parent1[posi] = 1
        return parent1

推荐阅读