出于学习目的,我正在尝试从头开始进行线性回归(在代码和数学知识方面)。
我从循环转到NumPy,然后从手动计算梯度到使用Autograd。现在,我正在尝试将我的代码转换为使用Pandas而不是NumPy。但是似乎Autograd不适用于DataFrame
或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)
是NumPy数组,Pandas系列还是Pandas DataFrame,weights
函数都可以正常工作。但这会给我上面的错误:
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))
但这不是一个非常优雅或可读的解决方案。
我是否缺少有关Autograd或Pandas的东西?