Как добавить прогноз к полиномиальной регрессии - PullRequest
1 голос
/ 19 апреля 2019

Можно ли добавить функцию типа предиката из библиотеки Склина? И как это сделать?

def monomial(a,b):
    return lambda x : a * math.pow(x,b)

Возвращает список мономов, образующих полином желаемого порядка

def polyList(order):
    return [monomial(1,i) for i in range(0,order+1)]

Возвращает сумму функций для данного входа

def evaluate(functionList, x):
    return sum([f(x) for f in functionList])

Возвращает взвешенную сумму, т.е. w0f0 + w1f1 + ...

def weightedSum(w,F):
    if(len(w) != len(F)):
        raise Exception("Function/weight size mismatch")
    else:
        return lambda x:sum([w[i]*F[i](x) for i in range(0,len(w))])
############

Здесь мы подгоняем полином данного порядка с оценками максимального правдоподобия для весов.

def polyTrain(x,y,order): 
    #Initialize the weight vector and design matrix
    w = [1 for i in range(0,order)]
    F = polyList(order)
    design = [[f(i) for f in F] for i in x]
    #Convert them to numpy arrays
    w = numpy.asarray(w)
    design = numpy.asarray(design)
    #We solve Ax=b, [x values x 3][coefficients]T = [yvalues]
    pinv = numpy.linalg.pinv(design)
    t = numpy.asarray(y).T
    #We know that the ML estimates for w are w* = pinv(design)y.T
    w = numpy.dot(pinv,t)
    return weightedSum(w,F)

1 Ответ

2 голосов
/ 19 апреля 2019

Было бы лучше, если бы вы определили класс, который будет обрабатывать всю необходимую логику. Тем не менее, если вы хотите для написания кода, полностью совместимого с протоколом fit-transform-предсказывать, который используется в scikit-learn, вам нужно подкласс от некоторой базы классы scikit-learn, например BaseEstimator, TransformerMixin, BaseRegressor.

Numpy поставляется с очень удобной функцией Вандер , которая может существенно помочь вам когда вы работаете с полиномами.

Позволяет определить класс.

class PolyRegressor:  # I omit subclassing for now. 

    def __init__(self, weights=None):
        self.weights = np.array(weights) if weights is not None else None

    @property
    def order(self):
        return len(self.weights) if self.weights is not None else 0

    def evaluate(self, x):
        return np.dot(np.vander(x, self.order), self.weights[:, np.newaxis]).ravel()

    def fit(self, X, y=None):
        self.weights = (np.linalg.pinv(np.vander(X, self.order)) @ y[:, np.newaxis]).ravel()

    def predict(self, X):
        if self.weights is not None: 
            return self.evaluate(X)
        else:
            raise Exception("Model wasn't fitted. Fit model first. ")

    def fit_predict(self, X, y=None):
        self.fit(X, y)
        return self.predict(X)


reg = PolyRegressor()

reg.weights = np.array([1,2,3])  # we implicitly define order = 2 here, e.g. 3 + 2x + 1x^2

reg.evaluate(np.array([5])) # testing

массив ([38]) # вывод

reg.fit_predict(np.random.rand(10), np.random.rand(10) * 5)

массив ([2.55922997, 1.81433623, 2.29153779, 1.78458414, 1.75961514, 2.59770317, 2.65122647, 1.81313616, 2.61993941, 2.63325695])

Принять код для ваших нужд. Надеюсь, это поможет ...

...