Spaces:
Runtime error
Runtime error
Working Prototype
Browse files- .gitignore +5 -0
- Manufacturing_Downtime_Dataset.csv +0 -0
- README.md +152 -11
- app/__init__.py +0 -0
- app/__init__.py:Zone.Identifier +0 -0
- app/inference.py +26 -0
- app/inference.py:Zone.Identifier +0 -0
- app/main.py +66 -0
- app/main.py:Zone.Identifier +0 -0
- app/modelling.py +61 -0
- app/modelling.py:Zone.Identifier +0 -0
- plots/Confusion_Matrix.jpg +0 -0
- plots/Confusion_Matrix.jpg:Zone.Identifier +0 -0
- plots/Feature_Correlation.jpg +0 -0
- plots/Feature_Correlation.jpg:Zone.Identifier +0 -0
- plots/Feature_importance.jpg +0 -0
- plots/Feature_importance.jpg:Zone.Identifier +0 -0
- requirements.txt +7 -0
.gitignore
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
venv
|
| 2 |
+
__pycache__
|
| 3 |
+
*~
|
| 4 |
+
*.swp
|
| 5 |
+
*.swo_
|
Manufacturing_Downtime_Dataset.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
README.md
CHANGED
|
@@ -1,11 +1,152 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Manufacturing Downtime Prediction
|
| 2 |
+
|
| 3 |
+
## Project Links:
|
| 4 |
+
* **[Deployed FastAPI](https://omdena-jakarta-traffic-system.streamlit.app/)**
|
| 5 |
+
* **[Detailed Kaggle Notebook](https://www.kaggle.com/code/sudhanshu2198/machine-defect-prediction)**
|
| 6 |
+
|
| 7 |
+
## Background
|
| 8 |
+
- The Manufacturing Downtime Dataset contains information about the operational parameters of various machines and their downtime records.
|
| 9 |
+
- Analyze machine performance, predict potential failures, and develop predictive maintenance strategies based on operational parameters.
|
| 10 |
+
- Features
|
| 11 |
+
- Torque(Nm)
|
| 12 |
+
- Hydraulic_Pressure(bar)
|
| 13 |
+
- Cutting(kN)
|
| 14 |
+
- Coolant_Pressure(bar)
|
| 15 |
+
- Spindle_Speed(RPM)
|
| 16 |
+
- Coolant_Temperature
|
| 17 |
+
- Target
|
| 18 |
+
- Downtime
|
| 19 |
+
|
| 20 |
+
## Directory Tree
|
| 21 |
+
```bash
|
| 22 |
+
|
| 23 |
+
├── app
|
| 24 |
+
│ ├── __init__.py
|
| 25 |
+
│ ├── main.py
|
| 26 |
+
│ ├── modelling.py
|
| 27 |
+
│ └── inference.py
|
| 28 |
+
├── README.md
|
| 29 |
+
├── requirements.txt
|
| 30 |
+
├── Manufacturing_Downtime_Dataset.csv
|
| 31 |
+
└── .gitignore
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
## Run Webapp Locally
|
| 35 |
+
|
| 36 |
+
Clone the project
|
| 37 |
+
|
| 38 |
+
```bash
|
| 39 |
+
git clone https://github.com/sudhanshu2198/Manufacturing-Downtime-Prediction-API
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
Change to project directory
|
| 43 |
+
|
| 44 |
+
```bash
|
| 45 |
+
cd Manufacturing-Downtime-Prediction-API
|
| 46 |
+
```
|
| 47 |
+
Create Virtaul Environment and install dependencies
|
| 48 |
+
|
| 49 |
+
```bash
|
| 50 |
+
python3 -m venv venv
|
| 51 |
+
source venv/bin/activate
|
| 52 |
+
pip install -r requirements.txt
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
Run Locally
|
| 56 |
+
```bash
|
| 57 |
+
|
| 58 |
+
uvicorn app.main:app
|
| 59 |
+
|
| 60 |
+
```
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
cURL Commands
|
| 65 |
+
1) Upload
|
| 66 |
+
```bash
|
| 67 |
+
|
| 68 |
+
Request
|
| 69 |
+
curl -X 'POST' \
|
| 70 |
+
'http://127.0.0.1:8000/upload/' \
|
| 71 |
+
-H 'accept: application/json' \
|
| 72 |
+
-H 'Content-Type: multipart/form-data' \
|
| 73 |
+
-F 'uploaded_file=@Manufacturing_Downtime_Dataset.csv;type=text/csv'
|
| 74 |
+
|
| 75 |
+
Response
|
| 76 |
+
{
|
| 77 |
+
"file": "Manufacturing_Downtime_Dataset.csv",
|
| 78 |
+
"content": "text/csv",
|
| 79 |
+
"path": "dataset.csv"
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
```
|
| 83 |
+
2) Train
|
| 84 |
+
```bash
|
| 85 |
+
Request
|
| 86 |
+
curl -X 'POST' \
|
| 87 |
+
'http://127.0.0.1:8000/train/' \
|
| 88 |
+
-H 'accept: application/json' \
|
| 89 |
+
-d ''
|
| 90 |
+
Response
|
| 91 |
+
{
|
| 92 |
+
"Accuracy": 0.9897750511247444,
|
| 93 |
+
"F1_Score": 0.9896049896049895
|
| 94 |
+
}
|
| 95 |
+
```
|
| 96 |
+
3) Predict
|
| 97 |
+
```bash
|
| 98 |
+
Request 1
|
| 99 |
+
curl -X 'POST' \
|
| 100 |
+
'http://127.0.0.1:8000/predict/' \
|
| 101 |
+
-H 'accept: application/json' \
|
| 102 |
+
-H 'Content-Type: application/json' \
|
| 103 |
+
-d '{
|
| 104 |
+
"Torque": 28.38124,
|
| 105 |
+
"Hydraulic_Pressure": 131.265854,
|
| 106 |
+
"Cutting": 2.01,
|
| 107 |
+
"Coolant_Pressure": 4.982836,
|
| 108 |
+
"Spindle_Speed": 20033.0,
|
| 109 |
+
"Coolant_Temperature": 20.1
|
| 110 |
+
}'
|
| 111 |
+
|
| 112 |
+
Response 1
|
| 113 |
+
{
|
| 114 |
+
"Downtime": "No",
|
| 115 |
+
"Confidence": 0.87
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
Request 2
|
| 119 |
+
curl -X 'POST' \
|
| 120 |
+
'http://127.0.0.1:8000/predict/' \
|
| 121 |
+
-H 'accept: application/json' \
|
| 122 |
+
-H 'Content-Type: application/json' \
|
| 123 |
+
-d '{
|
| 124 |
+
"Torque": 25.614444,
|
| 125 |
+
"Hydraulic_Pressure": 98.7,
|
| 126 |
+
"Cutting": 3.49,
|
| 127 |
+
"Coolant_Pressure": 6.839413,
|
| 128 |
+
"Spindle_Speed": 18638.0,
|
| 129 |
+
"Coolant_Temperature": 24.4
|
| 130 |
+
}'
|
| 131 |
+
|
| 132 |
+
Response 2
|
| 133 |
+
{
|
| 134 |
+
"Downtime": "Yes",
|
| 135 |
+
"Confidence": 0.98
|
| 136 |
+
}
|
| 137 |
+
```
|
| 138 |
+
|
| 139 |
+
## Plots
|
| 140 |
+
|
| 141 |
+
RandomForest Model is using for modelling the relation between features and target variable in Manufacturing Downtime Dataset.
|
| 142 |
+
|
| 143 |
+
- Accuracy: **0.9897**
|
| 144 |
+
- F1_Score: **0.9896**
|
| 145 |
+
|
| 146 |
+
#### Feature Correlation
|
| 147 |
+
#### Feature Importance
|
| 148 |
+
#### Confusion Matrix
|
| 149 |
+
|
| 150 |
+
## 🛠 Skills
|
| 151 |
+
Numpy, Pandas, Scikit-learn, FastAPI, Git
|
| 152 |
+
|
app/__init__.py
ADDED
|
File without changes
|
app/__init__.py:Zone.Identifier
ADDED
|
File without changes
|
app/inference.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import joblib
|
| 3 |
+
import numpy as np
|
| 4 |
+
|
| 5 |
+
def predict(array):
|
| 6 |
+
label_value_mapping={"No_Machine_Failure":"No",
|
| 7 |
+
"Machine_Failure":"Yes"}
|
| 8 |
+
cwd=os.getcwd()
|
| 9 |
+
|
| 10 |
+
transform_pth=os.path.join(cwd,"app","transform.pkl")
|
| 11 |
+
transform=joblib.load(transform_pth)
|
| 12 |
+
|
| 13 |
+
encoder_pth=os.path.join(cwd,"app","encoder.pkl")
|
| 14 |
+
encoder=joblib.load(encoder_pth)
|
| 15 |
+
|
| 16 |
+
scaled_array=transform.transform(array)
|
| 17 |
+
|
| 18 |
+
model_pth=os.path.join(cwd,"app","model.pkl")
|
| 19 |
+
trained_model=joblib.load(model_pth)
|
| 20 |
+
|
| 21 |
+
idx=trained_model.predict(scaled_array)[0].item()
|
| 22 |
+
label=encoder.inverse_transform([idx]).item()
|
| 23 |
+
confidence=np.max(trained_model.predict_proba(scaled_array)).item()
|
| 24 |
+
|
| 25 |
+
return {"Downtime":label_value_mapping[label],
|
| 26 |
+
"Confidence":confidence}
|
app/inference.py:Zone.Identifier
ADDED
|
File without changes
|
app/main.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import shutil
|
| 2 |
+
import glob
|
| 3 |
+
import os
|
| 4 |
+
|
| 5 |
+
import numpy as np
|
| 6 |
+
from fastapi import FastAPI,UploadFile,File
|
| 7 |
+
from pydantic import BaseModel,Field
|
| 8 |
+
|
| 9 |
+
from app.modelling import train
|
| 10 |
+
from app.inference import predict
|
| 11 |
+
|
| 12 |
+
class Item(BaseModel):
|
| 13 |
+
Torque:float=Field(gt=0,default=24.25)
|
| 14 |
+
Hydraulic_Pressure:float=Field(gt=0,default=121.86)
|
| 15 |
+
Cutting:float=Field(gt=0,default=2.89)
|
| 16 |
+
Coolant_Pressure:float=Field(gt=0,default=6.96)
|
| 17 |
+
Spindle_Speed:float=Field(gt=0,default=20504.0)
|
| 18 |
+
Coolant_Temperature:float=Field(gt=0,default=14.9)
|
| 19 |
+
|
| 20 |
+
app=FastAPI()
|
| 21 |
+
|
| 22 |
+
@app.get("/")
|
| 23 |
+
def home():
|
| 24 |
+
return {"message":"Hello World!"}
|
| 25 |
+
|
| 26 |
+
@app.post("/upload/")
|
| 27 |
+
def upload_csv(uploaded_file:UploadFile=File(...)):
|
| 28 |
+
cwd=os.getcwd()
|
| 29 |
+
path=os.path.join(cwd,"app","dataset.csv")
|
| 30 |
+
with open(path, 'w+b') as file:
|
| 31 |
+
shutil.copyfileobj(uploaded_file.file, file)
|
| 32 |
+
|
| 33 |
+
return {'file': uploaded_file.filename,
|
| 34 |
+
'content': uploaded_file.content_type,
|
| 35 |
+
'path': path}
|
| 36 |
+
|
| 37 |
+
@app.post("/train/")
|
| 38 |
+
def training():
|
| 39 |
+
cwd=os.getcwd()
|
| 40 |
+
path=os.path.join(cwd,"app","dataset.csv")
|
| 41 |
+
if os.path.exists(path):
|
| 42 |
+
results=train(path)
|
| 43 |
+
return results
|
| 44 |
+
else:
|
| 45 |
+
return {"message":"First Upload Dataset"}
|
| 46 |
+
|
| 47 |
+
@app.post("/predict/")
|
| 48 |
+
def prediction(item:Item):
|
| 49 |
+
cwd=os.getcwd()
|
| 50 |
+
path=os.path.join(cwd,"app","model.pkl")
|
| 51 |
+
if os.path.exists(path):
|
| 52 |
+
arr=[[item.Torque,item.Hydraulic_Pressure,item.Cutting,item.Coolant_Pressure,item.Spindle_Speed,item.Coolant_Temperature]]
|
| 53 |
+
results=predict(arr)
|
| 54 |
+
return results
|
| 55 |
+
else:
|
| 56 |
+
return {"message":"First Train Model"}
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
|
app/main.py:Zone.Identifier
ADDED
|
File without changes
|
app/modelling.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import numpy as np
|
| 3 |
+
import pandas as pd
|
| 4 |
+
from sklearn.metrics import accuracy_score
|
| 5 |
+
from sklearn.preprocessing import LabelEncoder
|
| 6 |
+
from sklearn.preprocessing import PowerTransformer
|
| 7 |
+
from sklearn.model_selection import train_test_split
|
| 8 |
+
from sklearn.ensemble import RandomForestClassifier
|
| 9 |
+
from sklearn.metrics import f1_score
|
| 10 |
+
import argparse
|
| 11 |
+
import joblib
|
| 12 |
+
|
| 13 |
+
def train(dataset_pth):
|
| 14 |
+
df=pd.read_csv(dataset_pth)
|
| 15 |
+
features=["Torque(Nm)","Hydraulic_Pressure(bar)","Cutting(kN)","Coolant_Pressure(bar)","Spindle_Speed(RPM)","Coolant_Temperature","Downtime"]
|
| 16 |
+
|
| 17 |
+
df=df[features]
|
| 18 |
+
df.dropna(inplace=True,ignore_index=True)
|
| 19 |
+
X=df.drop("Downtime",axis=1)
|
| 20 |
+
y=df["Downtime"]
|
| 21 |
+
|
| 22 |
+
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.20,random_state=42,stratify=y)
|
| 23 |
+
|
| 24 |
+
transform=PowerTransformer()
|
| 25 |
+
X_train=transform.fit_transform(X_train)
|
| 26 |
+
X_test=transform.transform(X_test)
|
| 27 |
+
|
| 28 |
+
encoder=LabelEncoder()
|
| 29 |
+
y_train=encoder.fit_transform(y_train)
|
| 30 |
+
y_test=encoder.transform(y_test)
|
| 31 |
+
|
| 32 |
+
model=RandomForestClassifier(random_state=42)
|
| 33 |
+
model.fit(X_train,y_train)
|
| 34 |
+
predict=model.predict(X_test)
|
| 35 |
+
|
| 36 |
+
cwd=os.getcwd()
|
| 37 |
+
transform_pth=os.path.join(cwd,"app","transform.pkl")
|
| 38 |
+
encoder_pth=os.path.join(cwd,"app","encoder.pkl")
|
| 39 |
+
model_pth=os.path.join(cwd,"app","model.pkl")
|
| 40 |
+
|
| 41 |
+
joblib.dump(transform,transform_pth)
|
| 42 |
+
joblib.dump(encoder,encoder_pth)
|
| 43 |
+
joblib.dump(model,model_pth)
|
| 44 |
+
|
| 45 |
+
return {"Accuracy":accuracy_score(y_test,predict),
|
| 46 |
+
"F1_Score":f1_score(y_test,predict)}
|
| 47 |
+
|
| 48 |
+
if __name__=="__main__":
|
| 49 |
+
parser=argparse.ArgumentParser()
|
| 50 |
+
parser.add_argument("--dataset_pth",default="/home/sudhanshu/manufacturing_defect/Manufacturing_Downtime_Dataset.csv")
|
| 51 |
+
args=parser.parse_args()
|
| 52 |
+
results=train(args.dataset_pth)
|
| 53 |
+
|
| 54 |
+
print(f"Accuracy: {results['Accuracy']}\n")
|
| 55 |
+
print(f"F1_Score: {results['F1_Score']}")
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
|
app/modelling.py:Zone.Identifier
ADDED
|
File without changes
|
plots/Confusion_Matrix.jpg
ADDED
|
plots/Confusion_Matrix.jpg:Zone.Identifier
ADDED
|
File without changes
|
plots/Feature_Correlation.jpg
ADDED
|
plots/Feature_Correlation.jpg:Zone.Identifier
ADDED
|
File without changes
|
plots/Feature_importance.jpg
ADDED
|
plots/Feature_importance.jpg:Zone.Identifier
ADDED
|
File without changes
|
requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
pandas==2.2.2
|
| 2 |
+
numpy==1.26.4
|
| 3 |
+
scikit-learn==1.2.2
|
| 4 |
+
joblib==1.4.2
|
| 5 |
+
fastapi==0.115.6
|
| 6 |
+
uvicorn==0.34.0
|
| 7 |
+
python-multipart==0.0.20
|