Python: обработка больших чисел - PullRequest
0 голосов
/ 16 декабря 2018

Мне нужно посчитать недоумение, и я пытаюсь сделать это с

def get_perplexity(test_set, model):
    perplexity = 1
    n = 0
    for word in test_set:
        n += 1
        perplexity = perplexity * 1 / get_prob(model, word)
    perplexity = pow(perplexity, 1/float(n))
    return perplexity

И после некоторых шагов мой perplexity равен бесконечности.Мне нужно получить номер и в качестве последнего шага сделать pow(perplexity, 1/float(n))

Есть ли умножить числа, как и получить результат?

3.887311155784627e+243
8.311806360146177e+250
1.7707049372801292e+263
1.690802669602979e+271
3.843294667766984e+278
5.954424789834101e+290
8.859529887856071e+295
7.649470766862909e+306

Ответы [ 2 ]

0 голосов
/ 16 декабря 2018

, так как e + 306 - это просто 10 ^ 306, вы можете сделать класс из двух частей

class BigPowerFloat:
    POWER_STEP = 10**100
    def __init__(self, input_value):
        self.value = float(input_value)
        self.power = 0

    def _move_to_power(self):
        while self.value > self.POWER_STEP:
            self.value = self.value / self.POWER_STEP
            self.power += self.POWER_STEP
        # you can add similar for negative values           


    def __mul__(self, other):
        self.value *= other
        self._move_to_power()

    # TODO other __calls for /, +, - ...

    def __str__(self):
        pass
        # make your cust to str
0 голосов
/ 16 декабря 2018

Повторное умножение вызовет некоторую хитрую числовую нестабильность, так как результаты ваших умножений требуют все больше и больше битов для представления.Я предлагаю вам перевести это в лог-пространство и использовать суммирование, а не умножение:

import math

def get_perplexity(test_set, model):
    log_perplexity = 0
    n = 0
    for word in test_set:
        n += 1
        log_perplexity -= math.log(get_prob(model, word))
    log_perplexity /= float(n)
    return math.exp(log_perplexity)

Таким образом, все ваши логарифмы могут быть представлены в стандартном количестве битов, и вы не получите числовые увеличения и потериточности.Кроме того, вы можете ввести произвольную степень точности, используя модуль decimal:

import decimal

def get_perplexity(test_set, model):
    with decimal.localcontext() as ctx:
        ctx.prec = 100  # set as appropriate
        log_perplexity = decimal.Decimal(0)
        n = 0
        for word in test_set:
            n += 1
            log_perplexity -= decimal.Decimal(get_prob(model, word))).ln()
        log_perplexity /= float(n)
        return log_perplexity.exp()
...