constraining parameters during optimization

For example, I’m using the Similarity2DTransform. Here, I would like to enforce that the scale must be non-zero and positive, however I would like to allow for negative translation.
Is it correct, that the only optimizer which can handle constraints is the LBFGSBOptimizer?
But, it looks like that I can only constraint all parameters with the same bounds - is this correct?

So I tried something like this:

R = sitk.ImageRegistrationMethod()
R.SetInitialTransform(sitk.Similarity2DTransform())
R.SetOptimizerAsLBFGSB(lowerBound=0.1, upperBound=10)

But in that case all four parameters of the Similarity2DTransform are constraint. From the C++ documentation of ITK, it looks like that you could pass an array to the LBFGSB Optimizer, and this is not implemented in SimpleITK right now? Or is there some other method I’m not aware of?

Thanks in advance!

Are you running into a case which violates this? Because this might already be implemented.

Yes, I have a case were the scale is set to -0.7, which flips the image around.

>>> sitk.Version_VersionString()
'1.2.4'
>>> sitk.Version_ITKVersionString()
'4.13'

But in any case, is it possible to constraint certain parameters? Or can I only constraint all with one integer?

The SimpleITK interface for the LBFGSB Optimizer is designed to work with the uniform parameter spaces such as the b-spline transform.

With C++, in the past I have tried to use the LBFGS(B) optimizers on non-uniform parameter spaces with mix rotation, scale and translation without success.

Ah okay, good to know.
Yes, for b-splines it seems quite good.

I tested now with SimpleITK 2.0r1 and I get the same thing - the scale gets negative and the image flips around.
However, I can prevent it by setting the lineSearchUpperLimit to something like 2.0 instead of 5.0 in the ConjugateGradientLineSearch.

As I recall going from ITK 4 to ITK 5 there should be a nice performance improvement with the line search optimizers.

I recently has a similar problem which required reducing the lineSearchUpperLimit. I should have also tried setting the estimateLearningRate parameter to EachIteration. If if have time please share the results.

Just setting it to EachIteration does not work. For me the upperLimit must be less than 4.8 to work…

This is my iteration output with EachIteration and upperLimit=default:

  0 = 63225.35480: (0.9417236641686194, -0.002710882030060366, 0.8318583144239113, 0.4403867697114576)
  1 = 24769.04467: (0.8193635679960766, -0.00806438148396374, 1.4708275792215932, 0.9126646303280062)
  2 = 1767.91351: (-0.7590296165364513, -0.0729438940676933, 5.470181184104698, 6.600428933823899)
  3 = 13756.57000: (-0.7659270933004365, -0.0731529783270789, 5.452503302655331, 6.608979898210135)
  4 = 13736.14770: (-0.768255924423802, -0.07284864593329286, 5.26900889478838, 6.514027014632924)
  5 = 13441.74994: (-0.7684237804039744, -0.07101113472142932, 4.441187056947582, 6.013047016875679)
  6 = 12250.67285: (-0.7771872535221632, -0.06321687611669763, 1.8315534893073226, 3.985288601825094)
  7 = 10609.89473: (-0.8121235582069708, -0.04965874076607467, 2.23606855339464, 0.9635690675693827)
  8 = 9056.59000: (-0.8125653109713288, -0.04284474209336353, 2.99296637371436, 1.1378312713558225)
  9 = 8879.27372: (-0.8136129653985188, -0.022699197350708775, 3.1357057410231066, 1.612590588916469)
 10 = 8773.04976: (-0.8135741278665546, -0.010558835438296896, 2.8956102643952506, 1.6573513625957272)
 11 = 8735.90026: (-0.811643162579073, -0.009135066951720481, 2.7770013051208857, 1.138088712794068)
 12 = 8694.28999: (-0.812168851724825, -0.008694164360242599, 2.812388135976882, 1.118838263678742)
 13 = 8693.64139: (-0.8124058125952398, -0.008334040773027964, 2.81696398489521, 1.1103428072832422)
 14 = 8693.55494: (-0.8123499948450742, -0.0076758323348522966, 2.7855202798384577, 1.1094840570836944)
 15 = 8693.23957: (-0.8119820121293603, -0.006968355987709816, 2.779354293222849, 1.1091571368946627)
 16 = 8693.07748: (-0.8118681080825537, -0.00670457643779322, 2.7929565747861345, 1.1069767734546279)
 17 = 8693.00478: (-0.8120219163519984, -0.0067023357717718385, 2.796942887223431, 1.1059202723531565)
 18 = 8692.98036: (-0.8120314496176448, -0.006702709889591167, 2.797055148813363, 1.105881984756556)
 19 = 8692.98026: (-0.8120267059637083, -0.006704935770477283, 2.796420117201529, 1.106019114958926)
 20 = 8692.98008: (-0.8120260062327926, -0.006705173062985829, 2.7963733472433963, 1.106030409581191)
 21 = 8692.98005: (-0.8120236434686153, -0.0067059900652930785, 2.796218697008211, 1.1060680706710344)
SIMILARITY finished after 22 metric 1767.913507049963 param (-0.7590296165364513, -0.0729438940676933, 5.470181184104698, 6.600428933823899)

Using EachIteration and upperLimit=4.8:

  0 = 63225.35480: (0.9440497130545455, -0.002602679548968489, 0.7986554186359417, 0.42280911764308055)
  1 = 25850.19966: (0.8206294588975955, -0.008022046595299665, 1.514568822644362, 0.9199073072495313)
  2 = 1814.59713: (0.8187457259455184, -0.008099258407641155, 1.5197085229633467, 0.9269372766024895)
  3 = 1811.08426: (0.818653795478708, -0.008076694980941069, 1.492367347124886, 0.9246892483926054)
  4 = 1785.67003: (0.8185732377151316, -0.007955043505412658, 1.363403933217665, 0.9125857590736595)
  5 = 1672.19161: (0.8181608274396125, -0.00738645060923019, 0.7981358788324328, 0.8533063442635993)
  6 = 1281.99700: (0.8163800232208098, -0.005900265984633511, -0.20465544868203256, 0.666351040391283)
  7 = 1006.89600: (0.8103944606886667, -0.003366207607840059, -0.20516253289142863, 0.336790773308636)
  8 =  962.20778: (0.8100575564958342, 0.004954745462649816, -0.42594213936184366, 0.18496877660497926)
  9 =  938.80399: (0.8098298647815174, 0.005849897334587465, -0.24354708038403497, 0.17819897896596495)
 10 =  928.99950: (0.8113208593766895, 0.008969101509811141, -0.23320375350858244, 0.19634801636209162)
 11 =  924.32931: (0.8116036904031729, 0.01093351824316089, -0.22643254122091977, 0.18103902497958455)
 12 =  923.56114: (0.8099247706128822, 0.012822934766515613, -0.21575698032430035, 0.08663447156407175)
 13 =  920.32931: (0.8094925838062388, 0.013393909218753258, -0.23243313373910182, 0.05882734414525096)
 14 =  920.11439: (0.8097127884418852, 0.013440776205586433, -0.25893936479197244, 0.06346169879332969)
 15 =  919.80532: (0.8097553217003186, 0.013456662073142521, -0.260020528847502, 0.06393092465554676)
 16 =  919.80259: (0.8097845307160055, 0.013471196967725894, -0.2600766540332024, 0.06422811307493391)
 17 =  919.80174: (0.8098022562670975, 0.013481817719600438, -0.2598698801030021, 0.06440154705876333)
 18 =  919.80142: (0.8098025038945809, 0.013494394778774836, -0.25849005039563466, 0.06436680385329568)
 19 =  919.79789: (0.8097703555151784, 0.013523894965600402, -0.25846175362705154, 0.06394991474796959)
 20 =  919.79591: (0.8097710511099022, 0.013524156837837531, -0.258497151628061, 0.06393588908119192)
 21 =  919.79591: (0.8097720811681713, 0.013524558875546072, -0.25854793660592784, 0.06391445860762386)
 22 =  919.79593: (0.8097732312458021, 0.01352503444526458, -0.2586017317688072, 0.06388934265827186)
SIMILARITY finished after 23 metric 919.7959106749754 param (0.8097710511099022, 0.013524156837837531, -0.258497151628061, 0.06393588908119192)

Subjectively, it feels faster now actually - but for proper results I would had to record the timing as well :smiley: