轮盘赌选择原理
轮盘赌选择法(roulette wheel selection)是最简单也是最常用的选择方法,在该方法中,各个个体的选择概率和其适应度值成比例,适应度越大,选中概率也越大。
从图中可以看出一等奖、二等奖、三等奖和四等奖的概率分别为10%、20%、30%、40%,和为100%。
个体 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
概率 | 0.1 | 0.2 | 0.3 | 0.4 |
python代码实现如下:
import numpy as np# 轮盘赌选择,list1为 list []
def roulette1(list1):# 产生 [0, 1) 的随机数r = np.random.rand()s = 0for i, v in enumerate(list1):s += vif s > r:# 返回个体索引{0,1,2,3}return ireturn len(list1) - 1
我们测试一下roulette1
,测试代码如下:
from unittest import TestCaseclass Test(TestCase):def test_roulette1(self):l1 = [0.1, 0.2, 0.3, 0.4]result1 = [0, 0, 0, 0]# 执行1000次,记录每个个体的选择结果for i in range(1000):index = roulette1(l1)result1[index] += 1print('result1 =', result1)
result1 = [109, 198, 304, 389]
可以看出比例接近{0.1,0.2,0.3,0.4}。
但是对于和不为100%的情况该怎么办呢?可以将每个个体的概率进行归一化处理,即每个个体的概率除以概率之和。这样做其实比较麻烦。
也可以采用另一种方法。即在取随机数的时候不取 [0,1)
的随机数,而是取 [0, s)
的随机数,s
为所有个体概率之和,比如每个个体概率如下表所示:
个体 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
概率 | 0.05 | 0.01 | 0.15 | 0.2 |
所有个体概率之和为0.5,在计算时只需要取[0,0.5)的随机数即可。
python代码如下:
import numpy as npdef roulette2(list1):# 产生 [0, sum(list1)) 的随机数r = np.random.uniform(0, np.sum(list1))s = 0for i, v in enumerate(list1):s += vif s > r:return ireturn len(list1) - 1
同样的,测试一下:
from unittest import TestCaseclass Test(TestCase):def test_roulette2(self):l2 = [0.05, 0.1, 0.15, 0.2]result2 = [0, 0, 0, 0]# 执行1000次,记录每个个体的选择结果for i in range(1000):index = roulette2(l2)result2[index] += 1print('result2 =', result2)
result2 = [105, 201, 296, 398]
可以看出比例接近{0.1,0.2,0.3,0.4}。
那么个体的排列顺序对概率是否有影响呢?没有影响。我们可以测试一下。
from unittest import TestCaseclass Test(TestCase):def test_roulette3(self):# 将个体顺序调换l3 = [0.15, 0.2, 0.05, 0.1]result3 = [0, 0, 0, 0]for i in range(1000):index = roulette2(l3)result3[index] += 1print('result3 =', result3)
result3 = [300, 406, 101, 193]
可以看出结果接近{0.3,0.4,0.1,0.2}。