Использование градиентного спуска при линейной регрессии приводит к неправильному смещению

#python #machine-learning

#python #машинное обучение

Вопрос:

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

Я написал два фрагмента кода, gen_data который генерирует данные и GradientDescent который выполняет этот алгоритм градиентного спуска для определения веса и смещения.

 def gen_data(num_points=50, slope=1, bias=10, x_max=50):
    f = lambda z: slope * z   bias
    x = np.zeros(shape=(num_points, 1))
    y = np.zeros(shape=(num_points, 1))

    for i in range(num_points):
        x_temp = np.random.uniform()*x_max
        x[i] = x_temp
        y[i] = f(x_temp)   np.random.normal(scale=3.0)

    return (x, y)

# mathbb{R}^1 with no regularization
def gradientDescent2(x, y, learning_rate=0.0001, epochs=100):
    theta = np.random.rand()
    bias = np.random.rand()

    for i in range(0, epochs):
        loss = (theta * x   bias) - y
        cost = np.mean(loss**2) / 2
        # print('Iteration {} | Cost: {}'.format(i, cost))

        grad_b = np.mean(loss)
        grad_t = np.mean(loss*x)

        # updates
        bias -= learning_rate * grad_b
        theta -= learning_rate * grad_t

    return (theta, bias)
  

Ответ №1:

  1. Если вы хотите использовать пакетное обновление, не устанавливайте batch_size равным вашему простому размеру. (Я также считаю, что batch_update не очень подходит для этого случая.)

2. Ваш расчет градиента и обновление параметров неверны, градиент должен быть:

 grad_b =  1
grad_t =  x
  

Для обновления параметра вы всегда должны пытаться минимизировать loss , поэтому оно должно быть

 if loss>0:
  bias -= learning_rate * grad_b
  theta -= learning_rate * grad_t
elif loss< 0:
  bias  = learning_rate * grad_b
  theta  = learning_rate * grad_t
  

В конце концов, приведенный ниже модифицированный код работает хорошо.
импортируйте numpy как np
импортировать sys

 def gen_data(num_points=500, slope=1, bias=10, x_max=50):
    f = lambda z: slope * z   bias
    x = np.zeros(shape=(num_points))
    y = np.zeros(shape=(num_points))

    for i in range(num_points):
        x_temp = np.random.uniform()*x_max
        x[i] = x_temp
        y[i] = f(x_temp) #  np.random.normal(scale=3.0)
        #print('x:',x[i],'        y:',y[i])

    return (x, y)

def gradientDescent2(x, y, learning_rate=0.001, epochs=100):
    theta = np.random.rand()
    bias = np.random.rand()

    for i in range(0, epochs):
      for j in range(len(x)):
        loss = (theta * x[j]   bias) - y[j]
        cost = np.mean(loss**2) / 2
        # print('Iteration {} | Cost: {}'.format(i, cost))

        grad_b = 1
        grad_t = x[j]

        if loss>0:
            bias -= learning_rate * grad_b
            theta -= learning_rate * grad_t
        elif loss< 0:
            bias  = learning_rate * grad_b
            theta  = learning_rate * grad_t

    return (theta, bias)

def main():
    x,y =gen_data()
    ta,bias = gradientDescent2(x,y)
    print('theta:',ta)
    print('bias:',bias)

if __name__ == '__main__':
    sys.exit(int(main() or 0))
  

Комментарии:

1. grad_t = frac{частичная стоимость}{частичная тета} = frac{1}{n} потери times frac{частичная потеря}{partial theta} = frac{1}{n} потери в разы times x neq theta. Как вы вычисляли grad_t = theta ?

2. @Lukasz Очевидно, что градиент был неправильным, но просто пометить мой ответ как бесполезный — это не круто. Вторая часть моего ответа о потерях имеет смысл. Кроме того, я обновлю свой ответ.

3. Кстати, если вы хотите общаться с другими, пожалуйста, сначала сделайте свой комментарий читабельным.

4. хорошо, кто-нибудь может сказать мне, почему мой ответ бесполезен? Сначала спасибо.