source("Smart LASSO.R")
cores = detectCores()

First, simulating on any dataset containing failures (naive)

Last week, we discussed how model performance is affected when we allow our simulation process to throw out training sets (and resample) when the training set didn’t include enough bank failures that we wanted it to. The baseline for model performance is the situation where we simluate a model n times (100 is quite stable, so I’ve been going with that) and collect the test stats, but where we use all training sets which contain at least 1 failure into the model. From previous weeks, we have a pretty good idea of what that looks like.

(Note the choice of 2008Q2, sample size of 100, and number of simulations = 100, which will remain the case throughout.

run_models(100, "2008-06-30", 100, "logreg")
     in_sample_mse  out_of_sample_mse     in_sample_rmse out_of_sample_rmse      in_sample_auc  out_of_sample_auc 
        0.06320000         0.07238642         0.24471943         0.26838221         0.89054422         0.80045269 
run_models(100, "2008-06-30", 100, "lasso")
     in_sample_mse  out_of_sample_mse     in_sample_rmse out_of_sample_rmse      in_sample_auc  out_of_sample_auc 
        0.07360000         0.06226483         0.26871622         0.24940062         0.85637157         0.79371096 
run_models_each_variable(100, "2009-06-30", 100)

As we can see – based on the training set size, in-sample MSE on the full model is low, out-of-sample MSE on the full model is about the same as the one-variable MSEs.

Second, simulating on any dataset containing at least m failures (less naive; m = 5)

Some improvement can hopefully be made by discriminating our training sets a bit. The code below adds two new parameters to my modeling function that outputs the graph of MSE: (1) the minimum number of failures a training set is allowed to contain (otherwise, it’s resampled), and (2) the ratio we apply between the number of failures in a training set and the number of predictors in the model. The ratio is what decides the lambda used for our LASSO model.

Let’s try m >= 5 for different training set sizes:

run_models_each_variable_lasso(100, "2008-06-30", 100, 5, 1)

run_models_each_variable_lasso(100, "2008-06-30", 500, 5, 1)

run_models_each_variable_lasso(100, "2008-06-30", 500, 20, 1)

A little disappointing, I have to say!

Nothing seems to lower MSE below this ~0.07 threshold.

Third, simulating on any dataset containing at least m failures divided by a certain number of predictors, m

run_models_each_variable_lasso(100, "2008-06-30", 100, 5, 2)

run_models_each_variable_lasso(100, "2008-06-30", 100, 5, 4)

run_models_each_variable_lasso(100, "2008-06-30", 100, 10, 3)

run_models_each_variable_lasso(100, "2008-06-30", 100, 10, 4)

This was a somewhat suprising result until I understood what was going on. These models run into a situation where many of the training sets have only ten failures, and the LASSO is being forced to drop 2-3 variables and predict badly on the training set. The remaining variables don’t explain much about the outcome than each one would individually. What I can’t figure out – and I double-checked the method I’m building – is why the test data universally outperforms training data. “Underfitting?”

LS0tCnRpdGxlOiAiUGxheWluZyB3aXRoIFZhcmlhYmxlIFNlbGVjdGlvbiBhbmQgTEFTU08iCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnNvdXJjZSgiRWFjaCBWYXJpYWJsZSBNb2RlbHMuUiIpCnNvdXJjZSgiU21hcnQgTEFTU08uUiIpCmNvcmVzID0gZGV0ZWN0Q29yZXMoKQpgYGAKCiMjIyMgRmlyc3QsIHNpbXVsYXRpbmcgb24gYW55IGRhdGFzZXQgY29udGFpbmluZyBmYWlsdXJlcyAobmFpdmUpCgpMYXN0IHdlZWssIHdlIGRpc2N1c3NlZCBob3cgbW9kZWwgcGVyZm9ybWFuY2UgaXMgYWZmZWN0ZWQgd2hlbiB3ZSBhbGxvdyBvdXIgc2ltdWxhdGlvbiBwcm9jZXNzIHRvIHRocm93IG91dCB0cmFpbmluZyBzZXRzIChhbmQgcmVzYW1wbGUpIHdoZW4gdGhlIHRyYWluaW5nIHNldCBkaWRuJ3QgaW5jbHVkZSBlbm91Z2ggYmFuayBmYWlsdXJlcyB0aGF0IHdlIHdhbnRlZCBpdCB0by4gVGhlIGJhc2VsaW5lIGZvciBtb2RlbCBwZXJmb3JtYW5jZSBpcyB0aGUgc2l0dWF0aW9uIHdoZXJlIHdlIHNpbWx1YXRlIGEgbW9kZWwgbiB0aW1lcyAoMTAwIGlzIHF1aXRlIHN0YWJsZSwgc28gSSd2ZSBiZWVuIGdvaW5nIHdpdGggdGhhdCkgYW5kIGNvbGxlY3QgdGhlIHRlc3Qgc3RhdHMsIGJ1dCB3aGVyZSB3ZSBfdXNlIGFsbCB0cmFpbmluZyBzZXRzIHdoaWNoIGNvbnRhaW4gYXQgbGVhc3QgMSBmYWlsdXJlIGludG8gdGhlIG1vZGVsLl8gRnJvbSBwcmV2aW91cyB3ZWVrcywgd2UgaGF2ZSBhIHByZXR0eSBnb29kIGlkZWEgb2Ygd2hhdCB0aGF0IGxvb2tzIGxpa2UuIAoKKE5vdGUgdGhlIGNob2ljZSBvZiAyMDA4UTIsIHNhbXBsZSBzaXplIG9mIDEwMCwgYW5kIG51bWJlciBvZiBzaW11bGF0aW9ucyA9IDEwMCwgd2hpY2ggd2lsbCByZW1haW4gdGhlIGNhc2UgdGhyb3VnaG91dC4gCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpydW5fbW9kZWxzKDEwMCwgIjIwMDgtMDYtMzAiLCAxMDAsICJsb2dyZWciKQpydW5fbW9kZWxzKDEwMCwgIjIwMDgtMDYtMzAiLCAxMDAsICJsYXNzbyIpCnJ1bl9tb2RlbHNfZWFjaF92YXJpYWJsZSgxMDAsICIyMDA5LTA2LTMwIiwgMTAwKQpgYGAKCkFzIHdlIGNhbiBzZWUgLS0gYmFzZWQgb24gdGhlIHRyYWluaW5nIHNldCBzaXplLCBpbi1zYW1wbGUgTVNFIG9uIHRoZSBmdWxsIG1vZGVsIGlzIGxvdywgb3V0LW9mLXNhbXBsZSBNU0Ugb24gdGhlIGZ1bGwgbW9kZWwgaXMgYWJvdXQgdGhlIHNhbWUgYXMgdGhlIG9uZS12YXJpYWJsZSBNU0VzLiAKCiMjIyMgU2Vjb25kLCBzaW11bGF0aW5nIG9uIGFueSBkYXRhc2V0IGNvbnRhaW5pbmcgYXQgbGVhc3QgbSBmYWlsdXJlcyAobGVzcyBuYWl2ZTsgbSA9IDUpCgpTb21lIGltcHJvdmVtZW50IGNhbiBob3BlZnVsbHkgYmUgbWFkZSBieSBkaXNjcmltaW5hdGluZyBvdXIgdHJhaW5pbmcgc2V0cyBhIGJpdC4gVGhlIGNvZGUgYmVsb3cgYWRkcyB0d28gbmV3IHBhcmFtZXRlcnMgdG8gbXkgbW9kZWxpbmcgZnVuY3Rpb24gdGhhdCBvdXRwdXRzIHRoZSBncmFwaCBvZiBNU0U6ICgxKSB0aGUgbWluaW11bSBudW1iZXIgb2YgZmFpbHVyZXMgYSB0cmFpbmluZyBzZXQgaXMgYWxsb3dlZCB0byBjb250YWluIChvdGhlcndpc2UsIGl0J3MgcmVzYW1wbGVkKSwgYW5kICgyKSB0aGUgcmF0aW8gd2UgYXBwbHkgYmV0d2VlbiB0aGUgbnVtYmVyIG9mIGZhaWx1cmVzIGluIGEgdHJhaW5pbmcgc2V0IGFuZCB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgaW4gdGhlIG1vZGVsLiBUaGUgcmF0aW8gaXMgd2hhdCBkZWNpZGVzIHRoZSBsYW1iZGEgdXNlZCBmb3Igb3VyIExBU1NPIG1vZGVsLiAKCkxldCdzIHRyeSBtID49IDUgZm9yIGRpZmZlcmVudCB0cmFpbmluZyBzZXQgc2l6ZXM6CgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpydW5fbW9kZWxzX2VhY2hfdmFyaWFibGVfbGFzc28oMTAwLCAiMjAwOC0wNi0zMCIsIDEwMCwgNSwgMSkKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpydW5fbW9kZWxzX2VhY2hfdmFyaWFibGVfbGFzc28oMTAwLCAiMjAwOC0wNi0zMCIsIDUwMCwgNSwgMSkKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpydW5fbW9kZWxzX2VhY2hfdmFyaWFibGVfbGFzc28oMTAwLCAiMjAwOC0wNi0zMCIsIDUwMCwgMjAsIDEpCmBgYApBIGxpdHRsZSBkaXNhcHBvaW50aW5nLCBJIGhhdmUgdG8gc2F5IQoKTm90aGluZyBzZWVtcyB0byBsb3dlciBNU0UgYmVsb3cgdGhpcyB+MC4wNyB0aHJlc2hvbGQuIAoKIyMjIyBUaGlyZCwgc2ltdWxhdGluZyBvbiBhbnkgZGF0YXNldCBjb250YWluaW5nIGF0IGxlYXN0IG0gZmFpbHVyZXMgX2RpdmlkZWQgYnlfIGEgY2VydGFpbiBudW1iZXIgb2YgcHJlZGljdG9ycywgbQoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcnVuX21vZGVsc19lYWNoX3ZhcmlhYmxlX2xhc3NvKDEwMCwgIjIwMDgtMDYtMzAiLCAxMDAsIDUsIDIpCnJ1bl9tb2RlbHNfZWFjaF92YXJpYWJsZV9sYXNzbygxMDAsICIyMDA4LTA2LTMwIiwgMTAwLCA1LCA0KQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJ1bl9tb2RlbHNfZWFjaF92YXJpYWJsZV9sYXNzbygxMDAsICIyMDA4LTA2LTMwIiwgMTAwLCAxMCwgMykKcnVuX21vZGVsc19lYWNoX3ZhcmlhYmxlX2xhc3NvKDEwMCwgIjIwMDgtMDYtMzAiLCAxMDAsIDEwLCA0KQpgYGAKVGhpcyB3YXMgYSBzb21ld2hhdCBzdXByaXNpbmcgcmVzdWx0IHVudGlsIEkgdW5kZXJzdG9vZCB3aGF0IHdhcyBnb2luZyBvbi4gVGhlc2UgbW9kZWxzIHJ1biBpbnRvIGEgc2l0dWF0aW9uIHdoZXJlIG1hbnkgb2YgdGhlIHRyYWluaW5nIHNldHMgaGF2ZSBvbmx5IHRlbiBmYWlsdXJlcywgYW5kIHRoZSBMQVNTTyBpcyBiZWluZyBmb3JjZWQgdG8gZHJvcCAyLTMgdmFyaWFibGVzIGFuZCBwcmVkaWN0IGJhZGx5IG9uIHRoZSB0cmFpbmluZyBzZXQuIFRoZSByZW1haW5pbmcgdmFyaWFibGVzIGRvbid0IGV4cGxhaW4gbXVjaCBhYm91dCB0aGUgb3V0Y29tZSB0aGFuIGVhY2ggb25lIHdvdWxkIGluZGl2aWR1YWxseS4gV2hhdCBJIGNhbid0IGZpZ3VyZSBvdXQgLS0gYW5kIEkgZG91YmxlLWNoZWNrZWQgdGhlIG1ldGhvZCBJJ20gYnVpbGRpbmcgLS0gaXMgd2h5IHRoZSB0ZXN0IGRhdGEgdW5pdmVyc2FsbHkgb3V0cGVyZm9ybXMgdHJhaW5pbmcgZGF0YS4gIlVuZGVyZml0dGluZz8iICA=