HF-Sum commited on
Commit
49bd160
·
verified ·
1 Parent(s): f2e19ab

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +24 -0
  2. app.py +76 -0
  3. best_rf_model.joblib +3 -0
  4. requirements.txt +10 -0
Dockerfile ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use an official Python runtime as a parent image
2
+ FROM python:3.9-slim
3
+
4
+ # Set the working directory in the container
5
+ WORKDIR /app
6
+
7
+ # Copy the requirements file into the container at /app (corrected path)
8
+ COPY requirements.txt .
9
+
10
+ # Install any needed packages specified in requirements.txt
11
+ RUN pip install --no-cache-dir -r requirements.txt
12
+
13
+ # Copy the Flask application file into the container at /app (corrected path)
14
+ COPY app.py .
15
+
16
+ # Copy the trained model file into the container at /app (corrected path)
17
+ COPY best_rf_model.joblib .
18
+
19
+ # Expose the port that the app will run on
20
+ EXPOSE 8000
21
+
22
+ # Run Gunicorn to serve the Flask application
23
+ # The 'app:app' refers to the 'app' object in the 'app.py' file
24
+ CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]
app.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import flask
2
+ from flask import Flask, request, jsonify
3
+ import joblib
4
+ import pandas as pd
5
+ import numpy as np
6
+ import sys # Import sys for stdout redirection
7
+
8
+ print('Starting Superkart Sales Predictor Flask app...', file=sys.stdout)
9
+
10
+ # Instantiate Flask app
11
+ app = Flask("Superkart Sales Predictor")
12
+ print('Flask app instantiated.', file=sys.stdout)
13
+
14
+ # Load the pre-trained model
15
+ print('Attempting to load model...', file=sys.stdout)
16
+ loaded_model = joblib.load('best_rf_model.joblib')
17
+ print('Model loaded successfully!', file=sys.stdout)
18
+
19
+ # For demonstration, let's manually define the expected features based on the notebook's X_train structure
20
+ # In a real app, you'd load this from a saved file to ensure consistency
21
+ expected_features_list = ['Product_Weight', 'Product_Sugar_Content', 'Product_Allocated_Area',
22
+ 'Product_Type', 'Product_MRP', 'Store_Size',
23
+ 'Store_Location_City_Type', 'Store_Type', 'yr_since_store_estab']
24
+
25
+ # Define the prediction endpoint
26
+ @app.route('/predict', methods=['POST'])
27
+ def predict():
28
+ print('Prediction request received.', file=sys.stdout)
29
+ try:
30
+ # Get data from POST request
31
+ print('Attempting to get JSON data from request...', file=sys.stdout)
32
+ data = request.get_json(force=True)
33
+ print(f'Received data: {data}', file=sys.stdout)
34
+
35
+ # Convert incoming data to DataFrame matching training features structure
36
+ if isinstance(data, dict):
37
+ input_df = pd.DataFrame([data])
38
+ elif isinstance(data, list):
39
+ input_df = pd.DataFrame(data)
40
+ else:
41
+ print('Invalid input data format.', file=sys.stdout)
42
+ return jsonify({'error': 'Invalid input data format, expected dict or list of dicts'}), 400
43
+
44
+ # Reindex the DataFrame to ensure all expected columns are present, filling missing with NaN
45
+ # The order of columns is crucial for the preprocessor.
46
+ print('Reindexing input DataFrame and converting dtypes...', file=sys.stdout)
47
+ input_df = input_df.reindex(columns=expected_features_list, fill_value=np.nan)
48
+
49
+ # Ensure categorical columns have 'category' dtype as expected by the preprocessor
50
+ # Identify categorical columns from the original X_train
51
+ categorical_cols_expected = ['Product_Sugar_Content', 'Product_Type', 'Store_Size',
52
+ 'Store_Location_City_Type', 'Store_Type']
53
+
54
+ for col in categorical_cols_expected:
55
+ if col in input_df.columns:
56
+ input_df[col] = input_df[col].astype('category')
57
+ else:
58
+ # Handle cases where a categorical column might be missing from input_df
59
+ pass
60
+ print('Input DataFrame prepared for prediction.', file=sys.stdout)
61
+
62
+ # Make prediction using the loaded model pipeline
63
+ print('Making prediction...', file=sys.stdout)
64
+ predictions = loaded_model.predict(input_df)
65
+ print('Prediction successful.', file=sys.stdout)
66
+
67
+ # Convert predictions to a list or array for JSON response
68
+ return jsonify(predictions.tolist())
69
+
70
+ except Exception as e:
71
+ print(f'Error during prediction: {str(e)}', file=sys.stderr) # Log errors to stderr
72
+ return jsonify({'error': str(e)}), 500
73
+
74
+ # This part is for local testing and should be commented out or protected for deployment
75
+ # if __name__ == '__main__':
76
+ # app.run(debug=True, host='0.0.0.0', port=5000)
best_rf_model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2326677ef77a20fc5201db9d125fbc24f8c8261079a828a2244ba17b4cc8d953
3
+ size 20544778
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ pandas==2.2.2
2
+ numpy==2.0.2
3
+ scikit-learn==1.6.1
4
+ xgboost==2.1.4
5
+ joblib==1.4.2
6
+ Werkzeug==2.2.2
7
+ flask==2.2.2
8
+ gunicorn==20.1.0
9
+ requests==2.28.1
10
+ uvicorn[standard]