【问题标题】:Python replace integers in a Counter with their permillages of the total [duplicate]Python用它们的总百分比替换计数器中的整数[重复]
【发布时间】:2021-12-02 12:53:00
【问题描述】:

我正在尝试使用马尔可夫链生成任何字典中都没有的可读的类似单词的随机字符串。

我从GCIDE拉取的总共105230个词中提取了大量ngram频率的数据,目前这些数据以Counter格式存储(序列化为JSON),利用马尔可夫链涉及随机选择具有权重的集合中的元素。

我已经找到了一种做加权随机抽样的方法,像这样:

random.choices(keys, weights=values, k=1)

(keys 和 values 是从 Counter 中提取的)

但是我发现的所有教程都是使用numpy 实现马尔可夫链,并且要使用这种方法,我需要将整数转换为总数的千分位数,并确保数字加起来为 1.0。

正如我所说,我希望数字采用 permillage 格式(float 具有三个小数位)并且 floats 必须加起来为 1.0 才能使 numpy 方法起作用。

我可以将数字转换为 floats,但由于 53 位双精度浮点格式固有的精度限制,数字之和不会总是等于 1.0。

例如:

initcon = {'c': 7282,
 'm': 6015,
 'd': 5866,
 'p': 5699,
 's': 5294,
 'b': 4103,
 'r': 4097,
 'h': 3926,
 'l': 3352,
 't': 2841,
 'f': 2699,
 'n': 2171,
 'g': 2051,
 'pr': 1991,
 'v': 1626,
 'tr': 1337,
 'w': 1337,
 'st': 1153,
 'ch': 1121,
 'cr': 827,
 'br': 803,
 'j': 799,
 'sp': 746,
 'gr': 694,
 'k': 676,
 'ph': 651,
 'pl': 645,
 'fl': 622,
 'th': 594,
 'sh': 572,
 'q': 553,
 'cl': 538,
 'fr': 522,
 'sc': 516,
 'bl': 494,
 'gl': 428,
 'dr': 421,
 'z': 376,
 'wh': 338,
 'str': 335,
 'sl': 325,
 'sw': 245,
 'rh': 210,
 'sk': 167,
 'sn': 165,
 'scr': 148,
 'sm': 143,
 'x': 143,
 'chr': 141,
 'kn': 139,
 'thr': 125,
 'sq': 124,
 'ps': 123,
 'wr': 113,
 'sch': 106,
 'tw': 95,
 'spr': 73,
 'spl': 72,
 'shr': 66,
 'sph': 65,
 'chl': 54,
 'pt': 51,
 'gn': 49,
 'phl': 41,
 'scl': 39,
 'gh': 37,
 'pn': 37,
 'phr': 33,
 'kr': 30,
 'kl': 22,
 'dw': 16,
 'kh': 15}

total = sum(initcon.values())

initcon = {k: v/total for k, v in initcon.items()}
print(sum(initcon.values()))

它打印0.9999999999999999。

我怎样才能使initcon 中的数字加起来正好为 1.0 并让它们每个都有 3 个小数位?

【问题讨论】:

  • 如果你想让它们四舍五入到小数点后 3 位,你可以这样做 round(value, 3)
  • “Permillage”是一个稀有词,使用时应该定义,并且您使用的数字不是permillages。一个分区的千分之和加到 1000,而不是 1。例如,对于十分之一、四分之一和 65% 的部分,千分是 100、250 和 650,总和为 1000。
  • 关于“我怎样才能使 initcon 中的数字加起来正好为 1.0 并使它们每个都有 3 个小数位?”:这在使用基于二进制的浮点时通常是不可能的。 0 和 1 之间的数字只有三个小数位是 0、.125、.250、.375、.500、.625、.750、.875 和 1。例如,没有基于二进制的浮点数值为 .123 的点数。
  • 除了我将其标记为副本的问题之外,我记得还有一个副本得到了相当多的讨论,但我目前找不到它。也许其他人可以。

标签: python python-3.x floating-point precision floating-accuracy


【解决方案1】:

我在工作中也遇到了类似的问题。我们发现保持总和等于 1 的唯一方法是添加一个额外的步骤。

之后

initcon = {k: v/total for k, v in initcon.items()}

您可以检查余数是什么,以便 sum(initcon.values())==1 即

remainder = 1-sum(initcon.values())

然后您可以将此数字添加到任何键。您可以使用random.choice 方法随机选择它。因此,最后,您将执行以下操作:

initcon[random_key]+=remainder

【讨论】:

  • remainder 可能为负数,将其添加到随机元素可能会使该元素为负数。
猜你喜欢
  • 2014-09-06
  • 2021-02-24
  • 2018-06-24
  • 1970-01-01
  • 2021-02-20
  • 1970-01-01
  • 2018-03-05
  • 2019-01-26
  • 2021-08-12
相关资源
最近更新 更多