/// <summary>Add tensors from the second map to the first map, in place.</summary> public static void AddTensors(TwoDimensionalMap <string, string, SimpleTensor> first, TwoDimensionalMap <string, string, SimpleTensor> second) { foreach (TwoDimensionalMap.Entry <string, string, SimpleTensor> entry in first) { if (second.Contains(entry.GetFirstKey(), entry.GetSecondKey())) { first.Put(entry.GetFirstKey(), entry.GetSecondKey(), entry.GetValue().Plus(second.Get(entry.GetFirstKey(), entry.GetSecondKey()))); } } foreach (TwoDimensionalMap.Entry <string, string, SimpleTensor> entry_1 in second) { if (!first.Contains(entry_1.GetFirstKey(), entry_1.GetSecondKey())) { first.Put(entry_1.GetFirstKey(), entry_1.GetSecondKey(), entry_1.GetValue()); } } }
/// <summary>The traditional way of initializing an empty model suitable for training.</summary> public SentimentModel(RNNOptions op, IList <Tree> trainingTrees) { this.op = op; rand = new Random(op.randomSeed); if (op.randomWordVectors) { InitRandomWordVectors(trainingTrees); } else { ReadWordVectors(); } if (op.numHid > 0) { this.numHid = op.numHid; } else { int size = 0; foreach (SimpleMatrix vector in wordVectors.Values) { size = vector.GetNumElements(); break; } this.numHid = size; } TwoDimensionalSet <string, string> binaryProductions = TwoDimensionalSet.HashSet(); if (op.simplifiedModel) { binaryProductions.Add(string.Empty, string.Empty); } else { // TODO // figure out what binary productions we have in these trees // Note: the current sentiment training data does not actually // have any constituent labels throw new NotSupportedException("Not yet implemented"); } ICollection <string> unaryProductions = Generics.NewHashSet(); if (op.simplifiedModel) { unaryProductions.Add(string.Empty); } else { // TODO // figure out what unary productions we have in these trees (preterminals only, after the collapsing) throw new NotSupportedException("Not yet implemented"); } this.numClasses = op.numClasses; identity = SimpleMatrix.Identity(numHid); binaryTransform = TwoDimensionalMap.TreeMap(); binaryTensors = TwoDimensionalMap.TreeMap(); binaryClassification = TwoDimensionalMap.TreeMap(); // When making a flat model (no symantic untying) the // basicCategory function will return the same basic category for // all labels, so all entries will map to the same matrix foreach (Pair <string, string> binary in binaryProductions) { string left = BasicCategory(binary.first); string right = BasicCategory(binary.second); if (binaryTransform.Contains(left, right)) { continue; } binaryTransform.Put(left, right, RandomTransformMatrix()); if (op.useTensors) { binaryTensors.Put(left, right, RandomBinaryTensor()); } if (!op.combineClassification) { binaryClassification.Put(left, right, RandomClassificationMatrix()); } } numBinaryMatrices = binaryTransform.Size(); binaryTransformSize = numHid * (2 * numHid + 1); if (op.useTensors) { binaryTensorSize = numHid * numHid * numHid * 4; } else { binaryTensorSize = 0; } binaryClassificationSize = (op.combineClassification) ? 0 : numClasses * (numHid + 1); unaryClassification = Generics.NewTreeMap(); // When making a flat model (no symantic untying) the // basicCategory function will return the same basic category for // all labels, so all entries will map to the same matrix foreach (string unary in unaryProductions) { unary = BasicCategory(unary); if (unaryClassification.Contains(unary)) { continue; } unaryClassification[unary] = RandomClassificationMatrix(); } numUnaryMatrices = unaryClassification.Count; unaryClassificationSize = numClasses * (numHid + 1); }