diff --git a/app/services/gaze_tracker.py b/app/services/gaze_tracker.py index 3354551..f987b17 100644 --- a/app/services/gaze_tracker.py +++ b/app/services/gaze_tracker.py @@ -1,4 +1,6 @@ # Necessary imports +import os +import threading import math import warnings @@ -42,7 +44,7 @@ func_total_accuracy, ) from app.services.config import hyperparameters - +from collections import defaultdict,OrderedDict # Machine learning models to use models = { @@ -76,6 +78,32 @@ "mae": make_scorer(mean_absolute_error), } +class LRUCache: + def __init__(self, max_size=100): + self.max_size = max_size + self.cache = OrderedDict() + + def get(self, key): + if key in self.cache: + # Move to end + self.cache.move_to_end(key) + return self.cache[key] + return None + + def put(self, key, value): + if key in self.cache: + self.cache.move_to_end(key) + elif len(self.cache) >= self.max_size: + # Remove LRU + self.cache.popitem(last=False) + + self.cache[key] = value + + def __contains__(self, key): + return key in self.cache + +model_cache=LRUCache(max_size=100) +calibration_locks = defaultdict(threading.Lock) def squash(v, limit=1.0): """Squash não-linear estilo WebGazer""" @@ -249,6 +277,8 @@ def predict_new_data_simple( SQUASH_LIMIT_X = 1.0 SQUASH_LIMIT_Y = 1.0 Y_GAIN = 1.2 # adjustment to compensate for vertical bias + csv_filename = os.path.basename(calib_csv_path) + calib_id = csv_filename.replace("_fixed_train_data.csv", "") # ============================ # LOAD TRAIN @@ -309,14 +339,31 @@ def predict_new_data_simple( diff_y_norm, rel_y_norm ]) - # ============================ - # MODELS - # ============================ - model_x = make_pipeline(StandardScaler(), Ridge(alpha=1.0)) - model_y = make_pipeline(StandardScaler(), Ridge(alpha=1.0)) + with calibration_locks[calib_id]: + cached_models = model_cache.get(calib_id) + + if cached_models: + print(f'Loading models from cache') + model_x = cached_models.get('x') + model_y = cached_models.get('y') + else: + + # ============================ + # MODELS + # ============================ + model_x = make_pipeline(StandardScaler(), Ridge(alpha=1.0)) + model_y = make_pipeline(StandardScaler(), Ridge(alpha=1.0)) + + model_x.fit(X_train_x, y_train_x) + model_y.fit(X_train_y, y_train_y) + + model_cache.put(calib_id,{ + "x":model_x, + "y":model_y + }) + + - model_x.fit(X_train_x, y_train_x) - model_y.fit(X_train_y, y_train_y) # ============================ # Real scale (calibration) - normalize predicted values to screen coordinates