Линейная регрессия: Autograd не работает с типами данных Pandas? - PullRequest
0 голосов
/ 24 января 2019

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

Я перешел от циклов к NumPy, затем от вычисления градиента вручную до использования Autograd. Сейчас я пытаюсь преобразовать свой код для использования Pandas вместо NumPy. Но кажется, что Autograd не работает с DataFrame s или Series, потому что я продолжаю получать эту ошибку:

TypeError: Can't differentiate w.r.t. type <class 'pandas.core.series.Series'>
# or DataFrame

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

Вот соответствующие части кода:

import autograd.numpy as np
import pandas as pd
from autograd import grad

raw_data = pd.read_csv('FiveCitiePMData/BeijingPM20100101_20151231.csv')
df = raw_data.filter(['HUMI','TEMP', 'PM_US Post'], axis=1).dropna()

class LinRegModel:
    def __init__(self, dataset):
        self.X = dataset.iloc[:,:-1].copy()  # all but last column
        self.X.insert(0, 'dummy', 1)         # padding (w_0)
        self.y = dataset.iloc[:,-1].copy()   # last column

    def __cost__(self, weights):
        errors = self.X @ weights - self.y
        return np.square(errors).mean() # no need to div by 2 because autodiff

    def train(self, epsilon=0.001, learning_rate=0.01):
        self.weights = pd.Series(0.0, index=list(self.X)) # np.zeros((self.X.shape[1], 1))
        grad_cost = grad(self.__cost__)
        last_cost = 0
        while True:
            self.weights -= learning_rate * grad_cost(self.weights)
            this_cost = self.__cost__(self.weights)
            if abs(this_cost - last_cost) < epsilon:
                break
            last_cost = this_cost

lrm = LinRegModel(df)

Функция __cost__(weights) работает нормально, независимо от того, является ли weights массивом NumPy, Pandas Series или Pandas DataFrame. Но это даст мне ошибку выше:

grad_cost(self.weights)

Если я сделаю это:

grad_cost(np.array(self.weights))

Затем он зависает, и в конце концов я получаю это:

TypeError: Could not convert Autograd ArrayBox with value 523236993.0 to numeric

Единственный способ заставить его работать - это сделать:

def __cost__(self, weights):
        errors = np.array(self.X) @ np.array(weights) - np.array(self.y)
        return np.square(errors).mean()

grad_cost(np.array(self.weights))

Но это не очень элегантное или удобочитаемое решение.

Я что-то упускаю из-за Автограда или Панд?

...