Тензорная арифметика TF дает менее точные ответы, чем использование констант с плавающей запятой.

По сути, это то, что я делаю:

print (P, Q, R)
>>> tf.Tensor(4.0, shape=(), dtype=float32) 1024.0 tf.Tensor(315.0, shape=(), dtype=float32)

P*R/Q
>>> <tf.Tensor: shape=(), dtype=float32, numpy=1.2304688>

4.0*315.0/1024.0
>>> 1.23046875

Арифметика, выполненная с использованием констант, дает тот же результат, что и точное вычисление. Однако арифметика, выполненная с использованием тензоров, дает ответ, который отличается в двух последних местах.

Чтобы разобраться в этом, я попытался понять, как тензорное умножение происходит под капотом. По-видимому, сценарий, подробно описывающий процесс умножения тензоров TF, создается автоматически (Where скрипт gen_math_ops в тензорном потоке?)

Я сделал так, как предложил ответ, и нашел следующую функцию mul:

def mul(x, y, name=None):
  r"""Returns x * y element-wise.

  *NOTE*: `Multiply` supports broadcasting. More about broadcasting
  [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)

  Args:
    x: A `Tensor`. Must be one of the following types: `bfloat16`, `half`, `float32`, `float64`, `uint8`, `int8`, `uint16`, `int16`, `int32`, `int64`, `complex64`, `complex128`.
    y: A `Tensor`. Must have the same type as `x`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor`. Has the same type as `x`.
  """
  _ctx = _context._context or _context.context()
  tld = _ctx._thread_local_data
  if tld.is_eager:
    try:
      _result = pywrap_tfe.TFE_Py_FastPathExecute(
        _ctx, "Mul", name, x, y)
      return _result
    except _core._NotOkStatusException as e:
      _ops.raise_from_not_ok_status(e, name)
    except _core._FallbackException:
      pass
    try:
      return mul_eager_fallback(
          x, y, name=name, ctx=_ctx)
    except _core._SymbolicException:
      pass  # Add nodes to the TensorFlow graph.
  # Add nodes to the TensorFlow graph.
  _, _, _op, _outputs = _op_def_library._apply_op_helper(
        "Mul", x=x, y=y, name=name)
  _result = _outputs[:]
  if _execute.must_record_gradient():
    _attrs = ("T", _op._get_attr_type("T"))
    _inputs_flat = _op.inputs
    _execute.record_gradient(
        "Mul", _inputs_flat, _attrs, _result)
  _result, = _result
  return _result

К сожалению, я не мог понять этого и, следовательно, зашел в тупик.

Итак, мой вопрос двоякий:

  1. ожидается ли тензорная арифметика TF менее точной в том виде, в котором она представлена ​​во фрагменте кода? Если да, то хотелось бы понять, почему так.
  2. Есть ли способ заставить тензорную арифметику TF быть настолько точной, насколько позволяет арифметика с постоянным числом с плавающей запятой, с минимальными изменениями в коде, например, с дополнительным аргументом или чем-то еще?

Любая помощь будет принята с благодарностью.


person Satan'sSidekick    schedule 19.05.2021    source источник