bayespy.nodes.SumMultiply

class bayespy.nodes.SumMultiply(*args, iterator_axis=None, **kwargs)[source]

Node for computing general products and sums of Gaussian nodes.

The node is similar to numpy.einsum, which is a very general function for computing dot products, sums, products and other sums of products of arrays.

For instance, consider the following arrays:

>>> import numpy as np
>>> X = np.random.randn(2, 3, 4)
>>> Y = np.random.randn(3, 5)
>>> Z = np.random.randn(4, 2)

Then, the Einstein summation can be used as:

>>> np.einsum('abc,bd,ca->da', X, Y, Z)
array([[...]])

SumMultiply node can be used similarly for Gaussian nodes. For instance, consider the following Gaussian nodes:

>>> from bayespy.nodes import GaussianARD
>>> X = GaussianARD(0, 1, shape=(2, 3, 4))
>>> Y = GaussianARD(0, 1, shape=(3, 5))
>>> Z = GaussianARD(0, 1, shape=(4, 2))

Then, similarly to numpy.einsum, SumMultiply could be used as:

>>> from bayespy.nodes import SumMultiply
>>> SumMultiply('abc,bd,ca->da', X, Y, Z)
<bayespy.inference.vmp.nodes.dot.SumMultiply object at 0x...>

or

>>> SumMultiply(X, [0,1,2], Y, [1,3], Z, [2,0], [3,0])
<bayespy.inference.vmp.nodes.dot.SumMultiply object at 0x...>

which is similar to the alternative syntax of numpy.einsum.

This node operates similarly as numpy.einsum. However, you must use all the elements of each node, that is, an operation like np.einsum(‘ii->i’,X) is not allowed. Thus, for each node, each axis must be given unique id. The id identifies which axes correspond to which axes between the different nodes. Also, Ellipsis (‘...’) is not yet supported for simplicity. It would also have some problems with constant inputs (because how to determine ndim), so let us just forget it for now.

Each output axis must appear in the input mappings.

The keys must refer to variable dimension axes only, not plate axes.

The input nodes may be Gaussian-gamma (isotropic) nodes.

The output message is Gaussian-gamma (isotropic) if any of the input nodes is Gaussian-gamma.

Notes

This operation can be extremely slow if not used wisely. For large and complex operations, it is sometimes more efficient to split the operation into multiple nodes. For instance, the example above could probably be computed faster by

>>> XZ = SumMultiply(X, [0,1,2], Z, [2,0], [0,1])
>>> F = SumMultiply(XZ, [0,1], Y, [1,2], [2,0])

because the third axis (‘c’) could be summed out already in the first operation. This same effect applies also to numpy.einsum in general.

Examples

Sum over the rows: ‘ij->j’

Inner product of three vectors: ‘i,i,i’

Matrix-vector product: ‘ij,j->i’

Matrix-matrix product: ‘ik,kj->ij’

Outer product: ‘i,j->ij’

Vector-matrix-vector product: ‘i,ij,j’

__init__(Node1, map1, Node2, map2, ..., NodeN, mapN[, map_out])[source]

Methods

__init__(Node1, map1, Node2, map2, ..., ...)
add_plate_axis(to_plate)
broadcasting_multiplier(plates, *args)
delete() Delete this node and the children
get_mask()
get_moments()
get_parameters()
get_pdf_nodes()
get_shape(ind)
has_plotter() Return True if the node has a plotter
lower_bound_contribution([gradient])
move_plates(from_plate, to_plate)
plot([fig]) Plot the node distribution using the plotter of the node
random()
set_plotter(plotter)

Attributes

plates
plates_multiplier Plate multiplier is applied to messages to parents