GithubHelp home page GithubHelp logo

bdusell / semiring-einsum Goto Github PK

View Code? Open in Web Editor NEW
42.0 2.0 8.0 943 KB

Generic PyTorch implementation of einsum that supports different semirings

Home Page: https://bdusell.github.io/semiring-einsum/

License: MIT License

Shell 19.50% Python 80.50%
pytorch einsum semirings

semiring-einsum's Introduction

semiring-einsum's People

Contributors

bdusell avatar ccshan avatar davidweichiang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

semiring-einsum's Issues

More than 26 indices?

torch.einsum limits you to 26 indices but can semiring_einsum provide a non-string interface that allows more than 26?

log_viterbi_einsum_forward raises exception with no summed-out variables

eq = compile_equation('a,a->a')
x = torch.arange(5, dtype=float)
y = torch.arange(5, dtype=float)

log_viterbi_einsum_forward(eq, x, y, block_size=1)

Expected output:
(tensor([0., 2., 4., 6., 8.], dtype=torch.float64), tensor([], size=(5, 0)))

Actual output:

  File ".../torch_semiring_einsum/log_viterbi_forward.py", line 102, in max_argmax_block
    argmax = torch.stack(argmaxes, dim=-1)
RuntimeError: stack expects a non-empty TensorList

Allow repeated and unmatched output indices?

Although the original einsum doesn't allow it, it would be convenient if:

  • einsum('i->ii', torch.tensor([1., 2.])) returns torch.tensor([[1., 0.], [0., 2.]]) (that is, it's like torch.diag_embed)
  • einsum('->i', torch.tensor(1.) returns torch.tensor([1.]) (that is, it's like torch.unsqueeze)

I can imagine that the second proposal is more controversial than the first one.

log_einsum returns nan instead of inf

log_einsum(s.compile_equation(',->'), torch.tensor(2e38), torch.tensor(2e38), block_size=1)

Expected output: torch.tensor(inf)

Actual output: torch.tensor(nan)

sync examples regarding specifying block_size

First of all, thanks very much for this great work! (I'm surprised that I'm only now finding this since it it's been on my wish-list for years! A year or two ago, I also ran into the block_size trade off with my own generalized semiring tensordot implementation, so I'm happy to see that in here, too.)

Related to issue #1 , the examples on the home page don't specify a block_size which leads to a runtime error:

C = torch_semiring_einsum.log_einsum(EQUATION, A, B)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-33-d81285427569> in <module>
----> 1 C = torch_semiring_einsum.log_einsum(EQUATION, A, B)

TypeError: result() missing 1 required keyword-only argument: 'block_size'

Specifying block_size fixes it:

C = torch_semiring_einsum.log_einsum(EQUATION, A, B, block_size=1)

One of the following should probably be done:

  1. update the examples to include the block_size
  2. add a default value for the block_size (this is probably preferred since new users wouldn't need to figure out the block_size thing in order to get started using the package).

Even-better, I wonder about the feasibility of implementing a more reasonable, adaptive default.
From your explanation on #1 , It sounds like you have a reasonable heuristic in mind for block_size as a function of input tensor shapes and available memory (psutil can get access to available memory: e.g. psutil.virtual_memory().available). Maybe that function could be constructed and cached at the same time that the equation is compiled and then block_size=torch_semiring_einsum.heuristic_block_size could indicate that it should be used to compute the block_size? Is it worth opening a separate issue and possibly a pull-request?

(feat): Support For Complex Numbers

Hello! This seems like it would be a huge boost for me, but I need support for complex numbers - any chance I could make a PR? Right now I'm getting:

a = tensor([[[9.9567e-01, 9.9567e-01, 9.9567e-01,  ..., 9.9567e-01,
          9.9567e-01, 9.9567e-01],
         [9.9567e-0...       [1.6774e-05, 1.6774e-05, 1.6774e-05,  ..., 1.6774e-05,
          1.6774e-05, 1.6774e-05]]], dtype=torch.float64)
b = tensor([[[ 0.0000+0.0000j, -0.0024-0.0698j, -0.0097-0.1392j,  ...,
          -0.0219+0.2079j, -0.0097+0.1392j, -0.0024...698j, -0.0097-0.1392j,  ...,
          -0.0219+0.2079j, -0.0097+0.1392j, -0.0024+0.0698j]]],
       requires_grad=True)

    def multiply_in_place(a, b):
>       a.mul_(b)
E       RuntimeError: result type ComplexDouble can't be cast to the desired output type Double

Better error messages

A common error I get is in Equation.validate_sizes():

IndexError: Dimension out of range (expected to be in range of [-1, 0], but got 1)

which is not as clear as the other error message that this function prints out.

out= option

Can an out= option be added to overwite an existing tensor instead of creating a new one?

[feature request] support multiple simultaneous right-hand-sides

I have a situation where many of my formulas come in sets like the following:

'bijklmn,bij,bkl,bm,bn->'
'bijklmn,bij,bkl,bm,bn->bij'
'bijklmn,bij,bkl,bm,bn->bkl'
'bijklmn,bij,bkl,bm,bn->bm'
'bijklmn,bij,bkl,bm,bn->bn'

It seems like there should be a substantial amount of work between these that could be shared, but I might be misunderstanding the way that you are doing the reducing.

If there is a possibility to support more efficient bulk work (or maybe even if there isn't), I'd suggest allowing the above set of formulas to be replaced with the following (which should indicate that *einsum should return a tuple of tensors with the respective results):

'bijklmn,bij,bkl,bm,bn->,bij,bkl,bm,bn'

@bdusell would you please comment on the following when you get a chance:

  1. Are you open to the proposed notation?
  2. Are you open to pull requests?
  3. Do you see an opportunity for reused computation in the above scenario? (after a quick look, it doesn't look as easy as I had initially thought)

Thanks!

Zero-dimensional tensors

Desired behavior:

>>> torch.einsum('->', torch.tensor(1.))
tensor(1.)

Actual behavior:

>>> eq = compile_equation('->')
>>> einsum(eq, torch.tensor(1.), block_size=1)
...
  File ".../torch_semiring_einsum/equation.py", line 159, in lookup
    return arg[index].permute(self.permutation)
IndexError: too many indices for tensor of dimension 0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.