/** * Returns true iff every element of matrix is 0 */ public static boolean isZero(SimpleMatrix matrix) { int size = matrix.getNumElements(); for (int i = 0; i < size; ++i) { if (matrix.get(i) != 0.0) { return false; } } return true; } }
private Comparator<Tree> scoreComparator(final int prediction) { return (tree1, tree2) -> { double score1 = RNNCoreAnnotations.getPredictions(tree1).get(prediction); double score2 = RNNCoreAnnotations.getPredictions(tree2).get(prediction); if (score1 < score2) { return -1; } else if (score1 > score2) { return 1; } else { return 0; } }; }
/** * Returns the index with the highest value in the {@code predictions} matrix. * Indexed from 0. */ private static int getPredictedClass(SimpleMatrix predictions) { int argmax = 0; for (int i = 1; i < predictions.getNumElements(); ++i) { if (predictions.get(i) > predictions.get(argmax)) { argmax = i; } } return argmax; }
public static List<Double> getPredictionsAsStringList(Tree tree) { SimpleMatrix predictions = getPredictions(tree); List<Double> listOfPredictions = new ArrayList<>(); for (int i = 0 ; i < predictions.numRows() ; i++) { listOfPredictions.add(predictions.get(i)); } return listOfPredictions; }
public static void outputMatrix(BufferedWriter bout, SimpleMatrix matrix) throws IOException { for (int i = 0; i < matrix.getNumElements(); ++i) { bout.write(" " + matrix.get(i)); } bout.newLine(); }
public String toString() { StringBuilder result = new StringBuilder(); for (int prediction = 0; prediction < numClasses; ++prediction) { result.append("Best scores for class " + prediction + "\n"); Map<Integer, PriorityQueue<Tree>> ngrams = classToNGrams.get(prediction); for (Map.Entry<Integer, PriorityQueue<Tree>> entry : ngrams.entrySet()) { List<Tree> trees = Generics.newArrayList(entry.getValue()); Collections.sort(trees, scoreComparator(prediction)); result.append(" Len " + entry.getKey() + "\n"); for (int i = trees.size() - 1; i >= 0; i--) { Tree tree = trees.get(i); result.append(" " + SentenceUtils.listToString(tree.yield()) + " [" + RNNCoreAnnotations.getPredictions(tree).get(prediction) + "]\n"); } } } return result.toString(); } }
/** * Given a sequence of iterators over the matrices, builds a vector * out of those matrices in the order given. Asks for an expected * total size as a time savings. AssertionError thrown if the * vector sizes do not exactly match. */ @SafeVarargs public static double[] paramsToVector(int totalSize, Iterator<SimpleMatrix> ... matrices) { double[] theta = new double[totalSize]; int index = 0; for (Iterator<SimpleMatrix> matrixIterator : matrices) { while (matrixIterator.hasNext()) { SimpleMatrix matrix = matrixIterator.next(); int numElements = matrix.getNumElements(); //System.out.println(Integer.toString(numElements)); // to know what matrices are for (int i = 0; i < numElements; ++i) { theta[index] = matrix.get(i); ++index; } } } if (index != totalSize) { throw new AssertionError("Did not entirely fill the theta vector: expected " + totalSize + " used " + index); } return theta; }
/** Return as a double the probability of the predicted class. If it is not defined for a node, * it will return -1 * * @return Either the label probability or -1.0 if none */ public static double getPredictedClassProb(Label label) { if (!(label instanceof CoreLabel)) { throw new IllegalArgumentException("CoreLabels required to get the attached predicted class probability"); } Integer val = ((CoreLabel) label).get(PredictedClass.class); SimpleMatrix predictions = ((CoreLabel) label).get(Predictions.class); if (val != null) { return predictions.get(val); } else { return -1.0; } }
/** * Given a sequence of iterators over the matrices, builds a vector * out of those matrices in the order given. The vector is scaled * according to the <code>scale</code> parameter. Asks for an * expected total size as a time savings. AssertionError thrown if * the vector sizes do not exactly match. */ @SafeVarargs public static double[] paramsToVector(double scale, int totalSize, Iterator<SimpleMatrix> ... matrices) { double[] theta = new double[totalSize]; int index = 0; for (Iterator<SimpleMatrix> matrixIterator : matrices) { while (matrixIterator.hasNext()) { SimpleMatrix matrix = matrixIterator.next(); int numElements = matrix.getNumElements(); for (int i = 0; i < numElements; ++i) { theta[index] = matrix.get(i) * scale; ++index; } } } if (index != totalSize) { throw new AssertionError("Did not entirely fill the theta vector: expected " + totalSize + " used " + index); } return theta; }
/** * Applies log to each of the entries in the matrix. Returns a new matrix. */ public static SimpleMatrix elementwiseApplyLog(SimpleMatrix input) { SimpleMatrix output = new SimpleMatrix(input); for (int i = 0; i < output.numRows(); ++i) { for (int j = 0; j < output.numCols(); ++j) { output.set(i, j, Math.log(output.get(i, j))); } } return output; }
/** * Outputs the vectors from the tree. Counts the tree nodes the * same as setIndexLabels. */ private static int outputTreeVectors(PrintStream out, Tree tree, int index) { if (tree.isLeaf()) { return index; } out.print(" " + index + ':'); SimpleMatrix vector = RNNCoreAnnotations.getNodeVector(tree); for (int i = 0; i < vector.getNumElements(); ++i) { out.print(" " + NF.format(vector.get(i))); } out.println(); index++; for (Tree child : tree.children()) { index = outputTreeVectors(out, child, index); } return index; }
/** * Applies ReLU to each of the entries in the matrix. Returns a new matrix. */ public static SimpleMatrix elementwiseApplyReLU(SimpleMatrix input) { SimpleMatrix output = new SimpleMatrix(input); for (int i = 0; i < output.numRows(); ++i) { for (int j = 0; j < output.numCols(); ++j) { output.set(i, j, Math.max(0, output.get(i, j))); } } return output; }
/** * Outputs the scores from the tree. Counts the tree nodes the * same as setIndexLabels. */ private static int outputTreeScores(PrintStream out, Tree tree, int index) { if (tree.isLeaf()) { return index; } out.print(" " + index + ':'); SimpleMatrix vector = RNNCoreAnnotations.getPredictions(tree); for (int i = 0; i < vector.getNumElements(); ++i) { out.print(" " + NF.format(vector.get(i))); } out.println(); index++; for (Tree child : tree.children()) { index = outputTreeScores(out, child, index); } return index; }
/** * Just for some debug informations in order to compare the results with the scilab computation program. * @param name the name of the matrix * @param m the matrix to print out * @return the String format of the matrix to easily input it to Scilab */ public String toScilabString(String name, SimpleMatrix m) { String result = name + " = ["; for(int i=0;i<m.numRows();++i) { for(int j=0;j<m.numCols();++j) { result += m.get(i, j) + " "; } result += ";"; } return result; }
private static SimpleTensor getTensorGradient(SimpleMatrix deltaFull, SimpleMatrix leftVector, SimpleMatrix rightVector) { int size = deltaFull.getNumElements(); SimpleTensor Wt_df = new SimpleTensor(size*2, size*2, size); // TODO: combine this concatenation with computeTensorDeltaDown? SimpleMatrix fullVector = NeuralUtils.concatenate(leftVector, rightVector); for (int slice = 0; slice < size; ++slice) { Wt_df.setSlice(slice, fullVector.scale(deltaFull.get(slice)).mult(fullVector.transpose())); } return Wt_df; }
/** * Compute dot product between two vectors. */ public static double dot(SimpleMatrix vector1, SimpleMatrix vector2){ if(vector1.numRows()==1){ // vector1: row vector, assume that vector2 is a row vector too return vector1.mult(vector2.transpose()).get(0); } else if (vector1.numCols()==1){ // vector1: col vector, assume that vector2 is also a column vector. return vector1.transpose().mult(vector2).get(0); } else { throw new AssertionError("Error in neural.Utils.dot: vector1 is a matrix " + vector1.numRows() + " x " + vector1.numCols()); } }
private static SimpleMatrix computeTensorDeltaDown(SimpleMatrix deltaFull, SimpleMatrix leftVector, SimpleMatrix rightVector, SimpleMatrix W, SimpleTensor Wt) { SimpleMatrix WTDelta = W.transpose().mult(deltaFull); SimpleMatrix WTDeltaNoBias = WTDelta.extractMatrix(0, deltaFull.numRows() * 2, 0, 1); int size = deltaFull.getNumElements(); SimpleMatrix deltaTensor = new SimpleMatrix(size*2, 1); SimpleMatrix fullVector = NeuralUtils.concatenate(leftVector, rightVector); for (int slice = 0; slice < size; ++slice) { SimpleMatrix scaledFullVector = fullVector.scale(deltaFull.get(slice)); deltaTensor = deltaTensor.plus(Wt.getSlice(slice).plus(Wt.getSlice(slice).transpose()).mult(scaledFullVector)); } return deltaTensor.plus(WTDeltaNoBias); }
/** * Returns a column vector where each entry is the nth bilinear * product of the nth slices of the two tensors. */ public SimpleMatrix bilinearProducts(SimpleMatrix in) { if (in.numCols() != 1) { throw new AssertionError("Expected a column vector"); } if (in.numRows() != numCols) { throw new AssertionError("Number of rows in the input does not match number of columns in tensor"); } if (numRows != numCols) { throw new AssertionError("Can only perform this operation on a SimpleTensor with square slices"); } SimpleMatrix inT = in.transpose(); SimpleMatrix out = new SimpleMatrix(numSlices, 1); for (int slice = 0; slice < numSlices; ++slice) { double result = inT.mult(slices[slice]).mult(in).get(0); out.set(slice, result); } return out; }
/** * Applies tanh to each of the entries in the matrix. Returns a new matrix. */ public static SimpleMatrix elementwiseApplyTanh(SimpleMatrix input) { SimpleMatrix output = new SimpleMatrix(input); for (int i = 0; i < output.numRows(); ++i) { for (int j = 0; j < output.numCols(); ++j) { output.set(i, j, Math.tanh(output.get(i, j))); } } return output; }
/** * Applies softmax to all of the elements of the matrix. The return * matrix will have all of its elements sum to 1. If your matrix is * not already a vector, be sure this is what you actually want. */ public static SimpleMatrix softmax(SimpleMatrix input) { SimpleMatrix output = new SimpleMatrix(input); for (int i = 0; i < output.numRows(); ++i) { for (int j = 0; j < output.numCols(); ++j) { output.set(i, j, Math.exp(output.get(i, j))); } } double sum = output.elementSum(); // will be safe, since exp should never return 0 return output.scale(1.0 / sum); }