我正在尝试生成一个字符串内核,该内核为支持向量分类器提供支持。我尝试了一个计算内核的函数,类似于
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
当我把它作为参数传递给SVC时,我得到
clf = svm.SVC(kernel = my_kernel)
clf.fit(data, target)
ValueError: could not convert string to float: photography
其中,我的数据是字符串列表,目标是该字符串所属的对应类。我在stackoverflow中复习了一些关于这个问题的问题,但我认为Bag of words表示不适合这种情况。
这是scikit学习中的一个限制,很难消除。您可以尝试此解决方法。只使用一个特征来表示特征向量中的字符串,这实际上只是字符串表的索引。
>>> data = ["foo", "bar", "baz"]
>>> X = np.arange(len(data)).reshape(-1, 1)
>>> X
array([[0],
[1],
[2]])
重新定义字符串内核函数来处理这个表示:
>>> 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)
这样做的缺点是,要对新样本进行分类,必须将它们添加到data
中,然后为它们构建新的伪特征向量。
>>> data.extend(["bla", "fool"])
>>> clf.predict([[3], [4]])
array(['yes', 'no'],
dtype='|S3')
(你可以通过对你的伪特征进行更多的解释来解决这个问题,例如,为i >= len(X_train)
查找不同的表。但这仍然很麻烦。)
这是一个丑陋的破解,但它是有效的(它对集群来说稍微不那么丑陋,因为在fit
之后数据集不会改变)。我代表scikit学习开发人员说,欢迎使用一个补丁来正确修复这个问题。
我认为shogun库可能是解决方案,也是免费和开源的,我建议查看这个例子:https://github.com/shogun-toolbox/shogun/tree/develop/src/shogun/kernel/string