/// <summary> /// Gets the pre-selection triphone for each leaf nodes in pre-selection forest. /// </summary> /// <param name="forest">The pre-selection forest.</param> /// <param name="labels">The given list of the labels in training set.</param> /// <returns>A Dictionary whose key is a Label to indicate a triphone, whose value is leaf nodes in forest.</returns> public static Dictionary<Label, DecisionTreeNode> GetPreselectionTriphone(this DecisionForest forest, List<Label> labels) { Dictionary<Label, DecisionTreeNode> triphoneToNode = new Dictionary<Label, DecisionTreeNode>(); // In order to get the all pre-selection tri-phone, all full-context label in training set will be visited. foreach (Label label in labels) { // Get the tri-phone label from the full-context label. Label triphone = new Label(label); triphone.ResizeFeatureValue(LabelFeatureNameSet.Triphone); // If the tri-phone exists, it can be ignored. However, we can process it again to perform verifications. if (!triphoneToNode.ContainsKey(triphone)) { // Travel the forest using the full-context label to get the matched leaf nodes. List<DecisionTreeNode> nodes = FilterDecisionForest(forest, label); // Please notice: in pre-selection tree, each label only match one leaf node since the pre-selection tree is clustered by phone model. if (nodes.Count != 1) { throw new InvalidDataException("The forest is not a invalid pre-selection forest."); } triphoneToNode.Add(triphone, nodes[0]); } } return triphoneToNode; }
/// <summary> /// Extracts the features of the given utterance. /// </summary> /// <param name="sentId"> /// Sentence id. /// </param> /// <param name="utterance"> /// Service Provider utterance object. /// </param> /// <returns> /// The sentence contains all the features. /// </returns> /// <exception cref="InvalidDataException"> /// Exception. /// </exception> public Sentence Extract(string sentId, TtsUtterance utterance) { List<FeatureVector> vectors; try { // Then, extracts the features. vectors = ExtractionEngine.Extract(utterance, FeatureMetas); } catch (EspException e) { throw new InvalidDataException(Helper.NeutralFormat("Extract feature error on sentence \"{0}\"", sentId), e); } // Validates the extracted vectors. if (vectors.Count != FeatureMetas.Count) { throw new InvalidDataException( Helper.NeutralFormat("Length of result is mismatch on sentence \"{0}\"", sentId)); } for (int i = 0; i < vectors.Count; i++) { if (vectors[i].Count != utterance.Phones.Count) { throw new InvalidDataException( Helper.NeutralFormat("Length of vector is mismatch on sentence \"{0}\"", sentId)); } } // Creates a sentence to store all the features. Sentence sentence = new Sentence { Id = sentId }; for (int i = 0; i < vectors[0].Count; ++i) { // Create candidates for each phoneme. PhoneSegment p = new PhoneSegment { Sentence = sentence, Index = i, Features = vectors.Select(v => v[i]) .Skip(LabelFeatureNameSet.MandatoryFeatureNames.Length).ToArray(), }; // Create the label to store the features. Label label = new Label(FeatureNameSet); for (int j = 0; j < vectors.Count; ++j) { if (vectors[j][i].ValueType == FeatureValueType.FEATURE_VALUE_TYPE_UNKOWN) { label.SetFeatureValue(FeatureNameSet.FeatureNames[j], Label.NotApplicableFeatureValue); } else if (FeatureMetas[j].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_PHONE_ID) { Phone phone = PhoneSet.GetPhone(vectors[j][i].IntValue); label.SetFeatureValue(FeatureNameSet.FeatureNames[j], Offline.Phoneme.ToHtk(phone.Name)); } else { label.SetFeatureValue(FeatureNameSet.FeatureNames[j], vectors[j][i].IntValue.ToString(CultureInfo.InvariantCulture)); } // Updates the corresponding value records. FeatureValueRecords[j].Update(vectors[j][i]); } p.Label = label; sentence.PhoneSegments.Add(p); } return sentence; }
/// <summary> /// Build cross correlation matrix. /// </summary> /// <param name="phoneList">Mono phone list.</param> /// <returns>Cross correlation matrix.</returns> public List<Pair<CandidateGroup, CandidateGroup>> BuildCCMatrix(IEnumerable<string> phoneList) { List<Pair<CandidateGroup, CandidateGroup>> matrix = new List<Pair<CandidateGroup, CandidateGroup>>(); foreach (CandidateGroup group in CandidateGroups) { Label label = new Label(LabelFeatureNameSet.Triphone) { Text = group.Name }; foreach (string phone in phoneList) { string triphone = Helper.NeutralFormat("{0}-{1}+{2}", label.CentralPhoneme, label.RightPhoneme, phone); if (_nameIndexedCandidateGroup.ContainsKey(triphone)) { Pair<CandidateGroup, CandidateGroup> pair = new Pair<CandidateGroup, CandidateGroup>(group, _nameIndexedCandidateGroup[triphone]); matrix.Add(pair); } } } return matrix; }
/// <summary> /// Finds the corresponding candidate in the given sentence set. /// </summary> /// <param name="sentenceSet">The given sentence set.</param> /// <param name="sentId">The sentence id which contains the candidate.</param> /// <param name="indexOfNonSilence">The index of non-silence unit of the candidate.</param> /// <param name="label">The label of the candidate.</param> /// <returns>The corresponding candidate.</returns> private static UnitCandidate FindCandidate(TrainingSentenceSet sentenceSet, string sentId, int indexOfNonSilence, string label) { if (!sentenceSet.Sentences.ContainsKey(sentId)) { throw new InvalidDataException(Helper.NeutralFormat("Cannot find the sentence \"{0}\"", sentId)); } Sentence sentence = sentenceSet.Sentences[sentId]; UnitCandidate result = null; foreach (UnitCandidate candidate in sentence.Candidates) { if (candidate.IndexOfNonSilence == indexOfNonSilence) { result = candidate; break; } } if (result == null) { throw new InvalidDataException(Helper.NeutralFormat("Cannot find the candidate \"{0}:{1}\"", sentId, indexOfNonSilence)); } Label myLabel = new Label { Text = label }; if (result.Label.CentralPhoneme != myLabel.CentralPhoneme) { throw new InvalidDataException( Helper.NeutralFormat( "Mismatched full-context label, expected current phone \"{0}\" but \"{1}\"", result.Label.CentralPhoneme, myLabel.CentralPhoneme)); } return result; }
/// <summary> /// Gets the all leaf nodes which can match the given label in the decision forst. /// </summary> /// <param name="forest">The given decision forest.</param> /// <param name="label">The given label.</param> /// <returns>A List object contains all the matched leaf nodes.</returns> public static List<DecisionTreeNode> FilterDecisionForest(this DecisionForest forest, Label label) { List<DecisionTreeNode> nodes = new List<DecisionTreeNode>(); // For each decision tree in forest, it need to be traveled. foreach (DecisionTree tree in forest.TreeList) { // Firstly, the tree should be matched by phone name if it is a phone-dependent tree. bool matched; string phone = tree.Phone; if (Phoneme.IsAnyPhone(phone)) { matched = true; } else { matched = label.CentralPhoneme == phone; } if (matched) { // Travel the matched tree, each tree will return a single leaf node. nodes.Add(FilterTree(tree.NodeList[0], forest.Questions, label)); } } return nodes; }
/// <summary> /// Gets the all possible tri-phone from this set. /// </summary> /// <returns>The list of Label object to hold the tri-phone.</returns> public List<Label> GetAllTriphone() { List<Label> list = new List<Label>(); foreach (string left in LeftPhones) { foreach (string central in CentralPhones) { foreach (string right in RightPhones) { Label label = new Label(LabelFeatureNameSet.Triphone); label.LeftPhoneme = left; label.CentralPhoneme = central; label.RightPhoneme = right; list.Add(label); } } } return list; }
/// <summary> /// Filters a tree to get the leaf node. /// </summary> /// <param name="node">The first node of the tree.</param> /// <param name="questions">A Dictionary to contains all the Question used by the tree.</param> /// <param name="label">The given label.</param> /// <returns>The leaf node which match the label.</returns> public static DecisionTreeNode FilterTree(DecisionTreeNode node, IDictionary<string, Question> questions, Label label) { while (node.NodeType != DecisionTreeNodeType.Leaf) { Question question = questions[node.QuestionName]; // If the value set of question contains the feature value, it means matched with question mark. if (MatchHtsQuestion(question.ValueSet, label.GetFeatureValue(question.FeatureName))) { node = node.RightChild; } else { node = node.LeftChild; } } return node; }
/// <summary> /// Initializes a new instance of the Label class as a copy of the given one. /// </summary> /// <param name="label">The given label to copy.</param> public Label(Label label) { _featureNames = label._featureNames; Text = label.Text; }