使用Python / Numpy的dlib SVM的最小示例

时间:2017-10-18 09:53:32

标签: python numpy machine-learning svm dlib

我需要在C ++构建目标系统中部署SVM。因此,我想使用dlib和python / numpy训练SVM,将其序列化并在目标系统中进行评估。

dlib的python文档对我来说相当模糊,所以任何人都可以帮我解决这个最小的例子吗?

import dlib

# My data in numpy
feature_column_1 = np.array([-1, -2, -3, 1, 2, 3])
feature_column_2 = np.array([1, 2, 3, -1, -2, -3])
labels = np.array([True, True, True, False, False, False])

# Features
feature_vectors = dlib.vectors()
for feature_column in [feature_column_1, feature_column_2]:
    feature_vectors.append(dlib.vector(feature_column.tolist()))

# Labels
labels_array = dlib.array(labels.tolist())

# Train
svm = dlib.svm_c_trainer_linear()
svm.train(feature_vectors, labels_array)

# Test
y_probibilities = svm.predict(labels_array_new)

我收到了以下关于培训的错误:

---> 18 svm.train(vectors, array)

ValueError: Invalid inputs

3 个答案:

答案 0 :(得分:3)

我刚刚为dlib添加了一个官方示例。当我看时,我很惊讶地发现它没有被包括在内。它可以在这里找到:https://github.com/davisking/dlib/blob/master/python_examples/svm_binary_classifier.py。以下是相关细节:

import dlib
import pickle    

x = dlib.vectors()
y = dlib.array()

# Make a training dataset.  Here we have just two training examples.  Normally
# you would use a much larger training dataset, but for the purpose of example
# this is plenty.  For binary classification, the y labels should all be either +1 or -1.
x.append(dlib.vector([1, 2, 3, -1, -2, -3]))
y.append(+1)

x.append(dlib.vector([-1, -2, -3, 1, 2, 3]))
y.append(-1)


# Now make a training object.  This object is responsible for turning a
# training dataset into a prediction model.  This one here is a SVM trainer
# that uses a linear kernel.  If you wanted to use a RBF kernel or histogram
# intersection kernel you could change it to one of these lines:
#  svm = dlib.svm_c_trainer_histogram_intersection()
#  svm = dlib.svm_c_trainer_radial_basis()
svm = dlib.svm_c_trainer_linear()
svm.be_verbose()
svm.set_c(10)

# Now train the model.  The return value is the trained model capable of making predictions.
classifier = svm.train(x, y)

# Now run the model on our data and look at the results.
print("prediction for first sample:  {}".format(classifier(x[0])))
print("prediction for second sample: {}".format(classifier(x[1])))


# classifier models can also be pickled in the same was as any other python object.
with open('saved_model.pickle', 'wb') as handle:
    pickle.dump(classifier, handle)

但是,如果你想使用C ++,你应该只使用C ++。 Dlib主要是一个C ++库而不是python库。 dlib的重点是为想要进行机器学习的人提供一个很好的C ++ API。所以你最好只使用C ++进行培训。 dlib和完整的C ++ API文档附带了99个完整的C ++示例。例如,这是一个相关示例http://dlib.net/svm_c_ex.cpp.html

我真的应该强调dlib的C ++ API比python API更灵活。实际上,dlib的目的是在C ++中简化机器学习,dlib的python API是事后的想法。实际上,dlib的许多功能都是用C ++模板表达的,这些模板在Python中没有可能的相关性(例如,因为python没有像C ++模板那样),因此这些功能不会暴露给python。所以,如果你想使用C ++,那么使用C ++。 如果您知道如何编写C ++ ,则没有理由使用Python API。

答案 1 :(得分:2)

不是一个完整的答案,而是一些评论:

(1)

您观察到的错误至少部分是由于支票here

    for (long r = 0; r < x_labels.nr(); ++r)
    {
        if (x_labels(r) != -1 && x_labels(r) != 1)
            return false;

表示: labels = np.array([True, True, True, False, False, False])错误,而labels = np.array([1, 1, 1, -1, -1, -1])是正确的。

(2)

通常,在大多数MLlib中,数据格式为(n_samples,n_features),其中行是观察值。

打印出你的特征向量时,这看起来是正确的,你的代码,在更改(1)之后仍然会抛出相同的错误,除非你把它当作另一种方式处理:所以另一个解释是:你有2个样本,每个6个特征。使用这个假设,y需要有2个值。 Etvoilà......至少是训练!

没有抛出错误的代码(我忽略了它真正在做的事情)

import dlib
import numpy as np

# My data in numpy
feature_column_1 = np.array([-1, -2, -3, 1, 2, 3])
feature_column_2 = np.array([1, 2, 3, -1, -2, -3])
labels = np.array([-1, 1])  # +1/-1 & size == 2

# Features
feature_vectors = dlib.vectors()
for feature_column in [feature_column_1, feature_column_2]:
    feature_vectors.append(dlib.vector(feature_column.tolist()))

# Labels
labels_array = dlib.array(labels.tolist())

# Train
svm = dlib.svm_c_trainer_linear()
svm.be_verbose = 10

svm.train(feature_vectors, labels_array)
print('k')

(3)

dlib的python-API没有predict()函数。 C ++ - API有一些用于预测的learned_function属性,但thisthis表示你必须自己做(可能使用c_class1和co。因为我无法映射其他任何可用于API-doc候选人的东西。)

编辑:我错误的预测,正如dlib的维护者/开发人员在评论中提到的那样!

我真的不喜欢这个状态,会用别的东西! (或改进dlib)

不确定如何解释您的环境限制,但是:

  • libsvm / liblinear对于像这样的任务仍然是最先进的,它们是用来自C ++的构建的!
  • 到目前为止,
  • sklearn是从python(内部使用上面的库)执行此操作的最佳方式。

答案 2 :(得分:0)

当我将for循环更改为此时(我没有dlib):

for feature_column in [feature_column_1, feature_column_2]:
    print(feature_column.tolist())

我得到了这个结果

[-1, -2, -3, 1, 2, 3]
[1, 2, 3, -1, -2, -3]

我认为您的数据应如下所示:

[-1, 1]
[-2, 2]
[-2, 2]
[1, -1]
[2, -2]
[3, -3]

使用这段代码可以得到什么:

features = [[-1,1],[-2,2],[-2,2],[1,-1],[2,-2],[3,-3]]
for feature in features:
    feature_vectors.append(dlib.vector(feature_column.tolist()))