wordpruningbreadthfirstsearchmanager.java
来自「It is the Speech recognition software. 」· Java 代码 · 共 1,685 行 · 第 1/4 页
JAVA
1,685 行
/** * Gets the initial grammar node from the linguist and creates a * GrammarNodeToken */ protected void localStart() { SearchGraph searchGraph = linguist.getSearchGraph(); currentFrameNumber = 0; curTokensScored.value = 0; skewMap = new HashMap(); numStateOrder = searchGraph.getNumStateOrder(); activeListManager.setNumStateOrder(numStateOrder); if (buildWordLattice) { loserManager = new AlternateHypothesisManager(maxLatticeEdges); } SearchState state = searchGraph.getInitialState(); activeList = activeListManager.getEmittingList(); activeList.add(new Token(state, currentFrameNumber)); resultList = new LinkedList(); bestTokenMap = new HashMap(); growBranches(); growNonEmittingLists(); // tokenTracker.setEnabled(false); // tokenTracker.startUtterance(); } /** * Local cleanup for this search manager */ protected void localStop() { // tokenTracker.stopUtterance(); } /** * Goes through the active list of tokens and expands each token, finding * the set of successor tokens until all the successor tokens are emitting * tokens. * */ protected void growBranches() { growTimer.start(); Iterator iterator = activeList.iterator(); float relativeBeamThreshold = activeList.getBeamThreshold(); if (logger.isLoggable(Level.FINE)) { logger.fine("Frame: " + currentFrameNumber + " thresh : " + relativeBeamThreshold + " bs " + activeList.getBestScore() + " tok " + activeList.getBestToken()); } while (iterator.hasNext()) { Token token = (Token) iterator.next(); if (token.getScore() >= relativeBeamThreshold && skewPrune(token)) { collectSuccessorTokens(token); } } growTimer.stop(); // activeListManager.dump(); } /** * Grows the emitting branches. This version applies a simple acoustic * lookahead based upon the rate of change in the current acoustic score. */ protected void growEmittingBranches() { if (acousticLookaheadFrames > 0F) { growTimer.start(); float bestScore = -Float.MAX_VALUE; for (Iterator i = activeList.iterator(); i.hasNext();) { Token t = (Token) i.next(); float score = t.getScore() + t.getAcousticScore() * acousticLookaheadFrames; if (score > bestScore) { bestScore = score; } t.setWorkingScore(score); } float relativeBeamThreshold = bestScore + relativeBeamWidth; for (Iterator i = activeList.iterator(); i.hasNext();) { Token t = (Token) i.next(); if (t.getWorkingScore() >= relativeBeamThreshold) { collectSuccessorTokens(t); } } growTimer.stop(); } else { growBranches(); } } /** * Grow the non-emitting ActiveLists, until the tokens reach an emitting * state. */ private void growNonEmittingLists() { for (Iterator i = activeListManager.getNonEmittingListIterator(); i .hasNext();) { activeList = (ActiveList) i.next(); if (activeList != null) { i.remove(); pruneBranches(); growBranches(); } } } /** * Calculate the acoustic scores for the active list. The active list * should contain only emitting tokens. * * @return <code>true</code> if there are more frames to score, * otherwise, false * */ protected boolean scoreTokens() { boolean moreTokens; Token bestToken = null; scoreTimer.start(); bestToken = (Token) scorer.calculateScores(activeList.getTokens()); scoreTimer.stop(); moreTokens = (bestToken != null); activeList.setBestToken(bestToken); // monitorWords(activeList); monitorStates(activeList); if (false) { System.out.println("BEST " + bestToken); } curTokensScored.value += activeList.size(); totalTokensScored.value += activeList.size(); return moreTokens; } /** * Keeps track of and reports all of the active word histories for the * given active list * * @param activeList * the activelist to track */ private void monitorWords(ActiveList activeList) { WordTracker tracker = new WordTracker(currentFrameNumber); for (Iterator i = activeList.iterator(); i.hasNext();) { Token t = (Token) i.next(); tracker.add(t); } tracker.dump(); } /** * Keeps track of and reports statistics about the number of active states * * @param activeList * the active list of states */ private void monitorStates(ActiveList activeList) { tokenSum += activeList.size(); tokenCount++; if ((tokenCount % 1000) == 0) { logger.info("Average Tokens/State: " + (tokenSum / tokenCount)); } } /** * Removes unpromising branches from the active list * */ protected void pruneBranches() { pruneTimer.start(); activeList = pruner.prune(activeList); pruneTimer.stop(); } /** * Gets the best token for this state * * @param state * the state of interest * * @return the best token */ protected Token getBestToken(SearchState state) { Object key = getStateKey(state); if (!wantTokenStacks) { return (Token) bestTokenMap.get(key); } else { // new way... if the heap for this state isn't full return // null, otherwise return the worst scoring token TokenHeap th = (TokenHeap) bestTokenMap.get(key); Token t; if (th == null) { return null; } else if ((t = th.get(state)) != null) { return t; } else if (!th.isFull()) { return null; } else { return th.getSmallest(); } } } /** * Sets the best token for a given state * * @param token * the best token * * @param state * the state * */ protected void setBestToken(Token token, SearchState state) { Object key = getStateKey(state); if (!wantTokenStacks) { bestTokenMap.put(key, token); } else { TokenHeap th = (TokenHeap) bestTokenMap.get(key); if (th == null) { th = new TokenHeap(maxTokenHeapSize); bestTokenMap.put(key, th); } th.add(token); } } /** * Find the best token to use as a predecessor token given a candidate * predecessor. The predecessor is the most recent word token unless * keepAllTokens is set, in which case, the predecessor is always the * candidate predecessor. * * @param token * the token of interest * * @return the immediate successor word token */ protected Token getWordPredecessor(Token token) { if (keepAllTokens) { return token; } else { float logAcousticScore = 0.0f; float logLanguageScore = 0.0f; while (token != null && !token.isWord()) { logAcousticScore += token.getAcousticScore(); logLanguageScore += token.getLanguageScore(); token = token.getPredecessor(); } if (buildWordLattice) { return new Token(logAcousticScore, logLanguageScore, token); } else { return token; } } } /** * Returns the state key for the given state. If we are using token stacks * then the key will be related to the search state and the word history * (depending on the type of token stacks), otherwise, the key will simply * be the state itself. Currently we are not using token stacks so the * state is the key. * * @param state * the state to get the key for * * @return the key for the given state */ private Object getStateKey(SearchState state) { if (!wantTokenStacks) { return state; } else { if (state.isEmitting()) { return new SinglePathThroughHMMKey(((HMMSearchState) state)); // return ((HMMSearchState) state).getHMMState().getHMM(); } else { return state; } } } /** * Checks that the given two states are in legitimate order. */ private void checkStateOrder(SearchState fromState, SearchState toState) { if (fromState.getOrder() == numStateOrder - 1) { return; } if (fromState.getOrder() > toState.getOrder()) { throw new Error("IllegalState order: from " + fromState.getClass().getName() + " " + fromState.toPrettyString() + " order: " + fromState.getOrder() + " to " + toState.getClass().getName() + " " + toState.toPrettyString() + " order: " + toState.getOrder()); } } /** * Collects the next set of emitting tokens from a token and accumulates * them in the active or result lists * * @param token * the token to collect successors from be immediately * expaned are placed. Null if we should always expand all * nodes. * */ protected void collectSuccessorTokens(Token token) { // tokenTracker.add(token); // tokenTypeTracker.add(token); // If this is a final state, add it to the final list if (token.isFinal()) { resultList.add(getWordPredecessor(token)); return; } // if this is a non-emitting token and we've already // visited the same state during this frame, then we // are in a grammar loop, so we don't continue to expand. // This check only works properly if we have kept all of the // tokens (instead of skipping the non-word tokens). // Note that certain linguists will never generate grammar loops // (lextree linguist for example). For these cases, it is perfectly // fine to disable this check by setting keepAllTokens to false if (!token.isEmitting() && (keepAllTokens && isVisited(token))) { return; } SearchState state = token.getSearchState(); SearchStateArc[] arcs = state.getSuccessors(); Token predecessor = getWordPredecessor(token); // For each successor // calculate the entry score for the token based upon the // predecessor token score and the transition probabilities // if the score is better than the best score encountered for // the SearchState and frame then create a new token, add // it to the lattice and the SearchState. // If the token is an emitting token add it to the list, // othewise recursively collect the new tokens successors. for (int i = 0; i < arcs.length; i++) { SearchStateArc arc = arcs[i]; SearchState nextState = arc.getState(); if (checkStateOrder) { checkStateOrder(state, nextState); } // We're actually multiplying the variables, but since // these come in log(), multiply gets converted to add float logEntryScore = token.getScore() + arc.getProbability(); Token bestToken = getBestToken(nextState); boolean firstToken = bestToken == null; if (firstToken || bestToken.getScore() < logEntryScore) { Token newBestToken = new Token(predecessor, nextState, logEntryScore, arc.getLanguageProbability(), arc .getInsertionProbability(), currentFrameNumber); tokensCreated.value++; setBestToken(newBestToken, nextState); if (firstToken) { activeListAdd(newBestToken); } else { if (false) { System.out.println("Replacing " + bestToken + " with " + newBestToken); } activeListReplace(bestToken, newBestToken); if (buildWordLattice && newBestToken.isWord()) { // Move predecessors of bestToken to precede // newBestToken, bestToken will be garbage collected. loserManager.changeSuccessor(newBestToken, bestToken); loserManager.addAlternatePredecessor(newBestToken, bestToken.getPredecessor()); } } } else { if (buildWordLattice && nextState instanceof WordSearchState) { if (predecessor != null) { loserManager.addAlternatePredecessor(bestToken, predecessor); } } } } } /** * Determines whether or not we've visited the state associated with this * token since the previous frame. * * @return true if we've visted the search state since the last frame
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?