From 8103b98d1e58d56e0f7dfb468fee7208944a7939 Mon Sep 17 00:00:00 2001 From: ltcptgeneral <35508619+ltcptgeneral@users.noreply.github.com> Date: Fri, 4 Oct 2019 00:26:21 -0500 Subject: [PATCH] analysis.py v 1.1.3.000 --- .../__pycache__/analysis.cpython-37.pyc | Bin 15912 -> 21322 bytes .../__pycache__/regression.cpython-37.pyc | Bin 6985 -> 6981 bytes data analysis/analysis/analysis.py | 114 +++++++++++++++++- 3 files changed, 112 insertions(+), 2 deletions(-) diff --git a/data analysis/analysis/__pycache__/analysis.cpython-37.pyc b/data analysis/analysis/__pycache__/analysis.cpython-37.pyc index e608752d4b625da3c53b615fa6a69e3cd3105f14..32ddefec1fe6baad9ac956f9d4f3c1a9d669f4c1 100644 GIT binary patch delta 7970 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 delta 2723 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 diff --git a/data analysis/analysis/analysis.py b/data analysis/analysis/analysis.py index f9f77603..6170d322 100644 --- a/data analysis/analysis/analysis.py +++ b/data analysis/analysis/analysis.py @@ -7,10 +7,13 @@ # current benchmark of optimization: 1.33 times faster # setup: -__version__ = "1.1.2.003" +__version__ = "1.1.3.000" # changelog should be viewed using print(analysis.__changelog__) __changelog__ = """changelog: +1.1.3.000: + - added glicko2_engine class and glicko() + - verified glicko2() accuracy 1.1.2.003: - fixed elo() 1.1.2.002: @@ -307,6 +310,14 @@ def elo(starting_score, opposing_scores, observed, N, K): return starting_score + K*(np.sum(observed) - np.sum(expected)) +def gliko2(opp_ratings, opp_rd, observations, rating = 1500, rd = 350, vol = 0.06): + + player = gliko2_engine(rating = rating, rd = rd, vol = vol) + + player.update_player([x for x in opp_ratings], [x for x in opp_rd], observations) + + return [player.rating, player.rd, player.vol] + @jit(forceobj=True) def r_squared(predictions, targets): # assumes equal size inputs @@ -560,4 +571,103 @@ class regression: ls=loss(pred,ground_cuda) ls.backward() optim.step() - return kernel \ No newline at end of file + return kernel + +class gliko2_engine: + + _tau = 0.5 + + def getRating(self): + return (self.__rating * 173.7178) + 1500 + + def setRating(self, rating): + self.__rating = (rating - 1500) / 173.7178 + + rating = property(getRating, setRating) + + def getRd(self): + return self.__rd * 173.7178 + + def setRd(self, rd): + self.__rd = rd / 173.7178 + + rd = property(getRd, setRd) + + def __init__(self, rating = 1500, rd = 350, vol = 0.06): + + self.setRating(rating) + self.setRd(rd) + self.vol = vol + + def _preRatingRD(self): + + self.__rd = math.sqrt(math.pow(self.__rd, 2) + math.pow(self.vol, 2)) + + def update_player(self, rating_list, RD_list, outcome_list): + + rating_list = [(x - 1500) / 173.7178 for x in rating_list] + RD_list = [x / 173.7178 for x in RD_list] + + v = self._v(rating_list, RD_list) + self.vol = self._newVol(rating_list, RD_list, outcome_list, v) + self._preRatingRD() + + self.__rd = 1 / math.sqrt((1 / math.pow(self.__rd, 2)) + (1 / v)) + + tempSum = 0 + for i in range(len(rating_list)): + tempSum += self._g(RD_list[i]) * \ + (outcome_list[i] - self._E(rating_list[i], RD_list[i])) + self.__rating += math.pow(self.__rd, 2) * tempSum + + + def _newVol(self, rating_list, RD_list, outcome_list, v): + + i = 0 + delta = self._delta(rating_list, RD_list, outcome_list, v) + a = math.log(math.pow(self.vol, 2)) + tau = self._tau + x0 = a + x1 = 0 + + while x0 != x1: + # New iteration, so x(i) becomes x(i-1) + x0 = x1 + d = math.pow(self.__rating, 2) + v + math.exp(x0) + h1 = -(x0 - a) / math.pow(tau, 2) - 0.5 * math.exp(x0) \ + / d + 0.5 * math.exp(x0) * math.pow(delta / d, 2) + h2 = -1 / math.pow(tau, 2) - 0.5 * math.exp(x0) * \ + (math.pow(self.__rating, 2) + v) \ + / math.pow(d, 2) + 0.5 * math.pow(delta, 2) * math.exp(x0) \ + * (math.pow(self.__rating, 2) + v - math.exp(x0)) / math.pow(d, 3) + x1 = x0 - (h1 / h2) + + return math.exp(x1 / 2) + + def _delta(self, rating_list, RD_list, outcome_list, v): + + tempSum = 0 + for i in range(len(rating_list)): + tempSum += self._g(RD_list[i]) * (outcome_list[i] - self._E(rating_list[i], RD_list[i])) + return v * tempSum + + def _v(self, rating_list, RD_list): + + tempSum = 0 + for i in range(len(rating_list)): + tempE = self._E(rating_list[i], RD_list[i]) + tempSum += math.pow(self._g(RD_list[i]), 2) * tempE * (1 - tempE) + return 1 / tempSum + + def _E(self, p2rating, p2RD): + + return 1 / (1 + math.exp(-1 * self._g(p2RD) * \ + (self.__rating - p2rating))) + + def _g(self, RD): + + return 1 / math.sqrt(1 + 3 * math.pow(RD, 2) / math.pow(math.pi, 2)) + + def did_not_compete(self): + + self._preRatingRD() \ No newline at end of file