import logging import os from flask import jsonify from . import app, request from .tasks.train_model import train_models logging.getLogger().setLevel(logging.INFO) DATABASE_NAME = os.getenv('DATABASE_NAME') @app.route('/train_models', methods=['POST']) def invoke_train_models(): """ Expects some feature engineering, but can do without too Trains multiple ML models and stores results in mlflow s3. Accessible through UI mlflow.fansifter.cloud. Returns modelling_runs dictionary with mlflow run_ids to search data from mlflow tracking server later. """ data = request.json if request.json else request.data logging.info(f"input data: {repr(data)}") schema = data['schema'] collection_ids = data['collection_ids'] bucket = data['bucket'] file_key = data['file_key'] """ We used this in legacy to differentiate between "RFM modelling" and "other". When feeding input fields from whatever is calling model training, we no longer have a need for this. """ modelling_config = { 'plot_2d': False, 'plot_3d': False, 'plot_silhouette': False, 'importance': True, 'boxplot': False, 'save_model': False, 'modelling_type': 'clustering', # -1 means no pca dimensionality reduction is done. Multiple values mean for each of those values a model will be trained 'pca_components': [4], # TODO! All experiments with -1 (no pca) were inferior to PCA, but there is more room to experiment 'drop_corr_threshold': 0.99 # Drop features that are highly correlated. That's why - https://www.trchome.com/docs/5-cluster-analysis-gets-complicated/file } modelling_runs = train_models(schema, collection_ids, bucket, file_key, modelling_config) return jsonify(modelling_runs), 200