<span style="font-size:24px;">public class Lattice Aisee是一个图形可视化工具。具体情况请看:http://www.AbsInt.com 提供了识别的lattices 结果(results)。Lattice是从Result类所创建,创建的lattice可以是局部的也可以完整的。 Lattices describe all theories considered by the Recognizer that have not been pruned out。Lattice描述的是被识别器所考虑的所有未被剪枝的理论。 Lattice是一个包含节点和边所组成的有向图。一个节点代表了特定时间内所说的一个字。一条边对应于一个字跟随另一个字的得分。通常的result结果脚本是贯通lattice的有着最高得分路径的节点的序列。Lattice是一个非常有用的工具用来分析“alternate results”即可选择的结果。 一个lattice网格对象从一个有这全标记数的result结果对象产生。目前,仅有WordPruningBreadthFirstSearchManager类有一个AlternativeHypothesisManager。此外,构造lattice的代码仅在语言学家中起作用,在字搜索状态在iswordstart方法中返回为false处,在字的状态出现在语言学家字的结束处。所有lattice应该是来自与lextreelinguist和WordPruningBreadthFirstSearchManager的结果所创建。 Lattice网格也能够被一个收缩状态的标记token树和它的 AlternativeHypothesisManager所创建。一般,在两个字token标记之间是一系列的其它类型状态的token,例如:单元状态,hmm状态。使用’w’表示字token标记,u为单元标记,h为hmm标记,则一个标记链如下: W - U - H - H - H - H - U - H - H - H - H - W 一般hmm标记包含声学得分,字标记包含语言得分。如果我们想知道在任何两个字之间的声学和语言得分,则保留单元和hmm标记是有必要的。因此对于使用它们的声学得分和语言得分被collapsed“收缩成”一个token标记。如此看上去为如下所示: W - P - W 其中p为一标记表示在两个字之间的路径,p包含在两字之间的声学和语言得分。这是一个lattice类所期待的典型的collapsed token tree即收缩标记树。一般收缩标记树的任务是由WordPruningBreadthFirstSearchManager类或对象所完成的。一棵收缩的标记树看上去如下所示: "cat" - P - </s> / P / <s> - P - "a" - P - "big" \ P \ "dog" - P - </s> 当一个lattice对象被一个result对象所创建,以上的用可选择的假设all代替a的收缩的标记树,将会转化为看上去如下的lattice: "a" "cat" / \ / \ <s> "big" - </s> \ / \ / "all" "dog" 开始或首先,一个lattice网格对象可以有冗余的节点,也就是有表示相同字来源于相同前续节点的节点。这些节点被collapsed 收缩通过使用latticeoptimizer,即网格优化器。 本类的属性: protected Node initialNode;初始节点 protected Node terminalNode;终止节点 protected Set<Edge> edges;边集 protected Map<String, Node> nodes;节点map protected double logBase;log基 protected LogMath logMath; private Set<Token> visitedWordTokens;已经访问过的标记集 private AlternateHypothesisManager loserManager;可选择假设选择管理。 本类的构造方法: protected Lattice();创建一个空的lattice网格。 public Lattice(LogMath logMath);创建一个空的lattice。 public Lattice(Result result);从result对象创建一个lattice对象。Lattice网格从result所引用的token树所所创建。然后lattice被优化即被collapsed 化。 本类的方法: private Node getNode(Token token);返回与给定字标记相关的节点为字节点。输入参数:token为我们想要的节点的标记。 private String getNodeID(Token token);返回的是与给定标记token相关的节点的id。返回的是此节点的id。本方法分为两种情况,一是:与token相关的节点存在与nodes中的情况,存在则返回此节点,2是token相关的节点不存在于nodes中的情况,则新建与token相关的节点,并加入nodes中,返回新建的节点。 protected void addNode(Node n);把给定的输入节点添加入lattice的节点集中即nodes属性中。此nodes不存在着输入节点时加入,否则不加入。 protected boolean hasNode(String ID);参数:id为查找节点的id。即lattice即nodes属性中存在着与输入id相关的节点返回为true。否则为false。检测lattice是否已经包含与一个给定token相关的一个节点。 boolean hasNode(Node node);检测lattice是否包含给定的节点,即nodes属性中是否存在此输入节点,存在则返回为true。 boolean hasEdge(Edge edge);检测lattice是否包含给定的边,即edges属性是否包含输入的边,存在则返回为true。否则为false。 protected Node addNode(Token token, int beginTime, int endTime);根据来自于result标记树中与节点相关的标记,以及开始和结束时间来添加节点入lattice的节点集中。一般一个标记应该引用一个是字搜索状态的搜索状态,尽管其他的标记也许是用来调试的。 public Node addNode(Word word, int beginTime, int endTime) ;添加一个给定字表示,加入时间和结束时间的节点入lattice的nodes属性中。 protected Node addNode(String id, Word word, int beginTime, int endTime);此方法用于从.LAT文件中装载lattice时使用,添加给定节点的id,字,开始和结束时间的节点入lattice的nodes属性中。 public Node addNode(String id, String word, int beginTime, int endTime);此方法用于从.LAT文件中装载lattice时使用,添加给定节点的id,字的字符串表示,开始和结束时间的节点入lattice的nodes属性中。 public Edge addEdge(Node fromNode, Node toNode,double acousticScore, double lmScore);添加一给定起始节点,目标节点,及其声学和语言得分的边到lattice的边集中即Edges中,并返回此边。起始节点和目标节点都添加了此边。 public Lattice(String fileName);从一个LAT文件创建一个lattice网格。LAT文件是由Lattice.dump()方法所创建的。对lattice的相关属性进行了设置。此方法一般先创建一个空的lattice,在根据此方法来对空的lattice进行设置。以便使之成为非空的。 private void collapseWordPath(Node parentWordNode, Token token,float acousticScore, float languageScore);输入参数:parentWordNode为返回边的目标节点。Token的节点为边的开始节点,此token的前续token被parentWordNode所表示。acousticScore为直到并包括token的祖先(parent)前续的声学得分。languageScore为为直到并包括token的祖先(parent)前续的语言得分。:如果此标记是表示一个字,则创建一个节点为此标记,然后创建一条从创建的节点指向parentWordNode节点的边。收缩到此标记结束的token标记序列。我们已经到达了句的开始标记。如果是一个非字标记,则仅仅添加声学和语言得分到当前的得分(和得分)上,然后移动到此标记的前续标记。快速移动通过那些不感兴趣的状态来节省栈空间。对所有的丢失的token也进行相同的处理。 private void collapseWordToken(Token token);collapse收缩给定的字结束标记。这意味着收缩此标记所表示的字相关的所有单元和hmm标记入一条lattice的弧中。即字的所有单元及hmm标记用一条弧表示。 protected void removeNode(Node n);从lattice的nodes中移除给定节点。 protected Node getNode(String id);获得与输入id相关的节点,是通过nodes来获得的。 protected Collection<Node> getCopyOfNodes();获得lattice中的nodes属性的一份拷贝。返回的是节点的Collection。此方法被LatticeOptimizer类对象所使用来防止并发的修改节点列表。即防止同时修改。(在多线程使用。) public Collection<Node> getNodes();返回的是所有节点的Collection,即nodes.values()。 protected void removeEdge(Edge e);从lattice的Edges属性中移除给定输入的边,即移除给定的边。 public Collection<Edge> getEdges();得到所有的边的集合即edges属性。 public void dumpAISee(String fileName, String title);以Aisee理解的方式打印此lattice到指定的文件中。Aisee是一个图形可视化工具。具体情况请看:http://www.AbsInt.com public void dumpDot(String fileName, String title);以 Graphviz理解的方式打印此lattice到指定的文件中。Graphviz的具体情况请看: http://graphviz.org/ protected void dump(PrintWriter out);以LAT文件的形式打印lattice。 public void dump(String file) ;以LAT文件的形式打印lattice。为了测试和实现用于把lattice存储在ASCII文件中即当做ASCII文件存储。 protected void removeNodeAndEdges(Node n);移除从lattice中一个通过输入给定节点以及与此节点相连的所有的边。移除后检测了一致性。仅是从lattice的边集合节点集中移除相应的项。 protected void removeNodeAndCrossConnectEdges(Node n);从lattice中移除通过输入给定节点及相连的边,用边连接连接要移除的节点的所有节点。给予如下例子: Nodes A, B, X, M, N Edges A-->X, B-->X, X-->M, X-->N Removing and cross connecting X would result in Nodes A, B, M, N Edges A-->M, A-->N, B-->M, B-->N public Node getInitialNode();获得此lattice的初始节点,一般为<s>符号。 public void setInitialNode(Node p_initialNode);为此lattice设置初始节点,一般为<s>符号。 public Node getTerminalNode();获得此lattice的终止节点。一般为</s>符号. public void setTerminalNode(Node p_terminalNode);为此lattice设置终止节点,一般为</s>符号。 public double getLogBase();获得logmath所使用的基。 public LogMath getLogMath();获得在lattice中使用的logmath。 public void setLogMath(LogMath logMath);设置使用的logmath。 protected List<String> allPathsFrom(String path, Node n);符号的是节点列表的一个列表。用于产生从给定的输入节点开始的内部路径包括从此节点开始的所有路径。直接和间接节点所组成的直到每一条路的终止节点为止。 public List<String> allPaths();产生从开始节点开始的所有路径,产生的是通过此lattice的所有路径列表。在此方法中调用了allPathsFrom("", initialNode)方法。 public void dumpAllPaths();打印出通过此lattice的所有路径。用于调试。 boolean checkConsistency();一致性检查,即lattice中的nodes中的节点与edges中的边是否完整的对应。必须完整对应返回为true,否则抛出错误。 protected void sortHelper(Node n, List<Node> sorted, Set<Node> visited);对此节点及所有的后续(直接和间接)节点进行sort,即放入输入的sorted中,已经访问过的所有节点放入输入的visited中。从右到左的形式 public List<Node> sortNodes();拓扑分类(sort)在lattice中的所有节点。返回的拓扑sort后的所有节点的列表。以lattice图的从左到右的形式。 boolean isFillerNode(Node node);此节点是否表示填充节点即节点字的拼写是否等于<sil>。 public void removeFillers();移除在lattice中所有填充字的节点,并用边连接移除节点的前续和后续节点。检测了一致性。 private boolean checkNodesEquivalent(Node n1, Node n2);输入参数:n1为第一个lattice的开始节点。n2为第二个lattice的开始节点。如果这两个lattice相等则返回为true。本方法会迭代的检查两个lattice的所有子节点,直到两lattice的节点不存在子节点为止。它们的所有节点和边都相等才会返回true。 public boolean isEquivalent(Lattice other);把此lattice与给定的输入lattice对象比较,看它们是否相等,相等返回true。 private double computeEdgeScore(Edge edge, float languageModelWeightAdjustment,boolean useAcousticScoresOnly);计算给定边的得分。它乘以一个调整因子,因为语言模型得分被在语言学家中的语言模型权重所scored(比例化)。参数: edge为要计算得分的边。languageModelWeightAdjustment为用于已经被语言模型权重比例化scale的语言得分的权重乘数。useAcousticScoresOnly为是否只使用声学得分。返回edge.getAcousticScore() + edge.getLMScore() * languageModelWeightAdjustment 或edge.getAcousticScore(); public List<Node> getViterbiPath();获得此lattice的MAP 路径,仅在computeNodePosteriors方法调用时才会起作用。返回的是表示MAP 路径的节点列表。 public void computeNodePosteriors(float languageModelWeightAdjustment,boolean useAcousticScoresOnly);为在lattice中的每一个节点计算utterance(句)层次上的后验概率。也就是此节点发生在通过lattice的所有路径上的概率。使用用了一个前向-后向算法来确定非循环的从左到右的lattice结构的特性。对于节点层次的节点后验概率通过节点对象的getPosterior()方法获得。languageModelWeightAdjustment为用于已经被语言模型权重比例化scale的语言得分的权重乘数。useAcousticScoresOnly为是否仅使用声学得分来计算后验概率而忽视语言模型权重和得分。此方法分为3本方,前向,后向,inner三部分。 public void computeNodePosteriors(float languageModelWeightAdjustment) { computeNodePosteriors(languageModelWeightAdjustment, false); }计算utterance层次的节点的后验概率。 public void computeNodePosteriors(float languageModelWeightAdjustment, boolean useAcousticScoresOnly) { if (initialNode == null) return; //forward initialNode.setForwardScore(LogMath.getLogOne()); initialNode.setViterbiScore(LogMath.getLogOne()); List<Node> sortedNodes = sortNodes(); assert sortedNodes.get(0) == initialNode; for (Node currentNode : sortedNodes) { for (Edge edge : currentNode.getLeavingEdges()) { double forwardProb = edge.getFromNode().getForwardScore(); double edgeScore = computeEdgeScore (edge, languageModelWeightAdjustment, useAcousticScoresOnly); forwardProb += edgeScore; edge.getToNode().setForwardScore (logMath.addAsLinear ((float) forwardProb, (float) edge.getToNode().getForwardScore())); double vs = edge.getFromNode().getViterbiScore() + edgeScore; if (edge.getToNode().getBestPredecessor() == null || vs > edge.getToNode().getViterbiScore()) { edge.getToNode().setBestPredecessor(currentNode); edge.getToNode().setViterbiScore(vs); } } } //backward terminalNode.setBackwardScore(LogMath.getLogOne()); assert sortedNodes.get(sortedNodes.size() - 1) == terminalNode; ListIterator<Node> n = sortedNodes.listIterator(sortedNodes.size() - 1); while (n.hasPrevious()) { Node currentNode = n.previous(); Collection<Edge> currentEdges = currentNode.getLeavingEdges(); for (Edge edge : currentEdges) { double backwardProb = edge.getToNode().getBackwardScore(); backwardProb += computeEdgeScore (edge, languageModelWeightAdjustment, useAcousticScoresOnly); edge.getFromNode().setBackwardScore (logMath.addAsLinear((float) backwardProb, (float) edge.getFromNode().getBackwardScore())); } } //inner double normalizationFactor = terminalNode.getForwardScore(); for (Node node : nodes.values()) { node.setPosterior((node.getForwardScore() + node.getBackwardScore()) - normalizationFactor); } }</span>