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 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
- plot_key = None
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
- "plot_key": self.plot_key,
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
- from plt_id import generate_image_key
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
- image_key = generate_image_key()
39
-
40
- plot_filename = os.path.join(UPLOAD_FOLDER, f"{image_key}.png")
41
- fig.savefig(plot_filename, format="png")
42
- plt.close(fig)
43
 
44
- clusterer.plot_key = image_key
 
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
- plot()
 
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
- plot()
 
 
 
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(model=model)
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
- plot_key = None
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
- # not returning this because we are making our own
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
-