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

enter image description here Я пробовал этот фрагмент кода для многопараметрической регрессии для нахождения коэффициентов, но не смог найти, где я делаю ошибку или я на правильном пути? Проблема в том, что значение mse не сходится.

здесь x1, x2, x3 - это 3 переменные объекта, которые у меня есть (я нарезал каждый столбец объектов на эти переменные x1, x2, x3)

def gradientDescent(x,y):
   mCurrent1=mCurrent2=mCurrent3=bCurrent=0
   iteration=1000
   learningRate=0.0000001
   n=len(x)


   for i in range(0,iteration):
       y_predict=mCurrent1*x1+mCurrent2*x2+mCurrent3*x3+bCurrent
       mse=(1/n)*np.sum([val**2 for val in (y-y_predict)])


       mPartDerivative1=-(2/n)*np.sum(x1*(y-y_predict))
       mPartDerivative2=-(2/n)*np.sum(x2*(y-y_predict))
       mPartDerivative3=-(2/n)*np.sum(x3*(y-y_predict))

       bPartDerivative=-(2/n)*np.sum(y-y_predict)

       mCurrent1=mCurrent1-(learningRate*mPartDerivative1)
       mCurrent2=mCurrent2-(learningRate*mPartDerivative2)
       mCurrent3=mCurrent3-(learningRate*mPartDerivative3)

       bCurrent=bCurrent-(learningRate*bPartDerivative)
       print('m1:{} m2:{} m3:{} b:{} iter:{} mse:{}'.format(mCurrent1,mCurrent2,mCurrent3,bCurrent,i,mse))

    return(round(mCurrent1,3),round(mCurrent2,3),round(mCurrent3,3),round(bCurrent,3))

1 Ответ

0 голосов
/ 24 января 2019

Похоже, ваша программа должна работать. Тем не менее, скорее всего, ваша скорость обучения слишком мала. Помните, что скорость обучения - это размер шага, на котором вы выполняете функцию затрат. Если скорость обучения слишком мала, она будет двигаться вниз по кривой затрат слишком медленно, и для достижения конвергенции потребуется много времени (требуя большого числа итераций). Однако, если скорость обучения слишком велика, у вас есть проблема расхождения. Выбор правильной скорости обучения и количества итераций (другими словами, настройка ваших гиперпараметров) - это больше искусство, чем наука. Вы должны играть с разными темпами обучения.

Я создал свой собственный набор данных и случайно сгенерированные данные (где (m1, m2, m3, b) = (10, 5, 4, 2)) и запустил ваш код:

import pandas as pd
import numpy as np

x1 = np.random.rand(100,1)
x2 = np.random.rand(100,1)
x3 = np.random.rand(100,1)
y = 2 + 10 * x1 + 5 * x2 + 4 * x3 + 2 * np.random.randn(100,1)
df = pd.DataFrame(np.c_[y,x1,x2,x3],columns=['y','x1','x2','x3'])

#df.head()
#            y        x1        x2        x3
# 0  11.970573  0.785165  0.012989  0.634274
# 1  19.980349  0.919672  0.971063  0.752341
# 2   2.884538  0.170164  0.991058  0.003270
# 3   8.437686  0.474261  0.326746  0.653011
# 4  14.026173  0.509091  0.921010  0.375524

Запуск вашего алгоритма со скоростью обучения 0.0000001 дает следующие результаты:

(m1, m2, m3, b) = (0.001, 0.001, 0.001, 0.002)

Запуск вашего алгоритма со скоростью обучения .1 дает следующие результаты:

(m1, m2, m3, b) = (9.382, 4.841, 4.117, 2.485)

Обратите внимание, что когда скорость обучения равна 0.0000001, ваши коэффициенты не слишком отличаются от того, с чего они начали (0). Как я уже говорил ранее, небольшая скорость обучения делает это таким образом, что мы изменяем коэффициенты с слишком малой скоростью, так как мы движемся вниз по функции стоимости при очень малых размерах шагов.

Я добавил картинку, чтобы помочь визуализировать выбор размера шага. Обратите внимание, что первая картинка использует небольшую скорость обучения, а вторая использует большую скорость обучения.

Небольшая скорость обучения: enter image description here

Большая скорость обучения: enter image description here

...