Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@santisoler
Copy link
Member

@santisoler santisoler commented Jan 31, 2025

Summary

Apply some minor improvements to the stopping criteria method of directives.UpdateIRLS. Ditch the hard-coded 1e-12 value that gets added to the f_old to avoid division by zero: assign f_change to np.inf instead. Remove the absolute value computation while comparing 1 - chi_factor with the misfit_tolerance. This way we avoid ending the inversion with a chi factor above the 1.0.

PR Checklist

  • If this is a work in progress PR, set as a Draft PR
  • Linted my code according to the style guides.
  • Added tests to verify changes to the code.
  • Added necessary documentation to any new functions/classes following the
    expect style.
  • Marked as ready for review (if this is was a draft PR), and converted
    to a Pull Request
  • Tagged @simpeg/simpeg-developers when ready for review.

Reference issue

What does this implement/fix?

Additional information

TODO

  • Enable users to use np.abs when checking for the chifactor within tolerance. Basically, allow users to stop the IRLS even if the chifact is slightly higher than the target.

Ditch the hard-coded 1e-12 value that gets added to the `f_old` to avoid
division by zero: assign `f_change` to `np.inf` instead.
Remove the absolute value computation while comparing `1 - chi_factor`
with the `misfit_tolerance`. This way we avoid ending the inversion with
a chi factor above the 1.0.
@santisoler
Copy link
Member Author

@domfournier would you like to take a look at this?

Just some minor improvements to a couple of things I noticed in the stopping criteria for the IRLS.

  • I didn't quite like the hardcoded 1e-12 value. A given regularization might have values close to that, so the assumption of 1e-12 being a small value could fall, and the algorithm wouldn't work as expected.
  • I noticed that by using the abs when checking for the misfit tolerance, we would allow the inversion to finish with chi factors slightly greater than the target. For example, if misfit_tolerance=0.1 and the current chi factor is 1.09, then np.abs(1.0 - 1.09) < misfit_tolerance will hold, and the inversion will finish (assuming the other conditions are also true).

Please, let me know what do you think.

Comment on lines 414 to 416
chi_factor_diff = 1.0 - self.invProb.phi_d / self.misfit_from_chi_factor(
self.chifact_target
)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One other thing: shouldn't the hard coded 1.0 be the self.chifact_target? Or should it always be 1.0?

Suggested change
chi_factor_diff = 1.0 - self.invProb.phi_d / self.misfit_from_chi_factor(
self.chifact_target
)
chi_factor_diff = self.chifact_target - self.invProb.phi_d / self.misfit_from_chi_factor(
self.chifact_target
)

Copy link
Contributor

@domfournier domfournier Jan 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think so? The 1 in there is equivalent as doing

(phi_d* - phi_d) / phi_d*

meaning the relative deviation from the target. The function self.misfit_from_chi_factor converts the chifact to phi_d value.
Unfortunately the units of what you are proposing don't match: chi_fact is phi_d / N, the other is unitless.

I guess the name change that was previously merged doesn't really reflect the quantity calculated.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right! My bad. I think what we can do is to rename the variable to make it reflect better what value it holds.

One minor thing: I get that by definition the chi factor is going to have the units of phi_d / N, but we always assume that the chi factor is unitless, meaning that phi_d is also unitless (because we are dividing by the uncertainties). This becomes quite clear when we look at the stopping criteria in TargetMisfit where we check if phi_d < chifact * phi_d_star, meaning that chifact is assumed to be always unitless. Nothing to take action on, but just wanted to mention it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, you are right - that would make phi_d already unitless.

Comment on lines 414 to 416
chi_factor_diff = 1.0 - self.invProb.phi_d / self.misfit_from_chi_factor(
self.chifact_target
)
Copy link
Contributor

@domfournier domfournier Jan 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think so? The 1 in there is equivalent as doing

(phi_d* - phi_d) / phi_d*

meaning the relative deviation from the target. The function self.misfit_from_chi_factor converts the chifact to phi_d value.
Unfortunately the units of what you are proposing don't match: chi_fact is phi_d / N, the other is unitless.

I guess the name change that was previously merged doesn't really reflect the quantity calculated.

- self.invProb.phi_d / self.misfit_from_chi_factor(self.chifact_target)
)
< self.misfit_tolerance
and (0 <= chi_factor_diff < self.misfit_tolerance)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The absolute value was intended to allow to be "within range" of the target. That is, it's ok if the misfit is slightly higher or lower than the target.
Forcing it to be strictly smaller is a bit more restrictive.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, not using the absolute value would make the stopping criteria more restrictive. The reason of the change is that it sounds unintuitive that it's possible to get a model that generates a chifact greater than the target.

Talking with @lheagy, one option would be to offer a flag to allow users to make the stopping criteria less restrictive by using the abs, but not using the abs by default. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no objection. The only risk I can foresee is an IRLS that runs longer, but ending below the target makes sense.
We can make the change, and revert the default later if we see instability.

@codecov
Copy link

codecov bot commented Jan 31, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 86.50%. Comparing base (2e36896) to head (9158c85).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1604      +/-   ##
==========================================
- Coverage   86.52%   86.50%   -0.03%     
==========================================
  Files         409      409              
  Lines       52692    52695       +3     
  Branches     5000     5000              
==========================================
- Hits        45594    45584      -10     
- Misses       5678     5691      +13     
  Partials     1420     1420              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Now if phi_d > phi_d_star, then misfit_ratio will be positive.
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.

3 participants