<div dir="ltr">also - to take away a bit of the &quot;mystery&quot; surrounding v4 optimization, let&#39;s see how the gradient descent AdvanceOneStep function works:<div><br></div><div><div>void</div><div>GradientDescentOptimizerv4</div>

<div>::AdvanceOneStep()</div><div>{</div><div>  itkDebugMacro(&quot;AdvanceOneStep&quot;);</div><div><br></div><div>  /* Begin threaded gradient modification.</div><div>   * Scale by gradient scales, then estimate the learning</div>

<div>   * rate if options are set to (using the scaled gradient),</div><div>   * then modify by learning rate. The m_Gradient variable</div><div>   * is modified in-place. */</div><div>  this-&gt;ModifyGradientByScales();</div>

<div>  this-&gt;EstimateLearningRate();</div><div>  this-&gt;ModifyGradientByLearningRate();</div><div><br></div><div>  try</div><div>    {</div><div>    /* Pass graident to transform and let it do its own updating */</div>

<div>    this-&gt;m_Metric-&gt;UpdateTransformParameters( this-&gt;m_Gradient );</div><div>    }</div><div>  catch ( ExceptionObject &amp; )</div><div>    {</div><div>    this-&gt;m_StopCondition = UPDATE_PARAMETERS_ERROR;</div>

<div>    this-&gt;m_StopConditionDescription &lt;&lt; &quot;UpdateTransformParameters error&quot;;</div><div>    this-&gt;StopOptimization();</div><div><br></div><div>    // Pass exception to caller</div><div>    throw;</div>

<div>    }</div><div><br></div><div>  this-&gt;InvokeEvent( IterationEvent() );</div><div>}</div><div><br></div><div><br></div><div style>i hope this does not look too convoluted.  then the base metric class does this:</div>

<div><br></div><div><div>template&lt;unsigned int TFixedDimension, unsigned int TMovingDimension, class TVirtualImage&gt;</div><div>void</div><div>ObjectToObjectMetric&lt;TFixedDimension, TMovingDimension, TVirtualImage&gt;</div>

<div>::UpdateTransformParameters( const DerivativeType &amp; derivative, ParametersValueType factor )</div><div>{</div><div>  /* Rely on transform::UpdateTransformParameters to verify proper</div><div>   * size of derivative */</div>

<div>  this-&gt;m_MovingTransform-&gt;UpdateTransformParameters( derivative, factor );</div><div>}</div></div><div><br></div><div><br></div><div style>so the transform parameters should be updated in a way that is consistent with: </div>

</div><div style><br></div><div style><span style="color:rgb(80,0,80);font-family:arial,sans-serif;font-size:13px">newPosition[j] = currentPosition[j] + transformedGradient[j] * factor / scales[j];</span><br style="color:rgb(80,0,80);font-family:arial,sans-serif;font-size:13px">

</div><div style><span style="color:rgb(80,0,80);font-family:arial,sans-serif;font-size:13px"><br></span></div><div style><font color="#500050" face="arial, sans-serif">factor defaults to 1 ....  anyway, as you can infer from the above discussion, even the basic gradient descent optimizer can be used to take &quot; regular steps &quot;  if you want.</font></div>

<div style><br></div></div><div class="gmail_extra"><br clear="all"><div><div><br></div>brian<br><div><br></div><div><br></div></div>
<br><br><div class="gmail_quote">On Tue, May 7, 2013 at 10:23 AM, brian avants <span dir="ltr">&lt;<a href="mailto:stnava@gmail.com" target="_blank">stnava@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div dir="ltr">brad<div><br></div><div>did this issue ever go up on jira?  i do remember discussing with you at a meeting.   our solution is in the v4 optimizers.</div><div><br></div><div>the trivial additive parameter update doesnt work in more general cases e.g. when you need to compose parameters with parameter updates. </div>


<div><br></div><div>to resolve this limitation, the v4 optimizers pass the update step to the transformations </div><div><br></div><div>this implements the idea that  &quot; the transforms know how to update themselves &quot; </div>


<div><br></div><div>there are several other differences, as nick pointed out, that reduce the need for users to experiment with scales .</div><div><br></div><div>for basic scenarios like that being discussed by joel, i prefer the conjugate gradient optimizer with line search. </div>


<div><br></div><div><div>itkConjugateGradientLineSearchOptimizerv4.h</div><div><br></div><div>when combined with the scale estimators, this leads to registration algorithms with very few parameters to tune.   1 parameter if you dont consider multi-resolution.</div>

<span class="HOEnZb"><font color="#888888">
</font></span></div></div><div class="gmail_extra"><span class="HOEnZb"><font color="#888888"><br clear="all"><div><div><br></div>brian<br><div><br></div><div><br></div></div></font></span><div><div class="h5">
<br><br><div class="gmail_quote">On Tue, May 7, 2013 at 9:27 AM, Nick Tustison <span dir="ltr">&lt;<a href="mailto:ntustison@gmail.com" target="_blank">ntustison@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


Hi Brad,<br>
<br>
I certainly don&#39;t disagree with Joel&#39;s findings.  It seems like a<br>
good fix which should be put up on gerrit.  There were several<br>
components that we kept in upgrading the registration framework.<br>
The optimizers weren&#39;t one of them.<br>
<br>
Also, could you elaborate a bit more on the &quot;convoluted&quot; aspects<br>
of parameter advancement?  There&#39;s probably a reason for it and<br>
we could explain why.<br>
<span><font color="#888888"><br>
Nick<br>
</font></span><div><div><br>
<br>
<br>
On May 7, 2013, at 8:58 AM, Bradley Lowekamp &lt;<a href="mailto:blowekamp@mail.nih.gov" target="_blank">blowekamp@mail.nih.gov</a>&gt; wrote:<br>
<br>
&gt; Nick,<br>
&gt;<br>
&gt; What we are observing is an algorithmic bug in the RegularStepGradientOptimzer. The ITKv4 optimizers have quite a convoluted way to advance the parameters, and likely don&#39;t contain this bug.<br>
&gt;<br>
&gt;<br>
&gt; I think the figure Joel put together does a good job of illustrating the issue:<br>
&gt;<br>
&gt; <a href="http://i.imgur.com/DE6xqQ5.pnggithu" target="_blank">http://i.imgur.com/DE6xqQ5.pnggithu</a><br>
&gt;<br>
&gt;<br>
&gt; It just I think the math here:<br>
&gt; <a href="https://github.com/Kitware/ITK/blob/master/Modules/Numerics/Optimizers/src/itkRegularStepGradientDescentOptimizer.cxx#L44" target="_blank">https://github.com/Kitware/ITK/blob/master/Modules/Numerics/Optimizers/src/itkRegularStepGradientDescentOptimizer.cxx#L44</a><br>



&gt;<br>
&gt; newPosition[j] = currentPosition[j] + transformedGradient[j] * factor;<br>
&gt;<br>
&gt; should be:<br>
&gt;<br>
&gt; newPosition[j] = currentPosition[j] + transformedGradient[j] * factor / scales[j];<br>
&gt;<br>
&gt; Brad<br>
&gt;<br>
&gt;<br>
&gt; On May 7, 2013, at 8:07 AM, Nick Tustison &lt;<a href="mailto:ntustison@gmail.com" target="_blank">ntustison@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt;&gt; Not quite.  See below for a relevant block of code.<br>
&gt;&gt; The optimizer can take an optional scales estimator.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;   typedef itk::RegistrationParameterScalesFromPhysicalShift&lt;MetricType&gt; ScalesEstimatorType;<br>
&gt;&gt;   typename ScalesEstimatorType::Pointer scalesEstimator = ScalesEstimatorType::New();<br>
&gt;&gt;   scalesEstimator-&gt;SetMetric( singleMetric );<br>
&gt;&gt;   scalesEstimator-&gt;SetTransformForward( true );<br>
&gt;&gt;<br>
&gt;&gt;   typedef itk::ConjugateGradientLineSearchOptimizerv4 ConjugateGradientDescentOptimizerType;<br>
&gt;&gt;   typename ConjugateGradientDescentOptimizerType::Pointer optimizer = ConjugateGradientDescentOptimizerType::New();<br>
&gt;&gt;   optimizer-&gt;SetLowerLimit( 0 );<br>
&gt;&gt;   optimizer-&gt;SetUpperLimit( 2 );<br>
&gt;&gt;   optimizer-&gt;SetEpsilon( 0.2 );<br>
&gt;&gt;   //    optimizer-&gt;SetMaximumLineSearchIterations( 20 );<br>
&gt;&gt;   optimizer-&gt;SetLearningRate( learningRate );<br>
&gt;&gt;   optimizer-&gt;SetMaximumStepSizeInPhysicalUnits( learningRate );<br>
&gt;&gt;   optimizer-&gt;SetNumberOfIterations( currentStageIterations[0] );<br>
&gt;&gt;   optimizer-&gt;SetScalesEstimator( scalesEstimator );<br>
&gt;&gt;   optimizer-&gt;SetMinimumConvergenceValue( convergenceThreshold );<br>
&gt;&gt;   optimizer-&gt;SetConvergenceWindowSize( convergenceWindowSize );<br>
&gt;&gt;   optimizer-&gt;SetDoEstimateLearningRateAtEachIteration( this-&gt;m_DoEstimateLearningRateAtEachIteration );<br>
&gt;&gt;   optimizer-&gt;SetDoEstimateLearningRateOnce( !this-&gt;m_DoEstimateLearningRateAtEachIteration );<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; On May 7, 2013, at 8:01 AM, Joël Schaerer &lt;<a href="mailto:joel.schaerer@gmail.com" target="_blank">joel.schaerer@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt;&gt; Hi Nick,<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; I did indeed have a look at these new classes (not a very thorough one, I must confess). However if I understand correctly they allow estimating the parameter scales, but don&#39;t change the way the scales are used by the optimizer?<br>



&gt;&gt;&gt;<br>
&gt;&gt;&gt; joel<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; On 07/05/2013 13:52, Nick Tustison wrote:<br>
&gt;&gt;&gt;&gt; Hi Brad,<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; Have you seen the work we did with the class<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; <a href="http://www.itk.org/Doxygen/html/classitk_1_1RegistrationParameterScalesEstimator.html" target="_blank">http://www.itk.org/Doxygen/html/classitk_1_1RegistrationParameterScalesEstimator.html</a><br>



&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; and it&#39;s derived classes for the v4 framework?  They describe<br>
&gt;&gt;&gt;&gt; a couple different approaches to scaling the gradient for use<br>
&gt;&gt;&gt;&gt; with the v4 optimizers.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; Nick<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; On May 7, 2013, at 6:59 AM, Bradley Lowekamp &lt;<a href="mailto:blowekamp@mail.nih.gov" target="_blank">blowekamp@mail.nih.gov</a>&gt; wrote:<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; Hello Joel,<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; I have encountered the same issue. I ended up creating my own &quot;ScaledRegularStepGradientDescentOptimizer&quot; derived from the an ITK one. Please find it attached. Please note, I don&#39;t think I have migrated this code to ITKv4.... but I not certain.<br>



&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; I reported this issue to the ITKv4 registration team, but I am not sure what happened to it.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; I also tried to make the change in ITK a while ago, and a large number of the registration tests failed... not sure if the results were better or worse, they were just different.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; Brad<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; &lt;itkScaledRegularStepGradientDescentOptimizer.h&gt;<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; On Apr 25, 2013, at 11:10 AM, Joël Schaerer &lt;<a href="mailto:joel.schaerer@gmail.com" target="_blank">joel.schaerer@gmail.com</a>&gt; wrote:<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;<br>
&gt;<br>
<br>
</div></div></blockquote></div><br></div></div></div>
</blockquote></div><br></div>