import numpy as np
import matplotlib.pyplot as plt
import plotly.graph_objects as go
a=0.3
b=0.5
c=0.6
alpha = 1.2
def cost_function(w, sigma=1, a=a, b=b, c=c):
r_xd = np.array([a,b])
R_x = np.array([[1, c],[c, 1]])
return 1/2 * sigma ** 2 - r_xd @ w + 1/2 * (w.T @ R_x @ w)
w1 = np.linspace(-10, 10, 100)
w2 = np.linspace(-10, 10, 100)
W1, W2 = np.meshgrid(w1, w2)
Z = np.zeros_like(W1)
for i in range(len(w1)):
for j in range(len(w2)):
w = np.array([w1[i], w2[j]])
Z[i,j] = cost_function(w)
fig = go.Figure(data=[go.Surface(z=Z, x=W1, y=W2)])
fig.update_layout(title='Функція вартості', autosize=True,
width=800, height=600,
margin=dict(l=20, r=20, b=20, t=60))
fig.show()
def c_gradient(w):
E_w1 = -a + w[1]*c + w[0]
E_w2 = -b + w[0]*c + w[1]
return np.array([E_w1, E_w2])
def gradient_descent(w_0, alpha=1.2, max_iter = 1000, tol=1e-5, clip_value=1e6):
w = w_0.copy()
values = [w]
cost_list = [cost_function(w)]
for t in range(max_iter):
grad =np.clip(c_gradient(w), -clip_value, clip_value)
w_new = w - alpha * grad
if np.linalg.norm(w_new - w) < tol:
break
w = w_new
cost = cost_function(w)
cost_list.append(cost)
values.append(w_new)
return np.array(values), cost_list
w0 = np.array([-5,5])
values, cost_list = gradient_descent(w0)
print(f"Точка мінімуму:{values[-1]}")
print(f"Значення функції E(w) в точці мінімуму:{cost_function(values[-1])}")
fig = go.Figure(data=go.Contour(x=w1, y=w2, z=Z, name="Функція втрат"))
fig.add_trace(go.Scatter(x=values[:,0], y=values[:,1], name="Напрямок вектору ваг", mode="markers+lines",
line=go.scatter.Line(color='white')))
fig.update_layout(title='Проєкція цільової функції на площину W', autosize=True,
width=800, height=600,
margin=dict(l=20, r=20, b=20, t=60))
fig.show()
fig = go.Figure()
fig.add_trace(
go.Surface(name="Функція втрат",x=w1, y=w2,
z=Z.reshape((len(w1), len(w2)))))
fig.add_trace(
go.Scatter3d(x=values[:,1], y=values[:,0], z=[cost_function(w) for w in values],
line=dict(color='white'), name="Напрямок вектору ваг"))
fig.update_layout(title='Траєкторія вектору ваг у тривимірному просторі', autosize=True,
width=800, height=600,
margin=dict(l=20, r=20, b=20, t=60))
fig.show()
values, cost = gradient_descent(w0)
# Plot the convergence of the gradient descent algorithm
fig = go.Figure()
lr = [1.255, 1.2, 0.1, 0.01, 0.001]
for i in lr:
values, cost = gradient_descent(w0, alpha=i)
fig.add_trace(go.Scatter(x=np.arange(len(cost)), y=cost, mode='lines', name=f"швидкість навчання = {i}"))
fig.update_layout(title='Збіжність градієнтного спуску з різною швидкістю навчання', xaxis_title='Ітерації', yaxis_title='Вартість', height=600, width=900)
fig.update_layout(yaxis_range=[0,10])
fig.show()
values, cost = gradient_descent(w0, alpha=0.001)
fig = go.Figure(data=go.Contour(x=w1, y=w2, z=Z, name="Функція втрат", showscale=False))
fig.add_trace(go.Scatter(x=values[:,0], y=values[:,1], name="alpha=0.001", mode="markers+lines",
line=go.scatter.Line(color='magenta')))
values, cost = gradient_descent(w0, alpha=1.255)
fig.add_trace(go.Scatter(x=values[:,0], y=values[:,1], name="alpha=1.255", mode="markers+lines",
line=go.scatter.Line(color='mediumaquamarine')))
fig.update_layout(title='Траєкторія векторгу ваг при різній швидкості навчання', autosize=True,
width=800, height=600,
margin=dict(l=20, r=20, b=20, t=60), xaxis_range=[-10,10], yaxis_range=[-10,10])
fig.show()