2015年12月29日 星期二

『Android』SVM基本使用法

參考網址
https://www.csie.ntu.edu.tw/~cjlin/libsvm/
http://ntu.csie.org/~piaip/svm/svm_tutorial.html
https://www.csie.ntu.edu.tw/~cjlin/libsvm/#download

實作一 參數
protected void onCreate(Bundle savedInstanceState) {

    _param = new svm_parameter();

    _param.svm_type = svm_parameter.C_SVC;
    _param.kernel_type = svm_parameter.LINEAR;
    _param.degree = 3;
    _param.gamma = 0;     // 1/num_features    _param.coef0 = 0;
    _param.nu = 0.5;
    _param.cache_size = 100;
    _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];


實作二 訓練
protected void training(){
        loadData(true);    //這邊呼叫loadData(),使用true參數是因為在training階段        //透過loadData,將資料庫的資料儲存在全域變數_prob裡面
        System.out.print("Training...");
        _model_file = "/sdcard/svm_model.txt"; //指定SVM model儲存的檔案名稱
            svm_model model = svm.svm_train(_prob, _param);    //訓練SVM model            System.out.println("Done!!(training)");
            textView.setText("svm_model loaded");
        try {
            svm.svm_save_model(_model_file, model);        //將訓練結果寫入檔案        }catch (IOException e){
        }

    }

    protected void loadData(boolean is_training){
        String limit;
        if(is_training){   //訓練階段            System.out.print("Loading training data...");
            limit = " WHERE id <= 4700";
        }else{       //測試階段            System.out.print("Loading testing data...");
            limit = " WHERE id > 4700";
        }

        int max_index = 0; //紀錄資料中最大的維度(用來產生gamma參數)        _prob = new svm_problem();
                Vector vy = new Vector();
                Vector vx = new Vector();
                vy.add("1");
                vy.add("2");//labal為資料的標籤,為-1或+1                //SVM通常就是解決是好(+1)或壞(-1)的問題
                //讀取兩個維度的資料,這裡只有「有這個維度(true)」與「沒有這個維度(false)」                //因此兩個欄位只填寫維度的index,例如填寫30,就代表第30維有資料                //假設rdk1=30,rdk2=2789,則這個node只有這兩個維的值是true,                //其他2998維(比如第31, 32...維)的值都是false
        svm_node[] x = new svm_node[3];       //建立SVM node的陣列        x[0] = new svm_node();
        x[0].index = color_r;        //維度的index例如30        x[0].value = 15.0;          //有值,為true        x[1] = new svm_node();
        x[1].index = color_g;        //維度的index例如2789        x[1].value = 163.0;
        x[2] = new svm_node();
        x[2].index = color_b;        //維度的index例如2789        x[2].value = 15.0;
        vx.add(x);       //儲存SVM node的陣列        svm_node[] y = new svm_node[3];
        y[0] = new svm_node();
        y[0].index = color_r;        //維度的index例如30        y[0].value = 255.0;             //有值,為true        y[1] = new svm_node();
        y[1].index = color_g;        //維度的index例如2789        y[1].value = 42.0;
        y[2] = new svm_node();
        y[2].index = color_b;        //維度的index例如2789        y[2].value = 0.0;
        vx.add(y);
        svm_node[] z = new svm_node[3];
        z[0] = new svm_node();
        z[0].index = color_r;        //維度的index例如30        z[0].value = 255.0;             //有值,為true        z[1] = new svm_node();
        z[1].index = color_g;        //維度的index例如2789        z[1].value = 255.0;
        z[2] = new svm_node();
        z[2].index = color_b;        //維度的index例如2789        z[2].value = 255.0;
        vx.add(z);

        _prob.l = vy.size();                  //svm node的數量        _prob.x = new svm_node[_prob.l][];
        _prob.x[0] = (svm_node[]) vx.get(0);
        _prob.x[1] = (svm_node[]) vx.get(1);
//        for(int i=0;i<_prob.l;i++) _prob.x[i] = (svm_node[]) vx.elementAt(i);    //儲存每個node的向量        _prob.y = new double[_prob.l];
//        for(int i=0;i<_prob.l;i++) _prob.y[i] =(double)  vy.elementAt(i);    //儲存每個node的label  /        _prob.y[0]=1.01;
        _prob.y[1]=2.02;

        System.out.println("Done!!(ReadData)");
    }

實作三 測試
protected int touch_testing(){
//        loadData(false); //讀取剩下的300分資料,轉換成SVM問題(存在_prob裡)        double v;
        svm_model model;
        int correct = 0, total = 0;
        try {
            model = svm.svm_load_model(_model_file);   //載入model            textView.setText("svm_model loaded");

            textView.setText("_prob = " + _prob.l);

            svm_node[] x = new svm_node[3];       //建立SVM node的陣列            x[0] = new svm_node();
            x[0].index = color_r;        //維度的index例如30            x[0].value = r;             //有值,為true            x[1] = new svm_node();
            x[1].index = color_g;        //維度的index例如2789            x[1].value = g;
            x[2] = new svm_node();
            x[2].index = color_b;        //維度的index例如2789            x[2].value = b;
            Log.i(TAG, "Texting color: (" + r + ", " + g + ", " + b + ")");
                v = svm.svm_predict(model, x); //把node餵給預測器            Log.i(TAG, "svm_predict: (" + v + ")");
                //這時預測器會依照model與node內的向量資訊,產生預測的數值(-1或1)            int v_to_int = (int) v ;
            switch (v_to_int){
                case 1:
                    return 1;

                default:
                    return 0;
            }

沒有留言:

張貼留言