All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nak.liblinear.LiblinearClassifier.scala Maven / Gradle / Ivy

The newest version!
package nak.liblinear

/**
 * Configure the options for Liblinear training.
 */
case class LiblinearConfig(
  solverType: SolverType = SolverType.L2R_LR,
  cost: Double = 1.0, 
  eps: Double = 0.01, 
  showDebug: Boolean = false)

/**
 * Set up a problem to be solved.
 */ 
object LiblinearProblem {

  def apply(responses: Array[Double], observations: Array[Array[Feature]], numFeats: Int) = {
    val problem = new Problem
    problem.y = responses
    problem.x = observations
    problem.l = responses.length
    problem.n = numFeats
    problem
  }

}

/**
 * An object to help with solver descriptions.
 */
object Solver {

  /**
   * The set of all valid solver types.
   */
  lazy val solverTypes = Set(
    "L2R_LR", "L2R_L2LOSS_SVC_DUAL", "L2R_L2LOSS_SVC", "L2R_L1LOSS_SVC_DUAL",
    "MCSVM_CS","L1R_L2LOSS_SVC", "L1R_LR",
    "L2R_LR_DUAL", "L2R_L2LOSS_SVR", "L2R_L2LOSS_SVR_DUAL", "L2R_L1LOSS_SVR_DUAL")

  /**
   * Select the right solver given the textual description.
   */
  def apply(solverDescription: String) = solverDescription match {
    case "L2R_LR" => SolverType.L2R_LR
    case "L2R_L2LOSS_SVC_DUAL" => SolverType.L2R_L2LOSS_SVC_DUAL
    case "L2R_L2LOSS_SVC" => SolverType.L2R_L2LOSS_SVC
    case "L2R_L1LOSS_SVC_DUAL" => SolverType.L2R_L1LOSS_SVC_DUAL
    case "MCSVM_CS" => SolverType.MCSVM_CS
    case "L1R_L2LOSS_SVC" => SolverType.L1R_L2LOSS_SVC
    case "L1R_LR" => SolverType.L1R_LR
    case "L2R_LR_DUAL" => SolverType.L2R_LR_DUAL
    case "L2R_L2LOSS_SVR" => SolverType.L2R_L2LOSS_SVR
    case "L2R_L2LOSS_SVR_DUAL" => SolverType.L2R_L2LOSS_SVR_DUAL
    case "L2R_L1LOSS_SVR_DUAL" => SolverType.L2R_L1LOSS_SVR_DUAL 
    case invalid => throw new MatchError("No solver with the name " + invalid)
  }

}

/**
 * Helper functions for working with Liblinear.
 */
object LiblinearUtil {


  /**
   * Convert tuples into Liblinear Features, basically.
   */ 
  def createLiblinearMatrix(observations: Seq[Seq[(Int,Double)]]): Array[Array[Feature]] =  
    observations.map { features =>
      features.map{ case(a,v) => new FeatureNode(a,v).asInstanceOf[Feature] }.toArray
    }.toArray

  /**
   * Convert tuples into Liblinear Features, basically.
   *
   * TODO: Condense so there is just one createLiblinearMatrix.
   */ 
  def createLiblinearMatrix(observations: Array[Array[(Int,Float)]]): Array[Array[Feature]] =  
    observations.map { features => {
      features
        .sortBy(_._1)
        .map{ case(a,v) => new FeatureNode(a,v).asInstanceOf[Feature] }
    }}

}

/**
 * Train a Liblinear classifier from data.
 * 
 * @author jasonbaldridge
 */
class LiblinearTrainer(config: LiblinearConfig) {

  import LiblinearUtil._

  if (!config.showDebug) Linear.disableDebugOutput
  val param = new Parameter(config.solverType, config.cost, config.eps)

  /**
   * Train a liblinear model given the responses (the y's), the observations (the x's),
   * and the number of features.
   */ 
  def apply(
    responses: Array[Double], 
    observations: Array[Array[Feature]], 
    numFeatures: Int
  ): Model = {
    val problem = LiblinearProblem(responses, observations, numFeatures)
    Linear.train(problem, param)
  }

}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy