Skip to content

Commit

Permalink
Merge pull request #38 from sdevenes/issue_29/deployment
Browse files Browse the repository at this point in the history
Issue 29/deployment
  • Loading branch information
sdevenes authored Oct 11, 2020
2 parents a948a1d + 3e51dc9 commit 1b24f9f
Show file tree
Hide file tree
Showing 27 changed files with 340 additions and 142 deletions.
35 changes: 32 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,36 @@ data/
docs/build/*
docs/source/api/

### Python execution ###
scripts/__pycache__/
tests/output/
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# test results
rr/tests/output/

28 changes: 14 additions & 14 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,19 @@ python:
- "3.8"
install:
# Install phase of our CI pipeline
- wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
- bash miniconda.sh -b -p $HOME/miniconda
- source "$HOME/miniconda/etc/profile.d/conda.sh"
- hash -r
- conda config --set always_yes yes --set changeps1 no
- conda update -q conda
- conda info -a
- conda create -q -n project python=$TRAVIS_PYTHON_VERSION -c plotly --file requirements.txt --file build-requirements.txt
- conda activate project
- pip install .
- pip install -r build-requirements.txt

script:
# Run phase of our CI pipeline
# Run unitTests
- nosetests --nocapture -v tests/test.py --with-coverage --cover-package=scripts
- nosetests --nocapture -v rr --with-coverage --cover-package=rr
# Generate rst files from docstring
- sphinx-apidoc -fMeT -o docs/source/api scripts
- sphinx-apidoc -fMeT -o docs/source/api rr rr/tests
# Build documentation
- sphinx-build docs/source docs/build
- touch docs/build/.nojekyll
# Black lint checking
- black --check scripts/ tests/
- black --check rr/
after_success:
# update coveralls report
- coveralls
Expand All @@ -39,4 +31,12 @@ deploy:
local_dir: ./docs/build
on:
branch: master
condition: $TRAVIS_PYTHON_VERSION = 3.8
condition: "$TRAVIS_PYTHON_VERSION = 3.8"
# - provider: pypi
# server: https://test.pypi.org/legacy/ # Remove to deployment on pypi.org
# username: "__token__"
# password:
# secure: AgENdGVzdC5weXBpLm9yZwIkNDkzMjE2ZDMtYjlhYy00NTViLTg1MzYtZGU4N2YyNjA0NDY1AAIleyJwZXJtaXNzaW9ucyI6ICJ1c2VyIiwgInZlcnNpb24iOiAxfQAABiCE1UhRrnGVriZfsUQEp0YRaWTuAOLsDggCBBsOB-PbMQ
# on:
# tags: true
# condition: "$TRAVIS_PYTHON_VERSION = 3.8"
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include LICENSE README.rst buildout.cfg requirements.txt
recursive-include doc conf.py *.rst *.ico *.png
graft tests/inputs
1 change: 1 addition & 0 deletions build-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ nose
coverage
coveralls
black
twine
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import os
import sys
import subprocess
sys.path.insert(0, os.path.abspath('../../scripts'))
sys.path.insert(0, os.path.abspath('../../experiment'))


# -- Project information -----------------------------------------------------
Expand Down
7 changes: 7 additions & 0 deletions experiment.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[nb_trees_experiment]
nb_trees = 1, 2
tree_depth = 10

[tree_depth_experiment]
nb_trees = 10
tree_depth = 1, 2
File renamed without changes.
File renamed without changes.
22 changes: 22 additions & 0 deletions rr/download_data/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import sys
import argparse
import os.path
from rr.download_data import download_data


def main():

parser = argparse.ArgumentParser(
description="M05 mini-project: Download dataset.zip online"
)
parser.add_argument("source", type=str, help="Data zip url")
parser.add_argument("destination", type=str, help="Destination folder")
args = parser.parse_args()

download_destination = os.path.join(args.destination + "/dataset.zip")
download_data.download_url(args.source, download_destination)
download_data.unzip_file(download_destination, args.destination)


if __name__ == "__main__":
sys.exit(main())
20 changes: 5 additions & 15 deletions scripts/download_data.py → rr/download_data/download_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import zipfile


# Function to download a file through http.get using requests
# Function to download_data a file through http.get using requests
def download_url(url, save_path):
"""Download a file from the given url using http
Expand All @@ -16,7 +16,7 @@ def download_url(url, save_path):
None
"""
with open(save_path, "wb") as f:
print("Downloading {} from {}".format(save_path, url))
print("Downloading {} from {}...".format(save_path, url))
response = requests.get(url, stream=True)
total_length = response.headers.get("content-length")

Expand All @@ -31,7 +31,7 @@ def download_url(url, save_path):
done = int(50 * dl / total_length)
sys.stdout.write("\r[%s%s]" % ("=" * done, " " * (50 - done)))
sys.stdout.flush()
print()
print("Download succes.\n")


# Function to unzip files
Expand All @@ -46,17 +46,7 @@ def unzip_file(path_to_zip_file, directory_to_extract_to):
Raises:
None
"""
print("Unzip files..")
print("Unzip {} to {}...".format(path_to_zip_file, directory_to_extract_to))
with zipfile.ZipFile(path_to_zip_file, "r") as zip_ref:
zip_ref.extractall(directory_to_extract_to)


if __name__ == "__main__":
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/00506/casas-dataset.zip"
url_test = "https://archive.ics.uci.edu/ml/machine-learning-databases/00405/Postures.zip" # Smaller zip to test
save_path = "../data/casas-dataset.zip"
# Download zip file
download_url(url, save_path)
# Unzip it
unzip_file(save_path, "../data_test/")
print("Done")
print("Unzip succes.\n")
Empty file added rr/experiment/__init__.py
Empty file.
51 changes: 51 additions & 0 deletions rr/experiment/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import sys
import argparse
import configparser
from rr.experiment import experiments, database
import os.path


def main():
parser = argparse.ArgumentParser(description="M05 mini-project: experiments")
parser.add_argument("datapath", type=str, help="Dataset file in .csv")
parser.add_argument("output", type=str, help="Destination folder for the results")
parser.add_argument(
"config", type=str, help="Filepath for experiments configuration file in .ini"
)
args = parser.parse_args()

config = configparser.ConfigParser()
config.read(args.config)

print(
"M05 mini-project on Human Activity Recognition with Random Forest classifier"
)
tabnum = 1
experiment_results = experiments.experiment_impact_nb_trees(
tabnum,
filepath=args.datapath,
nb_trees=[int(n) for n in config["nb_trees_experiment"]["nb_trees"].split(",")],
max_depth=int(config["nb_trees_experiment"]["tree_depth"]),
plot_path=args.output,
)

tabnum += len(config["nb_trees_experiment"]["nb_trees"].split(",")) * len(
database.PROTOCOLS
)
experiment_results += experiments.experiment_impact_tree_depth(
tabnum,
filepath=args.datapath,
nb_trees=int(config["tree_depth_experiment"]["nb_trees"]),
max_depths=[
int(d) for d in config["tree_depth_experiment"]["tree_depth"].split(",")
],
plot_path=args.output,
)

with open(os.path.join(args.output, "experiment_results.txt"), "w+") as fout:
fout.write(experiment_results)
print("Experiments done\n")


if __name__ == "__main__":
sys.exit(main())
51 changes: 51 additions & 0 deletions rr/experiment/algorithm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from sklearn.ensemble import RandomForestClassifier

import logging

logger = logging.getLogger()


class Model:
def __init__(self, nb_tree_per_forest=50, max_depth=10):
"""Create a new ML model (Random forest classifier from scikitlearn)
Args:
nb_tree_per_forest (int): number of decision trees in the forest
max_depth (int): max depth of the trees
Returns:
None
Raises:
None
"""
self.model = RandomForestClassifier(
n_estimators=nb_tree_per_forest, max_depth=max_depth, random_state=0
)

def train(self, X, y):
"""Train the model using the given data
Args:
X (numpy.ndarray):A NxM 2D-array where each row corresponds to a sample and each column to a feature
y (numpy.ndarray): A 1D-array of length N, where each element corresponds to a sample label
Returns:
None
Raises:
None
"""
self.model.fit(X, y)

def predict(self, X):
"""Make a prediction on the data using the trained model
Args:
X (numpy.ndarray):A NxM 2D-array where each row corresponds to a sample and each column to a feature
Returns:
numpy.ndarray: A 1D array (with a dtype of int) containing the predicted
label for each sample
Raises:
None
"""
prediction = self.model.predict(X)

return prediction
8 changes: 2 additions & 6 deletions scripts/analysis.py → rr/experiment/analysis.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import plotly.express as px
from sklearn.metrics import confusion_matrix
import numpy as np
import itertools


def get_confusion_matrix(prediction_label, true_label):
"""Get the confusion matrix given the predicted and true labels
Args:
prediction_label (list): Estimated targets as returned by a classifier.
true_label (list): Ground truth (correct) target values.
true_label (list): Ground truth (correct) target values.
Returns:
numpy.ndarray: A 2D array (with a dtype of int) containing the confusion matrix.
Raises:
Expand All @@ -26,15 +25,14 @@ def plot_confusion_matrix(
Args:
cm (numpy.ndarray): A 2D array (with a dtype of int) containing the confusion matrix.
classes (numpy.ndarray): A 1D array (with a dtype of str) containing the lable name for each class
normalize (boolean): Flag to normalize the data
normalize (boolean): Flag to normalize the data
title (str): The title of the plot
file_name (str): File name to export the graph
Returns:
None
Raises:
None
"""
# Normalize if wanted
if normalize:
cm = cm / np.sum(cm)

Expand All @@ -47,6 +45,4 @@ def plot_confusion_matrix(
color_continuous_scale="Blues",
title=title,
)
# fig.show()
# Export graph
fig.write_html("{}.html".format(file_name))
1 change: 0 additions & 1 deletion scripts/database.py → rr/experiment/database.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python
import numpy as np
import csv
from sklearn.model_selection import train_test_split
Expand Down
Loading

0 comments on commit 1b24f9f

Please sign in to comment.