2010-10-01 4 views
7

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

Вот пример, который я пытаюсь воспроизвести, у меня есть данные о домах с (жилой площади (в feet2), а также количество спален) с результирующей цена:

Жилая площадь (feet2): 2104

#bedrooms: 3

Цена (1000 $ ы): 400

Я пытаюсь сделать простой регрессии с помощью метода градиентного спуска, но мой алгоритм не будет работать. .. Форма алгоритма не является usi ng векторов (я пытаюсь понять это шаг за шагом).

i = 1 
import sys 
derror=sys.maxint 
error = 0 
step = 0.0001 
dthresh = 0.1 
import random 

theta1 = random.random() 
theta2 = random.random() 
theta0 = random.random() 
while derror>dthresh: 
    diff = 400 - theta0 - 2104 * theta1 - 3 * theta2 
    theta0 = theta0 + step * diff * 1 
    theta1 = theta1 + step * diff * 2104 
    theta2 = theta2 + step * diff * 3 
    hserror = diff**2/2 
    derror = abs(error - hserror) 
    error = hserror 
    print 'iteration : %d, error : %s' % (i, error) 
    i+=1 

Я понимаю математику, я построения функции предсказывая $$h_{\theta}(x) = \theta_0 + \theta_1 x_1 + \theta_2 x_2$$ http://mathurl.com/hoy7ege.png с $x_1$ http://mathurl.com/2ga69bb.png и $x_2$ http://mathurl.com/2cbdldp.png быть переменные (жилая площадь, количество спален) и $h_{\theta}(x)$ http://mathurl.com/jckw8ke.png расчетная цена.

Я использую функцию стоимости ($hserror$ http://mathurl.com/guuqjv5.png) (для одной точки): $$hserror = \frac{1}{2} (h_{\theta}(x) - y)^2$$ http://mathurl.com/hnrqtkf.png Это обычная проблема, но я больше инженера-программиста, и я учусь на один шаг за один раз, могу вы говорите мне, что случилось?

я получил его работы с этим кодом:

data = {(2104, 3) : 400, (1600,3) : 330, (2400, 3) : 369, (1416, 2) : 232, (3000, 4) : 540} 
for x in range(10): 
    i = 1 
    import sys 
    derror=sys.maxint 
    error = 0 
    step = 0.00000001 
    dthresh = 0.0000000001 
    import random 

    theta1 = random.random()*100 
    theta2 = random.random()*100 
    theta0 = random.random()*100 
    while derror>dthresh: 
     diff = 400 - (theta0 + 2104 * theta1 + 3 * theta2) 
     theta0 = theta0 + step * diff * 1 
     theta1 = theta1 + step * diff * 2104 
     theta2 = theta2 + step * diff * 3 
     hserror = diff**2/2 
     derror = abs(error - hserror) 
     error = hserror 
     #print 'iteration : %d, error : %s, derror : %s' % (i, error, derror) 
     i+=1 
    print ' theta0 : %f, theta1 : %f, theta2 : %f' % (theta0, theta1, theta2) 
    print ' done : %f' %(theta0 + 2104 * theta1 + 3*theta2) 

который заканчивается с ответами, как это:

theta0 : 48.412337, theta1 : 0.094492, theta2 : 50.925579 
done : 400.000043 
theta0 : 0.574007, theta1 : 0.185363, theta2 : 3.140553 
done : 400.000042 
theta0 : 28.588457, theta1 : 0.041746, theta2 : 94.525769 
done : 400.000043 
theta0 : 42.240593, theta1 : 0.096398, theta2 : 51.645989 
done : 400.000043 
theta0 : 98.452431, theta1 : 0.136432, theta2 : 4.831866 
done : 400.000043 
theta0 : 18.022160, theta1 : 0.148059, theta2 : 23.487524 
done : 400.000043 
theta0 : 39.461977, theta1 : 0.097899, theta2 : 51.519412 
done : 400.000042 
theta0 : 40.979868, theta1 : 0.040312, theta2 : 91.401406 
done : 400.000043 
theta0 : 15.466259, theta1 : 0.111276, theta2 : 50.136221 
done : 400.000043 
theta0 : 72.380926, theta1 : 0.013814, theta2 : 99.517853 
done : 400.000043 

ответ

8

Первый вопрос заключается в том, что работает это только одна часть данных дает вам недоопределенной система ... это означает, что она может иметь бесконечное количество решений. С тремя переменными вы ожидаете иметь как минимум 3 точки данных, предпочтительно намного выше.

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

Таким образом, для фиксированного размера шага из

theta0 = theta0 - step * dEdtheta0 
theta1 = theta1 - step * dEdtheta1 
theta2 = theta2 - step * dEdtheta2 

вы можете сделать это

n = max([ dEdtheta1, dEdtheta1, dEdtheta2 ])  
theta0 = theta0 - step * dEdtheta0/n 
theta1 = theta1 - step * dEdtheta1/n 
theta2 = theta2 - step * dEdtheta2/n 

это также выглядит, как вы, возможно, ошибка в знак ваших шагов.

Я также не уверен, что ужас - хороший критерий остановки. (Но критерии остановки, как известно, трудно получить «правильно»)

Мое последнее замечание состоит в том, что градиентный спуск ужасно медленный для установки параметров. Вероятно, вы захотите использовать методы сопряженного градиента или Levenberg-Marquadt.Я подозреваю, что оба эти метода уже существуют для python в пакетах numpy или scipy (которые по умолчанию не являются частью python, но довольно просты в установке)

+0

Благодарим вас за отличный ответ! Я знаю, что это не отличный подход к проблеме, я хотел попробовать сначала реализовать это простое решение, а затем использовать переменный шаг и попробовать «спуск градиента партии» и «стохастический градиентный спуск». –

+0

Чтобы быть уверенным, какое выражение вы используете для dEthetheta? –

+0

Я бы взял d = 400 - theta0 - 2104 * theta1 - 3 * theta2, E = d^2, dEthethe0 = 2 * d * (-1), dEthethe1 = 2 * d * (-2104), dEdtheta2 = 2 * д * (- 3). Что бы сделать знак в ваших исходных уравнениях правильным. Но если вы посмотрите на размер градиентов, они огромны по сравнению с масштабным коэффициентом 0.0001, а это означает, что вы в конечном итоге делаете шаги, которые слишком велики с вашей начальной точки. Нормализация градиента или ограничение ступенчатой ​​стороны каким-либо другим способом должна решить вашу проблему. –

Смежные вопросы