/** * This is the method to call for assigning labels and node vectors to the Tree. After calling * this, each of the non-leaf nodes will have the node vector and the predictions of their classes * assigned to that subtree's node. */ public void forwardPropagateTree(Tree tree) { INDArray nodeVector; INDArray classification; if (tree.isLeaf()) { // We do nothing for the leaves. The preterminals will // calculate the classification for this word/tag. In fact, the // recursion should not have gotten here (unless there are // degenerate trees of just one leaf) throw new AssertionError("We should not have reached leaves in forwardPropagate"); } else if (tree.isPreTerminal()) { classification = getUnaryClassification(tree.label()); String word = tree.children().get(0).value(); INDArray wordVector = getFeatureVector(word); if (wordVector == null) { wordVector = featureVectors.vector(Word2Vec.UNK); } nodeVector = Nd4j.getExecutioner() .execAndReturn(Nd4j.getOpFactory().createTransform(activationFunction, wordVector)); } else if (tree.children().size() == 1) { throw new AssertionError( "Non-preterminal nodes of size 1 should have already been collapsed"); } else if (tree.children().size() == 2) { Tree left = tree.firstChild(), right = tree.lastChild(); forwardPropagateTree(left); forwardPropagateTree(right); String leftCategory = tree.children().get(0).label(); String rightCategory = tree.children().get(1).label(); INDArray W = getBinaryTransform(leftCategory, rightCategory); classification = getBinaryClassification(leftCategory, rightCategory); INDArray leftVector = tree.children().get(0).vector(); INDArray rightVector = tree.children().get(1).vector(); INDArray childrenVector = Nd4j.appendBias(leftVector, rightVector); if (useDoubleTensors) { INDArray doubleT = getBinaryINDArray(leftCategory, rightCategory); INDArray INDArrayIn = Nd4j.concat(0, leftVector, rightVector); INDArray INDArrayOut = Nd4j.bilinearProducts(doubleT, INDArrayIn); nodeVector = Nd4j.getExecutioner() .execAndReturn( Nd4j.getOpFactory() .createTransform( activationFunction, W.mmul(childrenVector).addi(INDArrayOut))); } else nodeVector = Nd4j.getExecutioner() .execAndReturn( Nd4j.getOpFactory() .createTransform(activationFunction, W.mmul(childrenVector))); } else { throw new AssertionError("Tree not correctly binarized"); } INDArray inputWithBias = Nd4j.appendBias(nodeVector); if (inputWithBias.rows() != classification.columns()) inputWithBias = inputWithBias.transpose(); INDArray preAct = classification.mmul(inputWithBias); INDArray predictions = Nd4j.getExecutioner() .execAndReturn(Nd4j.getOpFactory().createTransform(outputActivation, preAct)); tree.setPrediction(predictions); tree.setVector(nodeVector); }