How to use the 'svm_toy' Applet example in LibSVM?
Asked Answered
N

1

9

I'm using LIBSVM. In the download package is a svm_toy.java file. I could not find out how it works. Here is the source code:

import libsvm.*;
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import java.io.*;

/**
 * SVM package 
 * @author unknown
 *
 */
public class svm_toy extends Applet {

    static final String DEFAULT_PARAM="-t 2 -c 100";
    int XLEN;
    int YLEN;

    // off-screen buffer

    Image buffer;
    Graphics buffer_gc;

    // pre-allocated colors

    final static Color colors[] =
    {
      new Color(0,0,0),
      new Color(0,120,120),
      new Color(120,120,0),
      new Color(120,0,120),
      new Color(0,200,200),
      new Color(200,200,0),
      new Color(200,0,200)
    };

    class point {
        point(double x, double y, byte value)
        {
            this.x = x;
            this.y = y;
            this.value = value;
        }
        double x, y;
        byte value;
    }

    Vector<point> point_list = new Vector<point>();
    byte current_value = 1;

    public void init()
    {
        setSize(getSize());

        final Button button_change = new Button("Change");
        Button button_run = new Button("Run");
        Button button_clear = new Button("Clear");
        Button button_save = new Button("Save");
        Button button_load = new Button("Load");
        final TextField input_line = new TextField(DEFAULT_PARAM);

        BorderLayout layout = new BorderLayout();
        this.setLayout(layout);

        Panel p = new Panel();
        GridBagLayout gridbag = new GridBagLayout();
        p.setLayout(gridbag);

        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1;
        c.gridwidth = 1;
        gridbag.setConstraints(button_change,c);
        gridbag.setConstraints(button_run,c);
        gridbag.setConstraints(button_clear,c);
        gridbag.setConstraints(button_save,c);
        gridbag.setConstraints(button_load,c);
        c.weightx = 5;
        c.gridwidth = 5;
        gridbag.setConstraints(input_line,c);

        button_change.setBackground(colors[current_value]);

        p.add(button_change);
        p.add(button_run);
        p.add(button_clear);
        p.add(button_save);
        p.add(button_load);
        p.add(input_line);
        this.add(p,BorderLayout.SOUTH);

        button_change.addActionListener(new ActionListener()
        { public void actionPerformed (ActionEvent e)
          { button_change_clicked(); button_change.setBackground(colors[current_value]); }});

        button_run.addActionListener(new ActionListener()
        { public void actionPerformed (ActionEvent e)
          { button_run_clicked(input_line.getText()); }});

        button_clear.addActionListener(new ActionListener()
        { public void actionPerformed (ActionEvent e)
          { button_clear_clicked(); }});

        button_save.addActionListener(new ActionListener()
        { public void actionPerformed (ActionEvent e)
          { button_save_clicked(input_line.getText()); }});

        button_load.addActionListener(new ActionListener()
        { public void actionPerformed (ActionEvent e)
          { button_load_clicked(); }});

        input_line.addActionListener(new ActionListener()
        { public void actionPerformed (ActionEvent e)
          { button_run_clicked(input_line.getText()); }});

        this.enableEvents(AWTEvent.MOUSE_EVENT_MASK);
    }

    void draw_point(point p)
    {
        Color c = colors[p.value+3];

        Graphics window_gc = getGraphics();
        buffer_gc.setColor(c);
        buffer_gc.fillRect((int)(p.x*XLEN),(int)(p.y*YLEN),4,4);
        window_gc.setColor(c);
        window_gc.fillRect((int)(p.x*XLEN),(int)(p.y*YLEN),4,4);
    }

    void clear_all()
    {
        point_list.removeAllElements();
        if(buffer != null)
        {
            buffer_gc.setColor(colors[0]);
            buffer_gc.fillRect(0,0,XLEN,YLEN);
        }
        repaint();
    }

    void draw_all_points()
    {
        int n = point_list.size();
        for(int i=0;i<n;i++)
            draw_point(point_list.elementAt(i));
    }

    void button_change_clicked()
    {
        ++current_value;
        if(current_value > 3) current_value = 1;
    }

    private static double atof(String s)
    {
        return Double.valueOf(s).doubleValue();
    }

    private static int atoi(String s)
    {
        return Integer.parseInt(s);
    }

    void button_run_clicked(String args)
    {
        // guard
        if(point_list.isEmpty()) return;

        svm_parameter param = new svm_parameter();

        // default values
        param.svm_type = svm_parameter.C_SVC;
        param.kernel_type = svm_parameter.RBF;
        param.degree = 3;
        param.gamma = 0;
        param.coef0 = 0;
        param.nu = 0.5;
        param.cache_size = 40;
        param.C = 1;
        param.eps = 1e-3;
        param.p = 0.1;
        param.shrinking = 1;
        param.probability = 0;
        param.nr_weight = 0;
        param.weight_label = new int[0];
        param.weight = new double[0];

        // parse options
        StringTokenizer st = new StringTokenizer(args);
        String[] argv = new String[st.countTokens()];
        for(int i=0;i<argv.length;i++)
            argv[i] = st.nextToken();

        for(int i=0;i<argv.length;i++)
        {
            if(argv[i].charAt(0) != '-') break;
            if(++i>=argv.length)
            {
                System.err.print("unknown option\n");
                break;
            }
            switch(argv[i-1].charAt(1))
            {
                case 's':
                    param.svm_type = atoi(argv[i]);
                    break;
                case 't':
                    param.kernel_type = atoi(argv[i]);
                    break;
                case 'd':
                    param.degree = atoi(argv[i]);
                    break;
                case 'g':
                    param.gamma = atof(argv[i]);
                    break;
                case 'r':
                    param.coef0 = atof(argv[i]);
                    break;
                case 'n':
                    param.nu = atof(argv[i]);
                    break;
                case 'm':
                    param.cache_size = atof(argv[i]);
                    break;
                case 'c':
                    param.C = atof(argv[i]);
                    break;
                case 'e':
                    param.eps = atof(argv[i]);
                    break;
                case 'p':
                    param.p = atof(argv[i]);
                    break;
                case 'h':
                    param.shrinking = atoi(argv[i]);
                    break;
                case 'b':
                    param.probability = atoi(argv[i]);
                    break;
                case 'w':
                    ++param.nr_weight;
                    {
                        int[] old = param.weight_label;
                        param.weight_label = new int[param.nr_weight];
                        System.arraycopy(old,0,param.weight_label,0,param.nr_weight-1);
                    }

                    {
                        double[] old = param.weight;
                        param.weight = new double[param.nr_weight];
                        System.arraycopy(old,0,param.weight,0,param.nr_weight-1);
                    }

                    param.weight_label[param.nr_weight-1] = atoi(argv[i-1].substring(2));
                    param.weight[param.nr_weight-1] = atof(argv[i]);
                    break;
                default:
                    System.err.print("unknown option\n");
            }
        }

        // build problem
        svm_problem prob = new svm_problem();
        prob.l = point_list.size();
        prob.y = new double[prob.l];

        if(param.kernel_type == svm_parameter.PRECOMPUTED)
        {
        }
        else if(param.svm_type == svm_parameter.EPSILON_SVR ||
            param.svm_type == svm_parameter.NU_SVR)
        {
            if(param.gamma == 0) param.gamma = 1;
            prob.x = new svm_node[prob.l][1];
            for(int i=0;i<prob.l;i++)
            {
                point p = point_list.elementAt(i);
                prob.x[i][0] = new svm_node();
                prob.x[i][0].index = 1;
                prob.x[i][0].value = p.x;
                prob.y[i] = p.y;
            }

            // build model & classify
            svm_model model = svm.svm_train(prob, param);
            svm_node[] x = new svm_node[1];
            x[0] = new svm_node();
            x[0].index = 1;
            int[] j = new int[XLEN];

            Graphics window_gc = getGraphics();
            for (int i = 0; i < XLEN; i++)
            {
                x[0].value = (double) i / XLEN;
                j[i] = (int)(YLEN*svm.svm_predict(model, x));
            }

            buffer_gc.setColor(colors[0]);
            buffer_gc.drawLine(0,0,0,YLEN-1);
            window_gc.setColor(colors[0]);
            window_gc.drawLine(0,0,0,YLEN-1);

            int p = (int)(param.p * YLEN);
            for(int i=1;i<XLEN;i++)
            {
                buffer_gc.setColor(colors[0]);
                buffer_gc.drawLine(i,0,i,YLEN-1);
                window_gc.setColor(colors[0]);
                window_gc.drawLine(i,0,i,YLEN-1);

                buffer_gc.setColor(colors[5]);
                window_gc.setColor(colors[5]);
                buffer_gc.drawLine(i-1,j[i-1],i,j[i]);
                window_gc.drawLine(i-1,j[i-1],i,j[i]);

                if(param.svm_type == svm_parameter.EPSILON_SVR)
                {
                    buffer_gc.setColor(colors[2]);
                    window_gc.setColor(colors[2]);
                    buffer_gc.drawLine(i-1,j[i-1]+p,i,j[i]+p);
                    window_gc.drawLine(i-1,j[i-1]+p,i,j[i]+p);

                    buffer_gc.setColor(colors[2]);
                    window_gc.setColor(colors[2]);
                    buffer_gc.drawLine(i-1,j[i-1]-p,i,j[i]-p);
                    window_gc.drawLine(i-1,j[i-1]-p,i,j[i]-p);
                }
            }
        }
        else
        {
            if(param.gamma == 0) param.gamma = 0.5;
            prob.x = new svm_node [prob.l][2];
            for(int i=0;i<prob.l;i++)
            {
                point p = point_list.elementAt(i);
                prob.x[i][0] = new svm_node();
                prob.x[i][0].index = 1;
                prob.x[i][0].value = p.x;
                prob.x[i][1] = new svm_node();
                prob.x[i][1].index = 2;
                prob.x[i][1].value = p.y;
                prob.y[i] = p.value;
            }

            // build model & classify
            svm_model model = svm.svm_train(prob, param);
            svm_node[] x = new svm_node[2];
            x[0] = new svm_node();
            x[1] = new svm_node();
            x[0].index = 1;
            x[1].index = 2;

            Graphics window_gc = getGraphics();
            for (int i = 0; i < XLEN; i++)
                for (int j = 0; j < YLEN ; j++) {
                    x[0].value = (double) i / XLEN;
                    x[1].value = (double) j / YLEN;
                    double d = svm.svm_predict(model, x);
                    if (param.svm_type == svm_parameter.ONE_CLASS && d<0) d=2;
                    buffer_gc.setColor(colors[(int)d]);
                    window_gc.setColor(colors[(int)d]);
                    buffer_gc.drawLine(i,j,i,j);
                    window_gc.drawLine(i,j,i,j);
            }
        }

        draw_all_points();
    }

    void button_clear_clicked()
    {
        clear_all();
    }

    void button_save_clicked(String args)
    {
        FileDialog dialog = new FileDialog(new Frame(),"Save",FileDialog.SAVE);
        dialog.setVisible(true);
        String filename = dialog.getDirectory() + dialog.getFile();
        if (filename == null) return;
        try {
            DataOutputStream fp = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)));

            int svm_type = svm_parameter.C_SVC;
            int svm_type_idx = args.indexOf("-s ");
            if(svm_type_idx != -1)
            {
                StringTokenizer svm_str_st = new StringTokenizer(args.substring(svm_type_idx+2).trim());
                svm_type = atoi(svm_str_st.nextToken());
            }

            int n = point_list.size();
            if(svm_type == svm_parameter.EPSILON_SVR || svm_type == svm_parameter.NU_SVR)
            {
                for(int i=0;i<n;i++)
                {
                    point p = point_list.elementAt(i);
                    fp.writeBytes(p.y+" 1:"+p.x+"\n");
                }
            }
            else
            {
                for(int i=0;i<n;i++)
                {
                    point p = point_list.elementAt(i);
                    fp.writeBytes(p.value+" 1:"+p.x+" 2:"+p.y+"\n");
                }
            }
            fp.close();
        } catch (IOException e) { System.err.print(e); }
    }

    void button_load_clicked()
    {
        FileDialog dialog = new FileDialog(new Frame(),"Load",FileDialog.LOAD);
        dialog.setVisible(true);
        String filename = dialog.getDirectory() + dialog.getFile();
        if (filename == null) return;
        clear_all();
        try {
            BufferedReader fp = new BufferedReader(new FileReader(filename));
            String line;
            while((line = fp.readLine()) != null)
            {
                StringTokenizer st = new StringTokenizer(line," \t\n\r\f:");
                if(st.countTokens() == 5)
                {
                    byte value = (byte)atoi(st.nextToken());
                    st.nextToken();
                    double x = atof(st.nextToken());
                    st.nextToken();
                    double y = atof(st.nextToken());
                    point_list.addElement(new point(x,y,value));
                }
                else if(st.countTokens() == 3)
                {
                    double y = atof(st.nextToken());
                    st.nextToken();
                    double x = atof(st.nextToken());
                    point_list.addElement(new point(x,y,current_value));
                }else
                    break;
            }
            fp.close();
        } catch (IOException e) { System.err.print(e); }
        draw_all_points();
    }

    protected void processMouseEvent(MouseEvent e)
    {
        if(e.getID() == MouseEvent.MOUSE_PRESSED)
        {
            if(e.getX() >= XLEN || e.getY() >= YLEN) return;
            point p = new point((double)e.getX()/XLEN,
                        (double)e.getY()/YLEN,
                        current_value);
            point_list.addElement(p);
            draw_point(p);
        }
    }

    public void paint(Graphics g)
    {
        // create buffer first time
        if(buffer == null) {
            buffer = this.createImage(XLEN,YLEN);
            buffer_gc = buffer.getGraphics();
            buffer_gc.setColor(colors[0]);
            buffer_gc.fillRect(0,0,XLEN,YLEN);
        }
        g.drawImage(buffer,0,0,this);
    }

    public Dimension getPreferredSize() { return new Dimension(XLEN,YLEN+50); }

    public void setSize(Dimension d) { setSize(d.width,d.height); }
    public void setSize(int w,int h) {
        super.setSize(w,h);
        XLEN = w;
        YLEN = h-50;
        clear_all();
    }

    public static void main(String[] argv)
    {
        new AppletFrame("svm_toy",new svm_toy(),500,500+50);
    }
}

class AppletFrame extends Frame {
    AppletFrame(String title, Applet applet, int width, int height)
    {
        super(title);
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        applet.init();
        applet.setSize(width,height);
        applet.start();
        this.add(applet);
        this.pack();
        this.setVisible(true);
    }

}

Could someone give me an example or explanation? I also would like to scale my training data. Where is the right place to scale?

Thanks

Nerta answered 30/11, 2015 at 7:22 Comment(0)
S
10

SVM-Toy

SVM Toy is - as the name suggests - a simple toy build by the LIBSVM dev team and is not recommended for "productive" visualization of the SVM's decision boundary.

Moreover looking into the source-code of svm_toy it becomes clear, that this tool only supports 2D vectors.

Relevant code fragment is taken from the button_load_clicked() Method:

while ((line = fp.readLine()) != null) {
    StringTokenizer st = new StringTokenizer(line, " \t\n\r\f:");
        if (st.countTokens() == 5) {
            byte value = (byte) atoi(st.nextToken());
            st.nextToken();
            double x = atof(st.nextToken());
            st.nextToken();
            double y = atof(st.nextToken());
            point_list.addElement(new point(x, y, value));
        } else if (st.countTokens() == 3) {
            double y = atof(st.nextToken());
            st.nextToken();
            double x = atof(st.nextToken());
            point_list.addElement(new point(x, y, current_value));
        } else {
            break;
        }
    }

As you can see, the svm_toy implementation can only handle 2D vectors, which means it only supports vectors, which were constructed out of two features.

That means, you can only read and display files which are build from only two features like for example the fourclass dataset provided by the LIBSVM authors. However it seems, that this feature is not supported within this implementation.

I think, that the tool is designed for interactive visualization. You are able to change the color and click on the black application screen. After you set some points (each color representing an own class), you can click "run" and the decision boundary is displayed.

Two random clicked data sets

Decision boundary is shown after clicking on "run"

Displaying the desicion boundary in an high dimensional vector space is even nearly impossible. I would recommend to not use this tool implementation for any productive / scientific purpose.

Scaling

Scaling of your training data should be done after you transformed it into it's numeric representation and before you are going forward to train your SVM with this data.

In short that means, you have to do the following steps before using svm_train

  1. Construct the numeric representation for each data point (with the help of feature selection, ...)
  2. Analyse the resulting numeric representation for each data point
  3. Scale your data for example to [-1,1]
  4. Go ahead and train your SVM model. Note well, that you have to repeat 1-3 for predicting unknown data points. The only difference is, that you already know the necessary features, so there is no need for feature selection.
Stallard answered 2/12, 2015 at 12:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.