PTB-MR / mrpro

MR image reconstruction and processing.
https://ptb-mr.github.io/mrpro/
Apache License 2.0
13 stars 3 forks source link

Allow adjoint to be used as autograd backward #404

Open fzimmermann89 opened 1 week ago

fzimmermann89 commented 1 week ago

Alternative to #307 using init_subclass as I suggested in #68

fzimmermann89 commented 1 week ago

@ckolbPTB

fzimmermann89 commented 1 week ago

I removed all typing information from init_subclass. Myp will most likely never be able to check inside the autograd wrapper anyways and if I am not mistaken,currently mypy will works as-if there was no adjoint wrapper. The forward, the adjoint and all calls of these will still be type checked.

github-actions[bot] commented 1 week ago

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/mrpro/algorithms/csm
   inati.py24196%44
   iterative_walsh.py15193%37
src/mrpro/algorithms/dcf
   dcf_voronoi.py53492%15, 48–49, 76
src/mrpro/algorithms/optimizers
   adam.py20195%69
src/mrpro/algorithms/reconstruction
   DirectReconstruction.py281643%51–71, 85
   IterativeSENSEReconstruction.py422345%77–78, 88–98, 113–124, 138–149
   Reconstruction.py512453%41, 53–55, 79–86, 103–114
src/mrpro/data
   AcqInfo.py128298%174, 214
   CsmData.py28389%14, 84–86
   DcfData.py44882%17, 65, 77–82
   IData.py67987%119, 125, 129, 159–167
   IHeader.py75791%75, 109, 127–131
   KHeader.py1641790%24, 126–130, 157, 207, 218, 225–226, 229, 236, 275–286
   KNoise.py311552%39–52, 56–61
   KTrajectory.py69593%178–182
   MoveDataMixin.py1261489%14, 109, 125, 139–141, 202, 265, 279, 358, 378–379, 396–397
   QData.py39782%42, 65–73
   SpatialDimension.py46296%64, 103
   TrajectoryDescription.py14193%23
   acq_filters.py10190%47
src/mrpro/data/_kdata
   KData.py1051685%107–108, 117, 125, 179–180, 215, 220–221, 240–251
   KDataRemoveOsMixin.py29293%43, 45
   KDataSelectMixin.py20290%46, 62
   KDataSplitMixin.py48394%49, 79, 88
src/mrpro/data/traj_calculators
   KTrajectoryCalculator.py25292%23, 45
   KTrajectoryIsmrmrd.py13285%41, 50
   KTrajectoryPulseq.py29197%54
src/mrpro/operators
   CartesianSamplingOp.py50982%49–50, 55–56, 61–62, 88, 91, 114
   ConstraintsOp.py60297%46, 48
   EndomorphOperator.py51296%209, 213
   FiniteDifferenceOp.py27293%48, 113
   FourierOp.py77199%131
   GridSamplingOp.py123993%60–61, 70–71, 78–79, 82, 84, 86
   LinearOperator.py1021189%34, 42–43, 47, 51, 75–79, 87, 186, 314
   Operator.py52198%21
   SliceProjectionOp.py166895%39, 46, 48, 54, 191, 212, 245, 285
   WaveletOp.py120596%152, 170, 205, 210, 233
   ZeroPadOp.py16194%30
src/mrpro/utils
   Rotation.py4532894%58–66, 106, 283, 368, 370, 397, 452, 457, 460, 475, 492, 497, 640, 645, 648, 664, 668, 742, 744, 752–753, 993, 1075
   filters.py62297%44, 49
   slice_profiles.py45687%18, 34, 111–114, 147
   sliding_window.py34197%34
   split_idx.py10280%43, 47
   summarize_tensorvalues.py11918%20–29
   zero_pad_or_crop.py31681%26, 30, 54, 57, 60, 63
TOTAL363829492% 

Tests Skipped Failures Errors Time
828 0 :zzz: 0 :x: 0 :fire: 1m 7s :stopwatch:
fzimmermann89 commented 1 week ago

There is a fundamental issue with using the adjoint as the backward:

During the forward inside the wrapper, autograd is disabled. Thus gradients from any parameters of self do not flow to the output. This means, looking at for example the gridsampleop, the gradient wrt x of the operator will work, the gradient wrt the grid will not work.

this is difficult to solve without using a custom solution for each linearop.

We might be able to use it for operators that do not depend on any other tensor. But most of our operators will then not be covered by the solution:

no idea how to pursue.

maybe we just do a custom autograd for the fourier operator?

@schuenke @ckolbPTB

ckolbPTB commented 1 week ago

There is a fundamental issue with using the adjoint as the backward:

That is a shame!

maybe we just do a custom autograd for the fourier operator?

Can we provide an custom gradient wrt to x but use pytorch autograd wrt to e.g. traj or would we have to provide our own autograd functionality for each parameter?

fzimmermann89 commented 1 week ago

Torchkbnuftt also does not work for traj requiring gradients afaik.

We could

As I started doing that work in the torchkbnuftt repo already and we can look up the equations in https://arxiv.org/abs/2111.02912 and the finnuft pytorch wrapper.

I will try to mock something up tonight or tomorrow morning

fzimmermann89 commented 4 days ago

Now this can be enabled for operators, using the adjoint_as_backward setting, i.e. class Op(LinearOperator, adjoint_as_backward=True). The default is false, it has to be enabled for each Operator that should use this.