Spaces:
Sleeping
Sleeping
Jensen-holm
commited on
Commit
•
e571d8c
1
Parent(s):
714bc51
re formatting the api to contain the image bytes in json
Browse files- app.py +2 -26
- cluster/clusterer.py +4 -1
- cluster/kmeans.py +1 -1
- cluster/main.py +2 -1
- cluster/plot.py +7 -12
- example/kmeans.py +2 -28
- example/neural_network.py +1 -15
- neural_network/main.py +2 -4
- neural_network/neural_network.py +38 -9
- neural_network/plot.py +0 -32
- plt_id.py +0 -5
- templates/index.html +0 -12
app.py
CHANGED
@@ -4,38 +4,14 @@ from flask_cors import CORS
|
|
4 |
from dataset.iris import iris
|
5 |
from opts import options
|
6 |
|
7 |
-
import os
|
8 |
-
|
9 |
# using the iris data set for every algorithm
|
|
|
10 |
X, y = iris()
|
11 |
|
12 |
-
app = Flask(
|
13 |
-
__name__,
|
14 |
-
template_folder="templates",
|
15 |
-
)
|
16 |
|
17 |
CORS(app, origins="*")
|
18 |
|
19 |
-
UPLOAD_FOLDER = os.getcwd() + "/plots"
|
20 |
-
|
21 |
-
|
22 |
-
@app.route("/", methods=["GET"])
|
23 |
-
def index():
|
24 |
-
return render_template("index.html")
|
25 |
-
|
26 |
-
|
27 |
-
@app.route("/plots/<plt_key>", methods=["GET"])
|
28 |
-
def get_plot(plt_key):
|
29 |
-
filename = f"{plt_key}.png"
|
30 |
-
filepath = os.path.join(UPLOAD_FOLDER, filename)
|
31 |
-
|
32 |
-
if os.path.isfile(filepath):
|
33 |
-
with open(filepath, "rb") as file:
|
34 |
-
plot_bytes = file.read()
|
35 |
-
return plot_bytes, 200, {"Content-Type": "image/png"}
|
36 |
-
else:
|
37 |
-
return "Plot not found", 404
|
38 |
-
|
39 |
|
40 |
@app.route("/neural-network", methods=["POST"])
|
41 |
def neural_network():
|
|
|
4 |
from dataset.iris import iris
|
5 |
from opts import options
|
6 |
|
|
|
|
|
7 |
# using the iris data set for every algorithm
|
8 |
+
# just for simplicity sake
|
9 |
X, y = iris()
|
10 |
|
11 |
+
app = Flask(__name__)
|
|
|
|
|
|
|
12 |
|
13 |
CORS(app, origins="*")
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
@app.route("/neural-network", methods=["POST"])
|
17 |
def neural_network():
|
cluster/clusterer.py
CHANGED
@@ -5,7 +5,7 @@ from typing import Callable
|
|
5 |
@dataclass
|
6 |
class Clusterer:
|
7 |
cluster_func: Callable
|
8 |
-
|
9 |
|
10 |
def eval(
|
11 |
self,
|
@@ -14,6 +14,9 @@ class Clusterer:
|
|
14 |
) -> None:
|
15 |
...
|
16 |
|
|
|
|
|
|
|
17 |
@classmethod
|
18 |
def from_dict(cls, dct: dict):
|
19 |
return cls(**dct)
|
|
|
5 |
@dataclass
|
6 |
class Clusterer:
|
7 |
cluster_func: Callable
|
8 |
+
plt_data = None
|
9 |
|
10 |
def eval(
|
11 |
self,
|
|
|
14 |
) -> None:
|
15 |
...
|
16 |
|
17 |
+
def set_plot_data(self, plt_data):
|
18 |
+
self.plt_data = plt_data
|
19 |
+
|
20 |
@classmethod
|
21 |
def from_dict(cls, dct: dict):
|
22 |
return cls(**dct)
|
cluster/kmeans.py
CHANGED
@@ -74,5 +74,5 @@ class Kmeans(Clusterer):
|
|
74 |
"k": self.k,
|
75 |
"max_iter": self.max_iter,
|
76 |
"clusters": cluster_data,
|
77 |
-
"
|
78 |
}
|
|
|
74 |
"k": self.k,
|
75 |
"max_iter": self.max_iter,
|
76 |
"clusters": cluster_data,
|
77 |
+
"plt_data": self.plt_data,
|
78 |
}
|
cluster/main.py
CHANGED
@@ -17,5 +17,6 @@ def main(
|
|
17 |
alg = cluster_alg.from_dict(args)
|
18 |
|
19 |
alg.build(X)
|
20 |
-
plot(clusterer=alg, X=X)
|
|
|
21 |
return alg.to_dict(X)
|
|
|
17 |
alg = cluster_alg.from_dict(args)
|
18 |
|
19 |
alg.build(X)
|
20 |
+
plt_data = plot(clusterer=alg, X=X)
|
21 |
+
alg.set_plot_data(plt_data)
|
22 |
return alg.to_dict(X)
|
cluster/plot.py
CHANGED
@@ -1,18 +1,14 @@
|
|
1 |
import matplotlib
|
2 |
import matplotlib.pyplot as plt
|
3 |
import seaborn as sns
|
4 |
-
|
5 |
-
import os
|
6 |
|
7 |
|
8 |
matplotlib.use("Agg")
|
9 |
sns.set()
|
10 |
|
11 |
-
UPLOAD_FOLDER = os.getcwd() + "/plots"
|
12 |
-
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
13 |
|
14 |
-
|
15 |
-
def plot(clusterer, X) -> None:
|
16 |
cluster_data = clusterer.to_dict(X)["clusters"]
|
17 |
fig, ax = plt.subplots(figsize=(8, 6))
|
18 |
for cluster in cluster_data:
|
@@ -35,10 +31,9 @@ def plot(clusterer, X) -> None:
|
|
35 |
ax.set_ylabel("Normalized Petal Length (cm)")
|
36 |
ax.set_xlabel("Normalized Petal Length (cm)")
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
plt.close(fig)
|
43 |
|
44 |
-
|
|
|
1 |
import matplotlib
|
2 |
import matplotlib.pyplot as plt
|
3 |
import seaborn as sns
|
4 |
+
import io
|
|
|
5 |
|
6 |
|
7 |
matplotlib.use("Agg")
|
8 |
sns.set()
|
9 |
|
|
|
|
|
10 |
|
11 |
+
def plot(clusterer, X):
|
|
|
12 |
cluster_data = clusterer.to_dict(X)["clusters"]
|
13 |
fig, ax = plt.subplots(figsize=(8, 6))
|
14 |
for cluster in cluster_data:
|
|
|
31 |
ax.set_ylabel("Normalized Petal Length (cm)")
|
32 |
ax.set_xlabel("Normalized Petal Length (cm)")
|
33 |
|
34 |
+
# Save the plot to a BytesIO buffer
|
35 |
+
buffer = io.BytesIO()
|
36 |
+
plt.savefig(buffer, format='png')
|
37 |
+
buffer.seek(0)
|
|
|
38 |
|
39 |
+
return buffer.read()
|
example/kmeans.py
CHANGED
@@ -8,8 +8,8 @@ import seaborn as sns
|
|
8 |
ENDPOINT: str = "http://127.0.0.1:5000/"
|
9 |
|
10 |
request_params = {
|
11 |
-
"algorithm": "kmeans-clustering",
|
12 |
"arguments": {
|
|
|
13 |
"k": 3,
|
14 |
"max_iter": 100,
|
15 |
},
|
@@ -27,31 +27,5 @@ r = requests.post(
|
|
27 |
)
|
28 |
|
29 |
|
30 |
-
def plot():
|
31 |
-
cluster_data = r.json()["clusters"]
|
32 |
-
# plot the clusters and data points
|
33 |
-
fig, ax = plt.subplots(figsize=(8, 6))
|
34 |
-
|
35 |
-
sns.set()
|
36 |
-
for cluster in cluster_data:
|
37 |
-
sns.scatterplot(
|
38 |
-
x=[point[0] for point in cluster["points"]],
|
39 |
-
y=[point[1] for point in cluster["points"]],
|
40 |
-
label=f"Cluster {cluster['cluster_id']}",
|
41 |
-
ax=ax,
|
42 |
-
)
|
43 |
-
ax.scatter(
|
44 |
-
x=cluster["centroid"][0],
|
45 |
-
y=cluster["centroid"][1],
|
46 |
-
marker="x",
|
47 |
-
s=100,
|
48 |
-
linewidth=2,
|
49 |
-
color="black"
|
50 |
-
)
|
51 |
-
ax.set_title("K-means Clustering")
|
52 |
-
ax.legend()
|
53 |
-
plt.show()
|
54 |
-
|
55 |
-
|
56 |
if __name__ == "__main__":
|
57 |
-
|
|
|
8 |
ENDPOINT: str = "http://127.0.0.1:5000/"
|
9 |
|
10 |
request_params = {
|
|
|
11 |
"arguments": {
|
12 |
+
"clusterer": "kmeans-clustering",
|
13 |
"k": 3,
|
14 |
"max_iter": 100,
|
15 |
},
|
|
|
27 |
)
|
28 |
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
if __name__ == "__main__":
|
31 |
+
print(r.json())
|
example/neural_network.py
CHANGED
@@ -1,5 +1,3 @@
|
|
1 |
-
import matplotlib.pyplot as plt
|
2 |
-
import seaborn as sns
|
3 |
import requests
|
4 |
import json
|
5 |
|
@@ -25,17 +23,5 @@ r = requests.post(
|
|
25 |
data=json.dumps(request_params),
|
26 |
)
|
27 |
|
28 |
-
model = r.json()
|
29 |
-
|
30 |
-
|
31 |
-
def plot():
|
32 |
-
sns.set()
|
33 |
-
plt.plot(model["loss_history"])
|
34 |
-
plt.xlabel("Epoch")
|
35 |
-
plt.ylabel("Loss")
|
36 |
-
plt.title("Loss History")
|
37 |
-
plt.show()
|
38 |
-
|
39 |
-
|
40 |
if __name__ == "__main__":
|
41 |
-
|
|
|
|
|
|
|
1 |
import requests
|
2 |
import json
|
3 |
|
|
|
23 |
data=json.dumps(request_params),
|
24 |
)
|
25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
if __name__ == "__main__":
|
27 |
+
print(r.json()["plt_data"])
|
neural_network/main.py
CHANGED
@@ -3,7 +3,6 @@ import numpy as np
|
|
3 |
|
4 |
from neural_network.opts import activation
|
5 |
from neural_network.backprop import bp
|
6 |
-
from neural_network.plot import plot
|
7 |
|
8 |
|
9 |
def init(X: np.array, hidden_size: int):
|
@@ -19,7 +18,7 @@ def init(X: np.array, hidden_size: int):
|
|
19 |
}
|
20 |
|
21 |
|
22 |
-
def main(
|
23 |
X: np.array,
|
24 |
y: np.array,
|
25 |
args,
|
@@ -48,6 +47,5 @@ def main(
|
|
48 |
y_test=y_test,
|
49 |
)
|
50 |
|
51 |
-
plot(
|
52 |
-
|
53 |
return model.to_dict()
|
|
|
3 |
|
4 |
from neural_network.opts import activation
|
5 |
from neural_network.backprop import bp
|
|
|
6 |
|
7 |
|
8 |
def init(X: np.array, hidden_size: int):
|
|
|
18 |
}
|
19 |
|
20 |
|
21 |
+
def main(
|
22 |
X: np.array,
|
23 |
y: np.array,
|
24 |
args,
|
|
|
47 |
y_test=y_test,
|
48 |
)
|
49 |
|
50 |
+
model.plot()
|
|
|
51 |
return model.to_dict()
|
neural_network/neural_network.py
CHANGED
@@ -1,6 +1,15 @@
|
|
1 |
from dataclasses import dataclass, field
|
|
|
|
|
|
|
2 |
from typing import Callable
|
3 |
import numpy as np
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
|
6 |
@dataclass
|
@@ -19,7 +28,7 @@ class NeuralNetwork:
|
|
19 |
loss_history: list = field(
|
20 |
default_factory=lambda: [],
|
21 |
)
|
22 |
-
|
23 |
|
24 |
def predict(self, x: np.array) -> np.array:
|
25 |
n1 = self.compute_node(x, self.w1, self.b1, self.activation_func)
|
@@ -31,6 +40,29 @@ class NeuralNetwork:
|
|
31 |
def eval(self, X_test, y_test) -> None:
|
32 |
self.mse = np.mean((self.predict(X_test) - y_test) ** 2)
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
@staticmethod
|
35 |
def compute_node(arr, w, b, func) -> np.array:
|
36 |
return func(np.dot(arr, w) + b)
|
@@ -41,18 +73,15 @@ class NeuralNetwork:
|
|
41 |
|
42 |
def to_dict(self) -> dict:
|
43 |
return {
|
44 |
-
"w1": self.w1.tolist(),
|
45 |
-
"w2": self.w2.tolist(),
|
46 |
-
"b1": self.b1.tolist(),
|
47 |
-
"b2": self.b2.tolist(),
|
48 |
"epochs": self.epochs,
|
49 |
"learning_rate": self.learning_rate,
|
50 |
"activation_func": self.activation_func.__name__,
|
51 |
"func_prime": self.func_prime.__name__,
|
52 |
"hidden_size": self.hidden_size,
|
53 |
"mse": self.mse,
|
54 |
-
|
55 |
-
# plots and this can be a lot of data
|
56 |
-
# "loss_history": self.loss_history,
|
57 |
-
"plot_key": self.plot_key,
|
58 |
}
|
|
|
1 |
from dataclasses import dataclass, field
|
2 |
+
from matplotlib import pyplot as plt
|
3 |
+
import matplotlib
|
4 |
+
import seaborn as sns
|
5 |
from typing import Callable
|
6 |
import numpy as np
|
7 |
+
import base64
|
8 |
+
import binascii
|
9 |
+
import io
|
10 |
+
|
11 |
+
sns.set()
|
12 |
+
matplotlib.use("Agg")
|
13 |
|
14 |
|
15 |
@dataclass
|
|
|
28 |
loss_history: list = field(
|
29 |
default_factory=lambda: [],
|
30 |
)
|
31 |
+
plt_data = None
|
32 |
|
33 |
def predict(self, x: np.array) -> np.array:
|
34 |
n1 = self.compute_node(x, self.w1, self.b1, self.activation_func)
|
|
|
40 |
def eval(self, X_test, y_test) -> None:
|
41 |
self.mse = np.mean((self.predict(X_test) - y_test) ** 2)
|
42 |
|
43 |
+
def set_plot_data(self, plot_data):
|
44 |
+
self.plt_data = plot_data
|
45 |
+
|
46 |
+
def plot(self):
|
47 |
+
sns.set()
|
48 |
+
fig, ax = plt.subplots()
|
49 |
+
sns.lineplot(
|
50 |
+
x=np.arange(len(self.loss_history)),
|
51 |
+
y=self.loss_history,
|
52 |
+
ax=ax,
|
53 |
+
)
|
54 |
+
plt.ylabel("Loss")
|
55 |
+
plt.xlabel("Epoch")
|
56 |
+
plt.title("Loss / Epoch")
|
57 |
+
|
58 |
+
buffer = io.BytesIO()
|
59 |
+
plt.savefig(buffer, format='png')
|
60 |
+
buffer.seek(0)
|
61 |
+
plt_data = buffer.read()
|
62 |
+
plt_data_encoded = binascii.hexlify(plt_data).decode('utf-8')
|
63 |
+
self.set_plot_data(plt_data_encoded)
|
64 |
+
plt.close()
|
65 |
+
|
66 |
@staticmethod
|
67 |
def compute_node(arr, w, b, func) -> np.array:
|
68 |
return func(np.dot(arr, w) + b)
|
|
|
73 |
|
74 |
def to_dict(self) -> dict:
|
75 |
return {
|
76 |
+
# "w1": self.w1.tolist(),
|
77 |
+
# "w2": self.w2.tolist(),
|
78 |
+
# "b1": self.b1.tolist(),
|
79 |
+
# "b2": self.b2.tolist(),
|
80 |
"epochs": self.epochs,
|
81 |
"learning_rate": self.learning_rate,
|
82 |
"activation_func": self.activation_func.__name__,
|
83 |
"func_prime": self.func_prime.__name__,
|
84 |
"hidden_size": self.hidden_size,
|
85 |
"mse": self.mse,
|
86 |
+
"plt_data": self.plt_data,
|
|
|
|
|
|
|
87 |
}
|
neural_network/plot.py
DELETED
@@ -1,32 +0,0 @@
|
|
1 |
-
import numpy as np
|
2 |
-
import seaborn as sns
|
3 |
-
import matplotlib
|
4 |
-
import matplotlib.pyplot as plt
|
5 |
-
from plt_id import generate_image_key
|
6 |
-
import os
|
7 |
-
|
8 |
-
matplotlib.use("Agg")
|
9 |
-
|
10 |
-
UPLOAD_FOLDER = os.getcwd() + "/plots"
|
11 |
-
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
12 |
-
|
13 |
-
|
14 |
-
def plot(model) -> None:
|
15 |
-
sns.set()
|
16 |
-
fig, ax = plt.subplots()
|
17 |
-
sns.lineplot(
|
18 |
-
x=np.arange(len(model.loss_history)),
|
19 |
-
y=model.loss_history,
|
20 |
-
ax=ax,
|
21 |
-
)
|
22 |
-
plt.ylabel("Loss")
|
23 |
-
plt.xlabel("Epoch")
|
24 |
-
plt.title("Loss / Epoch")
|
25 |
-
|
26 |
-
image_key = generate_image_key()
|
27 |
-
|
28 |
-
plot_filename = os.path.join(UPLOAD_FOLDER, f"{image_key}.png")
|
29 |
-
fig.savefig(plot_filename, format="png")
|
30 |
-
plt.close(fig)
|
31 |
-
|
32 |
-
model.plot_key = image_key
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt_id.py
DELETED
@@ -1,5 +0,0 @@
|
|
1 |
-
import uuid
|
2 |
-
|
3 |
-
|
4 |
-
def generate_image_key() -> str:
|
5 |
-
return str(uuid.uuid4())
|
|
|
|
|
|
|
|
|
|
|
|
templates/index.html
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
<!DOCTYPE html>
|
2 |
-
<html>
|
3 |
-
<head>
|
4 |
-
<title>Data Mining From Scratch Backend</title>
|
5 |
-
</head>
|
6 |
-
<body>
|
7 |
-
<h1>Data Mining From Scratch Backend</h1>
|
8 |
-
<p>This is the backend source code for Data Mining From Scratch.</p>
|
9 |
-
<p>You can find the code on <a href="https://github.com/Jensen-holm/Data-Mining-From-Scratch-Backend">GitHub</a>.</p>
|
10 |
-
</body>
|
11 |
-
</html>
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|