From 93118297fa1b0bee1d1c47696e0198b9b343c803 Mon Sep 17 00:00:00 2001 From: lpetrov02 <71082527+lpetrov02@users.noreply.github.com> Date: Wed, 20 Dec 2023 21:55:01 +0300 Subject: [PATCH 1/4] ID-181_train_with_dataloader (#78) * Started migration from Data2dLayer to DataLayer Makes preparations for metrics logging on python Functionality for c++ http added, but not working yet Adds saving train metrics Adds saving train metrics and responding with PNG Adaptates code for new 4D blob cpprest CI support Add load possibility for zip Add load possibility for png on predict ------- GRA-122: Data loader implementation (#67) Data loader implementation ------- ID-154: Loss type selection (#70) * Add loss type selection * Add loss type selection * Remove layer-class loss * Clean up Loss type * Make format ------- ID-171: Fix input selection (#69) * Fix input selection * Clean up fix input selection ------- Change train and predict for zip file case Starts fixing train Fixes train with dataloader It's not fucking working :( (x3) server train fix Fixes train and predcit * Follow up review * Follow up review * ID-167: Upload zip (#74) * Fixes graph tests * Fixes DataLayer --------- Co-authored-by: lpetrov02 Co-authored-by: Artem Goldenberg <58527023+Artem-Goldenberg@users.noreply.github.com> --- .github/workflows/CI.yml | 4 + .gitignore | 8 +- README.md | 3 + client/scripts/requests.js | 102 +++++--- client/templates/main.html | 46 ++-- documentation/png-examples/Ours.png | Bin 0 -> 68180 bytes documentation/png-examples/Vectors.png | Bin 0 -> 14345 bytes py_server/Makefile | 2 +- py_server/mlcraft/__init__.py | 1 + py_server/mlcraft/check_dimensions.py | 6 +- py_server/mlcraft/dataset.py | 46 ---- py_server/mlcraft/db.py | 83 ++++++- py_server/mlcraft/errors.py | 2 +- py_server/mlcraft/server.py | 129 +++++++++-- py_server/mlcraft/static/swagger.yaml | 283 ++++++++++++++++++++--- py_server/mlcraft/utils.py | 17 ++ py_server/pyproject.toml | 1 + py_server/tests/test_check_dimensions.py | 16 +- server/Makefile | 8 +- server/api/DataLoader.cpp | 26 +-- server/api/DataLoader.h | 1 + server/api/GraphBuilder.cpp | 97 ++++---- server/api/GraphBuilder.h | 27 ++- server/api/Parser.cpp | 38 +-- server/api/Parser.h | 4 +- server/api/server.cpp | 221 ++++++++++++++---- server/core/Allocator.cpp | 2 +- server/core/Layer.cpp | 11 +- server/core/Layer.h | 7 +- server/core/LazyBlob.cpp | 6 +- server/core/Optimizer.cpp | 11 +- server/core/Optimizer.h | 12 +- server/core/Parameters.h | 5 - server/tests/GraphTests.cpp | 8 +- server/tests/linear_relu_linear_mse.json | 4 +- 35 files changed, 879 insertions(+), 358 deletions(-) create mode 100644 documentation/png-examples/Ours.png create mode 100644 documentation/png-examples/Vectors.png delete mode 100644 py_server/mlcraft/dataset.py diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 9798a4d5..9554a42c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -51,6 +51,10 @@ jobs: sudo apt install -y g++-11 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 90 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 90 + sudo apt install libzip-dev + + - name: install-cpprest + run: sudo apt install libcpprest-dev - name: install-boost uses: MarkusJx/install-boost@v2.4.4 diff --git a/.gitignore b/.gitignore index 901ef702..f966ca0c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ Build/ build/ +# Large-files +zip-examples +model_data + # IDE .vscode .idea @@ -10,6 +14,7 @@ build/ .DS_Store .AppleDouble .LSOverride +*.entitlements # Javascript package-lock.json @@ -21,6 +26,7 @@ __pycache__/ *$py.class .cache .venv +images/ # Flask stuff: instance/ @@ -49,4 +55,4 @@ dmypy.json # Makefile install bin -*.patch \ No newline at end of file +*.patch diff --git a/README.md b/README.md index 019427b8..97c2050c 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,9 @@ Other targets available: > **Important:** If you want to build a c++ server, you need to install [Boost](https://www.boost.org/users/download/). > Then, **in the `config.json` file** add the path to the boost root (folder with `include` and `lib` inside). > For example: `"BOOST_ROOT": "/usr/local/Cellar/boost/1.81.0_1"` + +> Also you need `cpprest`: on MacOS: `brew install cpprestsdk` +> on Linux: `sudo apt-get install libcpprest-dev` > After that you should be able to build everything just fine... There are 3(4) main targets available to build: diff --git a/client/scripts/requests.js b/client/scripts/requests.js index 35124124..c8049021 100644 --- a/client/scripts/requests.js +++ b/client/scripts/requests.js @@ -124,29 +124,60 @@ async function deleteConnection(sending_object) { return response } -function trainRequest() { - if (!train_data) { - errorNotification("No training data was set.") - } else { - fetch(`http://${py_server_address}/train/${user_id}/${model_id}/0`, { - method: "PUT", - mode: "cors", - headers: {"Content-Type": "text/csv"}, - body: train_data, - }).then(response => { - showBuildNotification(response.ok) - onTrainShowPredict(response.ok) - if (response.ok) { - setModelView("success") - } else { - setModelView("error") - } +function uploadRequest() { + if (data_upload.files.length == 0) return + const file = data_upload.files[0] + + fetch(`http://${py_server_address}/${user_id}/${model_id}`, { + method: "PATCH", + mode: "cors", + body: file, + }).then(response => { + if (!response.ok) { + Swal.fire({ + position: "top-end", + icon: "error", + title: "Failed to upload data", + showConfirmButton: false, + timer: 1500, + }) + console.error(`Failed to upload data for ${file.name}`) + return + } + Swal.fire({ + position: "top-end", + icon: "success", + title: "Successfully uploaded", + showConfirmButton: false, + timer: 1500, }) - } + }) + setModelView("irrelevant") + // allow user to press a train button from now on + button_wrapper = document.getElementById("train-button") + button_wrapper.getElementsByTy + train_button = button_wrapper.children[0] + button_wrapper.removeAttribute("disabled") + train_button.removeAttribute("disabled") +} + +function trainRequest() { + fetch(`http://${py_server_address}/train/${user_id}/${model_id}/0`, { + method: "PUT", + mode: "cors", + }).then(response => { + showBuildNotification(response.ok) + onTrainShowPredict(response.ok) + if (response.ok) { + setModelView("success") + } else { + setModelView("error") + } + }) } async function predictRequest() { - if (csv_predict.files.length == 0) { + if (predict_button.files.length == 0) { errorNotification("Empty predict file.") return } @@ -159,25 +190,34 @@ async function predictRequest() { showConfirmButton: true, }) } - const file = csv_predict.files[0] - const text = await file.text() - const response = await fetch( + const file = predict_button.files[0] + let response = await fetch( `http://${py_server_address}/predict/${user_id}/${model_id}`, { method: "PUT", mode: "cors", - headers: {"Content-Type": "text/csv"}, - body: text, + body: file, }, ) + if (!response.ok) { + Swal.fire("Error!", "Failed to upload the png image", "error") + console.error( + `Failed to upload the png with ${response.statusText}: ${responseJson.error}`, + ) + return + } + response = await fetch( + `http://${py_server_address}/predict/${user_id}/${model_id}`, + {method: "GET", mode: "cors"}, + ) const responseJson = await response.json() - hideResult() // hide previous predict result - if (response.ok) onPredictShowResult(responseJson) - else { - Swal.fire("Error!", "Server is not responding now.", "error") - errorNotification("Failed to predict.\n" + responseJson.error) - console.log( - `Predict failed with ${response.statusText}: ${responseJson.error}`, + if (!response.ok) { + Swal.fire("Error!", "Failed to predict", "error") + console.error( + `Failed to predict with with ${response.statusText}: ${responseJson.error}`, ) + return } + hideResult() // hide previous predict result + onPredictShowResult(responseJson) } diff --git a/client/templates/main.html b/client/templates/main.html index c62663e7..86db4342 100644 --- a/client/templates/main.html +++ b/client/templates/main.html @@ -113,7 +113,7 @@

MLCraft