giangtranml commited on
Commit
fa7b1e5
·
1 Parent(s): a9681df

Add application file

Browse files
Files changed (2) hide show
  1. app.py +57 -0
  2. linear_regression.py +122 -0
app.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ from linear_regression import LinearRegression
4
+
5
+ def transform_space(X, degree):
6
+ X_temp = X[:]
7
+ for d in range(2, degree + 1):
8
+ X_temp = np.concatenate(((X[:, 0] ** d).reshape(-1, 1), X_temp), axis=1)
9
+ return X_temp
10
+
11
+ def prepare_data(num_points=100, degree=1, noise=10):
12
+ X = np.linspace(-2, 4, num_points)
13
+ X = X.reshape(-1, 1)
14
+ coef = []
15
+ for d in range(degree):
16
+ coef.append(np.random.uniform(0, 8))
17
+ coef.append(np.random.uniform(0, 10))
18
+ coef = np.array(coef)
19
+ X_transform = transform_space(X, degree)
20
+ ones = np.ones((X.shape[0], 1))
21
+ X_transform = np.concatenate((X_transform, ones), axis=1)
22
+ y = X_transform.dot(coef).reshape((num_points, 1)) + np.random.uniform(1, noise, (num_points, 1))
23
+ return X, X_transform[:, :-1], y
24
+
25
+ def create_examples():
26
+ linear_X, linear_X_transform, linear_y = prepare_data(num_points=100, degree=1, noise=10)
27
+ polynomial2_X, polynomial2_X_transform, polynomial2_y = prepare_data(num_points=100, degree=2, noise=10)
28
+ polynomial3_X, polynomial3_X_transform, polynomial3_y = prepare_data(num_points=100, degree=3, noise=20)
29
+
30
+ LRModel = LinearRegression(alpha=0.05, epochs=1000, lambda_=0.01, do_visualize=True)
31
+ LRModel.train(linear_X_transform, linear_y)
32
+ LRModel.create_gif(linear_X, linear_X_transform, linear_y, "linear_regression_1.gif")
33
+
34
+ LR2Model = LinearRegression(alpha=0.05, epochs=1000, lambda_=0.01, do_visualize=True)
35
+ LR2Model.train(polynomial2_X_transform, polynomial2_y)
36
+ LR2Model.create_gif(polynomial2_X, polynomial2_X_transform, polynomial2_y, "linear_regression_2.gif")
37
+
38
+ LR3Model = LinearRegression(alpha=0.001, epochs=1000, lambda_=0.01, do_visualize=True)
39
+ LR3Model.train(polynomial3_X_transform, polynomial3_y)
40
+ LR3Model.create_gif(polynomial3_X, polynomial3_X_transform, polynomial3_y, "linear_regression_3.gif")
41
+
42
+ # create_examples()
43
+
44
+ def visualize(choice):
45
+ if choice == "Linear":
46
+ return "linear_regression_1.gif"
47
+ elif choice == "Polynomial":
48
+ return "linear_regression_2.gif"
49
+ else:
50
+ return "linear_regression_3.gif"
51
+
52
+ iface = gr.Interface(visualize,
53
+ inputs=[
54
+ gr.Dropdown(choices=["Linear", "Polynomial 2 degree", "Polynomial 3 degree"], value="Linear")
55
+ ],
56
+ outputs=gr.Image().style(full_width=True, height="600"))
57
+ iface.launch()
linear_regression.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Author: Giang Tran
3
+ Email: giangtran240896@gmail.com
4
+ Docs: https://giangtran.me/machine-learning/linear-regression
5
+ """
6
+ import sys
7
+ sys.path.append("..")
8
+ import numpy as np
9
+ import copy
10
+ import imageio
11
+ import io
12
+ import matplotlib.pyplot as plt
13
+
14
+ class LinearRegression:
15
+
16
+ def __init__(self, alpha, epochs=1000, lambda_=0.1, do_visualize=False):
17
+ self.alpha = alpha
18
+ self.epochs = epochs
19
+ self.lambda_ = lambda_
20
+ self.w = None
21
+ self.b = None
22
+ self.do_visualize = do_visualize
23
+ self.vis_elems = {
24
+ "loss": [],
25
+ "iteration": [],
26
+ "weight": [],
27
+ "bias": []
28
+ }
29
+
30
+ def _standardize(self, X, y):
31
+ x_mean = np.mean(X, axis=0)
32
+ x_std = np.std(X, axis=0)
33
+ print(x_mean, x_std)
34
+ y_mean = np.mean(y)
35
+ y_std = np.std(y)
36
+ print(y_mean, y_std)
37
+ return ((X - x_mean)/x_std, x_mean, x_std), ((y - y_mean) / y_std, y_mean, y_std)
38
+
39
+ def _hypothesis(self, X, w, b):
40
+ return np.dot(X, w) + b
41
+
42
+ def _mse_loss(self, X, y_hat, y):
43
+ m = y.shape[0]
44
+ return np.sum((y_hat - y)**2)/(2*m) + self.lambda_*np.linalg.norm(self.w, 2)**2 / (2*m)
45
+
46
+ def _gradient(self, X, y_hat, y):
47
+ m = X.shape[0]
48
+ return 1/m * np.dot(X.T, y_hat - y) + (self.lambda_/m*self.w)
49
+
50
+ def _gradient_bias(self, y_hat, y):
51
+ m = y.shape[0]
52
+ return 1/m * np.sum(y_hat - y)
53
+
54
+ def _train_one_epoch(self, X_train, y_train, e):
55
+ y_hat = self.predict(X_train)
56
+ loss = self._mse_loss(X_train, y_hat, y_train)
57
+ print("Loss at epoch %s: %f" % (e, loss))
58
+ w_grad = self._gradient(X_train, y_hat, y_train)
59
+ b_grad = self._gradient_bias(y_hat, y_train)
60
+ self._update_params(w_grad, b_grad)
61
+ w_grad_norm = np.linalg.norm(w_grad, 2)
62
+ return loss, w_grad_norm
63
+
64
+ def _train(self, X_train, y_train):
65
+ prev_loss = 0
66
+ for e in range(self.epochs):
67
+ loss, w_grad_norm = self._train_one_epoch(X_train, y_train, e)
68
+ if abs(prev_loss - loss) < 0.001:
69
+ break
70
+ prev_loss = loss
71
+ if self.do_visualize and e % 5 == 0:
72
+ self.vis_elems["loss"].append(loss)
73
+ self.vis_elems["iteration"].append(e)
74
+ self.vis_elems["weight"].append(copy.deepcopy(self.w))
75
+ self.vis_elems["bias"].append(copy.deepcopy(self.b))
76
+ prev_loss = loss
77
+
78
+ if w_grad_norm < 1e-4:
79
+ break
80
+
81
+ def _update_params(self, w_grad, b_grad):
82
+ self.w -= self.alpha*w_grad
83
+ self.b -= self.alpha*b_grad
84
+
85
+ def _plot(self, w, b, loss, iteration, X, X_transform, y):
86
+ y_plot = self._hypothesis(X_transform, w, b)
87
+ plt.figure(0, figsize=(6, 6))
88
+ plt.clf()
89
+ plt.title("Loss: " + str(loss))
90
+ plt.scatter(X[:, 0], y, color='r')
91
+ label = "Iteration: " + str(iteration)
92
+ for ind, w in enumerate(w):
93
+ label += "\nTheta %s: %.2f" % (ind+1, w)
94
+ label += "\nBias: %.2f" % b
95
+ plt.plot(X, y_plot, '-', label=label)
96
+ plt.legend()
97
+ img_buf = io.BytesIO()
98
+ plt.savefig(img_buf, format='png')
99
+ img_buf.seek(0)
100
+ return imageio.imread(img_buf)
101
+
102
+ def create_gif(self, X, X_transform, y, file_name):
103
+ imgs = []
104
+ for l, i, w, b in zip(self.vis_elems["loss"], self.vis_elems["iteration"], self.vis_elems["weight"], self.vis_elems["bias"]):
105
+ imgs.append(self._plot(w, b, l, i, X, X_transform, y))
106
+ imageio.mimsave(file_name, imgs, fps=5)
107
+
108
+ def train(self, X_train, y_train):
109
+ self.w = np.random.uniform(size=(X_train.shape[1], 1))
110
+ self.b = np.random.randint(low=20, high=50)
111
+ self._train(X_train, y_train)
112
+
113
+ def predict(self, X_test, w=None, b=None):
114
+ assert X_test.shape[1] == self.w.shape[0], "Incorrect shape."
115
+ pred = self._hypothesis(X_test, self.w, self.b)
116
+ return pred
117
+
118
+
119
+ def r2_score(self, y_hat, y_test):
120
+ total_sum_squares = np.sum((y_test - np.mean(y_test))**2)
121
+ residual_sum_squares = np.sum((y_test - y_hat)**2)
122
+ return 1 - residual_sum_squares/total_sum_squares