-
Notifications
You must be signed in to change notification settings - Fork 2
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
Instability and spline intercept term #214
Comments
I have not noticed this before, but I also haven't played around with excluding the intercept term... |
Hm, the intercept and splines are collinear. The following is is very unstable
[1] 1
Bounds on the target parameter: [-0.2952303, 0.1642794]
Audit terminated successfully after 2 rounds
[1] 2
Bounds on the target parameter: [-0.2952691, 0.1642836]
Audit terminated successfully after 3 rounds
[1] 3
Bounds on the target parameter: [-0.2951101, 0.1640856]
Audit terminated successfully after 3 rounds
[1] 4
Bounds on the target parameter: [-0.2952837, 0.1643171]
Audit terminated successfully after 3 rounds
But without the intercept (0+) it becomes quite stable?
[1] 1
Bounds on the target parameter: [-0.29517, 0.1641627]
Audit terminated successfully after 2 rounds
[1] 2
Bounds on the target parameter: [-0.29517, 0.1641618]
Audit terminated successfully after 3 rounds
[1] 3
Bounds on the target parameter: [-0.2951318, 0.1641147]
Audit terminated successfully after 2 rounds
[1] 4
Bounds on the target parameter: [-0.2951022, 0.1640747]
Audit terminated successfully after 3 rounds I'm not sure what is happening. |
I get unstable estimates. Running the example posted by @a-torgovitsky, I get the following output:
In case its relevant, some info on what I'm running (I haven't updated R in a while, though would be surprised if that explains anything...)
I updated to the most recent version of ivmte (master branch) immediately before running the code. |
R version 4.0.5 (2021-03-31) -- "Shake and Throw"
Platform: x86_64-pc-linux-gnu (64-bit) |
Hm, interesting. So here's what I have on my machine. R version 4.2.0 (2022-04-22) -- "Vigorous Calisthenics"
Platform: x86_64-pc-linux-gnu (64-bit)
Gurobi Optimizer version 9.1.2 build v9.1.2rc0 (linux64) Here is the university server, which also gets unstable estimates.
An easy way to check the Gurobi version is to add the following options to noisy = TRUE
debug = TRUE That will return the output from Gurobi, including the details on the version. |
I have the same Gurobi version as your machine:
Edit: I am happy to update my R version to 4.2.0 to see if that fixes things. But it may also be useful for me to keep testing on 4.1.0 if it's in fact true that minor changes to R versions are leading to big stability changes... |
Thanks @johnnybonney I think you can stay on 4.1.0 for now. |
@johnnybonney's hunch look to be correct: I think it's the the R versions. I've been running the example above on the server and my machine. Here's the part of the code where the main differences between my computer (R 4.2) and the server (R 4.1) arise. AA <- t(drX) %*% drX
cholAA <- suppressWarnings(chol(AA, pivot = TRUE))
...
[code on pivoting] The object The
So I'd be curious to see what happens if you update your version of R, @johnnybonney. |
Interesting! There should be a way to check the commit history for changes to I guess it's also not a fully satisfying answer to me because it's just saying that the new version of |
Ah you're right.
Good suggestion. |
I updated R to 4.2.0 but my results are still unstable with the intercept. (I get the exact same output as before.) |
Ah how unfortunate. |
(emphasis above added by me) At the moment, if the design matrix So one approach is to manually remove the collinear regressors. |
Hmm yes you're right, we certainly don't want to require Ok, so it is indeed just a matter of What would be the right way to debug this... |
Could I first check how differently our machines are executing This script tells me that I was wrong when I said this:
It turns out EDIT: Below is the script. |
Ah, I forgot to respond to this:
The randomness across estimates on each of our machines is because of the covariates in the initial grid. One way to eliminate this randomness is to set > for (i in 1:4) {
+ print(i)
+ result <- do.call(ivmte, args)
+ saveRDS(result, "result.rds")
+ print(result)
+ }
[1] 1
Bounds on the target parameter: [-0.2958118, 0.1643239]
Audit terminated successfully after 2 rounds
[1] 2
Bounds on the target parameter: [-0.2958118, 0.1643239]
Audit terminated successfully after 2 rounds
[1] 3
Bounds on the target parameter: [-0.2958118, 0.1643239]
Audit terminated successfully after 2 rounds
[1] 4
Bounds on the target parameter: [-0.2958118, 0.1643239]
Audit terminated successfully after 2 rounds
Any differences in estimates across our machines after setting |
Here are Got it on the randomness---that makes sense. |
Here is my output: |
Thanks everyone. Here is a summary of i.e, I'm summarizing the absolute values of the elements of Min. 1st Qu. Median Mean 3rd Qu. Max.
0.000e+00 0.000e+00 0.000e+00 6.383e-09 7.660e-11 3.597e-07 Now here is a summary of the difference in their Cholesky decompositions across our machines, The decomposition from my machine seems least sensitive to differences between Min. 1st Qu. Median Mean 3rd Qu. Max. Source
1: 0 0 0 6.704660e-11 0 3.235382e-08 JS
2: 0 0 0 7.073533e-09 0 2.571042e-06 Acropolis
3: 0 0 0 7.073533e-09 0 2.571042e-06 AT
4: 0 0 0 7.073533e-09 0 2.571042e-06 JB Here are the differences in Min. 1st Qu. Median Mean 3rd Qu. Max. Source
1: 0 0 0 2.932389e-05 0 0.008443555 JS vs. Acropolis
2: 0 0 0 2.932389e-05 0 0.008443555 JS vs. AT
3: 0 0 0 2.932389e-05 0 0.008443555 JS vs. JB And here are the differences in Min. 1st Qu. Median Mean 3rd Qu. Max. Source
1: 0 0 0 2.932935e-05 0 0.008444025 JS vs. Acropolis
2: 0 0 0 2.932935e-05 0 0.008444025 JS vs. AT
3: 0 0 0 2.932935e-05 0 0.008444025 JS vs. JB Again, the output from @a-torgovitsky, @johnnybonney, and Acropolis are identical. |
Is the behavior affected by any of the options of |
Hm, the options do not seem to be the cause (at the moment). So here are the options (reference here):
By default, EDIT: Or rather, the value of |
Yeah I have the same machine epsilon too...long-shot unless one of us was using a computer from the 90s ;) Have you found a way to determine what version of LAPACK you have? You could also try the decomposition in another language that uses LAPACK (my guess is SciPy would be doing that too? and Julia) to pin down whether it's the interfacing language or LAPACK itself. |
That seems to be it. Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3
LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3 Maybe the latest versions of Ubunutu use ATLAS. Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0 After doing this, our decompositions from a few posts up perfectly match. |
For me: Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0 Ok, so that partially resolves some mystery I suppose? If so, I'm not sure what we can do to improve this situation. I didn't follow this:
Sounds contradictory? |
Something I can try is detect which BLAS/LAPACK library is being used.
So even though I can replicate your (@a-torgovitsky) Cholesky decompositions, I cannot replicate your estimated bounds. [1] 1
Bounds on the target parameter: [-0.2943683, 0.1625186]
Audit terminated successfully after 2 rounds
[1] 2
Bounds on the target parameter: [-0.334092, 0.2076029]
Audit terminated successfully after 3 rounds
[1] 3
Bounds on the target parameter: [-0.288325, 0.1618743]
Audit terminated successfully after 2 rounds
[1] 4
Bounds on the target parameter: [-0.3665427, 0.2499749]
Audit terminated successfully after 3 rounds
But those are different from your estimates here. |
Yeah I definitely don't think we want to do this.
Is this maybe just due to differences in random number generation across versions/platforms? > set.seed(12345)
> runif(5)
[1] 0.7209039 0.8757732 0.7609823 0.8861246 0.4564810 Getting back to the main issue.
|
It does not seem to be, since I generate the same sequence of random numbers.
I can't think of a time when we want Our ~ uSplines(intercept = FALSE, degree = 3, knots = seq(from = .25, to = .75, by = .25)) This leads to stable estimates.
No duplicate rows. |
If the random number generator is the same, and the Cholesky decomposition is the same, how can the bounds be different?
Bingo, this explains it perfectly. ~ uSplines(intercept = TRUE, degree = 3, knots = seq(from = .25, to = .75, by = .25)) Here's what I get now with library("ivmte")
set.seed(1234)
args <- list(
data = AE,
outcome = "worked",
target = "ate",
propensity = morekids ~ samesex + yob + black + hisp + other,
solver = "gurobi",
audit.nu = 100,
audit.nx = 10000
)
args[["m0"]] <-
~ uSplines(degree = 3,
intercept = FALSE,
knots = seq(from = .25, to = .75, by = .25)) +
yob + black + hisp + other
args[["m1"]] <- args[["m0"]]
for (i in 1:4) {
print(i)
print(do.call(ivmte, args))
} produces: [1] 1
Bounds on the target parameter: [-0.2952359, 0.1642467]
Audit terminated successfully after 2 rounds
[1] 2
Bounds on the target parameter: [-0.2952378, 0.1642492]
Audit terminated successfully after 3 rounds
[1] 3
Bounds on the target parameter: [-0.2951021, 0.1640746]
Audit terminated successfully after 3 rounds
[1] 4
Bounds on the target parameter: [-0.2952322, 0.1642438]
Audit terminated successfully after 3 rounds
|
Hm, I don't know...
Okay! I will do that. |
Perfectly match up to how many digits? library("ivmte")
set.seed(1234)
args <- list(
data = AE,
outcome = "worked",
target = "ate",
propensity = morekids ~ samesex + yob + black + hisp + other,
solver = "gurobi",
audit.nu = 100,
audit.nx = 10000,
noisy = TRUE,
debug = TRUE
)
args[["m0"]] <-
~ uSplines(degree = 3,
knots = seq(from = .25, to = .75, by = .25)) +
yob + black + hisp + other
args[["m1"]] <- args[["m0"]]
do.call(ivmte, args) Output is attached in log.txt |
Ah, sorry, we match up to 6 decimal places.
It looks like we already differ when minimizing the criterion on the first audit. So here is your solution to minimizing the criterion on the first audit: Barrier solved model in 20 iterations and 0.02 seconds
Optimal objective -2.94835366e-01 And then here are the violations you get: Violations: 102
Expanding constraint grid to include 100 additional points... And here is what I get from minimizing the criterion on the first audit: Barrier solved model in 13 iterations and 0.01 seconds
Optimal objective -2.94824256e-01 And here are my violations: Violations: 136
Expanding constraint grid to include 100 additional points... And for documentation, here is the full output from my machine. |
Ok this is interesting. Related aside: I noticed Gurobi warns us that min criterion problem is badly scaled. |
Acropolis does not use ATLAS.
Hm, I don't know why but I only implemented the Cholesky approach for the bounds. |
But the same model fingerprint? How can that be? |
Sorry, I forgot that Acropolis has Gurobi 9.1.1. Also, I compared the models generated on my machine and Acropolis using Once incorporating the Cholesky decomposition into minimizing the criterion, the stability is greatly improved. The following is is very unstable
[1] 1
Bounds on the target parameter: [-0.2952358, 0.1640799]
Audit terminated successfully after 2 rounds
[1] 2
Bounds on the target parameter: [-0.2952103, 0.1642512]
Audit terminated successfully after 3 rounds
[1] 3
Bounds on the target parameter: [-0.295101, 0.1640724]
Audit terminated successfully after 3 rounds
[1] 4
Bounds on the target parameter: [-0.2946923, 0.1654988]
Audit terminated successfully after 3 rounds
But without the intercept (0+) it becomes quite stable?
[1] 1
Bounds on the target parameter: [-0.2951699, 0.1641617]
Audit terminated successfully after 2 rounds
[1] 2
Bounds on the target parameter: [-0.2951697, 0.1641617]
Audit terminated successfully after 3 rounds
[1] 3
Bounds on the target parameter: [-0.2951323, 0.1641149]
Audit terminated successfully after 2 rounds
[1] 4
Bounds on the target parameter: [-0.2951023, 0.1640746]
Audit terminated successfully after 3 rounds |
Ok, fantastic! Let's keep that then. I'd still like to know what's going on with the different solutions before we close this. |
We can finally close this thread :) It turns out it wasn't the version of Gurobi, but something simple my eyes kept skipping over. |
Ahhhhhhh...not so simple! Good thinking! |
Hi @jkcshea do you understand what's going on in this example?
I'm not so sure I understand what adding
0 +
does in the context of splines.(I know it removes the intercept, but not clear on what the significance of that is.)
@johnnybonney and @cblandhol --- have you run into anything like this?
Produces:
The text was updated successfully, but these errors were encountered: