public void Predict() { EbisuModel m = new EbisuModel(2, 2, 2); double p = Ebisu.PredictRecall(m, 2, true); Assert.AreEqual(0.5, p, EPS, "1 + 1 should equal 2"); }
public void TestAgainstReference() { try { // All this boilerplate is just to load JSON double maxTol = 5e-3; string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"Ebisu/Ebisu_test.json"); string[] testData = File.ReadAllLines(path); JArray expectedResult = (JArray)JsonConvert.DeserializeObject(testData[0]); foreach (var child in expectedResult) { //subtest might be either // a) ["update", [3.3, 4.4, 1.0], [0, 5, 0.1], {"post": [7.333641958415551, 8.949256654818793, // 0.4148304099305316]}] or b) ["predict", [34.4, 34.4, 1.0], [5.5], {"mean": 0.026134289032202798}] // // In both cases, the first two elements are a string and an array of numbers. Then the remaining vary depend on // what that string is. where the numbers are arbitrary. So here we go... String operation = child[0].ToString(); JArray second = (JArray)child[1]; EbisuModel ebisu = new EbisuModel(double.Parse(second[2].ToString()), double.Parse(second[0].ToString()), double.Parse(second[1].ToString())); if (operation.Equals("update")) { int successes = Convert.ToInt32(child[2][0].ToString()); int total = Convert.ToInt32(child[2][1].ToString()); double t = Convert.ToDouble(child[2][2].ToString()); JArray third = (JArray)child[3].Last.Last;//subtest.get(3).get("post"); EbisuModel expected = new EbisuModel(double.Parse(third[2].ToString()), double.Parse(third[0].ToString()), double.Parse(third[1].ToString())); IEbisu actual = Ebisu.UpdateRecall(ebisu, successes, total, t); Assert.AreEqual(expected.getAlpha(), actual.getAlpha(), maxTol); Assert.AreEqual(expected.getBeta(), actual.getBeta(), maxTol); Assert.AreEqual(expected.getTime(), actual.getTime(), maxTol); } else if (operation.Equals("predict")) { double t = Convert.ToDouble(child[2][0].ToString()); double expected = Convert.ToDouble(child[3].First.Last.ToString()); double actual = Ebisu.PredictRecall(ebisu, t, true); Assert.AreEqual(expected, actual, maxTol); } else { throw new Exception("unknown operation"); } } } catch (Exception ex) { ex.StackTrace.ToString(); Console.WriteLine("¡¡¡OOOPS SOMETHING BAD HAPPENED!!!"); Assert.IsTrue(false); } }
public void TestHalflife() { double hl = 20.0; EbisuModel m = new EbisuModel(hl, 2, 2); Assert.True(Math.Abs(Ebisu.ModelToPercentileDecay(m, .5, true) - hl) > 1e-2); Assert.True(Relerr(Ebisu.ModelToPercentileDecay(m, .5, 1e-6), hl) < 1e-3); //Assert.Throws<Exception>(() => Ebisu.ModelToPercentileDecay(m, 0.5, 1e-150)); }
/** * Actual worker method that calculates the posterior memory model at the same * time in the future as the prior, and rebalances as necessary. */ private static IEbisu UpdateRecall(IEbisu prior, int successes, int total, double tnow, bool rebalance, double tback) { double alpha = prior.getAlpha(); double beta = prior.getBeta(); double t = prior.getTime(); double dt = tnow / t; double et = tback / tnow; double[] binomlns = Enumerable.Range(0, total - successes + 1).Select(i => LogBinom(total - successes, i)).ToArray(); double[] logs = Enumerable.Range(0, 3) .Select(m => { List <Double> a = Enumerable.Range(0, total - successes + 1) .Select(i => binomlns[i] + LogBeta(beta, alpha + dt * (successes + i) + m * dt * et)).ToList(); //.boxed() //.collect(Collectors.toList()); List <Double> b = Enumerable.Range(0, total - successes + 1) .Select(i => Math.Pow(-1.0, i)).ToList(); //.boxed() //.collect(Collectors.toList()); return(LogSumExp(a, b)[0]); }).ToArray(); double logDenominator = logs[0]; double logMeanNum = logs[1]; double logM2Num = logs[2]; double mean = Math.Exp(logMeanNum - logDenominator); double m2 = Math.Exp(logM2Num - logDenominator); double meanSq = Math.Exp(2 * (logMeanNum - logDenominator)); double sig2 = m2 - meanSq; if (mean <= 0) { throw new Exception("invalid mean found"); } if (m2 <= 0) { throw new Exception("invalid second moment found"); } if (sig2 <= 0) { throw new Exception("invalid variance found " + String.Format("a=%g, b=%g, t=%g, k=%d, n=%d, tnow=%g, mean=%g, m2=%g, sig2=%g", alpha, beta, t, successes, total, tnow, mean, m2, sig2)); } List <Double> newAlphaBeta = MeanVarToBeta(mean, sig2); EbisuModel proposed = new EbisuModel(tback, newAlphaBeta[0], newAlphaBeta[1]); return(rebalance ? Rebalance(prior, successes, total, tnow, proposed) : proposed); }
public void Update() { IEbisu m = new EbisuModel(2, 2, 2); IEbisu success = Ebisu.UpdateRecall(m, 1, 1, 2.0); IEbisu failure = Ebisu.UpdateRecall(m, 0, 1, 2.0); Assert.AreEqual(3.0, success.getAlpha(), 500 * EPS, "success/alpha"); Assert.AreEqual(2.0, success.getBeta(), 500 * EPS, "success/beta"); Assert.AreEqual(2.0, failure.getAlpha(), 500 * EPS, "failure/alpha"); Assert.AreEqual(3.0, failure.getBeta(), 500 * EPS, "failure/beta"); }