From 0e3311bf0601a8db66058439bd1fff2a9cac2e58 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Tue, 20 Mar 2012 02:05:33 +0100 Subject: [PATCH] Invert the Hessian using Eigen instead of just using the diagonal. Gives slightly wider/better standard deviations, at the cost of more of numerical problems. --- bayeswf.cpp | 49 ++++++++++++++------------------------ www/ratings-explained.html | 2 +- 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/bayeswf.cpp b/bayeswf.cpp index 71686c9..ca205ef 100644 --- a/bayeswf.cpp +++ b/bayeswf.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include #include @@ -9,6 +11,7 @@ #include using namespace std; +using namespace Eigen; #define PRIOR_MU 1500 #define PRIOR_WEIGHT 1.0 @@ -196,13 +199,13 @@ float compute_total_logl(float *mu, int num_players) * * Note that this does not depend on mu or the margin at all. */ -double hessian[MAX_PLAYERS][MAX_PLAYERS]; +double hessian[MAX_PLAYERS * MAX_PLAYERS]; void construct_hessian(const float *mu, int num_players) { memset(hessian, 0, sizeof(hessian)); for (int i = 0; i < num_players; ++i) { - hessian[i][i] += 1.0f / (prior_sigma * prior_sigma); + hessian[i * num_players + i] += 1.0f / (prior_sigma * prior_sigma); } for (unsigned i = 0; i < all_matches.size(); ++i) { const match &m = all_matches[i]; @@ -213,44 +216,29 @@ void construct_hessian(const float *mu, int num_players) double sigma_sq = global_sigma * global_sigma; float w = m.weight; - hessian[p1][p2] -= w / sigma_sq; - hessian[p2][p1] -= w / sigma_sq; + hessian[p1 * num_players + p2] -= w / sigma_sq; + hessian[p2 * num_players + p1] -= w / sigma_sq; - hessian[p1][p1] += w / sigma_sq; - hessian[p2][p2] += w / sigma_sq; + hessian[p1 * num_players + p1] += w / sigma_sq; + hessian[p2 * num_players + p2] += w / sigma_sq; } } -// Compute uncertainty (stddev) of mu estimates, which is 1/sqrt(H_ii), +// Compute uncertainty (stddev) of mu estimates, which is sqrt((H^-1)_ii), // where H is the Hessian (see construct_hessian()). void compute_mu_uncertainty(const float *mu, int num_players) { - memset(mu_stddev, 0, sizeof(mu_stddev)); - - // Temporarily use mu_stddev to store the diagonal of the Hessian. - - // Prior. + Matrix h(num_players, num_players); for (int i = 0; i < num_players; ++i) { - mu_stddev[i] += 1.0f / (prior_sigma * prior_sigma); - } - - // Matches. - for (unsigned i = 0; i < all_matches.size(); ++i) { - const match &m = all_matches[i]; - - int p1 = m.player; - int p2 = m.other_player; - - double sigma_sq = global_sigma * global_sigma; - float w = m.weight; - - mu_stddev[p1] += w / sigma_sq; - mu_stddev[p2] += w / sigma_sq; + for (int j = 0; j < num_players; ++j) { + h(i, j) = hessian[i * num_players + j]; + } } - // Now convert to standard deviation. + // FIXME: Use pseudoinverse if applicable. + Matrix ih = h.inverse(); for (int i = 0; i < num_players; ++i) { - mu_stddev[i] = 1.0f / sqrt(mu_stddev[i]); + mu_stddev[i] = sqrt(ih(i, i)); } } @@ -357,6 +345,7 @@ int main(int argc, char **argv) #if DUMP_RAW dump_raw(mu, num_players); #else + construct_hessian(mu, num_players); compute_mu_uncertainty(mu, num_players); dump_scores(players, mu, mu_stddev, num_players); //fprintf(stderr, "Optimal sigma: %f (two-player: %f)\n", sigma[0], sigma[0] * sqrt(2.0f)); @@ -365,7 +354,5 @@ int main(int argc, char **argv) float total_logl = compute_total_logl(mu, num_players); printf("%f 0 -4\n", total_logl); - -// construct_hessian(mu, sigma, num_players); #endif } diff --git a/www/ratings-explained.html b/www/ratings-explained.html index c2e5c7f..c45075b 100755 --- a/www/ratings-explained.html +++ b/www/ratings-explained.html @@ -164,7 +164,7 @@

Dette var faktisk alt. Det skal sies at det sikkert er nok ̴ ta tak i som ikke er blitt dekket her Рfor eksempel er det ikke beskrevet hvordan man regner ut usikkerheten i de estimerte ratingene - (hvilket er passe komplekst, og basert p̴ en delvis invertering av + (hvilket er passe komplekst, og basert p̴ ̴ invertere Hess-matrisen til rimelighetsfunksjonen), eller hvordan modellen vekter kamper eldre kamper gis mindre betydning).

-- 2.39.2