Загрузка данных
import numpy as np
import matplotlib.pyplot as plt
# Исходные данные из урока
X = np.array([
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[10, 5, 3, 2, 0, 9, 1, 0, 8, 2]
]).T
y = np.array([45, 55, 50, 55, 65, 35, 75, 80, 50, 60])
# ==================================================
# ЗАДАНИЕ 1
# ==================================================
def gradient_descent(X, y, eta=1e-2, iterations=10000):
n = X.shape[0]
m = X.shape[1]
w = np.zeros(m)
for i in range(iterations):
y_pred = np.dot(X, w)
grad = 2 / n * np.dot(X.T, (y_pred - y))
w = w - eta * grad
return w
w_gd = gradient_descent(
X,
y,
eta=1e-2,
iterations=10000
)
# Веса, полученные методом наименьших квадратов
w_ols = np.linalg.inv(X.T @ X) @ X.T @ y
print("ЗАДАНИЕ 1")
print("Веса градиентного спуска:", w_gd)
print("Веса МНК:", w_ols)
# ==================================================
# ЗАДАНИЕ 2
# ==================================================
def gradient_descent_tol(X, y, eta=1e-2, tol=1e-4):
n = X.shape[0]
m = X.shape[1]
w = np.zeros(m)
error_prev = np.mean((np.dot(X, w) - y) ** 2)
iterations = 0
while True:
y_pred = np.dot(X, w)
grad = 2 / n * np.dot(X.T, (y_pred - y))
w = w - eta * grad
error = np.mean((np.dot(X, w) - y) ** 2)
iterations += 1
if abs(error_prev - error) < tol:
break
error_prev = error
return w, iterations, error
w_tol, iterations_tol, error_tol = gradient_descent_tol(
X,
y,
eta=1e-2,
tol=1e-4
)
print("\nЗАДАНИЕ 2")
print("Веса:", w_tol)
print("Количество итераций:", iterations_tol)
print("MSE:", error_tol)
# ==================================================
# ЗАДАНИЕ 3
# ==================================================
def gradient_descent_history(X, y, eta, iterations):
n = X.shape[0]
m = X.shape[1]
w = np.zeros(m)
errors = []
for i in range(iterations):
y_pred = np.dot(X, w)
grad = 2 / n * np.dot(X.T, (y_pred - y))
w = w - eta * grad
error = np.mean((np.dot(X, w) - y) ** 2)
errors.append(error)
return w, errors
etas = [0.001, 0.005, 0.01, 0.02]
iterations = 1000
plt.figure(figsize=(10, 6))
for eta in etas:
w, errors = gradient_descent_history(
X,
y,
eta,
iterations
)
plt.plot(
range(1, iterations + 1),
errors,
label=f'eta = {eta}'
)
print(
f"eta = {eta}, "
f"веса = {w}, "
f"MSE = {errors[-1]}"
)
plt.xlabel("Количество итераций")
plt.ylabel("MSE")
plt.title("Зависимость ошибки от количества итераций")
plt.legend()
plt.grid()
plt.show()
# ==================================================
# ЗАДАНИЕ 4
# ==================================================
print("\nЗАДАНИЕ 4")
print("""
Вывод:
1. При увеличении количества итераций ошибка уменьшается,
пока алгоритм не приблизится к минимуму.
2. Чем выше скорость обучения eta, тем быстрее алгоритм
может приблизиться к минимуму.
3. Слишком маленькая eta приводит к медленному обучению.
4. Слишком большая eta может привести к тому, что алгоритм
будет перескакивать через минимум, а ошибка может начать
колебаться или увеличиваться.
5. Скорость обучения и количество итераций связаны:
при маленькой eta требуется больше итераций.
6. Ускорить вычисление весов можно правильным подбором eta:
выбрать достаточно большую скорость обучения, при которой
алгоритм остается стабильным, а также использовать условие
остановки tol вместо лишних итераций.
""")