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

com.alpine.model.pack.multiple.sql.GroupByClassificationSQLTransformer.scala Maven / Gradle / Ivy

The newest version!
/*
 * COPYRIGHT (C) Feb 12 2016 Alpine Data Labs Inc. All Rights Reserved.
 */

package com.alpine.model.pack.multiple.sql

import com.alpine.model.pack.UnitModel
import com.alpine.model.pack.multiple.{CombinerModel, GroupByClassificationModel}
import com.alpine.model.{ClassificationRowModel, RowModel}
import com.alpine.plugin.core.io.{ColumnDef, ColumnType}
import com.alpine.sql.SQLGenerator
import com.alpine.transformer.Transformer
import com.alpine.transformer.sql._
import com.alpine.util.SQLUtility

/**
  * Created by Jennifer Thompson on 2/12/16.
  */
class GroupByClassificationSQLTransformer(val model: GroupByClassificationModel, val sqlGenerator: SQLGenerator) extends ClassificationSQLTransformer {

  override def getClassificationSQL = {
    val modelsByGroup = model.modelsByGroup.toSeq

    /**
      * TODO:
      * We could make this more efficient by consolidating duplicate expressions,
      * but this will work for now.
      */
    val combinedModels = CombinerModel.make(modelsByGroup.map(m => ConfidenceColumnsModel(m._2)) ++ Seq(new UnitModel(Seq(model.groupByFeature))))

    val combinedIntermediateLayers = combinedModels.sqlTransformer(sqlGenerator).get.getSQL

    val groupBySQLExpression = combinedIntermediateLayers.layers.last.last._2.asColumnarSQLExpression(sqlGenerator)

    val startingFeatureIndexByModel = modelsByGroup.map(_._1) zip cumulativeSum(modelsByGroup.map(_._2.classLabels.size))

    val finalLayerConfidences = model.classLabels.map(l => {
      (l, SQLUtility.groupBySQL(
        groupBySQLExpression,
        startingFeatureIndexByModel.map {
          case (value, startingIndex) =>
            val offset = model.modelsByGroup.get(value).get.classLabels.indexOf(l)
            val valueAsExpression: ColumnarSQLExpression = ColumnarSQLExpression(SQLUtility.wrapAsValue(value))
            if (offset > -1) {
              (valueAsExpression, combinedIntermediateLayers.layers.last(startingIndex + offset)._2.asColumnarSQLExpression(sqlGenerator))
            } else {
              (valueAsExpression, ColumnarSQLExpression("0"))
            }
        }.toMap
      ))
    })

    val confidenceColumnNames = model.classLabels.indices.map(i => ColumnName("CONF" + i))

    val intermediateLayers = combinedIntermediateLayers.layers ++ Seq(finalLayerConfidences.map(_._2) zip confidenceColumnNames)

    ClassificationModelSQLExpressions.apply(finalLayerConfidences.map(_._1) zip confidenceColumnNames, intermediateLayers, sqlGenerator)
  }

  private def cumulativeSum(values: Seq[Int]): Seq[Int] = {
    values.foldLeft(List[Int](0))((sumSoFar, value) => {
      (value + sumSoFar.head) :: sumSoFar
    }).reverse
  }

  /**
    * This will probably be made a fully fledged standalone class at some point,
    * but it's not clean enough yet (have to resolve what to do for the in-memory transformer).
    *
    * For now we keep it here to only be instantiated in the GroupByClassificationSQLTransformer.
    */
  private case class ConfidenceColumnsModel(c: ClassificationRowModel) extends RowModel {
    override def transformer: Transformer = ???

    override def sqlTransformer(sqlGenerator: SQLGenerator): Option[SQLTransformer] = {
      Some(
        new SQLTransformer() {

          override def getSQL: LayeredSQLExpressions = {
            val transformer = c.sqlTransformer(sqlGenerator).get
            val classificationSQL = transformer.getClassificationSQL
            val finalLayerConfidences = c.classLabels.map(l => classificationSQL.confidenceSQL(l)).toList
            val finalLayer = Seq(finalLayerConfidences zip outputColumnNames)
            LayeredSQLExpressions(classificationSQL.intermediateLayers ++ finalLayer)
          }

          override def model: RowModel = ConfidenceColumnsModel.this
        }
      )
    }

    override def inputFeatures = c.inputFeatures

    override def sqlOutputFeatures: Seq[ColumnDef] = {
      c.classLabels.indices.map(i => ColumnDef("CONF" + i, ColumnType.Double))
    }

    override def outputFeatures: Seq[ColumnDef] = ???
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy