Градиентный спуск для линейной регрессии в коде 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

Другие вопросы по тегам