Python KNeighborsClassifier是否比较不同大小的列表?
我必须使用Scikit Lean的KNeighborsClassifier,使用Python中的用户定义函数来比较时间序列Python KNeighborsClassifier是否比较不同大小的列表?,python,machine-learning,time-series,scikit-learn,knn,Python,Machine Learning,Time Series,Scikit Learn,Knn,我必须使用Scikit Lean的KNeighborsClassifier,使用Python中的用户定义函数来比较时间序列 knn = KNeighborsClassifier(n_neighbors=1,weights='distance',metric='pyfunc',func=dtw_dist) 问题是Kneighbors分类器似乎不支持我的训练数据。它们是时间序列,所以它们是大小不同的列表。当我尝试使用fit方法(knn.fit(X,Y))时,KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=1,weights='distance',metric='pyfunc',func=dtw_dist)
问题是Kneighbors分类器似乎不支持我的训练数据。它们是时间序列,所以它们是大小不同的列表。当我尝试使用fit
方法(knn.fit(X,Y)
)时,KNeighborsClassifier会给我此错误消息:
似乎KNeighborsClassifier只支持相同大小的训练集(只接受具有相同长度的时间序列,但这不是我的情况),但我的老师告诉我使用KNeighborsClassifier。所以我不知道该怎么办
有什么想法吗?据我所知,有两个(或一个…)选项:
NaN
s将数据转换为正方形,并在自定义距离函数中相应地处理这些数据NaN
s“平方”数据
因此,选择2是正确的。
假设我们有以下数据,其中每一行代表一个时间序列:
import numpy as np
series = [
[1,2,3,4],
[1,2,3],
[1],
[1,2,3,4,5,6,7,8]
]
我们只需通过添加NAN使数据成为方形:
def make_square(jagged):
# Careful: this mutates the series list of list
max_cols = max(map(len, jagged))
for row in jagged:
row.extend([None] * (max_cols - len(row)))
return np.array(jagged, dtype=np.float)
make_square(series)
array([[ 1., 2., 3., 4., nan, nan, nan, nan],
[ 1., 2., 3., nan, nan, nan, nan, nan],
[ 1., nan, nan, nan, nan, nan, nan, nan],
[ 1., 2., 3., 4., 5., 6., 7., 8.]])
现在数据“适合”算法。您只需调整距离函数以考虑NaN
s
预计算并使用缓存函数
哦,我们可能也可以做选项1(假设您有N
时间序列):
(N,N)
距离矩阵D
[0,N)
之间的(N,1)
矩阵(即距离矩阵中序列的索引)wrapper
包装器
作为距离函数包装器
函数:
def wrapper(row1, row2):
# might have to fiddle a bit here, but i think this retrieves the indices.
i1, i2 = row1[0], row2[0]
return D[i1, i2]
好的,我希望它清楚
完整示例
你能用失败的随机数据写一个例子吗?哪一个可以复制和粘贴?否则你的问题就不够清楚了。你说的“相同大小的训练集”是什么意思?每个样本都是不同长度的时间序列?这很容易出错,但由于我不知道knn的内部结构,因此有可能使用自定义距离函数来恢复这种情况。@Eikenberg一个例子可能是当用户41047告诉我使用NaNs时,他使用的时间序列。是的,我的时间序列与ea的长度不同ch other.问题是我已经在使用一个自定义距离函数(dtw_dist)。该函数支持不同长度的列表,但KNN甚至不能使用它。我想的更多的是一个示例,它是复制+粘贴的,包含虚假数据,如@user41047的答案,以及一个虚假的距离函数(或您真正的
dtw_dist
),它将无法给出与您收到的相同的错误消息。@eickenberg,无论我使用的是标准函数还是我的dtw_dist。如果我使用@user41047示例或任何其他列表长度不同的示例,我都会收到此错误消息。如果我使用类似于series=[[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]的东西,一切都会正常工作
或系列=[[1,2,3],[2,3,4],[3,4,5],[4,5,6]]
。我希望这一次我能说清楚。我理解你的问题。如果你提供了一个独立的代码块,它会中断,那么平均来说,可能会有更多的人倾向于尝试一下,也许会想出一些有趣的方法来解决你的问题。现在看来,这似乎是答案下面的注释看起来像一条路径。填充NaN是一个非常糟糕的主意,因为大多数scikit学习估计器都会被NaN阻塞。(也就是说,填充一个神奇的值是正确的方法。-1可能是一个选项。)@user41047当你告诉我预计算并使用缓存函数时,你是想说我应该更改“权重”或“度量”吗paramether?当我说我将“metrics”设置为“pyfunc”并将“function”设置为“dtw_dist”时,我已经使用了一个自定义函数。dtw_dist支持不同长度的列表,但KNeighborsClassifier给出了同样的错误…@larsmans我将尝试使用-1作为一个神奇的值。让我们看看它是否有效。您应该使用dtw_dist
来创建(N,N)
距离矩阵D
。然后创建另一个矩阵(N,1)
只包含索引值。这个新矩阵现在是fit方法的X
。传递给KNN
的距离函数应该是提供的包装器,而不是dtw\u dist
。使用-1
作为魔术值可能更容易。
def wrapper(row1, row2):
# might have to fiddle a bit here, but i think this retrieves the indices.
i1, i2 = row1[0], row2[0]
return D[i1, i2]
#!/usr/bin/env python2.7
# encoding: utf-8
'''
'''
from mlpy import dtw_std # I dont know if you are using this one: it doesnt matter.
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
# Example data
series = [
[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3],
[1],
[1, 2, 3, 4, 5, 6, 7, 8],
[1, 2, 5, 6, 7, 8],
[1, 2, 4, 5, 6, 7, 8],
]
# I dont know.. these seemed to make sense to me!
y = np.array([
0,
0,
0,
0,
1,
2,
2,
2
])
# Compute the distance matrix
N = len(series)
D = np.zeros((N, N))
for i in range(N):
for j in range(i+1, N):
D[i, j] = dtw_std(series[i], series[j])
D[j, i] = D[i, j]
print D
# Create the fake data matrix: just the indices of the timeseries
X = np.arange(N).reshape((N, 1))
# Create the wrapper function that returns the correct distance
def wrapper(row1, row2):
# cast to int to prevent warnings: sklearn converts our integer indices to floats.
i1, i2 = int(row1[0]), int(row2[0])
return D[i1, i2]
# Only the ball_tree algorith seems to accept a custom function
knn = KNeighborsClassifier(weights='distance', algorithm='ball_tree', metric='pyfunc', func=wrapper)
knn.fit(X, y)
print knn.kneighbors(X[0])
# (array([[ 0., 0., 0., 1., 6.]]), array([[1, 2, 0, 3, 4]]))
print knn.kneighbors(X[0])
# (array([[ 0., 0., 0., 1., 6.]]), array([[1, 2, 0, 3, 4]]))
print knn.predict(X)
# [0 0 0 0 1 2 2 2]