KNN 回归:日期时间特征的距离函数和/或向量表示

数据挖掘 回归 特征工程 k-nn 距离
2021-09-16 18:18:05

背景:尝试使用日期时间特征和外生变量(如温度)来预测某种消耗值(如水)。

采用一些日期时间功能,例如工作日 ( mon=1, tue=2, ..., sun=7) 和月份 ( jan=1, ..., dec=12)。

一个天真的 KNN 回归器会判断周日和周一之间的距离是 6,十二月和一月之间的距离是 11,尽管在这两种情况下实际上都是 1。

hours = np.arange(1, 25)
days = np.arange(1, 8)
months = np.arange(1, 13)

days
>>> array([1, 2, 3, 4, 5, 6, 7])
type(days)
>>> numpy.ndarray

功能

自定义距离函数是可能的:

def distance(x, y, domain):
   direct = abs(x - y)
   round_trip = domain - direct
   return min(direct, round_trip)

导致:

# weeks
distance(x=1, y=7, domain=7)
>>> 1
distance(x=4, y=2, domain=7)
>>> 2

# months
distance(x=1, y=11, domain=12)
>>> 2
distance(x=1, y=3, domain=12)
>>> 2

但是,使用 Sci-Kit 的KNeighborsRegressor的自定义距离函数会使它变慢,我不想在其他功能上使用它本身。

坐标

我正在考虑的另一种方法是使用元组来表示向量空间中的坐标,就像我们在圆形时钟上表示一天中的小时一样。

def to_coordinates(domain):
    """ Projects a linear range on the unit circle, 
        by dividing the circumference (c) by the domain size,
        thus giving every point equal spacing.
    """
    # circumference
    c = np.pi * 2
    
    # equal spacing 
    a = c / max(domain)
    
    # array of x and y
    return np.sin(a*domain), np.cos(a*domain)

导致:

x, y = to_coordinates(days)

# figure
plt.figure(figsize=(8, 8), dpi=80)

# draw unit circle
t = np.linspace(0, np.pi*2, 100)
plt.plot(np.cos(t), np.sin(t), linewidth=1)

# add coordinates
plt.scatter(x, y);

线性域到单位圆坐标

显然,这让我在计算距离时得到了我正在寻找的对称性。

问题

现在我想不通的是:我可以使用什么数据类型来最好地表示这些向量,以便 knn 回归器自动计算距离?也许是一组元组;一个二维的numpy数组?

试图

一旦我尝试将坐标与其他变量混合,就会出现问题。目前,最直观的尝试引发了一个异常:

data = df.values

在哪里df
嵌套的 numpy 数组尝试

出于简单演示的目的,目标变量是分类域变量days

TypeError                                 Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
<ipython-input-112-a34d184ab644> in <module>
      1 neigh = KNeighborsClassifier(n_neighbors=3)
----> 2 neigh.fit(data, days)

ValueError: setting an array element with a sequence.

我只希望算法能够处理新的观察结果(coordinate代表星期几和temperature)并找到最接近的匹配项。我知道坐标当然是目标变量的直接表示,因此会泄露答案,但它是关于启用算法的数学运算。

先感谢您。

1个回答

我喜欢您转换为 2d(单位圆)的想法,2d numpy 数组将是这里的方法具体来说,如果您采用单位圆方法,请尝试将days_xanddays_y放入单独的列中。

另一种想法 - 看起来有一个“预先计算”的距离选项,它可以让你使用你“真正”想要的距离,并且不应该很慢,因为没有计算要做。