From 0f8f794c97b912d954c915ad759f6b2718ce1088 Mon Sep 17 00:00:00 2001 From: Adamantios Date: Thu, 18 Jul 2024 17:20:53 +0300 Subject: [PATCH] fix: the scaling of the weighted accuracy --- .../skills/decision_maker_abci/policy.py | 17 +++-- .../decision_maker_abci/utils/scaling.py | 65 +++++++++++++++++++ 2 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 packages/valory/skills/decision_maker_abci/utils/scaling.py diff --git a/packages/valory/skills/decision_maker_abci/policy.py b/packages/valory/skills/decision_maker_abci/policy.py index 65d652e0a..3fc69602d 100644 --- a/packages/valory/skills/decision_maker_abci/policy.py +++ b/packages/valory/skills/decision_maker_abci/policy.py @@ -24,9 +24,14 @@ from dataclasses import asdict, dataclass, field, is_dataclass from typing import Any, Dict, List, Optional, Union +from packages.valory.skills.decision_maker_abci.utils.scaling import scale_value + RandomnessType = Union[int, float, str, bytes, bytearray, None] -WEIGHTED_ACCURACY_MAX = 101 + +VOLUME_FACTOR_REGULARIZATION = 0.5 +UNSCALED_WEIGHTED_ACCURACY_INTERVAL = (0.5, 100.5) +SCALED_WEIGHTED_ACCURACY_INTERVAL = (0, 1) class DataclassEncoder(json.JSONEncoder): @@ -135,12 +140,14 @@ def best_tool(self) -> str: def update_weighted_accuracy(self) -> None: """Update the weighted accuracy for each tool.""" self.weighted_accuracy = { - tool: ( + tool: scale_value( ( acc_info.accuracy - + (acc_info.requests - acc_info.pending) / self.n_requests - ) - / WEIGHTED_ACCURACY_MAX + + ((acc_info.requests - acc_info.pending) / self.n_requests) + * VOLUME_FACTOR_REGULARIZATION + ), + UNSCALED_WEIGHTED_ACCURACY_INTERVAL, + SCALED_WEIGHTED_ACCURACY_INTERVAL, ) for tool, acc_info in self.accuracy_store.items() } diff --git a/packages/valory/skills/decision_maker_abci/utils/scaling.py b/packages/valory/skills/decision_maker_abci/utils/scaling.py new file mode 100644 index 000000000..b1fca4f2e --- /dev/null +++ b/packages/valory/skills/decision_maker_abci/utils/scaling.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2024 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + + +"""This package contains helpers for scaling operations.""" + + +from typing import List, Tuple + + +def min_max(li: List[float]) -> Tuple[float, float]: + """Get the min and max of a list.""" + if not li: + raise ValueError("The list is empty.") + + min_ = max_ = li[0] + + for num in li[1:]: + if num < min_: + min_ = num + elif num > max_: + max_ = num + + return min_, max_ + + +def scale_value( + value: float, + min_max_bounds: tuple[float, float], + scale_bounds: tuple[float, float] = (0, 1), +) -> float: + """Perform min-max scaling on a value.""" + min_, max_ = min_max_bounds + current_range = max_ - min_ + # normalize between 0-1 + std = (value - min_) / current_range + # scale between min_bound and max_bound + min_bound, max_bound = scale_bounds + target_range = max_bound - min_bound + return std * target_range + min_bound + + +def min_max_scale( + li: List[float], + scale_bounds: tuple[float, float] = (0, 1), +) -> List[float]: + """Perform min-max scaling on a list of values.""" + min_max_ = min_max(li) + return [scale_value(value, min_max_, scale_bounds) for value in li]