Repository navigation
add attributes for fitting uncertainties to models - #10552
Conversation
|
Hello @cshanahan1 👋! It looks like you've made some changes in your pull request, so I've checked the code again for style. There are no PEP8 style issues with this pull request - thanks! 🎉 Comment last updated at 2020-09-21 14:07:05 UTC |
| par = getattr(self, param_name) | ||
| par.std = param_stds.pop(0) | ||
| setattr(self, param_name, par) | ||
|
|
There was a problem hiding this comment.
Should the cov_matrix setter also set the stds?
There was a problem hiding this comment.
The cov_matrix setter does set the individual parameter stds (while the model.stds is set with its own setter). Do you think this should be done differently?
| param = self.param_names[i] | ||
| s = param + ' ' * (longest_name - len(param)) + ' |' | ||
| ret_str += s + ', '.join([str(np.round(x, round_val)) | ||
| for x in row[0:i+1]]) + '\n' |
There was a problem hiding this comment.
You might consider using a format string to make this simpler. Something like
fstring = '{{0:<{0}s}} | {{1}}'.format(str(longest_name))
outside the loop, and
s = fstring.format(param, repr(np.round(row[:i+1], round_val))[7: -2]))
inside the loop.
This could be split up on more lines to be more readable (make the repr string its own line. This is a bit more complicated since part of the formatting specification is itself a variable (length of the longest parameter name)
| else: | ||
| raise TypeError('Covariance must be indexed by two parameter names, or integer indicies.') | ||
| return(self.cov_matrix[i1][i2]) | ||
|
|
There was a problem hiding this comment.
I'm not sure but I wonder if this handles properly the case when some of the parameters are fixed. That is, are fixed parameters represented in the covariance matrix? I wouldn't think so, but I'm guessing the supplied parameter names exclude the fixed parameters. Is that so?
There was a problem hiding this comment.
Fixed and tied parameters are excluded from the list of fitted parameters. For example, a gaussian with one fixed parameter will have a cov_matrix of shape (2, 2), instead of (3, 3).
There was a problem hiding this comment.
@perrygreenfield that should be how it works, but since i'm currently using model.param_names, which contains all
parameters including fixed + tied parameters, it doesn't work in it's current state. I'll change that.
There was a problem hiding this comment.
I think this does work as expected now.
| param = self.param_names[i] | ||
| s = param + ' ' * (longest_name - len(param) + 1) | ||
| ret_str += s + str(np.round(std, round_val)) + '\n' | ||
| return(ret_str) |
There was a problem hiding this comment.
A similar simplification using format strings can be done here too.
f7c175e to
50a4c6e
Compare
perrygreenfield
left a comment
There was a problem hiding this comment.
Basically only one significant comment that looks like an error, one comment about why a nested definition is necessary, and one about why 2D models aren't included. The first one should be addressed. The latter two don't need to hold up merging though the 2D issue should either be explained, or added as an issue if it is a valid concern.
| masked = False or hasattr(y, 'mask') | ||
| msa = model.model_set_axis | ||
| # check if invertable. if not, can't calc covariance. | ||
| def _is_invertable(m): |
There was a problem hiding this comment.
Why is this defined here? I don't see any dependence on the enclosing method's context.
36f09f7 to
9f791f5
Compare
|
@perrygreenfield a few notes
PG - I agree it should be optional. No argument there. I suspect it could be made an part of the base Fitter class so that you don't have to add it to all. Those that can't do it won't use it (e.g., setting an attribute of the fitter and then using it if it can handle them)
PG - can you point to the specific code you are concerned about? I should take a look at it. However for 2D, instead of the number of points it seems to be the number of rows in the 2d x/y passed in? I don't understand the math behind this - I was using the LevMarLSQ fitter, where the numpy fitter actually returns the covariance matrix, as a reference for the 'correct' value and realized I had to do it this way instead of the total number of points in the input array. For example, if x & y are both 10x10 arrays, the computation requires 10 rather than 100 to return the correct result and match LevMarLSQ. I'm not sure how this should work with 2d arrays that have various values masked.
PG - don't bother optimizing for the window size now. That can be left to the user. If it is too much of a hassle at this point, just dump it all and we can worry about providing options later. |
8a6f3f8 to
f801e12
Compare
|
@cshanahan1 Please add a change log entry. |
db1706c to
417f79f
Compare
|
I can have a look by the end of next week. Is that soon enough? |
|
@karllark When you have time, much appreciated! I may merge it which will make it easier to test, but you can still leave comments. |
417f79f to
19ed935
Compare
|
🎉 |
| model_lhs = lhs[good] | ||
| model_rhs = model_rhs[good][..., np.newaxis] | ||
|
|
||
| a = model_lhs |
There was a problem hiding this comment.
I ran into some conflicts with this PR and #10687, and I do not understand how this line can work if there are multiple models. a should be different for each model isn't it ? cc @nden @cshanahan1
Also uncertanties is used everywhere thought that should be uncertainties, right?
There was a problem hiding this comment.
I also spotted invertable -> invertible.
There was a problem hiding this comment.
ahhh whoops! i am way too reliant on my spellchecker. I will fix these typos and take a look at the issue involving multiple models.
There was a problem hiding this comment.
Thank you! It would be good to figure that out so we can merge the other PR. I've only just seen this and am not clear enough on what it's doing to offer any immediate insight.
There was a problem hiding this comment.
@cshanahan1 - I already opened a PR for the typos (#10764), and can add the invertable correction there (thanks @jehturner ).
Fitting uncertainties are computed for models fit with LevMarLSQFitter and LinearLSQFitter. Models will have
model.cov_matrixandmodel.stdsattributes. Each model will have aparameter.stdattribute as well (e.g model.slope.std).The model attributes are set with a Covariance and StandardDeviations class, respectively, which are defined within fitting. Covariance can be indexed by two parameter names (e.g model.cov_matrix['slope', 'intercept'] for that covariance), or two integer indices corresponding to the order in
model.param_names. StandardDeviations can also be indexed by parameter name or index inmodel.param_names. The plain numpy arrays can be accessed from these as well. The standard deviations can also be accessed from the parameters directly. These classes both havepprintmethod to customize how many fit parameters are printed, as well as rounding.This does not work with units yet, but I will add that in the future.
This is a different approach to 10375, so that can be closed when this is merged.