python - español - ¿Cómo usar núcleos de cadena en scikit-learn?
scikit learn en python (2)
Creo que la biblioteca de shogun podría ser la solución, también es gratuita y de código abierto, sugiero que revisen este ejemplo: https://github.com/shogun-toolbox/shogun/tree/develop/src/shogun/kernel/string
Estoy intentando generar un núcleo de cadena que alimenta un clasificador de vector de soporte. Lo intenté con una función que calcula el núcleo, algo así
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
Y cuando lo paso a SVC como un parámetro consigo
clf = svm.SVC(kernel = my_kernel)
clf.fit(data, target)
ValueError: could not convert string to float: photography
donde mis datos son una lista de cadenas y el objetivo es la clase correspondiente a la que pertenece esta cadena. He revisado algunas preguntas en stackoverflow sobre este tema, pero creo que las representaciones de Bag-of-words no son apropiadas para este caso.
Esta es una limitación en scikit-learn que ha demostrado ser difícil de eliminar. Puedes probar esta solución . Represente las cadenas en vectores de características con una sola característica, que en realidad es solo un índice en la tabla de cadenas.
>>> data = ["foo", "bar", "baz"]
>>> X = np.arange(len(data)).reshape(-1, 1)
>>> X
array([[0],
[1],
[2]])
Redefina la función de núcleo de cadena para trabajar en esta representación:
>>> 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)
La desventaja de esto es que para clasificar nuevas muestras, debes agregarlas a los data
y luego construir nuevos vectores de pseudo-características para ellos.
>>> data.extend(["bla", "fool"])
>>> clf.predict([[3], [4]])
array([''yes'', ''no''],
dtype=''|S3'')
(Puede evitar esto haciendo más interpretaciones de sus pseudo-características, por ejemplo, buscando en una tabla diferente para i >= len(X_train)
. Pero sigue siendo engorroso).
Este es un truco feo, pero funciona (es un poco menos feo para la agrupación porque allí el conjunto de datos no cambia después del fit
). Hablando en nombre de los desarrolladores de scikit-learn, les digo que un parche para arreglar esto correctamente es bienvenido.