ssi*_*ral 4 python string svm scikit-learn
我正在尝试生成一个字符串内核,用于提供支持向量分类器。我用一个计算内核的函数尝试了它,类似的东西
def stringkernel(K, G):
for a in range(len(K)):
for b in range(len(G)):
R[a][b] = scipy.exp(editdistance(K[a] , G[b]) ** 2)
return R
Run Code Online (Sandbox Code Playgroud)
当我将它作为参数传递给 SVC 时,我得到
clf = svm.SVC(kernel = my_kernel)
clf.fit(data, target)
ValueError: could not convert string to float: photography
Run Code Online (Sandbox Code Playgroud)
其中我的数据是一个字符串列表,目标是这个字符串所属的通信类。我已经回顾了 stackoverflow 中关于这个问题的一些问题,但我认为词袋表示不适合这种情况。
这是 scikit-learn 中的一个限制,已被证明很难摆脱。您可以尝试此解决方法。仅用一个特征表示特征向量中的字符串,这实际上只是字符串表中的一个索引。
>>> data = ["foo", "bar", "baz"]
>>> X = np.arange(len(data)).reshape(-1, 1)
>>> X
array([[0],
[1],
[2]])
Run Code Online (Sandbox Code Playgroud)
重新定义字符串核函数以处理此表示:
>>> def string_kernel(X, Y):
... R = np.zeros((len(x), len(y)))
... for x in X:
... for y in Y:
... i = int(x[0])
... j = int(y[0])
... # simplest kernel ever
... R[i, j] = data[i][0] == data[j][0]
... return R
...
>>> clf = SVC(kernel=string_kernel)
>>> clf.fit(X, ['no', 'yes', 'yes'])
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0,
kernel=<function string_kernel at 0x7f5988f0bde8>, max_iter=-1,
probability=False, random_state=None, shrinking=True, tol=0.001,
verbose=False)
Run Code Online (Sandbox Code Playgroud)
这样做的缺点是要对新样本进行分类,您必须将它们添加到data
,然后为它们构建新的伪特征向量。
>>> data.extend(["bla", "fool"])
>>> clf.predict([[3], [4]])
array(['yes', 'no'],
dtype='|S3')
Run Code Online (Sandbox Code Playgroud)
(您可以通过对伪特征进行更多解释来解决这个问题,例如,查看 的不同表i >= len(X_train)
。但它仍然很麻烦。)
这是一个丑陋的黑客,但它有效(对于聚类来说它稍微不那么丑陋,因为在 之后数据集不会改变fit
)。我代表 scikit-learn 开发人员说,欢迎使用补丁来正确修复此问题。