#python #algorithm #optimization
#python #алгоритм #оптимизация
Вопрос:
Я попытался использовать игрушечную задачу линейной регрессии для внедрения оптимизации в функцию MSE с использованием алгоритма gradient decent.
import numpy as np
# Data points
x = np.array([1, 2, 3, 4])
y = np.array([1, 1, 2, 2])
# MSE function
f = lambda a, b: 1 / len(x) * np.sum(np.power(y - (a * x b), 2))
# Gradient
def grad_f(v_coefficients):
a = v_coefficients[0, 0]
b = v_coefficients[1, 0]
return np.array([1 / len(x) * np.sum(2 * (y - (a * x b)) * x),
1 / len(x) * np.sum(2 * (y - (a * x b)))]).reshape(2, 1)
# Gradient Decent with epsilon as tol vector and alpha as the step/learning rate
def gradient_decent(v_prev):
tol = 10 ** -3
epsilon = np.array([tol * np.ones([2, 1], int)])
alpha = 0.2
v_next = v_prev - alpha * grad_f(v_prev)
if (np.abs(v_next - v_prev) <= epsilon).all():
return v_next
else:
gradient_decent(v_next)
# v_0 is the initial guess
v_0 = np.array([[1], [1]])
gradient_decent(v_0)
Я пробовал разные альфа-значения, но код никогда не сходится (бесконечная рекурсия) кажется, что проблема связана с условием остановки рекурсии, но после нескольких запусков v_next и v_prev отскакивают от -infinte до бесконечности
Комментарии:
1. Вы пробовали отлаживать его?
2. @MadPhysicist да, конечно, вся математика кажется в порядке, и я ее отладил.
Ответ №1:
Здорово, что вы изучаете машинное обучение (^_^), самостоятельно реализуя некоторые базовые алгоритмы. Что касается вашего вопроса, в вашем коде есть две проблемы, первая из которых — математическая, вход в систему:
def grad_f(v_coefficients):
a = v_coefficients[0, 0]
b = v_coefficients[1, 0]
return np.array([1 / len(x) * np.sum(2 * (y - (a * x b)) * x),
1 / len(x) * np.sum(2 * (y - (a * x b)))]).reshape(2, 1)
должно быть
return -np.array(...)
поскольку
второй — это программирование, такой код не вернет вам результат в Python:
def add(x):
new_x = x 1
if new_x > 10:
return new_x
else:
add(new_x)
вы должны использовать return
в обоих предложениях if
инструкции, поэтому оно должно быть
def add(x):
new_x = x 1
if new_x > 10:
return new_x
else:
return add(new_x)
Существует также небольшая проблема с коэффициентом альфа для этих конкретных точек данных alpha=0.2
, который слишком велик для сходимости алгоритма, вам нужно использовать меньший alpha
. Я также слегка реорганизовал ваш исходный код, используя numpy broadcasting convention (https://numpy.org/doc/stable/user/basics.broadcasting.html ), чтобы получить следующий результат:
import numpy as np
# Data points
x = np.array([1, 2, 3, 4])
y = np.array([1, 1, 2, 2])
# MSE function
f = lambda a, b: np.mean(np.power(y - (a * x b), 2))
# Gradient
def grad_f(v_coefficients):
a = v_coefficients[0, 0]
b = v_coefficients[1, 0]
return -np.array([np.mean(2 * (y - (a * x b)) * x),
np.mean(2 * (y - (a * x b)))]).reshape(2, 1)
# Gradient Decent with epsilon as tol vector and alpha as the step/learning rate
def gradient_decent(v_prev):
tol = 1e-3
# epsilon = np.array([tol * np.ones([2, 1], int)]) do not need this, due to numpy broadcasting rules
alpha = 0.1
v_next = v_prev - alpha * grad_f(v_prev)
if (np.abs(v_next - v_prev) <= alpha).all():
return v_next
else:
return gradient_decent(v_next)
# v_0 is the initial guess
v_0 = np.array([[1], [1]])
gradient_decent(v_0)