Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tucker als #53

Merged
merged 1 commit into from
Feb 21, 2023
Merged

Tucker als #53

merged 1 commit into from
Feb 21, 2023

Conversation

ntjohnson1
Copy link
Collaborator

This is a single commit on top of #51. Mostly was using it as a sanity check of ttensor while I waited on approval to put up PR. Surprisingly required no changes to ttensor.

Two notes listed as TODO in the PR:

  • If normresidual is supposed to have an abs inside the square root (the Tucker_als papers are behind papers and I didn't dig that hard. Not immediately obvious that normX should always be larger) then we should probably push that to MATLAB tensortoolbox as well
  • tensor.ttm has an ambiguity in python because there is no negative zero. I special cased for this PR since we only use it one location. However tensor.ttm(dims=None, exclude_dims=None) is probably more explicit and avoids this subtle bug where you get only the first index instead of all but the first when using -n

@dmdunla dmdunla merged commit e1cb81f into sandialabs:main Feb 21, 2023
@ntjohnson1 ntjohnson1 deleted the tucker_als branch February 23, 2023 00:58
@dmdunla
Copy link
Collaborator

dmdunla commented Mar 4, 2023

@ntjohnson1 Can you provide an example where the norm of the tensor squared is less than the norm of the core squared? I cannot reproduce this in MATLAB.

@ntjohnson1
Copy link
Collaborator Author

@dmdunla this is from the test_tucker_als file

import numpy as np
import pyttb as ttb
data = np.array([[29, 39.], [63., 85.]])
shape = (2, 2)
params = {'data': data, 'shape': shape}
tensorInstance = ttb.tensor().from_data(data, shape)
(Solution, Uinit, output) = ttb.tucker_als(tensorInstance, 2)

With the absolute value I get something like:

 NormX: 116.43023662262307 Core norm: 129.9474584138604
 Iter 0: fit = 5.043460e-01 fitdelta = 5.0e-01
 NormX: 116.43023662262307 Core norm: 116.43023662262307
 Iter 1: fit = 1.000000e+00 fitdelta = 5.0e-01
 NormX: 116.43023662262307 Core norm: 116.43023662262307
 Iter 2: fit = 1.000000e+00 fitdelta = 0.0e+00

When I remove the absolute value I get nans for fit and fitdelta.

It's certainly possible there is a bug in my implementation so we could pick an example that converges in MATLAB and do a comparison. Or could try this one in MATLAB to see. I did get access to the Tucker references and based on my understanding there isn't a hard requirement for normX to always be greater than the core norm.

@ntjohnson1
Copy link
Collaborator Author

@dmdunla this was bothering me so I got my hands on the MATLAB free trial. There is a small but in ttm for ttensor that I will put up a fix for in a minute. It's related to zero vs one indexing as pointed out in this issue already actually #62

However, this absolute value issue is relevant but not a bug in the MATLAB tensortoolbox but is hidden based on the formatted printing:

>>> data = [29.,39.;63.,85.];
a_tensor = tensor(data);
Uinit = cell(2,1);
Uinit{2} = [0.05511886, 0.31326444; 0.28527485, 0.41035856];
result = tucker_als(a_tensor, 2, 'init', Uinit);
normx = norm(a_tensor);
normcore = norm(result.core);
fit = 1 - (sqrt(normx^2 - normcore^2)/normx);
fprintf('fit = %e', fit)

Results in:
fit = 1.000000e+00
However if we print the variable itself it is complex

fit

fit =

                      1 -   1.6381901198008e-08i

This doesn't seem to cause issues for MATLAB because apparently if we compare fit to a real it only considers the real portion so fit > 0 is true and fit < 2 is also true.

dmdunla added a commit that referenced this pull request Jun 2, 2023
* Update nvecs to use tenmat.

* Full implementation of collapse. Required implementation of tensor.from_tensor_type for tenmat objects. Updated tensor tests. (#32)

* Update __init__.py

Bump version.

* Create CHANGELOG.md

Changelog update

* Update CHANGELOG.md

Consistent formatting

* Update CHANGELOG.md

Correction

* Create ci-tests.yml

* Update README.md

Adding coverage statistics from coveralls.io

* Create requirements.txt

* 33 use standard license (#34)

* Use standard, correctly formatted LICENSE

* Delete LICENSE

* Create LICENSE

* Update and rename ci-tests.yml to regression-tests.yml

* Update README.md

* Fix bug in tensor.mttkrp that only showed up when ndims > 3. (#36)

* Update __init__.py

Bump version

* Bump version

* Adding files to support pypi dist creation and uploading

* Fix PyPi installs. Bump version.

* Fixing np.reshape usage. Adding more tests for tensor.ttv. (#38)

* Fixing issues with np.reshape; requires order='F' to align with Matlab functionality. (#39)

Closes #30 .

* Bump version.

* Adding tensor.ttm. Adding use case in tenmat to support ttm testing. (#40)

Closes #27

* Bump version

* Format CHANGELOG

* Update CHANGELOG.md

* pypi puslishing action on release

* Allowing rdims or cdims to be empty array. (#43)

Closes #42

* Adding  tensor.ttt implementation. (#44)

Closes 28

* Bump version

* Implement ktensor.score and associated tests.

* Changes to supporting pyttb data classes and associated tests to enable ktensor.score.

* Bump version.

* Compatibility with numpy 1.24.x (#49)

Close #48 

* Replace "numpy.float" with equivalent "float"

numpy.float was deprecated in 1.20 and removed in 1.24

* sptensor.ttv: support 'vector' being a plain list

(rather than just numpy.ndarray). Backwards compatible - an ndarray
argument still works. This is because in newer numpy, it's not allowed to do
np.array(list) where the elements of list are ndarrays of different shapes.

* Make ktensor.innerprod call ttv with 'vector' as plain list

(instead of numpy.ndarray, because newer versions don't allow ragged arrays)

* tensor.ttv: avoid ragged numpy arrays

* Fix two unit test failures due to numpy related changes

* More numpy updates

- numpy.int is removed - use int instead
- don't try to construct ragged/inhomogeneous numpy arrays in tests.
  Use plain lists of vectors instead

* Fix typo in assert message

* Let ttb.tt_dimscheck catch empty input error

In the three ttv methods, ttb.tt_dimscheck checks that 'vector' argument
is not an empty list/ndarray. Revert previous changes that checked for this
before calling tt_dimscheck.

* Bump version

* TENSOR: Fix slices ref shen return value isn't scalar or vector. #41 (#50)

Closes #41

* Ttensor implementation (#51)

* TENSOR: Fix slices ref shen return value isn't scalar or vector. #41

* TTENSOR: Add tensor creation (partial support of core tensor types) and display

* SPTENSOR: Add numpy scalar type for multiplication filter.

* TTENSOR: Double, full, isequal, mtimes, ndims, size, uminus, uplus, and partial innerprod.

* TTENSOR: TTV (finishes innerprod), mttkrp, and norm

* TTENSOR: TTM, permute and minor cleanup.

* TTENSOR: Reconstruct

* TTENSOR: Nvecs

* SPTENSOR:
* Fix argument mismatch for ttm (modes s.b. dims)
* Fix ttm for rectangular matrices
* Make error message consitent with tensor
TENSOR:
* Fix error message

* TTENSOR: Improve test coverage and corresponding bug fixes discovered.

* Test coverage (#52)

* SPTENSOR:
* Fix argument mismatch for ttm (modes s.b. dims)
* Fix ttm for rectangular matrices
* Make error message consitent with tensor
TENSOR:
* Fix error message

* SPTENSOR: Improve test coverage, replace prints, and some doc string fixes.

* PYTTUB_UTILS: Improve test coverage

* TENMAT: Remove impossible condition. Shape is a property, the property handles the (0,) shape condition. So ndims should never see it.

* TENSOR: Improve test coverage. One line left, but logic of setitem is unclear without MATLAB validation of behavior.

* CP_APR: Add tests fpr sptensor, and corresponding bug fixes to improve test coverage.

---------

Co-authored-by: Danny Dunlavy <[email protected]>

* Bump version

* TUCKER_ALS: Add tucker_als to validate ttucker implementation. (#53)

* Bump version of actions (#55)

actions/setup-python@v4 to avoid deprecation warnings

* Tensor docs plus Linting and Typing and Black oh my (#54)

* TENSOR: Apply black and enforce it

* TENSOR: Add isort and pylint. Fix to pass then enforce

* TENSOR: Variety of linked fixes:
* Add mypy type checking
* Update infrastructure for validating package
* Fix doc tests and add more examples

* DOCTEST: Add doctest automatically to regression
* Fix existing failures

* DOCTEST: Fix non-uniform array

* DOCTEST: Fix precision errors in example

* AUTOMATION: Add test directory otherwise only doctests run

* TENSOR: Fix bad rebase from numpy fix

* Auto formatting (#60)

* COVERAGE: Fix some coverage regressions from pylint PR

* ISORT: Run isort on source and tests

* BLACK: Run black on source and tests

* BLACK: Run black on source and tests

* FORMATTING: Add tests and verification for autoformatting

* FORMATTING: Add black/isort to root to simplify

* Add preliminary contributor guide instructions

Closes #59

* TUCKER_ALS: TTM with negative values is broken in ttensor (#62) (#66)

* Replace usage in tucker_als
* Update test for tucker_als to ensure result matches expectation
* Add early error handling in ttensor ttm for negative dims

* Hosvd (#67)

* HOSVD: Preliminary outline of core functionality

* HOSVD: Fix numeric bug
* Was slicing incorrectly
* Update test to check convergence

* HOSVD: Finish output and test coverage

* TENSOR: Prune numbers real
* Real and mypy don't play nice python/mypy#3186
* This allows partial typing support of HOSVD

* Add test that matches TTB for MATLAB output of HOSVD (#79)

This closes #78

* Bump version (#81)

Closes #80

* Lint pyttb_utils and lint/type sptensor (#77)

* PYTTB_UTILS: Fix and enforce pylint

* PYTTB_UTILS: Pull out utility only used internally in sptensor

* SPTENSOR: Fix and enforce pylint

* SPTENSOR: Initial pass a typing support

* SPTENSOR: Complete initial typing coverage

* SPTENSOR: Fix test coverage from typing changes.

* PYLINT: Update test to lint files in parallel to improve dev experience.

* HOSVD: Negative signs can be permuted for equivalent decomposition (#82)

* Pre commit (#83)

* Setup and pyproject are redundant. Remove and resolve install issue

* Try adding pre-commit hooks

* Update Makefile for simplicity and add notes to contributor guide.

* Make pre-commit optional opt-in

* Make regression tests use simplified dependencies so we track fewer places.

* Using dynamic version in pyproject.toml to reduce places where version is set. (#86)

* Adding shell=True to subprocess.run() calls (#87)

* Adding Nick to authors (#89)

* Release prep (#90)

* Fix author for PyPI. Bump to dev version.

* Exclude dims (#91)

* Explicit Exclude_dims:
* Updated tt_dimscheck
* Update all uses of tt_dimscheck and propagate interface

* Add test coverage for exclude dims changes

* Tucker_als: Fix workaround that motivated exclude_dims

* Bump version

* Spelling

* Tensor generator helpers (#93)

* TENONES: Add initial tenones support

* TENZEROS: Add initial tenzeros support

* TENDIAG: Add initial tendiag support

* SPTENDIAG: Add initial sptendiag support

* Link in autodocumentation for recently added code: (#98)

* TTENSOR, HOSVD, TUCKER_ALS, Tensor generators

* Remove warning for nvecs: (#99)

* Make debug level log for now
* Remove test enforcement

* Rand generators (#100)

* Non-functional change:
* Fix numpy deprecation warning, logic should be equivalent

* Tenrand initial implementation

* Sptenrand initial implementation

* Complete pass on ktensor docs. (#101)

* Bump version

* Bump version

* Trying to fix coveralls

* Trying coveralls github action

* Fixing arrange and normalize. (#103)

* Fixing arrange and normalize.

* Merge main (#104)

* Trying to fix coveralls

* Trying coveralls github action

* Rename contributor guide for github magic (#106)

* Rename contributor guide for github magic

* Update reference to contributor guide from README

* Fixed the mean and stdev typo for cp_als (#117)

* Changed cp_als() param 'tensor' to 'input_tensor' to avoid ambiguity (#118)

* Changed cp_als() param 'tensor' to 'input_tensor' to avoid ambiguity

* Formatted changes with isort and black.

* Updated all `tensor`-named paramteres to `input_tensor`, including in docs (#120)

* Tensor growth (#109)

* Tensor.__setitem__: Break into methods
* Non-functional change to make logic flow clearer

* Tensor.__setitem__: Fix some types to resolve edge cases

* Sptensor.__setitem__: Break into methods
* Non-functional change to make flow clearer

* Sptensor.__setitem__: Catch additional edge cases in sptensor indexing

* Tensor.__setitem__: Catch subtensor additional dim growth

* Tensor indexing (#116)

* Tensor.__setitem__/__getitem__: Fix linear index
* Before required numpy array now works on value/slice/Iterable

* Tensor.__getitem__: Fix subscripts usage
* Consistent with setitem now
* Update usages (primarily in sptensor)

* Sptensor.__setitem__/__getitem__: Fix subscripts usage
* Consistent with tensor and MATLAB now
* Update test usage

* sptensor: Add coverage for improved indexing capability

* tensor: Add coverage for improved indexing capability

---------

Co-authored-by: brian-kelley <[email protected]>
Co-authored-by: ntjohnson1 <[email protected]>
Co-authored-by: Dunlavy <[email protected]>
Co-authored-by: DeepBlockDeepak <[email protected]>
dmdunla added a commit that referenced this pull request Jun 3, 2023
* Merge latest updates (#124)

* Update nvecs to use tenmat.

* Full implementation of collapse. Required implementation of tensor.from_tensor_type for tenmat objects. Updated tensor tests. (#32)

* Update __init__.py

Bump version.

* Create CHANGELOG.md

Changelog update

* Update CHANGELOG.md

Consistent formatting

* Update CHANGELOG.md

Correction

* Create ci-tests.yml

* Update README.md

Adding coverage statistics from coveralls.io

* Create requirements.txt

* 33 use standard license (#34)

* Use standard, correctly formatted LICENSE

* Delete LICENSE

* Create LICENSE

* Update and rename ci-tests.yml to regression-tests.yml

* Update README.md

* Fix bug in tensor.mttkrp that only showed up when ndims > 3. (#36)

* Update __init__.py

Bump version

* Bump version

* Adding files to support pypi dist creation and uploading

* Fix PyPi installs. Bump version.

* Fixing np.reshape usage. Adding more tests for tensor.ttv. (#38)

* Fixing issues with np.reshape; requires order='F' to align with Matlab functionality. (#39)

Closes #30 .

* Bump version.

* Adding tensor.ttm. Adding use case in tenmat to support ttm testing. (#40)

Closes #27

* Bump version

* Format CHANGELOG

* Update CHANGELOG.md

* pypi puslishing action on release

* Allowing rdims or cdims to be empty array. (#43)

Closes #42

* Adding  tensor.ttt implementation. (#44)

Closes 28

* Bump version

* Implement ktensor.score and associated tests.

* Changes to supporting pyttb data classes and associated tests to enable ktensor.score.

* Bump version.

* Compatibility with numpy 1.24.x (#49)

Close #48 

* Replace "numpy.float" with equivalent "float"

numpy.float was deprecated in 1.20 and removed in 1.24

* sptensor.ttv: support 'vector' being a plain list

(rather than just numpy.ndarray). Backwards compatible - an ndarray
argument still works. This is because in newer numpy, it's not allowed to do
np.array(list) where the elements of list are ndarrays of different shapes.

* Make ktensor.innerprod call ttv with 'vector' as plain list

(instead of numpy.ndarray, because newer versions don't allow ragged arrays)

* tensor.ttv: avoid ragged numpy arrays

* Fix two unit test failures due to numpy related changes

* More numpy updates

- numpy.int is removed - use int instead
- don't try to construct ragged/inhomogeneous numpy arrays in tests.
  Use plain lists of vectors instead

* Fix typo in assert message

* Let ttb.tt_dimscheck catch empty input error

In the three ttv methods, ttb.tt_dimscheck checks that 'vector' argument
is not an empty list/ndarray. Revert previous changes that checked for this
before calling tt_dimscheck.

* Bump version

* TENSOR: Fix slices ref shen return value isn't scalar or vector. #41 (#50)

Closes #41

* Ttensor implementation (#51)

* TENSOR: Fix slices ref shen return value isn't scalar or vector. #41

* TTENSOR: Add tensor creation (partial support of core tensor types) and display

* SPTENSOR: Add numpy scalar type for multiplication filter.

* TTENSOR: Double, full, isequal, mtimes, ndims, size, uminus, uplus, and partial innerprod.

* TTENSOR: TTV (finishes innerprod), mttkrp, and norm

* TTENSOR: TTM, permute and minor cleanup.

* TTENSOR: Reconstruct

* TTENSOR: Nvecs

* SPTENSOR:
* Fix argument mismatch for ttm (modes s.b. dims)
* Fix ttm for rectangular matrices
* Make error message consitent with tensor
TENSOR:
* Fix error message

* TTENSOR: Improve test coverage and corresponding bug fixes discovered.

* Test coverage (#52)

* SPTENSOR:
* Fix argument mismatch for ttm (modes s.b. dims)
* Fix ttm for rectangular matrices
* Make error message consitent with tensor
TENSOR:
* Fix error message

* SPTENSOR: Improve test coverage, replace prints, and some doc string fixes.

* PYTTUB_UTILS: Improve test coverage

* TENMAT: Remove impossible condition. Shape is a property, the property handles the (0,) shape condition. So ndims should never see it.

* TENSOR: Improve test coverage. One line left, but logic of setitem is unclear without MATLAB validation of behavior.

* CP_APR: Add tests fpr sptensor, and corresponding bug fixes to improve test coverage.

---------

Co-authored-by: Danny Dunlavy <[email protected]>

* Bump version

* TUCKER_ALS: Add tucker_als to validate ttucker implementation. (#53)

* Bump version of actions (#55)

actions/setup-python@v4 to avoid deprecation warnings

* Tensor docs plus Linting and Typing and Black oh my (#54)

* TENSOR: Apply black and enforce it

* TENSOR: Add isort and pylint. Fix to pass then enforce

* TENSOR: Variety of linked fixes:
* Add mypy type checking
* Update infrastructure for validating package
* Fix doc tests and add more examples

* DOCTEST: Add doctest automatically to regression
* Fix existing failures

* DOCTEST: Fix non-uniform array

* DOCTEST: Fix precision errors in example

* AUTOMATION: Add test directory otherwise only doctests run

* TENSOR: Fix bad rebase from numpy fix

* Auto formatting (#60)

* COVERAGE: Fix some coverage regressions from pylint PR

* ISORT: Run isort on source and tests

* BLACK: Run black on source and tests

* BLACK: Run black on source and tests

* FORMATTING: Add tests and verification for autoformatting

* FORMATTING: Add black/isort to root to simplify

* Add preliminary contributor guide instructions

Closes #59

* TUCKER_ALS: TTM with negative values is broken in ttensor (#62) (#66)

* Replace usage in tucker_als
* Update test for tucker_als to ensure result matches expectation
* Add early error handling in ttensor ttm for negative dims

* Hosvd (#67)

* HOSVD: Preliminary outline of core functionality

* HOSVD: Fix numeric bug
* Was slicing incorrectly
* Update test to check convergence

* HOSVD: Finish output and test coverage

* TENSOR: Prune numbers real
* Real and mypy don't play nice python/mypy#3186
* This allows partial typing support of HOSVD

* Add test that matches TTB for MATLAB output of HOSVD (#79)

This closes #78

* Bump version (#81)

Closes #80

* Lint pyttb_utils and lint/type sptensor (#77)

* PYTTB_UTILS: Fix and enforce pylint

* PYTTB_UTILS: Pull out utility only used internally in sptensor

* SPTENSOR: Fix and enforce pylint

* SPTENSOR: Initial pass a typing support

* SPTENSOR: Complete initial typing coverage

* SPTENSOR: Fix test coverage from typing changes.

* PYLINT: Update test to lint files in parallel to improve dev experience.

* HOSVD: Negative signs can be permuted for equivalent decomposition (#82)

* Pre commit (#83)

* Setup and pyproject are redundant. Remove and resolve install issue

* Try adding pre-commit hooks

* Update Makefile for simplicity and add notes to contributor guide.

* Make pre-commit optional opt-in

* Make regression tests use simplified dependencies so we track fewer places.

* Using dynamic version in pyproject.toml to reduce places where version is set. (#86)

* Adding shell=True to subprocess.run() calls (#87)

* Adding Nick to authors (#89)

* Release prep (#90)

* Fix author for PyPI. Bump to dev version.

* Exclude dims (#91)

* Explicit Exclude_dims:
* Updated tt_dimscheck
* Update all uses of tt_dimscheck and propagate interface

* Add test coverage for exclude dims changes

* Tucker_als: Fix workaround that motivated exclude_dims

* Bump version

* Spelling

* Tensor generator helpers (#93)

* TENONES: Add initial tenones support

* TENZEROS: Add initial tenzeros support

* TENDIAG: Add initial tendiag support

* SPTENDIAG: Add initial sptendiag support

* Link in autodocumentation for recently added code: (#98)

* TTENSOR, HOSVD, TUCKER_ALS, Tensor generators

* Remove warning for nvecs: (#99)

* Make debug level log for now
* Remove test enforcement

* Rand generators (#100)

* Non-functional change:
* Fix numpy deprecation warning, logic should be equivalent

* Tenrand initial implementation

* Sptenrand initial implementation

* Complete pass on ktensor docs. (#101)

* Bump version

* Bump version

* Trying to fix coveralls

* Trying coveralls github action

* Fixing arrange and normalize. (#103)

* Fixing arrange and normalize.

* Merge main (#104)

* Trying to fix coveralls

* Trying coveralls github action

* Rename contributor guide for github magic (#106)

* Rename contributor guide for github magic

* Update reference to contributor guide from README

* Fixed the mean and stdev typo for cp_als (#117)

* Changed cp_als() param 'tensor' to 'input_tensor' to avoid ambiguity (#118)

* Changed cp_als() param 'tensor' to 'input_tensor' to avoid ambiguity

* Formatted changes with isort and black.

* Updated all `tensor`-named paramteres to `input_tensor`, including in docs (#120)

* Tensor growth (#109)

* Tensor.__setitem__: Break into methods
* Non-functional change to make logic flow clearer

* Tensor.__setitem__: Fix some types to resolve edge cases

* Sptensor.__setitem__: Break into methods
* Non-functional change to make flow clearer

* Sptensor.__setitem__: Catch additional edge cases in sptensor indexing

* Tensor.__setitem__: Catch subtensor additional dim growth

* Tensor indexing (#116)

* Tensor.__setitem__/__getitem__: Fix linear index
* Before required numpy array now works on value/slice/Iterable

* Tensor.__getitem__: Fix subscripts usage
* Consistent with setitem now
* Update usages (primarily in sptensor)

* Sptensor.__setitem__/__getitem__: Fix subscripts usage
* Consistent with tensor and MATLAB now
* Update test usage

* sptensor: Add coverage for improved indexing capability

* tensor: Add coverage for improved indexing capability

---------

Co-authored-by: brian-kelley <[email protected]>
Co-authored-by: ntjohnson1 <[email protected]>
Co-authored-by: Dunlavy <[email protected]>
Co-authored-by: DeepBlockDeepak <[email protected]>

* Adding tests and data for import_data, export_data, sptensor, ktensor. Small changes in code that was unreachable.

* Updating formatting with black

* More updates for coverage.

* Black formatting updates

* Update regression-tests.yml

Adding verbose to black and isort calls

* Black updated locally to align with CI testing

* Update regression-tests.yml

---------

Co-authored-by: brian-kelley <[email protected]>
Co-authored-by: ntjohnson1 <[email protected]>
Co-authored-by: Dunlavy <[email protected]>
Co-authored-by: DeepBlockDeepak <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants