Градиентный спуск для линейной регрессии в коде Python
def computeCost(X, y, theta):
inner = np.power(((X * theta.T) - y), 2)
return np.sum(inner) / (2 * len(X))
def gradientDescent(X, y, theta, alpha, iters):
temp = np.matrix(np.zeros(theta.shape))
params = int(theta.ravel().shape[1]) #flattens
cost = np.zeros(iters)
for i in range(iters):
err = (X * theta.T) - y
for j in range(params):
term = np.multiply(err, X[:,j])
temp[0, j] = theta[0, j] - ((alpha / len(X)) * np.sum(term))
theta = temp
cost[i] = computeCost(X, y, theta)
return theta, cost
Вот код для функции стоимости линейной регрессии и градиентного спуска, который я нашел в руководстве, но я не совсем уверен, как это работает.
Сначала я понимаю, как computeCost
код работает, так как он просто (1/2M), где M - количество данных.
За gradientDescent
код, я просто не понимаю, как это работает в целом. Я знаю, что формула для обновления тета-это что-то вроде
theta = theta - (learningRate) * derivative of J(cost function)
, Но я не уверен, где alpha / len(X)) * np.sum(term
) это происходит на линии обновления temp[0,j]
,
Пожалуйста, помогите мне понять!
2 ответа
Я сломаю это для тебя. Таким образом, в вашей функции GradientDescent вы берете переменные предиктора (X
), целевая переменная (y
), весовая матрица (theta
) и еще два параметра (alpha
, iters
) которые являются параметрами обучения. Работа функции состоит в том, чтобы выяснить, на сколько должен быть умножен каждый столбец в наборе переменных (X) предикторов, прежде чем добавлять, чтобы получить прогнозируемые значения целевой переменной (y
). В первой строке функции вы запускаете матрицу весов под названием temp
в нули. Это в основном является отправной точкой конечной весовой матрицы (theta
) что функция выведет в конце. params
переменная в основном количество весов или количество переменных предиктора. Эта строка имеет больше смысла в контексте нейронных сетей, где вы создаете абстракцию функций.
В линейной регрессии весовая матрица в основном будет одномерным массивом. В типичных нейронных сетях с прямой связью мы берем, скажем, 5 функций, преобразуем их в 4 или 6 или n функций, используя матрицу весов и так далее. В линейной регрессии мы просто объединяем все входные объекты в один выходной объект. Так theta
будет по существу эквивалентен вектору строки (что видно по линии temp[0,j]=...
) а также params
будет количество функций. Мы cost
массив просто хранит этот массив на каждой итерации. Теперь перейдем к двум петлям. В соответствии err = (X * theta.T) - y
под первым for
Цикл, мы рассчитываем ошибку предсказания для каждого примера обучения. Форма err
переменная быть number of examples,1
, Во втором цикле for мы тренируем модель, то есть постепенно обновляем наш term
матрица. Мы запускаем второй цикл iters
количество раз. В контексте нейронной сети мы обычно называем это эпохами. Это в основном количество раз, когда вы хотите тренировать модель.
Теперь линия term = np.multiply(err, X[:,j])
: здесь мы рассчитываем индивидуальную корректировку, которая должна быть сделана для каждого веса в temp
матрица. Мы определяем стоимость как (y_predicted-y_actual)**2/number_of_training_points, где y_predicted = X_1*w_1 + X_2*w_2 + X_3*w_3 +... Если мы дифференцируем эту стоимость по отношению к конкретному весу (скажем, W_i), мы get (y_predicted-y_actual)*(X_i)/number_of_training_points где X_i - это столбец, на который умножается W_i. Итак term =
Линия в основном вычисляет эту дифференцирующую часть. Мы можем умножить term
переменная с темпом обучения и вычитать из W_i. Но, как вы могли заметить, term
переменная является массивом. Но об этом позаботятся в следующей строке. В следующей строке мы берем среднее значение term
(суммируя, а затем разделив на len(X)
) и вычесть его из соответствующего веса в temp
матрица. После того, как веса были обновлены и сохранены и temp
матрицу заменяем оригиналом theta
от temp
, Мы повторяем этот процесс iters
количество раз
Если ты вместо этого пишешь как ((alpha / len(X)) * np.sum(term))
напиши как (alpha * (np.sum(term) / len(X)))
, что вам разрешено делать, так как умножение и деление являются коммутативными (если я правильно помню термин), то вы просто умножаете альфа на среднюю ошибку, так как термин в любом случае равен длине X.
Это означает, что вы вычитаете среднюю ошибку скорости обучения (альфа), которая будет выглядеть примерно так: X[j] * tetha (фактическая) - y (идеальная), которая, кстати, также достаточно близка к производной от (X*tetha - y).) ^2