Team Ai
Apppublic

binarythinkers89/deploy

sourceHugging Facemitupdated 9mo agoView on Hugging Face
0likes
app.py212 linesDownload Raw Back to root
1import pickle2import pandas as pd3import re4from flask import Flask, request, jsonify, render_template5 6# --- Helper function for text cleaning (as used during training) ---7def clean_text_for_prediction(text):8    """Replicates the text cleaning process for a single string."""9    if isinstance(text, str):10        return ' '.join(re.findall(r'[A-Za-z]+', text)).lower()11    return str(text).lower()12 13loaded_model = None14loaded_le = None15loaded_oEncoder = None16loaded_scaler = None17loaded_feature_columns = []18loaded_view_model = None19loaded_view_le = None20try:21    with open('feature_columns.pkl', 'rb') as file:22        loaded_feature_columns = pickle.load(file)23except Exception:24    loaded_feature_columns = []25try:26    with open('label_encoder.pkl', 'rb') as file:27        loaded_le = pickle.load(file)28except Exception:29    loaded_le = None30try:31    with open('ordinal_encoder.pkl', 'rb') as file:32        loaded_oEncoder = pickle.load(file)33except Exception:34    loaded_oEncoder = None35try:36    with open('standard_scaler.pkl', 'rb') as file:37        loaded_scaler = pickle.load(file)38except Exception:39    loaded_scaler = None40try:41    with open('stacking_ensemble_model.pkl', 'rb') as file:42        loaded_model = pickle.load(file)43except Exception:44    loaded_model = None45try:46    with open('best_political_view_model.pkl', 'rb') as file:47        loaded_view_model = pickle.load(file)48except Exception:49    loaded_view_model = None50try:51    with open('best_political_view_label_encoder.pkl', 'rb') as file:52        loaded_view_le = pickle.load(file)53except Exception:54    loaded_view_le = None55 56# --- Initialize Flask Application ---57app = Flask(__name__, template_folder='.')58 59# --- Define Home Route ---60@app.route('/')61def home():62    return render_template('view.html')63 64@app.route('/view')65def view():66    return render_template('view.html')67 68@app.route('/schema', methods=['GET'])69def schema():70    cats = {}71    if loaded_oEncoder and loaded_feature_columns:72        try:73            categories_list = loaded_oEncoder.categories_74            for k, v in zip(loaded_feature_columns, categories_list):75                cats[k] = [str(x) for x in list(v)]76        except Exception:77            cats = {}78    return jsonify({"feature_columns": loaded_feature_columns, "categories": cats})79 80# --- Define Prediction Route ---81@app.route('/predict', methods=['POST'])82def predict():83    if not loaded_feature_columns:84        return jsonify({"error": "Feature columns not loaded"}), 50385    if not request.is_json:86        return jsonify({"error": "Request must be JSON"}), 40087 88    new_data_raw = request.get_json()89 90    # Ensure input data keys match feature columns (case-insensitive for robustness, though training used specific casing)91    processed_input = {col: new_data_raw.get(col, "") for col in loaded_feature_columns}92 93    # Convert new_data to DataFrame, ensuring correct column order94    # Using a list of dictionaries to handle single row for DataFrame creation, which preserves column order from loaded_feature_columns95    new_df = pd.DataFrame([processed_input], columns=loaded_feature_columns)96 97    # Apply text cleaning preprocessing steps98    for col in new_df.columns:99        # Assuming 'F1' is the age column and should not be regex cleaned100        if col != 'F1': 101            new_df[col] = new_df[col].apply(clean_text_for_prediction)102        else:103            # Ensure 'F1' is lowercase string for consistent ordinal encoding if it contains non-numeric parts104            new_df[col] = new_df[col].astype(str).str.lower()105 106    if loaded_model and loaded_oEncoder and loaded_scaler and loaded_le:107        try:108            new_data_encoded = loaded_oEncoder.transform(new_df)109        except ValueError as e:110            return jsonify({"error": f"OrdinalEncoder transformation failed: {e}. Check input categories."}), 400111        new_data_scaled = loaded_scaler.transform(new_data_encoded)112        prediction_numerical = loaded_model.predict(new_data_scaled)113        predicted_label = loaded_le.inverse_transform(prediction_numerical)114        return jsonify({'predicted_engagement': predicted_label[0]})115    else:116        if loaded_le is not None and hasattr(loaded_le, 'classes_') and len(loaded_le.classes_) > 0:117            fallback_label = loaded_le.classes_[0]118        else:119            fallback_label = "unavailable"120        return jsonify({'predicted_engagement': fallback_label, 'note': 'fallback'}), 200121 122@app.route('/predict_debug', methods=['POST'])123def predict_debug():124    ready = all([loaded_feature_columns, loaded_model, loaded_oEncoder, loaded_scaler, loaded_le])125    if not request.is_json:126        return jsonify({"error": "Request must be JSON"}), 400127    raw = request.get_json()128    processed = {col: raw.get(col, "") for col in loaded_feature_columns} if loaded_feature_columns else raw129    df = pd.DataFrame([processed], columns=loaded_feature_columns) if loaded_feature_columns else pd.DataFrame([processed])130    for col in df.columns:131        if col != 'F1':132            df[col] = df[col].apply(clean_text_for_prediction)133        else:134            df[col] = df[col].astype(str).str.lower()135    debug = {136        'components': {137            'has_feature_columns': bool(loaded_feature_columns),138            'has_model': loaded_model is not None,139            'has_ordinal': loaded_oEncoder is not None,140            'has_scaler': loaded_scaler is not None,141            'has_label_encoder': loaded_le is not None,142        },143        'feature_columns_count': len(loaded_feature_columns) if loaded_feature_columns else 0,144        'cleaned_row': df.to_dict(orient='records')[0]145    }146    if ready:147        try:148            encoded = loaded_oEncoder.transform(df)149            scaled = loaded_scaler.transform(encoded)150            pred_num = loaded_model.predict(scaled)151            pred_label = loaded_le.inverse_transform(pred_num)152            debug['encoded'] = encoded[0].tolist()153            debug['scaled'] = scaled[0].tolist()154            debug['prediction_numerical'] = int(pred_num[0]) if hasattr(pred_num, '__iter__') else pred_num155            debug['prediction_label'] = pred_label[0]156            return jsonify(debug)157        except Exception as e:158            debug['error'] = str(e)159            return jsonify(debug), 500160    else:161        return jsonify(debug), 200162 163@app.route('/predict_view', methods=['POST'])164def predict_view():165    if not loaded_feature_columns:166        return jsonify({"error": "Feature columns not loaded"}), 503167    if not request.is_json:168        return jsonify({"error": "Request must be JSON"}), 400169    new_data_raw = request.get_json()170    processed_input = {col: new_data_raw.get(col, "") for col in loaded_feature_columns}171    new_df = pd.DataFrame([processed_input], columns=loaded_feature_columns)172    for col in new_df.columns:173        if col != 'F1':174            new_df[col] = new_df[col].apply(clean_text_for_prediction)175        else:176            new_df[col] = new_df[col].astype(str).str.lower()177    if loaded_view_model and loaded_oEncoder and loaded_scaler:178        try:179            new_data_encoded = loaded_oEncoder.transform(new_df)180        except ValueError as e:181            return jsonify({"error": f"OrdinalEncoder transformation failed: {e}. Check input categories."}), 400182        new_data_scaled = loaded_scaler.transform(new_data_encoded)183        expected_n = getattr(loaded_view_model, 'n_features_in_', None)184        if isinstance(expected_n, int) and expected_n > 0 and new_data_scaled.shape[1] != expected_n:185            new_data_scaled = new_data_scaled[:, :expected_n]186        yhat = loaded_view_model.predict(new_data_scaled)187        if loaded_view_le:188            try:189                yhat_label = loaded_view_le.inverse_transform(yhat)190                return jsonify({'predicted_view': str(yhat_label[0])})191            except Exception:192                return jsonify({'predicted_view': str(yhat[0])})193        else:194            classes_attr = getattr(loaded_view_model, 'classes_', None)195            if classes_attr is not None:196                mapping = None197                try:198                    as_str = [str(c) for c in list(classes_attr)]199                    if set(as_str) == set(['0','1','2']):200                        mapping = {'0': 'active', '1': 'moderately_interested', '2': 'not_interested'}201                except Exception:202                    mapping = None203                if mapping:204                    key = str(yhat[0])205                    return jsonify({'predicted_view': mapping.get(key, key)})206            return jsonify({'predicted_view': str(yhat[0])})207    else:208        return jsonify({'predicted_view': 'unavailable', 'note': 'fallback'}), 200209 210# --- Run the Flask application ---211if __name__ == '__main__':212    app.run(debug=True, host='0.0.0.0', port=7860)