由于这是一个复杂的问题(至少对我来说),我会尽量简短。
我的数据采用格式
import pandas as pd
import numpy as np
# edit: a1 and a2 are linked as they are part of the same object
a1 = np.array([[1, 2, 3], [4, 5], [7, 8, 9, 10]])
a2 = np.array([[5, 6, 5], [2, 3], [3, 4, 8, 1]])
b = np.array([6, 15, 24])
y = np.array([0, 1, 1])
df = pd.DataFrame(dict(a1=a1.tolist(),a2=a2.tolist(), b=b, y=y))
a1 a2 b y
0 [1, 2, 3] [5, 6, 5] 6 0
1 [4, 5] [2, 3] 15 1
2 [7, 8, 9, 10] [3, 4, 8, 1] 24 1
我想在sklearn中使用它进行分类,例如
from sklearn import tree
X = df[['a1', 'a2', 'b']]
Y = df['y']
clf = tree.DecisionTreeClassifier()
clf = clf.fit(X, Y)
print(clf.predict([[2., 2.]]))
然而,尽管panda可以将列表作为条目处理,但sklearn在设计上却不能。在本例中,clf.fit
将导致ValueError: setting an array element with a sequence.
,您可以找到大量答案。
但是你如何处理这些数据
我试图将数据拆分为多列(即a1[0] ... a1[3]
——代码有点长),但a1[3]
将为空(NaN
、0
或您认为的任何无效值)。推测在这里没有意义,因为那里不应该有价值。
当然,这样的过程会对分类结果产生影响,因为算法可能会将"零"值视为有意义的。
如果数据集足够大,所以我认为,可能值得将其拆分为相等长度的a1
。但是这个过程可以降低分类算法的能力,因为a1
的长度可能有助于区分类。
我还考虑将warm start
用于支持的算法(例如Perceptron),并将其适合于按a1
长度划分的数据。但这肯定会失败,不是吗?数据集会有不同数量的特征,所以我认为会出问题。
这个问题的解决方案肯定存在,我只是没有在文档中找到正确的位置。
让我们假设这些数字是数字类别。您可以做的是将列"a"转换为一组二进制列,其中每个列都对应于一个可能的值"a"。
以你的代码为例,我们会:
import pandas as pd
import numpy as np
a = np.array([[1, 2, 3], [4, 5], [7, 8, 9, 10]])
b = np.array([6, 15, 24])
y = np.array([0, 1, 1])
df = pd.DataFrame(dict(a=a.tolist(),b=b,y=y))
from sklearn.preprocessing import MultiLabelBinarizer
MLB = MultiLabelBinarizer()
df_2 = pd.DataFrame(MLB.fit_transform(df['a']), columns=MLB.classes_)
df_2
1 2 3 4 5 7 8 9 10
0 1 1 1 0 0 0 0 0 0
1 0 0 0 1 1 0 0 0 0
2 0 0 0 0 0 1 1 1 1
然后,我们可以直接连接新旧数据:
new_df = pd.concat([df_2, df.drop('a',1)],1)
1 2 3 4 5 7 8 9 10 b y
0 1 1 1 0 0 0 0 0 0 6 0
1 0 0 0 1 1 0 0 0 0 15 1
2 0 0 0 0 0 1 1 1 1 24 1
请注意,如果你有一个训练集和一个测试集,那么明智的做法是先将它们连接起来,进行转换,然后再将它们分离。这是因为其中一个数据集可以包含不属于另一个的术语。
希望能帮助
编辑:
如果你担心这可能会使你的df太大,那么将PCA应用于二进制变量是完全可以的。它将减少基数,同时保持任意数量的方差/相关性。
Sklearn喜欢2d数组中的数据,即shape(batch_size,features)最简单的解决方案是通过使用numpy.contenate连接数组来准备一个特征向量。将此特征向量传递给sklearn。由于每列的长度都是固定的,所以这应该是可行的。