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

 更新时间:2017年01月04日 08:58:12   投稿:jingxian  
下面小编就为大家带来一篇python的random模块及加权随机算法的python实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

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实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • python datetime中strptime用法详解

    python datetime中strptime用法详解

    这篇文章主要介绍了python 中datetime中strptime用法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • python递归实现快速排序

    python递归实现快速排序

    这篇文章主要为大家详细介绍了python递归实现快速排序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • Python绘制动态的521玫瑰花

    Python绘制动态的521玫瑰花

    敲了这么多年代码,每年都得画一些心啊花啊什么的,所以现在常规的已经有些倦怠了,至少也得来个三维图形才看着比较合理,所以本文就来绘制一个动态的玫瑰花吧
    2023-05-05
  • 给Python中的MySQLdb模块添加超时功能的教程

    给Python中的MySQLdb模块添加超时功能的教程

    这篇文章主要介绍了给Python中的MySQLdb模块添加超时功能的教程,timeout功能在服务器的运维当中非常有用,需要的朋友可以参考下
    2015-05-05
  • Python中defaultdict与dict的差异详情

    Python中defaultdict与dict的差异详情

    这篇文章主要介绍了Python中defaultdict与dict的差异,在collections模块中的defauldict使用时与dict有何不同,为何我们用dict中的key值不存在时会报错,而defaudict不会报错,下面文章做出解答,需要的朋友可以参考一下
    2021-11-11
  • Python 3.7新功能之dataclass装饰器详解

    Python 3.7新功能之dataclass装饰器详解

    这篇文章主要给大家介绍了关于Python 3.7新功能之dataclass装饰器的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-04-04
  • Python自定义线程池实现方法分析

    Python自定义线程池实现方法分析

    这篇文章主要介绍了Python自定义线程池实现方法,结合实例形式较为详细的分析了Python自定义线程池的概念、原理、实现方法及相关注意事项,需要的朋友可以参考下
    2018-02-02
  • python pandas.DataFrame选取、修改数据最好用.loc,.iloc,.ix实现

    python pandas.DataFrame选取、修改数据最好用.loc,.iloc,.ix实现

    今天小编就为大家分享一篇python pandas.DataFrame选取、修改数据最好用.loc,.iloc,.ix实现。具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06
  • 从零开始学Python第八周:详解网络编程基础(socket)

    从零开始学Python第八周:详解网络编程基础(socket)

    本篇文章主要介绍了从零开始学Python第八周:详解网络编程基础(socket) ,具有一定的参考价值,有兴趣的可以了解一下。
    2016-12-12
  • 大语言模型的开发利器langchainan安装使用快速入门学习

    大语言模型的开发利器langchainan安装使用快速入门学习

    这篇文章主要为大家介绍了大语言模型的开发利器langchain安装使用快速入门学习,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07

最新评论