コード例 #1
0
  def make_inverse_update_ops(self):
    """Create and return update ops corresponding to registered computations."""
    ops = super(InverseProvidingFactor, self).make_inverse_update_ops()

    num_inverses = len(self._inverses_by_damping)
    matrix_power_registered = bool(self._matpower_by_exp_and_damping)
    use_eig = (self._eigendecomp or matrix_power_registered or
               num_inverses >= EIGENVALUE_DECOMPOSITION_THRESHOLD)

    if use_eig:
      self.register_eigendecomp()  # ensures self._eigendecomp is set
      eigenvalues, eigenvectors = self._eigendecomp  # pylint: disable=unpacking-non-sequence

      # The matrix self._cov is positive semidefinite by construction, but the
      # numerical eigenvalues could be negative due to numerical errors, so here
      # we clip them to be at least EIGENVALUE_CLIPPING_THRESHOLD.
      clipped_eigenvalues = math_ops.maximum(eigenvalues,
                                             EIGENVALUE_CLIPPING_THRESHOLD)

      for damping, inv in self._inverses_by_damping.items():
        ops.append(
            inv.assign(
                math_ops.matmul(eigenvectors / (clipped_eigenvalues + damping),
                                array_ops.transpose(eigenvectors))))

      for (exp, damping), matpower in self._matpower_by_exp_and_damping.items():
        ops.append(
            matpower.assign(
                math_ops.matmul(eigenvectors * (clipped_eigenvalues + damping)**
                                exp, array_ops.transpose(eigenvectors))))
    else:
      for damping, inv in self._inverses_by_damping.items():
        ops.append(inv.assign(utils.posdef_inv(self._cov, damping)))

    return ops
コード例 #2
0
    def make_inverse_update_ops(self):
        """Create and return update ops corresponding to registered computations."""
        ops = []

        num_inverses = len(self._inverses_by_damping)
        matrix_power_registered = bool(self._matpower_by_exp_and_damping)
        use_eig = (self._eigendecomp or matrix_power_registered
                   or num_inverses >= EIGENVALUE_DECOMPOSITION_THRESHOLD)

        if use_eig:
            self.register_eigendecomp()  # ensures self._eigendecomp is set
            eigenvalues, eigenvectors = self._eigendecomp  # pylint: disable=unpacking-non-sequence

            for damping, inv in self._inverses_by_damping.items():
                ops.append(
                    inv.assign(
                        math_ops.matmul(eigenvectors / (eigenvalues + damping),
                                        array_ops.transpose(eigenvectors))))

            for (exp, damping
                 ), matpower in self._matpower_by_exp_and_damping.items():
                ops.append(
                    matpower.assign(
                        math_ops.matmul(
                            eigenvectors * (eigenvalues + damping)**exp,
                            array_ops.transpose(eigenvectors))))
            # These ops share computation and should be run on a single device.
            ops = [control_flow_ops.group(*ops)]
        else:
            for damping, inv in self._inverses_by_damping.items():
                ops.append(inv.assign(utils.posdef_inv(self._cov, damping)))

        return ops
コード例 #3
0
  def make_inverse_update_ops(self):
    """Create and return update ops corresponding to registered computations."""
    ops = []

    num_inverses = len(self._inverses_by_damping)
    matrix_power_registered = bool(self._matpower_by_exp_and_damping)
    use_eig = (
        self._eigendecomp or matrix_power_registered or
        num_inverses >= EIGENVALUE_DECOMPOSITION_THRESHOLD)

    if use_eig:
      self.register_eigendecomp()  # ensures self._eigendecomp is set
      eigenvalues, eigenvectors = self._eigendecomp  # pylint: disable=unpacking-non-sequence

      for damping, inv in self._inverses_by_damping.items():
        ops.append(
            inv.assign(
                math_ops.matmul(eigenvectors / (eigenvalues + damping),
                                array_ops.transpose(eigenvectors))))

      for (exp, damping), matpower in self._matpower_by_exp_and_damping.items():
        ops.append(
            matpower.assign(
                math_ops.matmul(eigenvectors *
                                (eigenvalues + damping)**exp,
                                array_ops.transpose(eigenvectors))))
      # These ops share computation and should be run on a single device.
      ops = [control_flow_ops.group(*ops)]
    else:
      for damping, inv in self._inverses_by_damping.items():
        ops.append(inv.assign(utils.posdef_inv(self._cov, damping)))

    return ops
コード例 #4
0
    def make_inverse_update_ops(self):
        """Create and return update ops corresponding to registered computations."""
        ops = []

        # We do this to ensure that we don't reuse the eigendecomp from old calls
        # to make_inverse_update_ops that may be placed on different devices.  This
        # can happen is the user has both a permanent and lazily constructed
        # version of the inverse ops (and only uses one of them).
        self.reset_eigendecomp()

        num_inverses = len(self._inverses_by_damping)
        matrix_power_registered = bool(self._matpower_by_exp_and_damping)
        use_eig = (self._eigendecomp or matrix_power_registered
                   or num_inverses >= EIGENVALUE_DECOMPOSITION_THRESHOLD)

        if use_eig:
            eigenvalues, eigenvectors = self.get_eigendecomp()  # pylint: disable=unpacking-non-sequence

            for damping, inv in self._inverses_by_damping.items():
                ops.append(
                    inv.assign(
                        math_ops.matmul(eigenvectors / (eigenvalues + damping),
                                        array_ops.transpose(eigenvectors))))

            for (exp, damping
                 ), matpower in self._matpower_by_exp_and_damping.items():
                ops.append(
                    matpower.assign(
                        math_ops.matmul(
                            eigenvectors * (eigenvalues + damping)**exp,
                            array_ops.transpose(eigenvectors))))
            # These ops share computation and should be run on a single device.
            ops = [control_flow_ops.group(*ops)]
        else:
            for damping, inv in self._inverses_by_damping.items():
                ops.append(inv.assign(utils.posdef_inv(self._cov, damping)))

        return ops
コード例 #5
0
  def make_inverse_update_ops(self):
    """Create and return update ops corresponding to registered computations."""
    ops = []

    # We do this to ensure that we don't reuse the eigendecomp from old calls
    # to make_inverse_update_ops that may be placed on different devices.  This
    # can happen is the user has both a permanent and lazily constructed
    # version of the inverse ops (and only uses one of them).
    self.reset_eigendecomp()

    num_inverses = len(self._inverses_by_damping)
    matrix_power_registered = bool(self._matpower_by_exp_and_damping)
    use_eig = (
        self._eigendecomp or matrix_power_registered or
        num_inverses >= EIGENVALUE_DECOMPOSITION_THRESHOLD)

    if use_eig:
      eigenvalues, eigenvectors = self.get_eigendecomp()  # pylint: disable=unpacking-non-sequence

      for damping, inv in self._inverses_by_damping.items():
        ops.append(
            inv.assign(
                math_ops.matmul(eigenvectors / (eigenvalues + damping),
                                array_ops.transpose(eigenvectors))))

      for (exp, damping), matpower in self._matpower_by_exp_and_damping.items():
        ops.append(
            matpower.assign(
                math_ops.matmul(eigenvectors *
                                (eigenvalues + damping)**exp,
                                array_ops.transpose(eigenvectors))))
      # These ops share computation and should be run on a single device.
      ops = [control_flow_ops.group(*ops)]
    else:
      for damping, inv in self._inverses_by_damping.items():
        ops.append(inv.assign(utils.posdef_inv(self._cov, damping)))

    return ops