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
|