Skip to content

Commit 9a3dc35

Browse files
committed
More Updations
1 parent 1d5e900 commit 9a3dc35

File tree

25 files changed

+716
-3
lines changed

25 files changed

+716
-3
lines changed

.dockerignore

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
build/
8+
develop-eggs/
9+
dist/
10+
downloads/
11+
eggs/
12+
.eggs/
13+
lib/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
*.egg-info/
20+
.installed.cfg
21+
*.egg
22+
23+
# Virtual environments
24+
.env
25+
.venv
26+
env/
27+
venv/
28+
ENV/
29+
env.bak/
30+
venv.bak/
31+
32+
# IDE
33+
.vscode/
34+
.idea/
35+
*.swp
36+
*.swo
37+
*~
38+
39+
# OS
40+
.DS_Store
41+
Thumbs.db
42+
43+
# Git
44+
.git/
45+
.gitignore
46+
47+
# Logs
48+
logs/
49+
*.log
50+
51+
# Jupyter Notebooks
52+
.ipynb_checkpoints
53+
54+
# Data files (optional - remove if you want to include sample data)
55+
data/
56+
57+
# Docker
58+
Dockerfile
59+
.dockerignore
60+
61+
# Documentation
62+
README.md
63+
*.md
64+
65+
# Scripts (optional - remove if needed in container)
66+
scripts/
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: MachineLearning Continuous Integartion & Delivery PipeLine
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
11+
env:
12+
PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
13+
DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USERNAME }}
14+
DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
15+
GIT_USERNAME: ${{ secrets.GIT_USERNAME }}
16+
GIT_EMAIL: ${{ secrets.GIT_EMAIL }}
17+
18+
jobs:
19+
Setup:
20+
name: Setup Environment for CI/CD
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Checkout code
24+
uses: actions/checkout@v4
25+
26+
- name: Set up Python
27+
uses: actions/setup-python@v5
28+
with:
29+
python-version: '3.11'
30+
31+
- name: Install dependencies
32+
run: |
33+
python -m pip install --upgrade pip
34+
pip install -r requirements.txt
35+
36+
build :
37+
name: Continuous Integration and Delivery
38+
runs-on: ubuntu-latest
39+
env:
40+
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
41+
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
42+
steps:
43+
- name: checkout code
44+
uses: actions/checkout@v4
45+
46+
- name: set up Docker Buildx
47+
uses: docker/setup-buildx-action@v3
48+
49+
- name: Log in to Docker Hub
50+
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
51+
52+
- name: Build image
53+
run: docker build -t $DOCKER_USERNAME/myapp:latest .
54+
55+
- name: Scan Docker image with Trivy
56+
run: |
57+
docker run --rm \
58+
-v /var/run/docker.sock:/var/run/docker.sock \
59+
aquasec/trivy:latest image $DOCKER_USERNAME/myapp:latest || true
60+
61+
- name: Push image to Docker Hub
62+
run: docker push $DOCKER_USERNAME/myapp:latest
63+
64+

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.venv/

Dockerfile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
FROM python:3.11-slim
2+
3+
WORKDIR /app
4+
5+
ENV PYTHONPATH=/app
6+
ENV FLASK_APP=app.py
7+
ENV FLASK_ENV=production
8+
9+
RUN apt-get update && apt-get install -y \
10+
gcc \
11+
&& rm -rf /var/lib/apt/lists/*
12+
13+
COPY requirements.txt .
14+
15+
RUN pip install --no-cache-dir -r requirements.txt
16+
17+
COPY . .
18+
19+
RUN mkdir -p artifacts/model_trainer
20+
21+
# Expose port
22+
EXPOSE 5000
23+
24+
# Health check
25+
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
26+
CMD curl -f http://localhost:5000/health || exit 1
27+
28+
# Run the application
29+
CMD ["python", "app.py"]

__pycache__/app.cpython-311.pyc

10.6 KB
Binary file not shown.

app.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from flask import Flask, request, render_template, jsonify
2+
import joblib
3+
import numpy as np
4+
5+
app = Flask(__name__)
6+
7+
# Load model on startup
8+
try:
9+
model = joblib.load("artifacts/model_trainer/model.joblib")
10+
print("Model loaded successfully")
11+
except:
12+
model = None
13+
print("Model not found - using fallback")
14+
15+
def prepare_features(sex, age, height, weight, duration, heart_rate, body_temp):
16+
"""Prepare 11 features for model prediction"""
17+
sex_numeric = 1 if sex.lower() == 'male' else 0
18+
bmi = weight / ((height / 100) ** 2)
19+
met_estimate = (heart_rate - 60) / 20 + 1
20+
estimated_calories_per_min = met_estimate * weight * 3.5 / 200
21+
age_weight = age * weight
22+
heart_temp = heart_rate * body_temp
23+
24+
return np.array([[sex_numeric, age, height, weight, duration, heart_rate,
25+
body_temp, bmi, estimated_calories_per_min, age_weight, heart_temp]])
26+
27+
def fallback_calories(sex, age, height, weight, duration, heart_rate):
28+
"""Simple fallback calculation"""
29+
if sex == 'male':
30+
bmr = 88.362 + (13.397 * weight) + (4.799 * height) - (5.677 * age)
31+
else:
32+
bmr = 447.593 + (9.247 * weight) + (3.098 * height) - (4.330 * age)
33+
34+
met = 6.0 if heart_rate < 140 else 8.0
35+
calories_per_minute = (met * weight * 3.5) / 200
36+
return round(calories_per_minute * duration, 2)
37+
38+
@app.route('/')
39+
def home():
40+
return render_template('index.html')
41+
42+
@app.route('/predict', methods=['POST'])
43+
def predict():
44+
try:
45+
# Get form data
46+
sex = request.form.get('sex', '').lower()
47+
age = float(request.form.get('age', 0))
48+
height = float(request.form.get('height', 0))
49+
weight = float(request.form.get('weight', 0))
50+
duration = float(request.form.get('duration', 0))
51+
heart_rate = float(request.form.get('heart_rate', 0))
52+
body_temp = float(request.form.get('body_temp', 0))
53+
54+
# Prepare features and predict
55+
features = prepare_features(sex, age, height, weight, duration, heart_rate, body_temp)
56+
57+
if model is not None:
58+
prediction = model.predict(features)[0]
59+
prediction = max(0, round(prediction, 2))
60+
else:
61+
prediction = fallback_calories(sex, age, height, weight, duration, heart_rate)
62+
63+
return jsonify({'success': True, 'prediction': prediction})
64+
65+
except Exception as e:
66+
return jsonify({'success': False, 'error': str(e)}), 400
67+
68+
@app.route('/health')
69+
def health():
70+
return jsonify({'status': 'healthy', 'model_loaded': model is not None})
71+
72+
if __name__ == '__main__':
73+
app.run(host='0.0.0.0', port=5000, debug=False)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"rmse": 2.102408382953637,
3-
"mae": 1.5072424263746285,
2+
"rmse": 2.1024083829536364,
3+
"mae": 1.5072424263746282,
44
"r2": 0.9988652238714363
55
}

docker-run.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
3+
# Build and Run ML Pipeline Docker Container
4+
5+
echo "🐳 Building Docker image for ML Pipeline..."
6+
docker build -t ml-pipeline-app .
7+
8+
echo "🚀 Running ML Pipeline container..."
9+
docker run -d \
10+
--name ml-pipeline \
11+
-p 5000:5000 \
12+
-v "$(pwd)/artifacts:/app/artifacts" \
13+
ml-pipeline-app
14+
15+
echo "✅ ML Pipeline is running at http://localhost:5000"
16+
echo "🔧 To stop: docker stop ml-pipeline"
17+
echo "🗑️ To remove: docker rm ml-pipeline"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[2025-07-12 13:51:28,793] 25 src.mlpipeline.logging - INFO - Model loaded successfully
2+
[2025-07-12 13:51:29,070] 97 werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
3+
* Running on all addresses (0.0.0.0)
4+
* Running on http://127.0.0.1:5000
5+
* Running on http://192.168.1.8:5000
6+
[2025-07-12 13:51:29,070] 97 werkzeug - INFO - Press CTRL+C to quit
7+
[2025-07-12 13:51:29,100] 97 werkzeug - INFO - * Restarting with stat
8+
[2025-07-12 13:53:43,665] 97 werkzeug - INFO - * Restarting with stat
9+
[2025-07-12 13:55:54,553] 97 werkzeug - INFO - * Restarting with stat
10+
[2025-07-12 13:57:36,739] 97 werkzeug - INFO - * Restarting with stat
11+
[2025-07-12 13:59:03,383] 97 werkzeug - INFO - * Restarting with stat
12+
[2025-07-12 13:59:32,567] 97 werkzeug - INFO - * Restarting with stat
13+
[2025-07-12 14:18:16,161] 97 werkzeug - INFO - * Restarting with stat
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[2025-07-12 13:51:33,293] 25 src.mlpipeline.logging - INFO - Model loaded successfully
2+
[2025-07-12 13:51:33,323] 97 werkzeug - WARNING - * Debugger is active!
3+
[2025-07-12 13:51:33,331] 97 werkzeug - INFO - * Debugger PIN: 119-896-947
4+
[2025-07-12 13:52:11,529] 97 werkzeug - INFO - 127.0.0.1 - - [12/Jul/2025 13:52:11] "GET / HTTP/1.1" 200 -
5+
[2025-07-12 13:52:11,768] 97 werkzeug - INFO - 127.0.0.1 - - [12/Jul/2025 13:52:11] "GET /favicon.ico HTTP/1.1" 404 -
6+
[2025-07-12 13:52:20,954] 97 werkzeug - INFO - 127.0.0.1 - - [12/Jul/2025 13:52:20] "GET /?id=9adb36d6-a812-4645-9ad8-7bbd5ed57abf&vscodeBrowserReqId=1752308540630 HTTP/1.1" 200 -
7+
[2025-07-12 13:53:24,502] 82 src.mlpipeline.logging - INFO - Prediction made: 294.99 calories
8+
[2025-07-12 13:53:24,502] 97 werkzeug - INFO - 127.0.0.1 - - [12/Jul/2025 13:53:24] "POST /predict HTTP/1.1" 200 -
9+
[2025-07-12 13:53:43,186] 97 werkzeug - INFO - * Detected change in 'D:\\MachineLearning PipeLine\\app.py', reloading

0 commit comments

Comments
 (0)