Стохастический градиентный спуск для линейной регрессии на частных производных - PullRequest
0 голосов
/ 14 мая 2018

Я реализую стохастический градиентный спуск для линейной регрессии вручную, учитывая частные производные (df / dm) и (df / db)

Цель состоит в том, чтобы мы случайным образом выбрали w0 (веса), а затемсходятсяПоскольку это стохастик, мы должны брать выборку набора данных при каждом прогоне

Первоначально скорость обучения должна составлять 1, а после каждого прогона она должна уменьшаться на 2, поэтому, когда wK + 1 равна wK (k = 1,2,3, ......) тогда цикл должен остановиться

Это реализовано в наборе данных Бостона в Sklearn

Поскольку я новичок в Python не сделалИспользуйте функции Ниже приведен код:

r= 1
m_deriv = 0
b_deriv = 0
learning_rate = 1
it = 1
w0_random = np.random.rand(13)
w0 = np.asmatrix(w0_random).T
b = np.random.rand()
b0 = np.random.rand()
while True:
    df_sample = bos.sample(100)

    price = df_sample['price']

    price = np.asmatrix(price)

    xi = np.asmatrix(df_sample.drop('price',axis=1))

    N = len(xi)

    for i in range(N):
   # -2x * (y-(mx +b))     
        m_deriv += np.dot(-2*xi[i].T , (price[:,i] - np.dot(xi[i] , w0_random) + b))

    # -2(y - (mx + b))
        b_deriv += -2*(price[:,i] - (np.dot(xi[i] , w0_random) + b))

    w0_new = m_deriv * learning_rate
    b0_new = b_deriv * learning_rate
    w1 = w0 - w0_new
    b1 = b0 - b0_new

    it += 1
    if (w0==w1).all():
        break
    else:
        w0 = w1
        b0 = b1
        learning_rate = learning_rate/2

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

Ответы [ 2 ]

0 голосов
/ 02 сентября 2018

В приведенном выше примере использование StandardScaler перед обработкой на xi дает хорошие результаты и использование w1 вместо w0_random.

from sklearn.preprocessing import StandardScaler
import numpy as np
bos['PRICE'] = boston.target
X = bos.drop('PRICE', axis = 1)
Y = bos['PRICE']
df_sample =X[:100]
price =Y[:100]
xi_1=[]
price_1=[]
N = len(df_sample)
for j in range(N):
    scaler = StandardScaler()
    scaler.fit(df_sample) 
    xtrs = scaler.transform(df_sample)
    xi_1.append(xtrs)
    yi=np.asmatrix(price)
    price_1.append(yi)
#print(price_1)
#print(xi_1)
xi=xi_1   
price=price_1
r= 1
m_deriv = 0
b_deriv = 0
learning_rate = 1
it = 1
w0_random = np.random.rand(13)
w0 = np.asmatrix(w0_random).T
b = np.random.rand()
b0 = np.random.rand() 
while True:
   for i in range(N):
       # -2x * (y-(mx +b))
       w1=w0
       b1=b0
       m_deriv = np.dot(-2*xi[i].T , (price[i] - np.dot(xi[i] , w1) + b1))
       # -2(y - (mx + b))
       b_deriv = -2*(price[i] - (np.dot(xi[i] , w1) + b1))
   w0_new = m_deriv * learning_rate
   b0_new = b_deriv * learning_rate
   w1 = w0 - w0_new
   b1 = b0 - b0_new
   it += 1
   if (w0==w1).all():
       break
   else:
       w0 = w1
       b0 = b1
       learning_rate = learning_rate/2
print("m_deriv=",m_deriv)
print("b_driv",b_deriv) 

0 голосов
/ 14 мая 2018

Вы не обновляете коэффициенты w после каждой итерации. В вашем внутреннем цикле вы всегда используете w0_random, в то время как вы должны использовать обновленные веса w1 в вашем случае. Вам нужно будет хранить обновленные значения w1 после каждой итерации таким образом, чтобы их можно было использовать на следующей итерации для вычисления производных.

Я бы также предложил нормализовать ваши данные, чтобы иметь mean=0 и std=1, чтобы вы избегали больших чисел.

Алгоритм сходится главным образом потому, что скорость обучения становится очень маленькой после некоторых итераций и, следовательно, w1==w0-learing_rate*diff*derivative по умолчанию. Он не сходится, потому что нашел решение в его нынешнем виде.

...