aliakyurek/LinearRegression1_OLS
0
1import pandas as pd
2import numpy as np
3import matplotlib
4matplotlib.use("Agg")
5import matplotlib.pyplot as plt
6import gradio as gr
7
8def load_dataset(n=100, w = 0.4, b=5., x_range = [0, 50]):
9 np.random.seed(42)
10 def s(x):
11 g = (x - x_range[0]) / (x_range[1] - x_range[0])
12 return 5 * (0.25 + g**2.)
13
14 x = (x_range[1] - x_range[0]) * np.random.rand(n) + x_range[0]
15 eps = np.random.randn(n) * s(x)
16 y = (w * x * (1. + np.sin(x)/5) + b) + eps
17 y = (y - y.mean()) / y.std()
18 idx = np.argsort(x)
19 return pd.DataFrame({"x": x[idx], "y": y[idx]})
20
21def check_sanitize_data(inp):
22 try:
23 inp=inp.astype(float)
24 except:
25 return None, [("Data points not numeric", "Error")]
26 x,y = inp["x"].to_numpy(), inp["y"].to_numpy()
27 if(len(x)<2):
28 return None, [("Data points not provided", "Error")]
29 return (x,y), [("", "OK")]
30
31def plot_data(inp, m=None, b=None):
32 xy, status = check_sanitize_data(inp)
33 if xy is None:
34 return None, status
35 x, y = xy
36 fig,ax = plt.subplots()
37 ax.set(aspect=np.std(x).item()/3, ylabel="Y-axis")
38 ax.plot(x, y, "o", label="Original data", markersize=2)
39 # center text
40 # fig.text(.5, .05, "OLS", ha="center")
41 if(m):
42 y_hat = m * x + b
43 rss = np.sum((y-y_hat)**2)
44 ax.set(xlabel = f"RSS:{rss:.4f}")
45 ax.xaxis.label.set(color="red")
46 ax.plot(x, m * x + b, "r", label="Fitted line")
47 ax.legend()
48 ax.grid()
49 fig.tight_layout()
50 return fig, [("Data check", "OK")]
51
52def linear_regression_from_scratch(X,y):
53 XT_X = np.matmul(X.T, X)
54 XT_y = np.matmul(X.T, y)
55 m,b = np.matmul(np.linalg.inv(XT_X), XT_y)
56 return m,b
57
58def linear_regression_linalg_lstsq(X,y):
59 (m,b),*_ = np.linalg.lstsq(X, y, rcond=None)
60 return m,b
61
62def linear_regression_plot(method, inp):
63 xy, status = check_sanitize_data(inp)
64 if xy is None:
65 return None, status
66 x,y = xy
67 X = np.column_stack((x, np.ones(len(x))))
68 if method == "numpy from scratch":
69 m, b = linear_regression_from_scratch(X, y)
70 elif method == "numpy.linalg.lstsq":
71 m, b = linear_regression_linalg_lstsq(X, y)
72 else:
73 return None, [("Method not selected", "Error")]
74 fig, _ = plot_data(inp, m, b)
75 return fig, [("Regression", "OK")]
76
77data = load_dataset()
78block_params = {
79 "title": "Ordinary Least Squares",
80 "css": """
81 #XY {max-height: 350px; overflow-y: scroll}
82 #images img {width:auto; height:auto}
83 #images .flex {display:none; height:auto}
84 #accord > div > span {font-weight: bold}
85 """
86}
87plot_data(data)
88
89with gr.Blocks(**block_params) as demo:
90 with gr.Row():
91 with gr.Column(scale=1):
92
93 data_frm = gr.Dataframe(headers=data.columns.tolist(),
94 datatype=["number", "number"],
95 col_count=(2, "fixed"), elem_id="XY"
96 )
97 plot_btn = gr.Button("Check&Plot")
98 gr.Examples([[data.values.tolist()]], inputs=data_frm)
99 gr.Markdown("""
100 #### How to use?
101 1.Fill the x-y table below (or use the example data provided)
102 2.**Check&Plot**
103 3.Select an implementation
104 4.**Regression&Plot**
105 """)
106 with gr.Column(scale=1):
107 status_hlt = gr.HighlightedText(
108 label="Status",
109 combine_adjacent=True,
110 ).style(color_map={"Error": "red", "OK": "green"})
111 data_plt = gr.Plot(label="Plot")
112 method_dd = gr.Dropdown(label="Select an implementation",choices=["numpy from scratch", "numpy.linalg.lstsq"],)
113 regression_btn = gr.Button("Regression&Plot")
114 # gr.Examples(label="Proofs", examples=[["img.png"]],inputs=img)
115
116 with gr.Accordion("Motivation", open=False, elem_id="accord"):
117 gr.Markdown("""
118 In this space, I tried to get most out of Gradio an HF. So that this combination can be
119 used not only for advanced ML models but also to demonstrate the topics regarding
120 mathematical background of ML. The first topic is Linear Regression optimized with OLS
121 """)
122 with gr.Accordion("Model Card", open=False, elem_id="accord"):
123 gr.Markdown("""
124 | Name | Objective | Metric | Solution |
125 | -------- | ------- | -------- | -------- |
126 | Linear regression | Ord. least squares (OLS) | Residual sum-of-squares (RSS) | Analytical |
127 """)
128 with gr.Accordion("Math Background", open=False, elem_id="accord"):
129 with gr.Row():
130 with gr.Column(scale=1):
131 gr.Markdown("""
132 We have a linear regression model in (1).
133 We want to minimize RSS (2).
134 We need the derivative of RSS(β) with respect to β to and set it zero.
135 The resulting formula is given (3).
136 An example matrix represenation of the model y = Xβ is given (4).
137 """)
138 with gr.Column(scale=1):
139 img = gr.Image(label="Proof", value="img.png", elem_id="images")
140 with gr.Accordion("References", open=False, elem_id="accord"):
141 links = ("statproofbook.github.io/P/mlr-ols",
142 "statproofbook.github.io/P/mlr-ols2",
143 "towardsdatascience.com/building-linear-regression-least-squares-with-linear-algebra-2adf071dd5dd")
144 gr.Markdown("\n".join(f"{i}.[https://{l}](https://{l}) " for i, l in enumerate(links,1)))
145
146 plot_btn.click(fn=plot_data, inputs=data_frm, outputs=[data_plt,status_hlt])
147 regression_btn.click(fn=linear_regression_plot, inputs=[method_dd,data_frm], outputs=[data_plt,status_hlt])
148
149demo.launch()
150 