最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

详解python的random模块及加权随机算法和实现方法

来源:动视网 责编:小采 时间:2020-11-27 14:16:07
文档

详解python的random模块及加权随机算法和实现方法

详解python的random模块及加权随机算法和实现方法:random是用于生成随机数的,我们可以利用它随机生成数字或者选择字符串。random.seed(x)改变随机数生成器的种子seed。一般不必特别去设定seed,Python会自动选择seed。random.random() 用于生成一个随机浮点数n,0 <= n < 1ra
推荐度:
导读详解python的random模块及加权随机算法和实现方法:random是用于生成随机数的,我们可以利用它随机生成数字或者选择字符串。random.seed(x)改变随机数生成器的种子seed。一般不必特别去设定seed,Python会自动选择seed。random.random() 用于生成一个随机浮点数n,0 <= n < 1ra
 random是用于生成随机数的,我们可以利用它随机生成数字或者选择字符串。
?random.seed(x)改变随机数生成器的种子seed。
一般不必特别去设定seed,Python会自动选择seed。
?random.random() 用于生成一个随机浮点数n,0 <= n < 1
?random.uniform(a,b) 用于生成一个指定范围内的随机浮点数,生成的随机整数a<=n<=b;
?random.randint(a,b) 用于生成一个指定范围内的整数,a为下限,b为上限,生成的随机整数a<=n<=b;若a=b,则n=a;若a>b,报错
?random.randrange([start], stop [,step]) 从指定范围[start,stop)内,按指定基数递增的集合中获取一个随机数,基数缺省值为1
?random.choice(sequence) 从序列中获取一个随机元素,参数sequence表示一个有序类型,并不是一种特定类型,泛指list,tuple,字符串等
?random.shuffle(x[,random]) 用于将一个列表中的元素打乱 (洗牌),会改变原始列表
?random.sample(sequence,k) 从指定序列中随机获取k个元素作为一个片段返回,不会改变原有序列
那么现在基础知识有了,我们来实现一个加权随机算法:
加权随机算法一般应用在以下场景:有一个集合S,里面比如有A,B,C,D这四项。这时我们想随机从中抽取一项,但是抽取的概率不同,比如我们希望抽到A的概率是50%,抽到B和C的概率是20%,D的概率是10%。一般来说,我们可以给各项附一个权重,抽取的概率正比于这个权重。那么上述集合就成了:
{A:5,B:2,C:2,D:1}
方法一:
最简单的方法可以这样:
把序列按权重值扩展成:lists=[A,A,A,A,A,B,B,C,C,D],然后random.choice(lists)随机选一个就行。虽然这样选取的时间复杂度是O(1),但是数据量一大,空间消耗就太大了。

# coding:utf-8
import random
def weight_choice(list, weight):
 """
 :param list: 待选取序列
 :param weight: list对应的权重序列
 :return:选取的值
 """
 new_list = []
 for i, val in enumerate(list):
 new_list.extend(val * weight[i])
 return random.choice(new_list)
if name == "main":
 print(weight_choice(['A', 'B', 'C', 'D'], [5, 2, 2, 1]))


方法二:
比较常用的方法是这样:
计算权重总和sum,然后在1到sum之间随机选择一个数R,之后遍历整个集合,统计遍历的项的权重之和,如果大于等于R,就停止遍历,选择遇到的项。
还是以上面的集合为例,sum等于10,如果随机到1-5,则会在遍历第一个数字的时候就退出遍历。符合所选取的概率。
选取的时候要遍历集合,它的时间复杂度是O(n)。

# coding:utf-8
import random
list = ['A', 'B', 'C', 'D']
def weight_choice(weight):
 """
 :param weight: list对应的权重序列
 :return:选取的值在原列表里的索引
 """
 t = random.randint(0, sum(weight) - 1)
 for i, val in enumerate(weight):
 t -= val
 if t < 0:
 return i
if name == "main":
 print(list[weight_choice([5, 2, 2, 1])])


方法三:
可以先对原始序列按照权重排序。这样遍历的时候,概率高的项可以很快遇到,减少遍历的项。(因为rnd递减的速度最快(先减去最大的数))
比较{A:5,B:2,C:2,D:1}和{B:2,C:2,A:5,D:1}
前者遍历步数的期望是5/10*1+2/10*2+2/10*3+1/10*4=19/10而后者是2/10*1+2/10*2+5/10*3+1/10*4=25/10。
这样提高了平均选取速度,但是原序列排序也需要时间。
先搞一个权重值的前缀和序列,然后在生成一个随机数t后,可以用二分法来从这个前缀和序列里找,那么选取的时间复杂度就是O(logn)了。

# coding:utf-8
import random
import bisect
list = ['A', 'B', 'C', 'D']
def weight_choice(weight):
 """
 :param weight: list对应的权重序列
 :return:选取的值在原列表里的索引
 """
 weight_sum = []
 sum = 0
 for a in weight:
 sum += a
 weight_sum.append(sum)
 t = random.randint(0, sum - 1)
 return bisect.bisect_right(weight_sum, t)
if name == "main":
 print(list[weight_choice([5, 2, 2, 1])])

-->

文档

详解python的random模块及加权随机算法和实现方法

详解python的random模块及加权随机算法和实现方法:random是用于生成随机数的,我们可以利用它随机生成数字或者选择字符串。random.seed(x)改变随机数生成器的种子seed。一般不必特别去设定seed,Python会自动选择seed。random.random() 用于生成一个随机浮点数n,0 <= n < 1ra
推荐度:
标签: 方法 随机 模块
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top