Liblinear usage format

529 views Asked by At

I am using .NET implementation of liblinear in my C# code by the following nuget package: https://www.nuget.org/packages/Liblinear/

But in the readme file of liblinear, the format for x is:

struct problem describes the problem:

    struct problem
    {
        int l, n;
        int *y;
        struct feature_node **x;
        double bias;
    };

where `l` is the number of training data. If bias >= 0, we assume
that one additional feature is added to the end of each data
instance. `n` is the number of feature (including the bias feature
if bias >= 0). `y` is an array containing the target values. (integers
in classification, real numbers in regression) And `x` is an array
of pointers, each of which points to a sparse representation (array
of feature_node) of one training vector.

For example, if we have the following training data:

    LABEL       ATTR1   ATTR2   ATTR3   ATTR4   ATTR5
    -----       -----   -----   -----   -----   -----
    1           0       0.1     0.2     0       0
    2           0       0.1     0.3    -1.2     0
    1           0.4     0       0       0       0
    2           0       0.1     0       1.4     0.5
    3          -0.1    -0.2     0.1     1.1     0.1

and bias = 1, then the components of problem are:

    l = 5
    n = 6

    y -> 1 2 1 2 3

    x -> [ ] -> (2,0.1) (3,0.2) (6,1) (-1,?)
         [ ] -> (2,0.1) (3,0.3) (4,-1.2) (6,1) (-1,?)
         [ ] -> (1,0.4) (6,1) (-1,?)
         [ ] -> (2,0.1) (4,1.4) (5,0.5) (6,1) (-1,?)
         [ ] -> (1,-0.1) (2,-0.2) (3,0.1) (4,1.1) (5,0.1) (6,1) (-1,?)

But, in the example showing java implementation: https://gist.github.com/hodzanassredin/6682771

problem.x <- [|
                        [|new FeatureNode(1,0.); new FeatureNode(2,1.)|]
                        [|new FeatureNode(1,2.); new FeatureNode(2,0.)|]
                    |]// feature nodes
problem.y <- [|1.;2.|] // target values

which means his data set is:

1 0 1
2 2 0

So, he is not storing the nodes as per sparse format of liblinear. Does, anyone know of correct format for x for liblinear implementation?

1

There are 1 answers

0
Cesar On

Though it doesn't address exactly the library you mentioned, I can offer you an alternative. The Accord.NET Framework has recently incorporated all of LIBLINEAR's algorithms in its machine learning namespaces. It is also available through NuGet.

In this library, the direct syntax to create a linear support vector machine from in-memory data is

// Create a simple binary AND
// classification problem:

double[][] problem =
{
    //             a    b    a + b
    new double[] { 0,   0,     0    },
    new double[] { 0,   1,     0    },
    new double[] { 1,   0,     0    },
    new double[] { 1,   1,     1    },
};

// Get the two first columns as the problem
// inputs and the last column as the output

// input columns
double[][] inputs = problem.GetColumns(0, 1);

// output column
int[] outputs = problem.GetColumn(2).ToInt32();

// However, SVMs expect the output value to be
// either -1 or +1. As such, we have to convert
// it so the vector contains { -1, -1, -1, +1 }:
//
outputs = outputs.Apply(x => x == 0 ? -1 : 1);

After the problem is created, one can learn a linear SVM using

// Create a new linear-SVM for two inputs (a and b)
SupportVectorMachine svm = new SupportVectorMachine(inputs: 2);

// Create a L2-regularized L2-loss support vector classification
var teacher = new LinearDualCoordinateDescent(svm, inputs, outputs)
{
    Loss = Loss.L2,
    Complexity = 1000,
    Tolerance = 1e-5
};

// Learn the machine
double error = teacher.Run(computeError: true);

// Compute the machine's answers for the learned inputs
int[] answers = inputs.Apply(x => Math.Sign(svm.Compute(x)));

This assumes, however, that your data is already in-memory. If you wish to load your data from the disk, from a file in libsvm sparse format, you can use the framework's SparseReader class. An example on how to use it can be found below:

// Suppose we are going to read a sparse sample file containing
//  samples which have an actual dimension of 4. Since the samples
//  are in a sparse format, each entry in the file will probably
//  have a much smaller number of elements.
// 
int sampleSize = 4;

// Create a new Sparse Sample Reader to read any given file,
//  passing the correct dense sample size in the constructor
// 
SparseReader reader = new SparseReader(file, Encoding.Default, sampleSize);

// Declare a vector to obtain the label
//  of each of the samples in the file
// 
int[] labels = null;

// Declare a vector to obtain the description (or comments)
//  about each of the samples in the file, if present.
// 
string[] descriptions = null;

// Read the sparse samples and store them in a dense vector array
double[][] samples = reader.ReadToEnd(out labels, out descriptions);

Afterwards, one can use the samples and labels vectors as the inputs and outputs of the problem, respectively.

I hope it helps.

Disclaimer: I am the author of this library. I am answering this question in the sincere hope it can be useful for the OP, since not long ago I also faced the same problems. If a moderator thinks this looks like spam, feel free to delete. However, I am only posting this because I think it might help others. I even came across this question by mistake while searching for existing C# implementations of LIBSVM, not LIBLINEAR.