Source code for theanolm.backend.probfunctions
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""A module that provides functions for operating with probabilities, and
defines logprob_type.
"""
from decimal import Decimal, getcontext
import numpy
import theano
logprob_type = numpy.dtype(theano.config.floatX).type
[docs]
def interpolate_linear(logprob1, logprob2, weight1):
"""Performs linear interpolation of two probabilities.
If a probability is so small that it will be rounded to zero, uses the
decimal library. If a weight is zero, the corresponding log probability will
be ignored. Otherwise if the log probability was ``-inf``, multiplication
would result in a ``nan``.
:type logprob1: logprob_type
:param logprob1: logarithm of first input probability
:type logprob2: logprob_type
:param logprob2: logarithm of second input probability
:type weight1: logprob_type
:param weight1: interpolation weight for the first probability
:rtype: logprob_type
:returns: logarithm of the weighted sum of the input probabilities
"""
prob1 = numpy.exp(numpy.float64(logprob1))
prob2 = numpy.exp(numpy.float64(logprob2))
if (prob1 > 0) and (prob2 > 0):
weight2 = 1.0 - weight1
prob = weight1 * prob1
prob += weight2 * prob2
return logprob_type(numpy.log(prob))
else:
# An exp() resulted in an underflow (or -inf logprob). Use the decimal
# library.
getcontext().prec = 16
d_weight1 = Decimal(float(weight1))
d_weight2 = Decimal(1.0) - d_weight1
d_logprob1 = Decimal(float(logprob1))
d_logprob2 = Decimal(float(logprob2))
d_zero = Decimal(0.0)
d_prob = d_zero
if d_weight1 != d_zero:
d_prob += d_weight1 * d_logprob1.exp()
if d_weight2 != d_zero:
d_prob += d_weight2 * d_logprob2.exp()
return logprob_type(d_prob.ln())
[docs]
def interpolate_loglinear(logprob1, logprob2, prior1, prior2):
"""Performs log-linear interpolation of two probabilities.
This is not real log-linear interpolation, because we don't normalize the
result. Thus the result is not a real probability.
If a prior is zero, the corresponding log probability will be ignored.
Otherwise if the log probability was ``-inf``, multiplication would result
in a ``nan``.
:type logprob1: logprob_type
:param logprob1: first input log probability
:type logprob2: logprob_type
:param logprob2: second input log probability
:type prior1: logprob_type
:param prior1: weight for the first log probability
:type prior2: logprob_type
:param prior2: weight for the second log probability
:rtype: logprob_type
:returns: weighted sum of the input log probabilities
"""
result = 0
if prior1 != 0:
result += prior1 * logprob1
if prior2 != 0:
result += prior2 * logprob2
assert not numpy.isnan(result)
return result