From: Roberto Stomeo Date: Tue, 1 Jul 2025 14:48:29 +0000 (+0200) Subject: Initial commit edera-ml X-Git-Url: https://git-hsc.dyrecta.com/?a=commitdiff_plain;h=refs%2Fremotes%2Forigin%2Federa-ml;p=pia_hsc.git Initial commit edera-ml --- diff --git a/edera-ml/.dockerignore b/edera-ml/.dockerignore new file mode 100644 index 0000000..02c3065 --- /dev/null +++ b/edera-ml/.dockerignore @@ -0,0 +1,3 @@ +env/* +data/*.csv +data/*.png \ No newline at end of file diff --git a/edera-ml/.gitignore b/edera-ml/.gitignore new file mode 100644 index 0000000..d2c67ab --- /dev/null +++ b/edera-ml/.gitignore @@ -0,0 +1,6 @@ +*.csv +__pycache__ +*.pyc +*.pyo +env/ +.idea/ \ No newline at end of file diff --git a/edera-ml/README.md b/edera-ml/README.md new file mode 100644 index 0000000..02b211e --- /dev/null +++ b/edera-ml/README.md @@ -0,0 +1,39 @@ +# Leggimi + +Lo scopo del progetto è fornire un modello che consenta di predire il numero di ore di utilizzo di una apparecchiatura +elettrica in un singolo giorno e di poter effettuare previsioni per i giorni successivi. + +## Come funziona + +Il modello è stato sviluppato utilizzando la libreria [TensorFlow](https://www.tensorflow.org/) e la rete neurale LSTM. +I dataset per l'addestramento sono stati generati manualmente. + +Puoi sempre generare nuovi dataset utilizzando `Simulator` come nell'esempio riportato di seguito: + +```python +from simulator import Simulator +from predictor import Predictor + +machines = 10 # Numero delle tipologie di apparecchiature elettromedicali da simulare. +samples = 5000 # Numero dei campioni da generare + +simulator = Simulator() +train_features, train_labels = simulator.generate(machines, samples, 'data/train.csv') +test_features, test_labels = simulator.generate(machines, samples, 'data/test.csv') + +Predictor.train(train_features, train_labels, test_features, test_labels, "model.h5") +``` + +Successivamente puoi utilizzare il modello per effettuare previsioni: + +```python +from predictor import Predictor + +predictor = Predictor("model.h5") + +# Previsione per il giorno 1 +features = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] +prediction = predictor.predict(features) +print(prediction) +predictor.plot(prediction, "day1.png") +``` diff --git a/edera-ml/bitbucket-pipelines.yml b/edera-ml/bitbucket-pipelines.yml new file mode 100644 index 0000000..edafbc8 --- /dev/null +++ b/edera-ml/bitbucket-pipelines.yml @@ -0,0 +1,54 @@ +image: google/cloud-sdk:412.0.0-slim +definitions: + steps: + - step: &publish + name: "Build" + caches: + - maven + - pip + services: + - docker + script: + - source scripts/set-env.sh + - cat scripts/service-account.json.base64 | base64 --decode >> service-account.json + - gcloud auth activate-service-account --key-file service-account.json + - export VERSION=1.0.${BITBUCKET_BUILD_NUMBER} + - export IMAGE_BASE="eu.gcr.io/${PROJECT_ID}/${NAMESPACE}-${MODULE}" + - export IMAGE="${IMAGE_BASE}:${VERSION}" + - gcloud config set project ${PROJECT_ID} + - gcloud config set compute/zone europe-west1-b + - gcloud auth configure-docker + - >- + docker build -t ${IMAGE} --build-arg PROFILE=${PROFILE} -f ./scripts/docker/Dockerfile . + - docker push ${IMAGE} + - docker tag $IMAGE "${IMAGE_BASE}:latest" + - docker push "${IMAGE_BASE}:latest" + - git tag -a "${VERSION}" -m "version ${VERSION}" + - git push origin "${VERSION}" + - mkdir -p ./build + - echo $VERSION > ./build/VERSION + - echo $IMAGE > ./build/IMAGE + artifacts: + - build/** + - step: &deploy + name: Deploy + script: + - source scripts/set-env.sh + - export VERSION=$(cat ./build/VERSION) + - export IMAGE=$(cat ./build/IMAGE) + - cat scripts/service-account.json.base64 | base64 --decode >> service-account.json + - gcloud auth activate-service-account --key-file service-account.json + - gcloud config set project ${PROJECT_ID} + - gcloud config set compute/zone europe-west1-b + - apt install kubectl + - apt install google-cloud-sdk-gke-gcloud-auth-plugin + - export USE_GKE_GCLOUD_AUTH_PLUGIN=True + - gcloud container clusters get-credentials applica + - kubectl set image deployment/${MODULE} ${MODULE}=${IMAGE} -n ${NAMESPACE} + artifacts: + - build/** +pipelines: + branches: + main: + - step: *publish + - step: *deploy \ No newline at end of file diff --git a/edera-ml/data/model.h5 b/edera-ml/data/model.h5 new file mode 100644 index 0000000..c74ca73 Binary files /dev/null and b/edera-ml/data/model.h5 differ diff --git a/edera-ml/data/plot.png b/edera-ml/data/plot.png new file mode 100644 index 0000000..9a7fd63 Binary files /dev/null and b/edera-ml/data/plot.png differ diff --git a/edera-ml/main.py b/edera-ml/main.py new file mode 100644 index 0000000..e01128c --- /dev/null +++ b/edera-ml/main.py @@ -0,0 +1,49 @@ +import json + +from flask import Flask, jsonify, request +from predictor import Predictor, PredictionItemEncoder + +app = Flask(__name__) +predictor = Predictor('data/model.h5') + + +@app.route('/predict', methods=['POST']) +def post_data(): + json_request = request.get_json() + machine = json_request.get('machine') + day = json_request.get('day') + + max_hours = json_request.get('max_hours', 24) + max_days = json_request.get('max_days', 7) + + threshold = json_request.get('threshold', 0.5) + + breakpoint_hours = json_request.get('breakpoint_hours', 40) + accumulated_hours = json_request.get('accumulated_hours', 0) + + if machine is None or day is None: + return jsonify({'message': 'Machine and day are required'}), 400 + + if not isinstance(max_hours, int) or not isinstance(max_days, int): + return jsonify({'message': 'max_hours and max_days must be integers'}), 400 + + if max_hours <= 0 or max_days <= 0: + return jsonify({'message': 'max_hours and max_days must be positive'}), 400 + + predictions = predictor.predict_until_break(machine, + day, + max_hours, + max_days, + accumulated_hours, + breakpoint_hours, + threshold) + return jsonify(json.loads(json.dumps(predictions, cls=PredictionItemEncoder))), 200 + + +@app.route('/') +def hello_world(): + return jsonify({'message': 'Hello, World!'}) + + +if __name__ == '__main__': + app.run(debug=True, host='0.0.0.0') diff --git a/edera-ml/predictor.py b/edera-ml/predictor.py new file mode 100644 index 0000000..ed4d098 --- /dev/null +++ b/edera-ml/predictor.py @@ -0,0 +1,217 @@ +import json +import os +# Disable Tensorflow warnings +os.environ['TF_CPP_MIN_LOG_LEVEL'] = '4' + +import string +import tensorflow as tf +from typing import Hashable +import matplotlib.pyplot as plt + + +class PredictionItem: + """ + A prediction item. + """ + day = 0 + hours = 0 + accumulated_hours = 0 + broken = False + + def __init__(self, day: int, hours: int, accumulated_hours: int, broken: bool): + """ + Initialize the prediction item. + + :type day: int + :param day: The day of the year. + :type hours: int + :param hours: The number of hours. + :type accumulated_hours: int + :param accumulated_hours: The accumulated hours. + :type broken: bool + :param broken: Whether the machine has a break. + :rtype: None + """ + self.day = day + self.hours = hours + self.accumulated_hours = accumulated_hours + self.broken = broken + + def __str__(self): + """ + Convert the prediction item to a string. + + :rtype: string + :return: The string representation of the prediction item. + """ + return 'Day: %d, Hours: %d, Accumulated Hours: %d, Has Break: %s' % ( + self.day, + self.hours, + self.accumulated_hours, + self.broken + ) + + +class PredictionItemEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, PredictionItem): + return { + "day": obj.day, + "hours": obj.hours, + "accumulated_hours": obj.accumulated_hours, + "broken": obj.broken + } + return json.JSONEncoder.default(self, obj) + + +class Predictor: + """ + A predictor for machine usage hours and break prediction. + """ + model = None + + def __init__(self, model_path: string): + """ + Initialize the predictor. + + :type model_path: string + :param model_path: The path to the model file. + :rtype: None + + :exception: Exception if the model file does not exist. + """ + if not os.path.exists(model_path): + raise Exception('Model not found: %s' % model_path) + + self.model = tf.keras.models.load_model(model_path) + + @staticmethod + def train(train_features: Hashable, + train_labels: Hashable, + test_features: Hashable, + test_labels: Hashable, + path: string) -> list: + """ + Train the model. + + :param train_features: The training features. + :type train_features: Hashable + :param train_labels: The training labels. + :type train_labels: Hashable + :param test_features: The test features. + :type test_features: Hashable + :param test_labels: The test labels. + :param path: The path to save the model. + :return: The test loss and accuracy. + """ + samples = len(train_features) + model = tf.keras.Sequential([ + tf.keras.layers.Embedding(samples, 3, input_length=3), + tf.keras.layers.LSTM(2), + tf.keras.layers.Dense(1, activation='sigmoid') + ]) + + model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) + model.fit(train_features, train_labels, epochs=50, batch_size=20) + model.save(path) + + test_loss, test_acc = model.evaluate(test_features, test_labels, verbose=2) + return [test_loss, test_acc] + + def predict_hours(self, machine: int, day: int, max_hours: int, threshold: float) -> int: + """ + Predict how many hours the machine will be used on a given day. + :param machine: The machine type. + :param day: The day of the year. + :param max_hours: The maximum number of hours to predict. + :param threshold: The threshold to stop predicting. + :return: The number of hours the machine will be used. + """ + hours = 1 + while hours < max_hours: + prediction = self.model.predict([[machine, day, hours]]) + if prediction.item() > threshold: + break + hours += 1 + + return hours + + def predict(self, + machine: int, + day: int, + max_days: int, + max_hours: int, + accumulated_hours: int, + breakpoint_hours: int, + threshold: float) -> list[PredictionItem]: + """ + Predict how many hours the machine will be used on a given day. + :param machine: The machine type. + :param day: The day of the year. + :param max_days: The maximum number of days to predict. + :param max_hours: The maximum number of hours to predict. + :param accumulated_hours: The accumulated hours. + :param breakpoint_hours: The breakpoint hours. + :param threshold: The threshold to use to validate the prediction. + :return: The number of hours the machine will be used. + """ + predictions = [] + while day < max_days: + hours = self.predict_hours(machine, day, max_hours, threshold) + day += 1 + accumulated_hours += hours + broken = accumulated_hours >= breakpoint_hours + prediction_item = PredictionItem(day, hours, accumulated_hours, broken) + predictions.append(prediction_item) + + return predictions + + def predict_until_break(self, + machine: int, + day: int, + max_hours: int, + max_days: int, + accumulated_hours: int, + breakpoint_hours: int, + threshold: float) -> list[PredictionItem]: + """ + Predict machine usage hours until a break is predicted. + :param machine: The machine type. + :param day: The day of the year. + :param max_hours: The maximum number of hours to predict. + :param max_days: The maximum number of days to predict. + :param accumulated_hours: The accumulated hours. + :param breakpoint_hours: The breakpoint hours. + :param threshold: The threshold to use to validate the prediction. + :return: The number of hours the machine will be used. + """ + predictions = [] + max_days_to_predict = day + max_days + while day < max_days_to_predict: + hours = self.predict_hours(machine, day, max_hours, threshold) + day += 1 + accumulated_hours += hours + broken = accumulated_hours >= breakpoint_hours + prediction_item = PredictionItem(day, hours, accumulated_hours, broken) + predictions.append(prediction_item) + + if broken: + break + + return predictions + + @staticmethod + def plot(predictions: list[PredictionItem], threshold: float, machine: int, path: string) -> None: + plt.clf() + # For each prediction show accumulated hours per day + plt.plot([prediction.day for prediction in predictions], [prediction.accumulated_hours for prediction in predictions]) + # Show red circle when broken is True + plt.plot([prediction.day for prediction in predictions if prediction.broken], + [prediction.accumulated_hours for prediction in predictions if prediction.broken], 'ro') + # Plot hours per day + plt.plot([prediction.day for prediction in predictions], [prediction.hours for prediction in predictions]) + plt.xlabel('Day') + plt.ylabel('Hours') + plt.legend(['Total Hours', 'Breakpoint', 'Daily Hours']) + plt.title('Machine %d' % machine) + plt.savefig(path) diff --git a/edera-ml/requirements.txt b/edera-ml/requirements.txt new file mode 100644 index 0000000..c659d70 --- /dev/null +++ b/edera-ml/requirements.txt @@ -0,0 +1,6 @@ +pandas~=2.1.4 +scikit-learn +matplotlib~=3.8.2 +flask~=3.0.1 +numpy~=1.26.3 +tensorflow \ No newline at end of file diff --git a/edera-ml/scripts/docker/Dockerfile b/edera-ml/scripts/docker/Dockerfile new file mode 100644 index 0000000..66170c6 --- /dev/null +++ b/edera-ml/scripts/docker/Dockerfile @@ -0,0 +1,12 @@ +FROM tensorflow/tensorflow + +WORKDIR /app +COPY . /app + +# Install pip and then install the requirements +RUN pip install --upgrade pip +RUN pip install -r requirements.txt --ignore-installed +# Configure firewall to allow traffic on port 5000 + +EXPOSE 5000 +CMD ["python", "main.py"] \ No newline at end of file diff --git a/edera-ml/scripts/kube/api.yml b/edera-ml/scripts/kube/api.yml new file mode 100644 index 0000000..e67dae4 --- /dev/null +++ b/edera-ml/scripts/kube/api.yml @@ -0,0 +1,38 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ml + labels: + app: ml +spec: + replicas: 1 + selector: + matchLabels: + app: ml + template: + metadata: + labels: + app: ml + spec: + containers: + - image: eu.gcr.io/applica-general/edera-ml:latest + name: ml + ports: + - containerPort: 5000 + name: ml + imagePullPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: ml + name: ml +spec: + type: NodePort + ports: + - port: 5000 + targetPort: 5000 + protocol: TCP + selector: + app: ml diff --git a/edera-ml/scripts/service-account.json.base64 b/edera-ml/scripts/service-account.json.base64 new file mode 100644 index 0000000..6841642 --- /dev/null +++ b/edera-ml/scripts/service-account.json.base64 @@ -0,0 +1,42 @@ +ewogICJ0eXBlIjogInNlcnZpY2VfYWNjb3VudCIsCiAgInByb2plY3RfaWQiOiAiYXBwbGljYS1n +ZW5lcmFsIiwKICAicHJpdmF0ZV9rZXlfaWQiOiAiNDk3YzZmNTU5N2Y0NTI3NWY3ZTlmZTQwMzFj +NGI4MjllMjY4NzEyMSIsCiAgInByaXZhdGVfa2V5IjogIi0tLS0tQkVHSU4gUFJJVkFURSBLRVkt +LS0tLVxuTUlJRXZnSUJBREFOQmdrcWhraUc5dzBCQVFFRkFBU0NCS2d3Z2dTa0FnRUFBb0lCQVFD +dDRrY1B3UVJ6bUQ3b1xucHlVQVBlTnBnS01TWGxTM25CYmVtSUFlcmk3dm5GeHJIMFV4RlJndmRN +VTlzRTJ6L0h5WXNTMGNnR1R3Y01Fd1xuQlVVYVF3UWpUMFVxdlBrN3ByY2lOWURSTXVNQXY1MW5Y +WkpRZ0RYeitMSG15VldhaE1VRTlMczM4YzJxeUFpalxuVTBjakhqTmxsMmp3S2J5OWJVNUVUcWlT +eEtxdE1FRVlwSUFzV2kvWG1iekx6NlVtSnladm56ZCtkRFNRQTU3aFxuY0NsOEFTdlBpQTdIeXVz +b1lzVWJ2S2xRS0tmcndtV3NBUllEVjdRc0t6bEpsR0ViWE1sWlozdzB1VCszVkxXOVxuTWMyS1Fo +SGpvaWpoTW9yRjdVdjVWMjJrTWkyL2V4RkI3L3ErbllCejU5K1MxUXZlRmpCd3E5L0gwQTRyTXpU +a1xubWZDYzhjMWZBZ01CQUFFQ2dnRUFOR1dsdlRrUUl0Y2pTYzhvSnJEL2lLaXpPeE5DMnd0Rmx2 +RUVWbnB0ZVZXNFxuUWExc0Y3VEFFM2pRQU4xU0pPVDJGTHI3R1lZVkpLRU5qZTlnbWQvTTdPanpz +a084cEwyQm5PVGJldTZuR2ZBalxudWVTbjlPc1ZsdjEvZWtoOEs3Skxma2xTNnpKSm8rZGdOdnNl +eWhYTkxoVllrVm82WGlpRWQ2L3VPei9aSUpPVVxuTFlHN1hPVHExNWhKcmZaM2trdDBBRldJc2NK +SXVFbFBlUTJOaDVWY3VSeVJwUVQwaFA0NUlRUTZFdElBWXp4OVxuUnRGUWFhd2tpWVFqZ0RkelFO +Qm1tUHN2ZWc4Y2JkQXlWZVlxcitaVkFiNk1pWjJ2N01RR0hyeEFBcnhSeXRMZlxuMmd2VUl0K3pv +dmJBemo3Q3h0YjUvS3JDdHUwMC9aWTcwNzRxTExnR1NRS0JnUUR2NXRkNmxWbUg5cXl3TThTc1xu +NnA5NE5lTVFrbU9vME41SjBUUisxTGFITnBkdjBaY3B0bEJDS0lCTXorVTBBc0p0cG11dlpGTGdH +cmp6U3E2cFxuVFlGUis0Mlc1NjJGMkoxWmlKZmdnWDdubWp3TmhUNzdrdWUwbjVWbE1iTHBUN0Iz +ajB6V3Ftc0hqZ09lZWhDblxueEIwOXpKcXJEYm96MkV3UGVvRkhDVjB5dHdLQmdRQzVqVmpJd21F +d01PU2g5UHF3QzJ5SVBYeS81UkpGTG4yL1xuNWxzUmhRbkkrTkxTZUJjWnRIV1BiOWcyNVF6SFVV +dWRRNGhiYWpHaDM1R2t5SGtIcjJ5MGVjdTFUd2pVTitGMFxubzdhejRzekk4a3kzRk9sRUpvdXM4 +enFNQWsrYnhFR1hrUUNkWmFiL0ltS0svR1dRK21RcXlDV0RtUkFvR3NVcVxuTEJNdUhKOXltUUtC +Z0YrRnJBRGNYT1RkWEk5Z1hZeDRjM3piQUFtR01IWjBqRDRhTmV2V2FNTllBbDU4dHRMZVxuREFE +N3ZYSllTU3czZVJGTjlZekZ4cFlETGVkNXNpZ3BlemVZa1Iwb0xKaWgwcTFtelFxUXBXWTBySHE1 +dG9WWFxuVGpsR1hhY0liZk9tVGw2Y3lYeWtLSysrWlVTQjJBWGsrYnUwcjFVeXh4U0RxRzExV3Vw +ZEdTWHJBb0dCQUo2YVxucm9CMGZvU2wxbGlGd2Q3RzlRK0RsMldqMWJraTQwUXNFRDNxZlJHM2R1 +V0cxeUFXdThKT3RQOC9UR3YzRm00blxuc3ArSkowR1ppN0hSMW5wMlBiSUt4ZENGN1NNUlhQckpr +YnN6cXg0ODFzeEw2SlJqYWxMOFdWZ2lCWkE4OG1BdlxuQnRxRGNIcDNGc3A4c2doNXJ6Tk9mNXA4 +Tkc1RGE3TC9sNmw3dCtOSkFvR0JBT2d6MHM1WGErRzZLTmlVN0IySFxuc0l2MmRNMzZvNlZ3a21P +T3FjdCtkVS8ycG12ZGM4aFpDbFZGYXBQeWZ4djFqVnNjSDUrZG5FaFJIaTEzYXdIU1xuVzc3MnQ5 +WUdBNWpGb2dnakVPRU5QbVR2QUwxd01NL0ExRCtmanVaWVArOEVDaEU0QmFmbVN3WWZGVzJRQmxE +eFxuZlhoOHNmT0FnMjhuMEc1QWNGcXZVSFJNXG4tLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tXG4i +LAogICJjbGllbnRfZW1haWwiOiAiYml0YnVja2V0LXBpcGVsaW5lc0BhcHBsaWNhLWdlbmVyYWwu +aWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLAogICJjbGllbnRfaWQiOiAiMTA4Mzk0ODE1Njc3NDgx +NDI2MjYwIiwKICAiYXV0aF91cmkiOiAiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1 +dGgyL2F1dGgiLAogICJ0b2tlbl91cmkiOiAiaHR0cHM6Ly9vYXV0aDIuZ29vZ2xlYXBpcy5jb20v +dG9rZW4iLAogICJhdXRoX3Byb3ZpZGVyX3g1MDlfY2VydF91cmwiOiAiaHR0cHM6Ly93d3cuZ29v +Z2xlYXBpcy5jb20vb2F1dGgyL3YxL2NlcnRzIiwKICAiY2xpZW50X3g1MDlfY2VydF91cmwiOiAi +aHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vcm9ib3QvdjEvbWV0YWRhdGEveDUwOS9iaXRidWNr +ZXQtcGlwZWxpbmVzJTQwYXBwbGljYS1nZW5lcmFsLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwK +ICAidW5pdmVyc2VfZG9tYWluIjogImdvb2dsZWFwaXMuY29tIgp9Cg== \ No newline at end of file diff --git a/edera-ml/scripts/set-env.sh b/edera-ml/scripts/set-env.sh new file mode 100644 index 0000000..5443338 --- /dev/null +++ b/edera-ml/scripts/set-env.sh @@ -0,0 +1,4 @@ +export PROJECT_ID=applica-general +export PROJECT_NAME=applica-general +export NAMESPACE=edera +export MODULE=ml \ No newline at end of file diff --git a/edera-ml/simulator.py b/edera-ml/simulator.py new file mode 100644 index 0000000..d79a461 --- /dev/null +++ b/edera-ml/simulator.py @@ -0,0 +1,31 @@ +import pandas as pd +import numpy as np +import string + + +class Simulator: + @staticmethod + def __generate_data(path: string, machines: int, size: int) -> None: + df = pd.DataFrame(columns=['machine', 'date', 'hours', 'failure']) + df['machine'] = np.random.randint(1, machines, size=size) + df['date'] = np.random.randint(1, 365, size=size) + df['hours'] = np.random.randint(1, 8, size=size) + df['failure'] = np.random.randint(0, 2, size=size) + df.to_csv(path, index=False) + + @staticmethod + def __load_data(path: string) -> pd.DataFrame: + df = pd.read_csv(path) + return df.sample(frac=1).reset_index(drop=True) + + @staticmethod + def __prepare(df: pd.DataFrame) -> pd.DataFrame: + features = df[['machine', 'date', 'hours']] + labels = df[['failure']] + + return features, labels + + def generate(self, machines: int, size: int, path: string) -> pd.DataFrame: + self.__generate_data(path, machines, size) + data = self.__load_data(path) + return self.__prepare(data) diff --git a/edera-ml/test.py b/edera-ml/test.py new file mode 100644 index 0000000..f090dca --- /dev/null +++ b/edera-ml/test.py @@ -0,0 +1,21 @@ +from simulator import Simulator +from predictor import Predictor + +# Configuration + +# machines = 10 # Number of machine types to simulate +# samples = 5000 # Number of samples to generate + +# simulator = Simulator() +# train_features, train_labels = simulator.generate(machines, samples, 'data/train.csv') +# test_features, test_labels = simulator.generate(machines, samples, 'data/test.csv') + +predictor = Predictor('data/model.h5') + +# predictions = predictor.predict(1, 1, 30, 8, 9, 120, 0.51) +predictions = predictor.predict_until_break(1, 1, 8, 0, 120, 0.51) +for prediction in predictions: + print(prediction) + + +predictor.plot(predictions, 0.7, 0, 'data/plot.png')