Skip to content

Commit

Permalink
Merge pull request #2 from Jaykold/client-side
Browse files Browse the repository at this point in the history
Client side
  • Loading branch information
Jaykold authored Aug 19, 2024
2 parents 01c8c4a + 269b1e9 commit c2e7e86
Show file tree
Hide file tree
Showing 9 changed files with 414 additions and 118 deletions.
17 changes: 17 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: detect-private-key
- id: requirements-txt-fixer
- id: check-merge-conflict
- id: name-tests-test
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
name: isort (python)
45 changes: 18 additions & 27 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# For windows, use the following command to run the makefile
PYTHON := python

# Define the scripts
DATA_TRAINING := src/components/model_trainer.py

# Default target
all: preprocess
all: preprocess

# Target to run model training
preprocess: ensure_artifacts_dir
Expand All @@ -24,35 +25,25 @@ clean:
.PHONY: all preprocess clean ensure_artifacts_dir


# # for linux, use the following command to run the makefile
# PYTHON := python3

# Makefile for ML Project

# Variables
TRAIN_DATA_PATH = artifacts/train_data.csv
VALIDATE_DATA_PATH = artifacts/validate_data.csv
TRAIN_SCRIPT = src/components/model_trainer.py
DATA_INGEST_SCRIPT = src/components/data_ingestion.py
DATA_PREPROCESS_SCRIPT = src/components/data_preprocessing.py

# Targets

.PHONY: all data_ingest preprocess train clean

all: data_ingest preprocess train
# Define the scripts
# DATA_TRAINING := src/components/model_trainer.py

data_ingest:
@echo "Running Data Ingestion..."
python $(DATA_INGEST_SCRIPT) --train_data $(TRAIN_DATA_PATH) --validate_data $(VALIDATE_DATA_PATH)
# # Default target
# all: preprocess

preprocess: data_ingest
@echo "Running Data Preprocessing..."
python $(DATA_PREPROCESS_SCRIPT) --train_data $(TRAIN_DATA_PATH) --validate_data $(VALIDATE_DATA_PATH)
# # Target to run model training
# preprocess: ensure_artifacts_dir
# $(PYTHON) $(DATA_TRAINING)

train: preprocess
@echo "Running Model Training..."
python $(TRAIN_SCRIPT) --train_data $(TRAIN_DATA_PATH) --validate_data $(VALIDATE_DATA_PATH)
# ensure_artifacts_dir:
# mkdir -p artifacts

clean:
@echo "Cleaning up..."
rm -rf artifacts/ logs/
# # Clean target (optional)
# clean:
# rm -f *.pyc
# rm -rf __pycache__

# .PHONY: all preprocess clean ensure_artifacts_dir
70 changes: 50 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,32 +61,24 @@ To run this project, you need to install the following packages:

### Clone the repository

```git clone https://github.com/Jaykold/dry-bean-predictor.git```
```
git clone https://github.com/Jaykold/dry-bean-predictor.git
```

### Navigate to the project directory

```cd dry-bean-predictor```
```
cd dry-bean-predictor
```

### Create a virtual environment
You can install the required packages using the provided`conda_dependencies.yml` file:
You can install the required packages using the code provided below:

```conda env create -f conda_dependencies.yml```
```
pip install -e .
```
Run this to install the required packages and project in editable mode.

After creating your virtual environment, you can activate it using:

<codespace/>```conda activate myenv // That's is the name specified in the .yml file```</codespace>

Or using `requirements.txt`:

```pip install -r requirements.txt```

Run ```pip install -e .``` to install the project in editable mode.

Run Jupyter Notebook

```jupyter notebook```

Open `dry_bean.ipynb` and execute the cells to preprocess the data and train the model

## Components

Expand All @@ -106,9 +98,47 @@ The `pipeline` directory contains script for model prediction.
#### Model training
To train the model, run the `model_trainer.py` script:

```python src/components/model_trainer.py```
```
python src/components/model_trainer.py
```

Or use the Makefile by typing ```make``` in your terminal

This will train the model and save the results to the `artifacts` directory.

If you are using windows you can install ```make``` by running this code in your terminal

```
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.WebClient]::new().DownloadString('https://community.chocolatey.org/install.ps1') | Invoke-Expression
```

then install make using choco

```
choco install make
```
On linux check if ```make``` is installed

```
make --version
```

if not installed, run

```
sudo apt update
sudo apt install make
```
.

To run app.py to predict your bean, use this code command

```
# On windows
waitress-serve --listen=0.0.0.0:9696 app:app
# On Linux
gunicorn --bind=0.0.0.0:9696 app:app
```

## Contributing
Contributions are welcome! Please open an issue or submit a pull request for any improvements or bug fixes.
43 changes: 42 additions & 1 deletion notebook/dry_bean.ipynb
Original file line number Diff line number Diff line change
@@ -1,5 +1,46 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The raw dataset for this study was obtained from the UCI Machine Learning Repository via an API call using ```ucimlrepo``` (fetch_ucirepo). \n",
"\n",
"It included grains with 16 features in total, comprising 12 dimensions and 4 distinct shapes. The study employed three well-known \n",
"\n",
"classifiers: Logistic Regression (LR), Random Forest (RF), and \n",
"\n",
"Extreme Gradient Boosting (XGB), all with balanced classes.\n",
"\n",
"This dataset has a shape of 13,611 data entries and 17 columns\n",
"\n",
"1. **Area (A)**: The area of a bean zone and the number of pixels within its boundaries.\n",
"\n",
"2. **Perimeter (P)**: Bean circumference is defined as the length of its border.\n",
"3. **Major axis length (L)**: The distance between the ends of the longest line that can be drawn from a bean.\n",
"4. **Minor axis length (l)**: The longest line that can be drawn from the bean while standing perpendicular to the main axis.\n",
"5. **Aspect ratio (K)**: Defines the relationship between L and l.\n",
"6. **Eccentricity (Ec)**: Eccentricity of the ellipse having the same moments as the region.\n",
"7. **Convex area (C)**: Number of pixels in the smallest convex polygon that can contain the area of a bean seed.\n",
"8. **Equivalent diameter (Ed)**: The diameter of a circle having the same area as a bean seed area.\n",
"9. **Extent (Ex)**: The ratio of the pixels in the bounding box to the bean area.\n",
"10. **Solidity (S)**: Also known as convexity. The ratio of the pixels in the convex shell to those found in beans.\n",
"11. **Roundness (R)**: Calculated with the following formula: \\( \\frac{4\\pi A}{P^2} \\)\n",
"12. **Compactness (CO)**: Measures the roundness of an object: \\( \\frac{Ed}{L} \\)\n",
"13. **ShapeFactor1 (SF1)**\n",
"14. **ShapeFactor2 (SF2)**\n",
"15. **ShapeFactor3 (SF3)**\n",
"16. **ShapeFactor4 (SF4)**\n",
"17. **Class**: Seker, Barbunya, Bombay, Cali, Dermosan, Horoz, and Sira"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 1,
Expand Down Expand Up @@ -97,7 +138,7 @@
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv('data/dry_bean.csv')"
"# df = pd.read_csv('data/dry_bean.csv')"
]
},
{
Expand Down
23 changes: 12 additions & 11 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
mlflow
evidently
Flask
gunicorn
imbalanced-learn
jupyter
scikit-learn
mlflow
pandas
seaborn
ucimlrepo
xgboost
imbalanced-learn
Flask
tdqm
pre-commit
psycopg
pydantic
pylint
evidently
psycopg
pytest
pytest-flask
gunicorn
scikit-learn
seaborn
tdqm
ucimlrepo
xgboost
13 changes: 8 additions & 5 deletions src/pipeline/predict.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import sys
from typing import Union

import pandas as pd
from pydantic import BaseModel

from src.exception import CustomException
from src.utils import load_object


class PredictPipeline:
def __init__(self):
pass
Expand All @@ -15,7 +18,7 @@ def predict(self, features:pd.DataFrame):
model_path = 'artifacts/model.pkl'
scaler_path = 'artifacts/scaler.pkl'
labelencoder_path = 'artifacts/labelencoder.pkl'

# Load the model, SMOTE, and scaler objects
model = load_object(file_path=model_path)
scaler = load_object(file_path=scaler_path)
Expand All @@ -24,10 +27,10 @@ def predict(self, features:pd.DataFrame):
# Transform the features using scaler
data_scaled = scaler.transform(features)
# Make predictions using the model
pred = model.predict(data_scaled)#.astype(int)
pred = model.predict(data_scaled).astype(int)
result = labelencoder.inverse_transform(pred)
return result[0].capitalize()

except Exception as e:
# Raise a custom exception if an error occurs
raise CustomException(e, sys) from e
Expand Down Expand Up @@ -71,6 +74,6 @@ def to_dataframe(self):
'ShapeFactor4': [self.ShapeFactor4]
}
return pd.DataFrame(data)

except Exception as e:
raise CustomException(e, sys) from e
raise CustomException(e, sys) from e
16 changes: 15 additions & 1 deletion static/css/home.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ body {
}

.login {
width: 400px;
width: 100%;
padding: 20px;
border: 1px solid #ccc;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
max-width: 700px;
}

.heading {
Expand Down Expand Up @@ -88,3 +89,16 @@ body {
.dropdown-item:hover {
background-color: #f0f0f0;
}

.two-grid{
display: flex;
flex-direction: row;
justify-content: space-between;
gap: 10px;
}
.two-grid-child{
width: 48%;
display: flex;
flex-direction: column;
gap: 20px;
}
25 changes: 22 additions & 3 deletions static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,44 @@ const dropDownChild = document.createElement('div');
console.log("input value",input.value)
areaDropDown.style.display = 'none'; // Hide dropdown after selection
});

dropDown.appendChild(dropDownChild);
});}

const areaValues = [1, 2, 3, 4, 5, 6];
const areaValues = [71236, 39318, 34045];

const areaInput = document.getElementById("area-input");
const areaDropDown = document.getElementById("area-dropdown");

populateDropdown(areaInput, areaDropDown, areaValues)


const perimeterValues = [1, 2, 3, 4, 5, 6, 7];
const perimeterValues = [1055.392, 746.921, 681.927];
const perimeterInput = document.getElementById("perimeter-input");
const perimeterDropDown = document.getElementById("perimeter-dropdown");

populateDropdown(perimeterInput, perimeterDropDown, perimeterValues)

const majoraxislengthValues = [345.968599, 279.815434, 252.167650];
const majoraxislengthInput = document.getElementById("majoraxislength-input");
const majoraxislengthDropDown = document.getElementById("majoraxislength-dropdown");

populateDropdown(majoraxislengthInput, majoraxislengthDropDown, majoraxislengthValues)

const minoraxislengthValues = [264.740746, 179.451019, 172.362100];
const minoraxislengthInput = document.getElementById("minoraxislength-input");
const minoraxislengthDropDown = document.getElementById("minoraxislength-dropdown");

populateDropdown(minoraxislengthInput, minoraxislengthDropDown, minoraxislengthValues)

const aspectratioValues = [1.487857, 2.092897, 1.606084];
const aspectratioInput = document.getElementById("aspectratio-input");
const aspectratioDropDown = document.getElementById("aspectratio-dropdown");

populateDropdown(aspectratioInput, aspectratioDropDown, aspectratioValues)

const eccentricityValues = [0.740453, 0.878465, 0.782514];
const eccentricityInput = document.getElementById("eccentricity-input");
const eccentricityDropDown = document.getElementById("eccentricity-dropdown");

populateDropdown(eccentricityInput, eccentricityDropDown, eccentricityValues)
Loading

0 comments on commit c2e7e86

Please sign in to comment.