use of org.knime.base.node.mine.treeensemble2.data.NominalValueRepresentation in project knime-core by knime.
the class TreeNominalColumnData method updateChildMembershipsBinary.
private BitSet updateChildMembershipsBinary(final TreeNodeNominalBinaryCondition childBinaryCondition, final DataMemberships parentMemberships) {
ColumnMemberships columnMemberships = parentMemberships.getColumnMemberships(getMetaData().getAttributeIndex());
columnMemberships.reset();
BitSet inChild = new BitSet(columnMemberships.size());
// TODO Check if this can be done more efficiently
NominalValueRepresentation[] reps = getMetaData().getValues();
int start = 0;
boolean reachedEnd = false;
final int lengthNonMissing = containsMissingValues() ? reps.length - 1 : reps.length;
for (int att = 0; att < lengthNonMissing; att++) {
if (childBinaryCondition.testCondition(att)) {
// move columnMemberships to correct position
if (!columnMemberships.nextIndexFrom(start)) {
// reached end of columnMemberships
break;
}
int end = start + m_nominalValueCounts[att];
for (int index = columnMemberships.getIndexInColumn(); index < end; index = columnMemberships.getIndexInColumn()) {
inChild.set(columnMemberships.getIndexInDataMemberships());
if (!columnMemberships.next()) {
reachedEnd = true;
break;
}
}
}
start += m_nominalValueCounts[att];
}
if (!reachedEnd && containsMissingValues() && childBinaryCondition.acceptsMissings()) {
if (columnMemberships.nextIndexFrom(start)) {
do {
inChild.set(columnMemberships.getIndexInDataMemberships());
} while (columnMemberships.next());
}
}
return inChild;
}
use of org.knime.base.node.mine.treeensemble2.data.NominalValueRepresentation in project knime-core by knime.
the class TreeNominalColumnData method calcBestSplitRegressionBinary.
private NominalBinarySplitCandidate calcBestSplitRegressionBinary(final ColumnMemberships columnMemberships, final RegressionPriors targetPriors, final TreeTargetNumericColumnData targetColumn, final NominalValueRepresentation[] nomVals, final RandomData rd) {
final int minChildSize = getConfiguration().getMinChildSize();
final double ySumTotal = targetPriors.getYSum();
final double nrRecordsTotal = targetPriors.getNrRecords();
final double criterionTotal = ySumTotal * ySumTotal / nrRecordsTotal;
final double[] ySums = new double[nomVals.length];
final double[] sumWeightsAttributes = new double[nomVals.length];
columnMemberships.next();
int start = 0;
for (int att = 0; att < nomVals.length; att++) {
int end = start + m_nominalValueCounts[att];
double weightSum = 0.0;
double ySum = 0.0;
boolean reachedEnd = false;
for (int index = columnMemberships.getIndexInColumn(); index < end; index = columnMemberships.getIndexInColumn()) {
final double weight = columnMemberships.getRowWeight();
assert weight > EPSILON : "Instances in columnMemberships must have weights larger than EPSILON.";
ySum += weight * targetColumn.getValueFor(columnMemberships.getOriginalIndex());
weightSum += weight;
if (!columnMemberships.next()) {
// reached end of columnMemberships
reachedEnd = true;
break;
}
}
sumWeightsAttributes[att] = weightSum;
ySums[att] = ySum;
start = end;
if (reachedEnd) {
break;
}
}
BinarySplitEnumeration splitEnumeration;
if (nomVals.length <= 10) {
splitEnumeration = new FullBinarySplitEnumeration(nomVals.length);
} else {
int maxSearch = (1 << 10 - 2);
splitEnumeration = new RandomBinarySplitEnumeration(nomVals.length, maxSearch, rd);
}
BigInteger bestPartitionMask = null;
boolean isBestSplitValid = false;
double bestPartitionGain = Double.NEGATIVE_INFINITY;
do {
double weightLeft = 0.0;
double ySumLeft = 0.0;
double weightRight = 0.0;
double ySumRight = 0.0;
for (int i = 0; i < nomVals.length; i++) {
final boolean isAttributeInRightBranch = splitEnumeration.isInRightBranch(i);
if (isAttributeInRightBranch) {
weightRight += sumWeightsAttributes[i];
ySumRight += ySums[i];
} else {
weightLeft += sumWeightsAttributes[i];
ySumLeft += ySums[i];
}
}
final boolean isValidSplit = weightRight >= minChildSize && weightLeft >= minChildSize;
double gain = ySumRight * ySumRight / weightRight + ySumLeft * ySumLeft / weightLeft - criterionTotal;
// use random tie breaker if gains are equal
boolean randomTieBreaker = gain == bestPartitionGain ? rd.nextInt(0, 1) == 1 : false;
// store if better than before or first valid split
if (gain > bestPartitionGain || (!isBestSplitValid && isValidSplit) || randomTieBreaker) {
if (isValidSplit || !isBestSplitValid) {
bestPartitionGain = gain;
bestPartitionMask = splitEnumeration.getValueMask();
isBestSplitValid = isValidSplit;
}
}
} while (splitEnumeration.next());
if (bestPartitionGain > 0.0) {
return new NominalBinarySplitCandidate(this, bestPartitionGain, bestPartitionMask, getMissedRows(columnMemberships), NominalBinarySplitCandidate.NO_MISSINGS);
}
return null;
}
use of org.knime.base.node.mine.treeensemble2.data.NominalValueRepresentation in project knime-core by knime.
the class TreeNominalColumnData method calcBestSplitClassification.
/**
* {@inheritDoc}
*/
@Override
public SplitCandidate calcBestSplitClassification(final DataMemberships dataMemberships, final ClassificationPriors targetPriors, final TreeTargetNominalColumnData targetColumn, final RandomData rd) {
final NominalValueRepresentation[] targetVals = targetColumn.getMetaData().getValues();
IImpurity impCriterion = targetPriors.getImpurityCriterion();
// distribution of target for each attribute value
final NominalValueRepresentation[] nomVals = getMetaData().getValues();
final boolean useBinaryNominalSplits = getConfiguration().isUseBinaryNominalSplits();
final ColumnMemberships columnMemberships = dataMemberships.getColumnMemberships(getMetaData().getAttributeIndex());
if (useBinaryNominalSplits) {
if (targetVals.length == 2) {
return calcBestSplitClassificationBinaryTwoClass(columnMemberships, targetPriors, targetColumn, impCriterion, nomVals, targetVals, rd);
} else {
return calcBestSplitClassificationBinaryPCA(columnMemberships, targetPriors, targetColumn, impCriterion, nomVals, targetVals, rd);
// return calcBestSplitClassificationBinary(membershipController, rowWeights, targetPriors, targetColumn,
// impCriterion, nomVals, targetVals, originalIndexInColumnList, rd);
}
} else {
return calcBestSplitClassificationMultiway(columnMemberships, targetPriors, targetColumn, impCriterion, nomVals, targetVals, rd);
}
}
use of org.knime.base.node.mine.treeensemble2.data.NominalValueRepresentation in project knime-core by knime.
the class NominalMultiwaySplitCandidate method getChildConditions.
/**
* {@inheritDoc}
*/
@Override
public TreeNodeNominalCondition[] getChildConditions() {
TreeNominalColumnMetaData columnMeta = getColumnData().getMetaData();
NominalValueRepresentation[] values = columnMeta.getValues();
final int lengthNonMissing = values[values.length - 1].getNominalValue().equals(NominalValueRepresentation.MISSING_VALUE) ? values.length - 1 : values.length;
List<TreeNodeCondition> resultList = new ArrayList<TreeNodeCondition>(lengthNonMissing);
for (int i = 0; i < lengthNonMissing; i++) {
if (m_sumWeightsAttributes[i] >= TreeColumnData.EPSILON) {
resultList.add(new TreeNodeNominalCondition(columnMeta, i, i == m_missingsGoToChildIdx));
}
}
return resultList.toArray(new TreeNodeNominalCondition[resultList.size()]);
}
use of org.knime.base.node.mine.treeensemble2.data.NominalValueRepresentation in project knime-core by knime.
the class LKGradientBoostedTreesLearner method learn.
/**
* {@inheritDoc}
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Override
public MultiClassGradientBoostedTreesModel learn(final ExecutionMonitor exec) throws CanceledExecutionException, InterruptedException, ExecutionException {
final TreeData data = getData();
final TreeTargetNominalColumnData target = (TreeTargetNominalColumnData) data.getTargetColumn();
final NominalValueRepresentation[] classNomVals = target.getMetaData().getValues();
final int numClasses = classNomVals.length;
final String[] classLabels = new String[numClasses];
final int nrModels = getConfig().getNrModels();
final int nrRows = target.getNrRows();
final TreeModelRegression[][] models = new TreeModelRegression[nrModels][numClasses];
final ArrayList<ArrayList<Map<TreeNodeSignature, Double>>> coefficientMaps = new ArrayList<ArrayList<Map<TreeNodeSignature, Double>>>(nrModels);
// variables for parallelization
final ThreadPool tp = KNIMEConstants.GLOBAL_THREAD_POOL;
final AtomicReference<Throwable> learnThrowableRef = new AtomicReference<Throwable>();
final int procCount = 3 * Runtime.getRuntime().availableProcessors() / 2;
exec.setMessage("Transforming problem");
// transform the original k class classification problem into k regression problems
final TreeData[] actual = new TreeData[numClasses];
for (int i = 0; i < numClasses; i++) {
final double[] newTarget = calculateNewTarget(target, i);
actual[i] = createNumericDataFromArray(newTarget);
classLabels[i] = classNomVals[i].getNominalValue();
}
final RandomData rd = getConfig().createRandomData();
final double[][] previousFunctions = new double[numClasses][nrRows];
TreeNodeSignatureFactory signatureFactory = null;
final int maxLevels = getConfig().getMaxLevels();
if (maxLevels < TreeEnsembleLearnerConfiguration.MAX_LEVEL_INFINITE) {
int capacity = IntMath.pow(2, maxLevels - 1);
signatureFactory = new TreeNodeSignatureFactory(capacity);
} else {
signatureFactory = new TreeNodeSignatureFactory();
}
exec.setMessage("Learn trees");
for (int i = 0; i < nrModels; i++) {
final Semaphore semaphore = new Semaphore(procCount);
final ArrayList<Map<TreeNodeSignature, Double>> classCoefficientMaps = new ArrayList<Map<TreeNodeSignature, Double>>(numClasses);
// prepare calculation of pseudoResiduals
final double[][] probs = new double[numClasses][nrRows];
for (int r = 0; r < nrRows; r++) {
double sumExpF = 0;
for (int j = 0; j < numClasses; j++) {
sumExpF += Math.exp(previousFunctions[j][r]);
}
for (int j = 0; j < numClasses; j++) {
probs[j][r] = Math.exp(previousFunctions[j][r]) / sumExpF;
}
}
final Future<?>[] treeCoefficientMapPairs = new Future<?>[numClasses];
for (int j = 0; j < numClasses; j++) {
checkThrowable(learnThrowableRef);
final RandomData rdSingle = TreeEnsembleLearnerConfiguration.createRandomData(rd.nextLong(Long.MIN_VALUE, Long.MAX_VALUE));
final ExecutionMonitor subExec = exec.createSubProgress(0.0);
semaphore.acquire();
treeCoefficientMapPairs[j] = tp.enqueue(new TreeLearnerCallable(rdSingle, probs[j], actual[j], subExec, numClasses, previousFunctions[j], semaphore, learnThrowableRef, signatureFactory));
}
for (int j = 0; j < numClasses; j++) {
checkThrowable(learnThrowableRef);
semaphore.acquire();
final Pair<TreeModelRegression, Map<TreeNodeSignature, Double>> pair = (Pair<TreeModelRegression, Map<TreeNodeSignature, Double>>) treeCoefficientMapPairs[j].get();
models[i][j] = pair.getFirst();
classCoefficientMaps.add(pair.getSecond());
semaphore.release();
}
checkThrowable(learnThrowableRef);
coefficientMaps.add(classCoefficientMaps);
exec.setProgress((double) i / nrModels, "Finished level " + i + "/" + nrModels);
}
return MultiClassGradientBoostedTreesModel.createMultiClassGradientBoostedTreesModel(getConfig(), data.getMetaData(), models, data.getTreeType(), 0, numClasses, coefficientMaps, classLabels);
}
Aggregations