Кривая фитинга с градиентным спуском - PullRequest
1 голос
/ 19 мая 2019

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

Я делаю одно из вычислений неправильно?Я на самом деле застрял в локальном минимуме или это что-то еще?

Вот мой код:

import numpy as np
import matplotlib.pyplot as plt

def estimate(weights, x, order):
    est = 0
    for i in range(order):
        est += weights[i] * x ** i
    return est

def cost_function(x, y, weights, m):
    cost = 0
    for i in range(m-1):
        cost += (((weights[i] * x ** i) - y) ** 2)
    return (np.sum(cost ** 2) / ( 2 * m ))

def descent(A, b, iterations, descent_rate, order):
    x = A.T[0]
    y = b.reshape(4)

    # features
    ones = np.vstack(np.ones(len(A)))
    x = np.vstack(A.T[0])
    x2 = np.vstack(A.T[0] ** 2)

    # Our feature matrix
    features = np.concatenate((ones,x,x2), axis = 1).T
    # Initialize our coefficients to zero
    weights = np.zeros(order + 1)
    m = len(y)

    # gradient descent
    for i in range(iterations):
        est = estimate(weights, x, order).T
        difference = est - y
        weights = weights + (-descent_rate * (1/m) * np.matmul(difference, features.T)[0])
        cost = cost_function(x, y, weights, m)
        print(cost)

    plt.scatter(x,y)
    u = np.linspace(0,3,100)
    plt.plot(u, (u ** 2) * weights[2] + u  * weights[1] + weights[0], '-')
    plt.show()

A = np.array(((0,1),
             (1,1),
             (2,1),
             (3,1)))

b = np.array((1,2,0,3), ndmin = 2 ).T

iterations = 150
descent_rate = 0.01
order = 2
descent(A, b, iterations, descent_rate, order)

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

Вот один из графиков, которые я получаю: enter image description here

А вот ожидаемый результат, полученный решением наименьших квадратов:

enter image description here

1 Ответ

1 голос
/ 19 мая 2019

Ваша estimate функция должна быть

def estimate(weights, x, order):
    est = 0
    for i in range(order+1):
        est += weights[i] * x ** i
    return est

Еще лучше, поскольку информация о заказе уже присутствует в размере вектора weights, удалите избыточность с помощью:

def estimate(weights, x):
    est = 0
    for i in range(len(weights)):
        est += weights[i] * x ** i
    return est

Вот что я получил при использовании вашего кода и выполнении 2000 итераций: enter image description here

...