public void buildClassifier(Instances insts) throws Exception {
    m_NominalToBinary = null;
    m_Filter = null;
    
    if (!isPresent())
      throw new Exception("liblinear classes not in CLASSPATH!");

    // remove instances with missing class
    insts = new Instances(insts);
    insts.deleteWithMissingClass();
    
    if (!getDoNotReplaceMissingValues()) {
      m_ReplaceMissingValues = new ReplaceMissingValues();
      m_ReplaceMissingValues.setInputFormat(insts);
      insts = Filter.useFilter(insts, m_ReplaceMissingValues);
    }
    
    // can classifier handle the data?
    // we check this here so that if the user turns off
    // replace missing values filtering, it will fail
    // if the data actually does have missing values
    getCapabilities().testWithFail(insts);

    if (getConvertNominalToBinary()) {
      insts = nominalToBinary(insts);
    }

    if (getNormalize()) {
      m_Filter = new Normalize();
      m_Filter.setInputFormat(insts);
      insts = Filter.useFilter(insts, m_Filter);
    }

    List<Integer> vy = new ArrayList<Integer>(insts.numInstances());
    List<Object> vx = new ArrayList<Object>(insts.numInstances());
    int max_index = 0;

    for (int d = 0; d < insts.numInstances(); d++) {
      Instance inst = insts.instance(d);
      Object x = instanceToArray(inst);
      int m = Array.getLength(x);
      if (m > 0)
        max_index = Math.max(max_index, ((Integer) getField(Array.get(x, m - 1), "index")).intValue());
      vx.add(x);
      double classValue = inst.classValue();
      int classValueInt = (int)classValue;
      if (classValueInt != classValue) throw new RuntimeException("unsupported class value: " + classValue);
      vy.add(Integer.valueOf(classValueInt));
    }

    if (!m_Debug) {
      invokeMethod(
          Class.forName(CLASS_LINEAR).newInstance(),
          "disableDebugOutput", null, null);
    } else {
      invokeMethod(
          Class.forName(CLASS_LINEAR).newInstance(),
          "enableDebugOutput", null, null);
    }

    // reset the PRNG for regression-stable results
    invokeMethod(
        Class.forName(CLASS_LINEAR).newInstance(),
        "resetRandom", null, null);

    // train model
    m_Model = invokeMethod(
        Class.forName(CLASS_LINEAR).newInstance(),
        "train",
        new Class[]{
          Class.forName(CLASS_PROBLEM),
            Class.forName(CLASS_PARAMETER)},
            new Object[]{
              getProblem(vx, vy, max_index),
            getParameters()});
  }