Spaces:
Sleeping
Sleeping
## CHOOSE BETWEEN ALTAIR & MATPLOTLIB | |
import gradio as gr | |
import altair as alt | |
import numpy as np | |
import pandas as pd | |
import matplotlib.pyplot as plt | |
import time | |
def make_plot(plot_type, a, epoch, progress=gr.Progress()): | |
if plot_type == "log": | |
return logReg(a=a, epoch=epoch, progress=progress) | |
elif plot_type == "lin": | |
return linReg(a=a,epoch=epoch, progress=progress) | |
# a = learning rate | |
# epoch = number of training iterations | |
def logReg(a, epoch, progress): | |
#### generate random data-set #### | |
progress(0.2, desc="Generating Data") | |
time.sleep(1) | |
#np.random.seed(0) # set random seed (optional) | |
## set mean and covariance of our datasets | |
mean1 = [20,35] | |
cov1 = [[100,100],[-100,100]] | |
mean2 = [60,70] | |
cov2 = [[100,100],[100,-100]] | |
## concatenate values to set x values for datasets | |
x1, x2 = np.random.multivariate_normal(mean1, cov1, 100).T | |
x_1, x_2 = np.random.multivariate_normal(mean2, cov2, 100).T | |
x1 = (np.concatenate((x1, x_1), axis=0))/10 | |
x2 = (np.concatenate((x2, x_2), axis=0))/10 | |
## set y values of datasets | |
y1 = np.zeros(100) # y[0:100] is zero dataset (dataset we want our decision boundary to be above) | |
y2 = np.ones(100) # y[101:200] is one dataset (dataset we want our decision boundary to be below) | |
y = np.concatenate((y1, y2), axis=0) # combine datasets into one term | |
w = np.matrix([(np.random.rand())/100,(np.random.rand())+0.0001/100]) # begin weights at random starting point | |
b = np.matrix([np.random.rand()]) # begin bias term at random starting point | |
wb = np.concatenate((b, w), axis=1) # combine w and b into one weight term | |
print('f = b + x1*w1 + x2*w2') | |
print('Starting weights:', 'f = ', wb[0,0],'+ x1', wb[0,1], '+ x2' , wb[0,2]) | |
loss = np.empty([epoch]) # term to store all loss terms for plotting | |
iterat = np.empty([epoch]) # term to store all epoch numbers to be plotted vs loss | |
for n in range (epoch): | |
iterat[n] = n | |
progress(0.5, desc="Finding Loss & Regression") | |
time.sleep(1.5) | |
for p in range (epoch): | |
L, J = np.matrix([[0.0, 0.0, 0.0]]), 0.0 # reset gradient (∂J(w)/∂w) and loss for each epoch | |
#### Code the equations to solve for the loss and to update | |
#### the weights and biases for each epoch below. | |
#### Hint: you will need to use the for loop below to create a summation to solve | |
#### for wb and J (loss) for each epoch. xj has been given as a starting point. | |
for i in range(len(x1)): | |
xj = np.matrix([1,x1[i],x2[i]]) | |
# y_hat = (y_hat or h_w(x) expression) | |
y_hat = 1 / (1 + np.exp(-(wb * xj.T))) | |
# J = (cost function, also referred to as L) | |
J = -((y[i] * np.log(y_hat)) + ((1 - y[i])*np.log(1 - y_hat))) | |
# d_J = (∂J(w)/∂w function, equation can be solved with information on slide 27) | |
d_J = ((y_hat) - y[i]) * xj | |
# wb = (weight updating equation) | |
wb = wb - a * (d_J) | |
loss[p] = J | |
if ((p % 100) == 0): | |
print('loss:', J,' Gradient (∂J(w)/∂w) [[b, w1, w2]]:',L[0]) | |
print('Updated weights:', 'f = ', wb[0,0],'+ x1', wb[0,1], '+ x2' , wb[0,2]) | |
equation = "f = {w1} + {w2}x1 + {w3}x2".format(w1 = wb[0,0], w2 = wb[0,1], w3 = wb[0,2]) | |
## Plot decision boundary and data | |
progress(0.8, desc="Plotting Data") | |
time.sleep(1.5) | |
scatterData1 = pd.DataFrame({'x': x1[1:100], | |
'y': x2[1:100]}) | |
scatterFig1 = alt.Chart(scatterData1).mark_point().encode( | |
x='x:Q', | |
y='y:Q' | |
).properties( | |
title="Decision Boundary" | |
) | |
scatterData2 = pd.DataFrame({'x': x1[101:200], | |
'y': x2[101:200]}) | |
scatterFig2 = alt.Chart(scatterData2).mark_point(color='green').encode( | |
x='x:Q', | |
y='y:Q', | |
).properties( | |
title="Decision Boundary" | |
) | |
y2 = np.array(np.array(-(x1*wb[0,1] + wb[0,0])/wb[0,2],dtype=float)) | |
trendLine = pd.DataFrame({'x': x1.flatten(), | |
'y': y2.flatten() }) | |
trendLineFig = alt.Chart(trendLine).mark_line().encode( | |
x='x:Q', | |
y='y:Q' | |
).properties( | |
title="Decision Boundary" | |
) | |
finalFig = scatterFig1 + scatterFig2 + trendLineFig | |
lossData = pd.DataFrame({'Number of Iterations': iterat[100:], | |
'Loss Value': loss[100:] }) | |
lossFig = alt.Chart(lossData).mark_line().encode( | |
x='Number of Iterations:Q', | |
y='Loss Value:Q' | |
).properties( | |
title='Plot of loss values over number of iterations' | |
) | |
plt.close() | |
plt.figure() | |
plt.plot(x1[1:100],x2[1:100],'x', x1[101:200], x2[101:200],'x') # plot random data points | |
plt.plot(x1, -(x1*wb[0,1] + wb[0,0])/wb[0,2] , linestyle = 'solid') # plot decision boundary | |
plt.axis('equal') | |
plt.xlabel('x1') | |
plt.ylabel('x2') | |
plt.title('Decision Boundary') | |
plt.savefig("plt1.png") | |
## Plot training loss v epoch | |
plt.figure() | |
plt.plot(iterat[100:],loss[100:],'x') | |
plt.xlabel('Epoch') | |
plt.ylabel('Loss') | |
plt.title('Training Loss v Epoch') | |
plt.savefig("plt2.png") | |
return [finalFig.interactive(),lossFig.interactive(),"plt1.png","plt2.png",str(loss[len(loss)-1]),str(equation)] | |
# a = learning rate step size | |
# epoch = number of training iterations | |
def linReg(a, epoch, progress): | |
# generate random data-set | |
progress(0.2, desc="Generating Data") | |
time.sleep(1) | |
# np.random.seed(0) # choose random seed (optional) | |
x = np.random.rand(100, 1) | |
y = 2 + 3 * x + np.random.rand(100, 1) | |
# J = 0 # initialize J, this can be deleted once J is defined in the loop | |
w = np.matrix([np.random.rand(),np.random.rand()]) # slope and y-intercept | |
ite = epoch # number of training iterations | |
jList = [] | |
numIte = [] | |
# Write Linear Regression Code to Solve for w (slope and y-intercept) Here ## | |
progress(0.5, desc="Finding Loss & Regression") | |
time.sleep(1.5) | |
for p in range (ite): | |
for i in range(len(x)): | |
# Calculate w and J here | |
x_vec = np.matrix([x[i][0],1]) # Option 1 | Setting up a vector for x (x_vec[j] corresponds to w[j]) | |
h = w * x_vec.T ## Hint: you may need to transpose x or w by adding .T to the end of the variable | |
w = w - a * (h - y[i]) * x_vec | |
J = (1/2) * (((h - y[i])) ** 2) | |
J = J.item() | |
jList.append(J) | |
numIte.append(p) | |
print('Loss:', J) | |
## if done correctly the line should be in line with the data points ## | |
print('f = ', w[0,0],'x + ', w[0,1]) | |
equation = "f = {w1}x + {w2}".format(w1 = w[0,0], w2 = w[0,1]) | |
progress(0.8, desc="Plotting Data") | |
time.sleep(1.5) | |
y2 = np.array(np.array((w[0,1]+(w[0,0] * x)),dtype=float)).T | |
scatterData = pd.DataFrame({'x': x.flatten(), | |
'y': y.flatten()}) | |
scatterFig = alt.Chart(scatterData).mark_point().encode( | |
x='x:Q', | |
y='y:Q' | |
).properties( | |
title='Plot of random data values with linear regression line' | |
) | |
trendLine = pd.DataFrame({'x': x.flatten(), | |
'y': y2.flatten() }) | |
trendLineFig = alt.Chart(trendLine).mark_line().encode( | |
x='x:Q', | |
y='y:Q' | |
) | |
finalFig = scatterFig + trendLineFig | |
lossData = pd.DataFrame({'Number of Iterations': range(1,len(jList)+1), | |
'Loss Value': jList }) | |
lossFig = alt.Chart(lossData).mark_line().encode( | |
x='Number of Iterations:Q', | |
y='Loss Value:Q' | |
).properties( | |
title='Plot of loss values over number of iterations' | |
) | |
# plot | |
plt.close() | |
plt.figure() | |
plt.scatter(x,y,s=ite) | |
plt.plot(x, w[0,1] + (w[0,0] * x), linestyle='solid') | |
plt.xlabel('x') | |
plt.ylabel('y') | |
plt.title('Plot of random data values with linear regression line') | |
plt.savefig("plt1.png") | |
plt.figure() | |
plt.plot(jList) | |
plt.xlabel('Number of Iterations') | |
plt.ylabel('Loss Value') | |
plt.title('Plot of loss values over number of iterations') | |
plt.savefig("plt2.png") | |
return [finalFig.interactive(),lossFig.interactive(),"plt1.png","plt2.png",str(jList[len(jList)-1]),str(equation)] | |
with gr.Blocks(title="Regression Visualization") as demo: | |
gr.Markdown( | |
""" | |
# Regression Visualization for Machine Learning | |
Choose your variables below to create a linear or logistic regression model! | |
""") | |
with gr.Row(): | |
pack = gr.Radio(label="Plot Package",info="Choose 'MatPlot' for MatPlotLib, Choose 'Altair' for Altair", | |
choices=['MatPlot','Altair'], value='Altair') | |
bType = gr.Radio(label="Regression Type",info="Choose 'log' for logistic, Choose 'lin' for linear", | |
choices=['log','lin'], value='log') | |
l_rate = gr.Number(value=0.01,label="Learning Rate",info="Enter a value in the range 0.0 - 1.0") | |
epochs = gr.Number(value=100,label="Number of Epochs (Number of Training Iterations)",info="Enter an integer larger than 0",precision=0) | |
bStart = gr.Button(value="Start") | |
with gr.Row() as alt_row: | |
altPlot1 = gr.Plot() | |
altPlot2 = gr.Plot() | |
with gr.Row(visible=False) as mat_row: | |
matPlot1 = gr.Image(type='filepath',label="Regression Graph",height=600,width=600) | |
matPlot2 = gr.Image(type='filepath',label="Regression Graph",height=600,width=600) | |
loss = gr.Textbox(label="Final Loss Value") | |
equ = gr.Textbox(label="Equation for Plotted Line") | |
def changeComp(package): | |
if package == "Altair": | |
return { | |
alt_row: gr.Row.update(visible=True), | |
mat_row: gr.Row.update(visible=False) | |
} | |
else: | |
return { | |
alt_row: gr.Row.update(visible=False), | |
mat_row: gr.Row.update(visible=True) | |
} | |
pack.input(changeComp, show_progress=True, inputs=[pack], outputs=[alt_row, mat_row]) | |
bStart.click(make_plot, show_progress=True, inputs=[bType,l_rate,epochs], outputs=[altPlot1,altPlot2, matPlot1, matPlot2, loss, equ]) | |
demo.load() | |
if __name__== "__main__" : | |
demo.queue().launch() |