Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rank update #331

Merged
merged 7 commits into from
Jul 15, 2020
Merged

Rank update #331

merged 7 commits into from
Jul 15, 2020

Conversation

dmbates
Copy link
Collaborator

@dmbates dmbates commented Jun 25, 2020

Clean up rankUpdate! methods. In particular use Hermitian{T, Diagonal{T, Vector{T}}} instead of branching on the diagonal case in updateL!. We want to use method dispatch instead of if statements that I had in the code. This should be rebased on master after #329 is merged.

Closes #290.

@codecov
Copy link

codecov bot commented Jun 25, 2020

Codecov Report

Merging #331 into master will decrease coverage by 0.15%.
The diff coverage is 86.20%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #331      +/-   ##
==========================================
- Coverage   95.91%   95.75%   -0.16%     
==========================================
  Files          21       22       +1     
  Lines        1492     1485       -7     
==========================================
- Hits         1431     1422       -9     
- Misses         61       63       +2     
Impacted Files Coverage Δ
src/arraytypes.jl 95.12% <0.00%> (-4.88%) ⬇️
src/remat.jl 95.00% <86.66%> (+0.05%) ⬆️
src/linalg/rankUpdate.jl 97.67% <100.00%> (-0.77%) ⬇️
src/linearmixedmodel.jl 100.00% <100.00%> (ø)
src/randomeffectsterm.jl 90.19% <0.00%> (ø)
src/generalizedlinearmixedmodel.jl 83.33% <0.00%> (ø)
src/schema.jl 100.00% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 64ba631...0f1c114. Read the comment docs.

Copy link
Member

@palday palday left a comment

Choose a reason for hiding this comment

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

If I understand everything correctly, then it looks pretty good. I have one question about assignment vs. dot assignment in a single method that needs attention, everything else is small.

The two big changes that I didn't comment on are:

  1. No default values for alpha and beta in the rank update methods. I think this is fine, but this is definitely a breaking change (admittedly on non-exported methods), so it's a good thing to get in now before the big release. Is this also in line with the related methods in LinearAlgebra?
  2. Removal of a catch-all rankUpdate! method. I'm wondering if we should still have that in there. Or maybe even something 'dumber', such as
function rankUpdate(A::Any, B::Any, alpha, beta) 
   error("We haven't implemented a method for $(typeof(A)), $(typeof(B)). Please file an issue on GitHub")
end

end
C
end
=#
Copy link
Member

Choose a reason for hiding this comment

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

suggest final newline so that various things stop complaining

Suggested change
=#
=#

@@ -531,7 +531,7 @@ end

nθ(m::LinearMixedModel) = length(m.parmap)

StatsBase.nobs(m::LinearMixedModel) = first(size(m))
StatsBase.nobs(m::LinearMixedModel) = length(first(m.allterms).refs)
Copy link
Member

Choose a reason for hiding this comment

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

why change this? (not opposed, just curious)

@@ -52,6 +52,7 @@ end
@test loglikelihood(fit!(wm1)) ≈ loglikelihood(m1)
end

#= I don't see this testset as meaningful b/c diagonal A does not occur after amalgamation of ReMat's for the same grouping factor - D.B.
Copy link
Member

Choose a reason for hiding this comment

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

I'm trying to think of a case where diagonal A could occur. Perhaps in one of the custom model types some of the ZiF spinoff projects are working on? Maybe this is something re-visit in a few weeks to months and see if we can further trim.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is best to think of how rankUpdate! gets called. After pre- and post-multiplication by Lambda and inflation of the diagonal the rankUpdate! methods get called with C being one of the diagonal blocks and A being a block to the left of C. So C is m.L[Block(2,2)] or higher because there are no blocks to the left of m.L[Block(1,1)]. The cases that matter are when there is more than one grouping factor for the random effects. If A were to be diagonal then it would need to be generated from two scalar random-effects terms, as in (1|G) + (1|H) and the number of levels of G and H would need to be equal and the levels would match. You can get that from (1|G) + (0+x|G) but that is now collapsed to a single r.e. term either through zerocorr(1+x|G) or by amalgamation of the random effects terms. So I don't think there will be real-life cases where A is diagonal. C is always a square matrix and either Diagonal or UniformBlockDiagonal or, through fill-in, Dense. The only special cases for A are Dense, SparseMatrixCSC or, in a new branch that I haven't pushed yet, KHotColumn. The last one is a special type of sparse matrix generated by nested grouping factors for vector-valued random effects where each column of A has exactly K adjacent non-zeros.

Copy link
Member

Choose a reason for hiding this comment

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

Right, so the only way that this could occur would be if someone had two identical grouping variables so that they wouldn't be amalgamated. Until we see a legitimate use case for that, I think we can safely ignore that possibility.

Thanks for the refresher! 😄

@dmbates
Copy link
Collaborator Author

dmbates commented Jul 10, 2020

If I understand everything correctly, then it looks pretty good. I have one question about assignment vs. dot assignment in a single method that needs attention, everything else is small.

The two big changes that I didn't comment on are:

1. No default values for alpha and beta in the rank update methods. I think this is fine, but this is definitely a breaking change (admittedly on non-exported methods), so it's a good thing to get in now before the big release. Is this also in line with the related methods in LinearAlgebra?

2. Removal of a catch-all `rankUpdate!` method. I'm wondering if we should still have that in there. Or maybe even something 'dumber', such as
function rankUpdate(A::Any, B::Any, alpha, beta) 
   error("We haven't implemented a method for $(typeof(A)), $(typeof(B)). Please file an issue on GitHub")
end

I don't see the benefit of adding a "catch-all" method to generate an error. Not having a method has the same effect, doesn't it?

@dmbates
Copy link
Collaborator Author

dmbates commented Jul 10, 2020

If I understand everything correctly, then it looks pretty good. I have one question about assignment vs. dot assignment in a single method that needs attention, everything else is small.

The two big changes that I didn't comment on are:

1. No default values for alpha and beta in the rank update methods. I think this is fine, but this is definitely a breaking change (admittedly on non-exported methods), so it's a good thing to get in now before the big release. Is this also in line with the related methods in LinearAlgebra?

I felt that this generic would be internal to the package and I dropped the default values for alpha and beta because there is only one call to generic in the package. It seemed it was easier to specify the values there than to add defaults for all the methods.

@palday
Copy link
Member

palday commented Jul 10, 2020

If I understand everything correctly, then it looks pretty good. I have one question about assignment vs. dot assignment in a single method that needs attention, everything else is small.
The two big changes that I didn't comment on are:

1. No default values for alpha and beta in the rank update methods. I think this is fine, but this is definitely a breaking change (admittedly on non-exported methods), so it's a good thing to get in now before the big release. Is this also in line with the related methods in LinearAlgebra?

2. Removal of a catch-all `rankUpdate!` method. I'm wondering if we should still have that in there. Or maybe even something 'dumber', such as
function rankUpdate(A::Any, B::Any, alpha, beta) 
   error("We haven't implemented a method for $(typeof(A)), $(typeof(B)). Please file an issue on GitHub")
end

I don't see the benefit of adding a "catch-all" method to generate an error. Not having a method has the same effect, doesn't it?

For us, yes. But for the average user, a MethodError followed by a stacktrace is big and scary and potentially looks like a bug. An error with "we haven't implemented this yet" seems less scary. But then again, both will generate huge stacktraces and that's probably the hardest thing for normal users anyway.

Ultimately, I'm neutral. Do we have a "normal" person we can ask?

@dmbates
Copy link
Collaborator Author

dmbates commented Jul 10, 2020

If I understand everything correctly, then it looks pretty good. I have one question about assignment vs. dot assignment in a single method that needs attention, everything else is small.
The two big changes that I didn't comment on are:

1. No default values for alpha and beta in the rank update methods. I think this is fine, but this is definitely a breaking change (admittedly on non-exported methods), so it's a good thing to get in now before the big release. Is this also in line with the related methods in LinearAlgebra?

2. Removal of a catch-all `rankUpdate!` method. I'm wondering if we should still have that in there. Or maybe even something 'dumber', such as
function rankUpdate(A::Any, B::Any, alpha, beta) 
   error("We haven't implemented a method for $(typeof(A)), $(typeof(B)). Please file an issue on GitHub")
end

I don't see the benefit of adding a "catch-all" method to generate an error. Not having a method has the same effect, doesn't it?

For us, yes. But for the average user, a MethodError followed by a stacktrace is big and scary and potentially looks like a bug. An error with "we haven't implemented this yet" seems less scary. But then again, both will generate huge stacktraces and that's probably the hardest thing for normal users anyway.

Ultimately, I'm neutral. Do we have a "normal" person we can ask?

I would value the opinions of either @christinabergmann or @debruine

@dmbates
Copy link
Collaborator Author

dmbates commented Jul 12, 2020

If I understand everything correctly, then it looks pretty good. I have one question about assignment vs. dot assignment in a single method that needs attention, everything else is small.
The two big changes that I didn't comment on are:

1. No default values for alpha and beta in the rank update methods. I think this is fine, but this is definitely a breaking change (admittedly on non-exported methods), so it's a good thing to get in now before the big release. Is this also in line with the related methods in LinearAlgebra?

2. Removal of a catch-all `rankUpdate!` method. I'm wondering if we should still have that in there. Or maybe even something 'dumber', such as
function rankUpdate(A::Any, B::Any, alpha, beta) 
   error("We haven't implemented a method for $(typeof(A)), $(typeof(B)). Please file an issue on GitHub")
end

I don't see the benefit of adding a "catch-all" method to generate an error. Not having a method has the same effect, doesn't it?

For us, yes. But for the average user, a MethodError followed by a stacktrace is big and scary and potentially looks like a bug. An error with "we haven't implemented this yet" seems less scary. But then again, both will generate huge stacktraces and that's probably the hardest thing for normal users anyway.

In retrospect I think it is fine to go ahead with adding a fallback-error method like this. Would you (@palday) be willing to add a test to ensure test coverage?

@palday
Copy link
Member

palday commented Jul 13, 2020

@dmbates I'll take care of it. 😄

@@ -52,6 +52,7 @@ end
@test loglikelihood(fit!(wm1)) ≈ loglikelihood(m1)
end

#= I don't see this testset as meaningful b/c diagonal A does not occur after amalgamation of ReMat's for the same grouping factor - D.B.
Copy link
Member

Choose a reason for hiding this comment

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

Right, so the only way that this could occur would be if someone had two identical grouping variables so that they wouldn't be amalgamated. Until we see a legitimate use case for that, I think we can safely ignore that possibility.

Thanks for the refresher! 😄

@palday
Copy link
Member

palday commented Jul 15, 2020

@dmbates If you're happy with the new error message, please squash and merge.

@dmbates dmbates merged commit aef7ec7 into master Jul 15, 2020
@palday palday deleted the rankUpdate branch November 19, 2020 17:14
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.

Error When Adding Random Slopes
2 participants