Базовый алгоритм градиентного спуска перебегает и не сходится в питоне - PullRequest
0 голосов
/ 06 мая 2019

Итак, я новичок в изучении ОД и использую градиентный спуск в качестве своего первого алгоритма, в котором я хотел бы научиться и хорошо учиться.Я написал свой первый код и искал в Интернете проблему, с которой столкнулся, но из-за недостатка конкретных знаний мне трудно понять, как мне поступить в диагностике своей проблемы.Мой градиент начинается с приближения к правильному ответу, и когда ошибка уменьшается в 8 раз, алгоритм теряет свое значение, и значение b начинает уменьшаться, а значение m выходит за целевое значение.Извините, если я сформулировал это странно, надеюсь, код поможет.

Я изучаю это из нескольких источников на YouTube и в Google.Я следил за математикой интеллекта Сираджа Равала на YouTube, я понял, как работает базовый алгоритм, но я решил использовать свой собственный подход, и, похоже, он работает не слишком хорошо.Я изо всех сил пытаюсь читать онлайн-ресурсы, поскольку я неопытен в том, что означает алгоритм и как он реализован в python.Я знаю, что эта проблема имеет отношение к обучению и тестированию, но я не знаю, где это применить.

def gradient_updater(error, mcurr, bcurr):

    for i in x:
        # gets the predicted y-value
        ypred = (mcurr * i) + bcurr
        # uses partial derivative formula to get new m and b
        new_m = -(2/N) * sum(x*(y - ypred))
        new_b = -(2/N) * sum(y - ypred)
    # applies the new b and m value
    mcurr = mcurr - (learning_rate * new_m)
    bcurr = bcurr - (learning_rate * new_b)
    return mcurr, bcurr

def run(iterations, initial_m, initial_b):

    current_m = initial_m
    current_b = initial_b
    for i in range(iterations):
        error = get_error(current_m, current_b)
        current_m, current_b = gradient_updater(error, current_m, current_b)
        print(current_m, current_b, error)

Я ожидал, что значения m и b сходятся к конкретному значению, это непроисходят и значения продолжают расти в противоположном направлении.

Ответы [ 2 ]

0 голосов
/ 06 мая 2019

Вот где я думаю, что ошибка в вашем коде лежит - вычисление градиента.Я полагаю, что ваша функция стоимости аналогична той, которая используется в https://ml -cheatsheet.readthedocs.io / en / latest / radius_descent.html .Чтобы решить градиент, вам нужно объединить эффекты всех частных производных.Однако в вашей реализации вы выполняете итерации в диапазоне x , не накапливая эффектов.Следовательно, ваши new_m и new_b рассчитываются только для окончательного срока, x (элементы, отмеченные 1 и 2 ниже).

Ваша реализация:

def gradient_updater(error, mcurr, bcurr):
    for i in x:
        # gets the predicted y-value
        ypred = (mcurr * i) + bcurr
        # uses partial derivative formula to get new m and b
        new_m = -(2/N) * sum(x*(y - ypred))    #-- 1 --
        new_b = -(2/N) * sum(y - ypred)    #-- 2 --
    # applies the new b and m value <-- Indent this block to place inside the for loop
    mcurr = mcurr - (learning_rate * new_m)
    bcurr = bcurr - (learning_rate * new_b)
    return mcurr, bcurr

Тем не менее, я думаю, что ваша реализация должна приближаться к математической формуле, если вы просто обновляете mcurr и bcurr на каждой итерации (см. Встроенный комментарий).Другая вещь, которую нужно сделать, это разделить sum(x*(y - ypred)) и sum(y - ypred) на N , а также в вычислениях new_m и new_b.

Примечание Поскольку я не знаю, какова ваша функция фактической стоимости, я просто хочу указать, что вы также используете постоянное значение y в своем коде.Скорее всего, это будет массив разных значений и будет вызван Y [i] и X [i] соответственно.

0 голосов
/ 06 мая 2019

Если я правильно понимаю ваш код, я думаю, что ваша проблема в том, что вы берете частную производную, чтобы получить свой новый уклон и перехватить только одну точку.Я не уверен, что именно некоторые из переменных в градиентном_датчике, поэтому я попытаюсь привести пример, который лучше объясняет концепцию:

Я не уверен, что мы рассчитываем оптимизацию таким же образомв моем коде b0 - это ваш «x» в y = mx + b, а b1 - ваш «b» в том же уравнении.Следующий код предназначен для вычисления общего b0_temp и b1_temp, которые будут разделены на размер пакета для представления новых b0 и b1, чтобы соответствовать вашему графику.

for i in range(len(X)):

    ERROR = ERROR + (b1*X[i] + b0 - Y[i])**2

    b1_temp = b1_temp + (1/2)*((1/len(X))*(b1*X[i] + b0 - Y[i])**2)**(-1/2) * (2/len(X))*(b1*X[i] + b0 - Y[i])*X[i]
    b0_temp = b0_temp + (1/2)*((1/len(X))*(b1*X[i] + b0 - Y[i])**2)**(-1/2) * (2/len(X))*(b1*X[i] + b0 - Y[i])

Я выполняю это для каждого значения в моем наборе данныхгде X[i] и Y[i] представляют отдельную точку данных.

Далее я настраиваю наклон, который в настоящее время соответствует графику:

        b1_temp = b1_temp / batch_size
        b0_temp = b0_temp / batch_size

        b0 = b0 - learning_rate * b0_temp
        b1 = b1 - learning_rate * b1_temp

        b1_temp = 0
        b0_temp = 0

Где batch_size можно просто принять за len(X).Я пробежался через это в течение некоторого количества эпох (то есть цикл for для некоторого числа, 100 должен работать), и линия наилучшего соответствия будет корректироваться со временем.Общая концепция заключается в том, чтобы уменьшить расстояние между каждой точкой и линией до ее минимума.

Надеюсь, я смог лучше вам это объяснить и предоставить вам базовую кодовую базу для корректировки вашихна!

...