Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nnet3-rnnlm lattice rescoring draft #1906

Merged
merged 27 commits into from
Nov 23, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0d839b0
draft
hainan-xv Sep 18, 2017
699c956
lattice-rescoring draft finished
hainan-xv Sep 20, 2017
ef09b62
lattice-rescoring runnable but buggy
hainan-xv Sep 22, 2017
390a1bb
making a PR
hainan-xv Sep 24, 2017
dc49709
small changes
hainan-xv Sep 24, 2017
8a33e77
include lmrescore_rnn_lat.sh
hainan-xv Sep 24, 2017
5965b87
Merge branch 'rnnlm' into rnnlm-rescoring
hainan-xv Sep 24, 2017
483450d
some aesthetic changes; not final yet
hainan-xv Sep 25, 2017
00912f7
Merge branch 'master' into rnnlm-rescoring
hainan-xv Sep 25, 2017
b1167a2
cached version of lattice rescoring; buggy it seems
hainan-xv Sep 27, 2017
a52da29
purely aesthetic changes
hainan-xv Sep 27, 2017
3bdaa4d
re-written some of the classes
hainan-xv Sep 28, 2017
2b08335
very small changes
hainan-xv Sep 28, 2017
7cf4af8
fix a typo
hainan-xv Sep 28, 2017
8f35242
make RNNLM share the same FST wordlist
hainan-xv Oct 2, 2017
705ecc8
fix small issue when running lattice-rescoring with normalize-probs o…
hainan-xv Oct 2, 2017
d19ecc1
minor changes
hainan-xv Oct 6, 2017
232ef04
fix small stylistic issues in code
hainan-xv Oct 14, 2017
bd9936b
fix wrong variable used in scripts/rnnlm/lmrescore_rnnlm_lat.sh
hainan-xv Oct 14, 2017
9cc7ba1
add rnnlm softlink in swbd/s5c
hainan-xv Oct 15, 2017
267177f
small style changes
hainan-xv Oct 30, 2017
87f2f6c
merge with latest upstream
hainan-xv Nov 3, 2017
c9bf5e0
move rescoring into rnnlm training scripts
hainan-xv Nov 7, 2017
091d4d5
move rescoring into rnnlm training scripts
hainan-xv Nov 8, 2017
a192ada
fix small issues mentioned by @danoneata
hainan-xv Nov 9, 2017
697f219
change SWBD script to accommodate s5_c; add paper link to RNNLM scrip…
hainan-xv Nov 20, 2017
acb5211
fix conflicts
hainan-xv Nov 20, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
some aesthetic changes; not final yet
  • Loading branch information
hainan-xv committed Sep 25, 2017
commit 483450dc80eb35c3e4acc9ab5c788f243d041b14
2 changes: 1 addition & 1 deletion egs/swbd/s5/local/rnnlm/run_rescoring.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ for decode_set in eval2000; do
decode_dir=${dir}/decode_${decode_set}_$LM

# Lattice rescoring
steps/lmrescore_rnnlm_lat.sh \
rnnlm/lmrescore_rnnlm_lat.sh \
--cmd "$decode_cmd --mem 16G" \
--rnnlm-ver kaldirnnlm --weight 0.5 --max-ngram-order $ngram_order \
data/lang_$LM $rnndir \
Expand Down
115 changes: 115 additions & 0 deletions scripts/rnnlm/lmrescore_rnnlm_lat.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#!/bin/bash

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the 'rnnlm' in the name here because it's redundant-- it's already in a directory called 'rnnlm'. You could call it 'lmrescore_lat.sh', but IMO the name 'lmrescore.sh' would be more ideal, and you could then have the n-best one be called 'lmrescore_nbest.sh', if needed.

# Copyright 2015 Guoguo Chen
# 2017 Hainan Xu
# Apache 2.0

# This script rescores lattices with RNNLM. See also rnnlmrescore.sh which is
# an older script using n-best lists.

# Begin configuration section.
cmd=run.pl
skip_scoring=false
max_ngram_order=4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarify via a comment that this is for the n-gram approximation in lattice rescoring, and if feasible, refer to some kind of paper that explains this concept.

N=10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this N variable is no longer needed.

inv_acwt=12
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we normally make this default to 10. making the default 12 would be confusing.

weight=1.0 # Interpolation weight for RNNLM.
# End configuration section.
rnnlm_ver=
#layer_string=

echo "$0 $@" # Print the command line for logging

. ./utils/parse_options.sh

if [ $# != 5 ]; then
echo "Does language model rescoring of lattices (remove old LM, add new LM)"
echo "with RNNLM."
echo ""
echo "Usage: $0 [options] <old-lang-dir> <rnnlm-dir> \\"
echo " <data-dir> <input-decode-dir> <output-decode-dir>"
echo " e.g.: $0 ./rnnlm data/lang_tg data/test \\"
echo " exp/tri3/test_tg exp/tri3/test_rnnlm"
echo "options: [--cmd (run.pl|queue.pl [queue opts])]"
exit 1;
fi

[ -f path.sh ] && . ./path.sh;

oldlang=$1
rnnlm_dir=$2
data=$3
indir=$4
outdir=$5

rescoring_binary=lattice-lmrescore-rnnlm


if [ "$rnnlm_ver" == "kaldirnnlm" ]; then
rescoring_binary="lattice-lmrescore-kaldi-rnnlm"
first_arg="\"rnnlm-get-word-embedding $rnnlm_dir/word_feats.txt $rnnlm_dir/feat_embedding.final.mat -|\" $rnnlm_dir/config/words.txt "
fi

oldlm=$oldlang/G.fst
if [ -f $oldlang/G.carpa ]; then
oldlm=$oldlang/G.carpa
elif [ ! -f $oldlm ]; then
echo "$0: expecting either $oldlang/G.fst or $oldlang/G.carpa to exist" &&\
exit 1;
fi

[ ! -f $oldlm ] && echo "$0: Missing file $oldlm" && exit 1;
[ ! -f $rnnlm_dir/final.raw ] && echo "$0: Missing file $rnnlm_dir/final.raw" && exit 1;
[ ! -f $rnnlm_dir/feat_embedding.final.mat ] && [ ! -f $rnnlm_dir/word_embedding.final.mat ] && echo "$0: Missing word embedding file" && exit 1;

[ ! -f $oldlang/words.txt ] &&\
echo "$0: Missing file $oldlang/words.txt" && exit 1;
! ls $indir/lat.*.gz >/dev/null &&\
echo "$0: No lattices input directory $indir" && exit 1;
awk -v n=$0 -v w=$weight 'BEGIN {if (w < 0 || w > 1) {
print n": Interpolation weight should be in the range of [0, 1]"; exit 1;}}' \
|| exit 1;

oldlm_command="fstproject --project_output=true $oldlm |"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this projection is no longer necessary because IIRC the code does the projection internally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this is not the pruned version of lattice-rescoring and it uses the old latbin binaries.


acwt=`perl -e "print (1.0/$inv_acwt);"`

word_embedding=
if [ -f $rnnlm_dir/word_embedding.final.mat ]; then
word_embedding=$rnnlm_dir/word_embedding.final.mat
else
word_embedding="\"rnnlm-get-word-embedding $rnnlm_dir/word_feats.txt $rnnlm_dir/feat_embedding.final.mat -|\""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid the need for escaping, I suggest using single quotes for the inner quotes.

fi

mkdir -p $outdir/log
nj=`cat $indir/num_jobs` || exit 1;
cp $indir/num_jobs $outdir

oldlm_weight=`perl -e "print -1.0 * $weight;"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I generally prefer $() to backticks. Not all of the older scripts follow this.

if [ "$oldlm" == "$oldlang/G.fst" ]; then
$cmd JOB=1:$nj $outdir/log/rescorelm.JOB.log \
lattice-lmrescore --lm-scale=$oldlm_weight \
"ark:gunzip -c $indir/lat.JOB.gz|" "$oldlm_command" ark:- \| \
$rescoring_binary --lm-scale=$weight \
--max-ngram-order=$max_ngram_order \
$oldlang/words.txt ark:- $rnnlm_dir/config/words.txt $word_embedding "$rnnlm_dir/final.raw" \
"ark,t:|gzip -c>$outdir/lat.JOB.gz" || exit 1;
else
$cmd JOB=1:$nj $outdir/log/rescorelm.JOB.log \
lattice-lmrescore-const-arpa --lm-scale=$oldlm_weight \
"ark:gunzip -c $indir/lat.JOB.gz|" "$oldlm" ark:- \| \
$rescoring_binary --lm-scale=$weight \
--max-ngram-order=$max_ngram_order \
$oldlang/words.txt ark:- $rnnlm_dir/config/words.txt $word_embedding "$rnnlm_dir/final.raw" \
"ark,t:|gzip -c>$outdir/lat.JOB.gz" || exit 1;
fi
if ! $skip_scoring ; then
err_msg="Not scoring because local/score.sh does not exist or not executable."
[ ! -x local/score.sh ] && echo $err_msg && exit 1;
local/score.sh --cmd "$cmd" $data $oldlang $outdir
else
echo "Not scoring because requested so..."
fi

exit 0;

3 changes: 0 additions & 3 deletions scripts/rnnlm/train_rnnlm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,8 @@ if [ $stage -le $num_iters ]; then
echo "$0: best iteration (out of $num_iters) was $best_iter, linking it to final iteration."
ln -sf $embedding_type.$best_iter.mat $dir/$embedding_type.final.mat
ln -sf $best_iter.raw $dir/final.raw
ln -sf $best_iter.raw $dir/rnnlm # to make it consistent with other RNNLMs
fi

touch $dir/unk.probs

# Now get some diagnostics about the evolution of the objective function.
if [ $stage -le $[num_iters+1] ]; then
(
Expand Down
16 changes: 8 additions & 8 deletions src/latbin/lattice-lmrescore-kaldi-rnnlm.cc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// latbin/lattice-lmrescore-kaldi-rnnlm.cc

// Copyright 2017 Johns Hopkins University (author: Daniel Povey)
// Hainan Xu
// Yiming Wang
// 2017 Hainan Xu
// 2017 Yiming Wang

// See ../../COPYING for clarification regarding multiple authors
//
Expand Down Expand Up @@ -66,10 +66,10 @@ int main(int argc, char *argv[]) {
std::string lats_rspecifier, rnn_wordlist, word_embedding_rxfilename,
word_symbols_rxfilename, rnnlm_rxfilename, lats_wspecifier;

word_embedding_rxfilename = po.GetArg(1);
rnn_wordlist = po.GetArg(2);
word_symbols_rxfilename = po.GetArg(3);
lats_rspecifier = po.GetArg(4);
word_symbols_rxfilename = po.GetArg(1);
lats_rspecifier = po.GetArg(2);
rnn_wordlist = po.GetArg(3);
word_embedding_rxfilename = po.GetArg(4);
rnnlm_rxfilename = po.GetArg(5);
lats_wspecifier = po.GetArg(6);

Expand All @@ -85,8 +85,8 @@ int main(int argc, char *argv[]) {
CuMatrix<BaseFloat> word_embedding_mat;
ReadKaldiObject(word_embedding_rxfilename, &word_embedding_mat);

const nnet3::DecodableRnnlmSimpleLoopedComputationOptions opts;
const nnet3::DecodableRnnlmSimpleLoopedInfo info(opts, rnnlm, word_embedding_mat);
const nnet3::RnnlmSimpleLoopedComputationOptions opts;
const nnet3::RnnlmSimpleLoopedInfo info(opts, rnnlm, word_embedding_mat);

// Reads and writes as compact lattice.
SequentialCompactLatticeReader compact_lattice_reader(lats_rspecifier);
Expand Down
2 changes: 1 addition & 1 deletion src/rnnlm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ TESTFILES = sampler-test sampling-lm-test rnnlm-example-test
OBJFILES = sampler.o rnnlm-example.o rnnlm-example-utils.o \
rnnlm-core-training.o rnnlm-embedding-training.o rnnlm-core-compute.o \
rnnlm-utils.o rnnlm-training.o rnnlm-test-utils.o sampling-lm-estimate.o \
sampling-lm.o rnnlm-decodable-simple-looped.o rnnlm-lattice-rescoring.o
sampling-lm.o rnnlm-simple-looped.o rnnlm-lattice-rescoring.o

LIBNAME = kaldi-rnnlm

Expand Down
28 changes: 15 additions & 13 deletions src/rnnlm/rnnlm-lattice-rescoring.cc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// rnnlm/rnnlm-lattice-rescoring.cc

// Copyright 2017 Johns Hopkins University (author: Daniel Povey)
// Yiming Wang
// Hainan Xu
// Copyright 2017 Johns Hopkins University (author: Daniel Povey)
// 2017 Yiming Wang
// 2017 Hainan Xu
//
// See ../../COPYING for clarification regarding multiple authors
//
Expand Down Expand Up @@ -64,7 +64,9 @@ void KaldiRnnlmDeterministicFst::ReadFstWordSymbolTableAndRnnWordlist(
int32 i = 0;
while (ifile >> word >> id) {
if (word == "</s>") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, other parts of the code don't assume that these are the written forms of BOS and EOS; they take these as options. The scripts do, currently, so this might not be fatal-- but generally speaking, programs don't take any arguments with written forms of words unless they absolutely have to for some reason, and this program breaks that pattern. I'd be happier to add the same options as for the training tools, with --bos-symbol and --eos-symbol (and an ignored option, --brk-symbol, if it makes your life easier scripting-wise).

final_word_index_ = id;
eos_index_ = id;
} else if (word == "<s>") {
bos_index_ = id;
}
KALDI_ASSERT(i == id);
i++;
Expand Down Expand Up @@ -95,18 +97,18 @@ void KaldiRnnlmDeterministicFst::ReadFstWordSymbolTableAndRnnWordlist(
KaldiRnnlmDeterministicFst::KaldiRnnlmDeterministicFst(int32 max_ngram_order,
const std::string &rnn_wordlist,
const std::string &word_symbol_table_rxfilename,
const DecodableRnnlmSimpleLoopedInfo &info) {
const RnnlmSimpleLoopedInfo &info) {
max_ngram_order_ = max_ngram_order;
ReadFstWordSymbolTableAndRnnWordlist(rnn_wordlist,
word_symbol_table_rxfilename);

std::vector<Label> bos;
bos.push_back(0); // 0 for <s>
state_to_wseq_.push_back(bos);
DecodableRnnlmSimpleLooped decodable_rnnlm(info);
decodable_rnnlm.TakeFeatures(std::vector<Label>(1, bos[0]));
std::vector<Label> bos_seq;
bos_seq.push_back(bos_index_);
state_to_wseq_.push_back(bos_seq);
RnnlmSimpleLooped decodable_rnnlm(info);
decodable_rnnlm.TakeFeatures(bos_seq);
state_to_decodable_rnnlm_.push_back(decodable_rnnlm);
wseq_to_state_[bos] = 0;
wseq_to_state_[bos_seq] = 0;
start_state_ = 0;
}

Expand All @@ -115,7 +117,7 @@ fst::StdArc::Weight KaldiRnnlmDeterministicFst::Final(StateId s) {
KALDI_ASSERT(static_cast<size_t>(s) < state_to_wseq_.size());

// log prob of end of sentence
BaseFloat logprob = state_to_decodable_rnnlm_[s].GetOutput(0, final_word_index_);
BaseFloat logprob = state_to_decodable_rnnlm_[s].GetOutput(0, eos_index_);
return Weight(-logprob);
}

Expand All @@ -125,7 +127,7 @@ bool KaldiRnnlmDeterministicFst::GetArc(StateId s, Label ilabel,
KALDI_ASSERT(static_cast<size_t>(s) < state_to_wseq_.size());

std::vector<Label> wseq = state_to_wseq_[s];
DecodableRnnlmSimpleLooped decodable_rnnlm = state_to_decodable_rnnlm_[s];
RnnlmSimpleLooped decodable_rnnlm = state_to_decodable_rnnlm_[s];
int32 rnn_word = fst_label_to_rnn_label_[ilabel];

BaseFloat logprob = decodable_rnnlm.GetOutput(0, rnn_word);
Expand Down
13 changes: 7 additions & 6 deletions src/rnnlm/rnnlm-lattice-rescoring.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// rnnlm/rnnlm-lattice-rescoring.h
//
// Copyright 2017 Johns Hopkins University (author: Daniel Povey)
// Yiming Wang
// Hainan Xu
// 2017 Yiming Wang
// 2017 Hainan Xu
//
// See ../../COPYING for clarification regarding multiple authors
//
Expand All @@ -27,7 +27,7 @@

#include "base/kaldi-common.h"
#include "fstext/deterministic-fst.h"
#include "rnnlm/rnnlm-decodable-simple-looped.h"
#include "rnnlm/rnnlm-simple-looped.h"
#include "util/common-utils.h"

namespace kaldi {
Expand All @@ -44,7 +44,7 @@ class KaldiRnnlmDeterministicFst
KaldiRnnlmDeterministicFst(int32 max_ngram_order,
const std::string &rnn_wordlist,
const std::string &word_symbol_table_rxfilename,
const DecodableRnnlmSimpleLoopedInfo &info);
const RnnlmSimpleLoopedInfo &info);

// We cannot use "const" because the pure virtual function in the interface is
// not const.
Expand All @@ -66,7 +66,8 @@ class KaldiRnnlmDeterministicFst
std::vector<std::string> fst_label_to_word_;
int32 full_voc_size_;
int32 out_OOS_index_;
int32 final_word_index_;
int32 bos_index_;
int32 eos_index_;

typedef unordered_map
<std::vector<Label>, StateId, VectorHasher<Label> > MapType;
Expand All @@ -75,7 +76,7 @@ class KaldiRnnlmDeterministicFst
std::vector<std::vector<Label> > state_to_wseq_;

int32 max_ngram_order_;
std::vector<DecodableRnnlmSimpleLooped> state_to_decodable_rnnlm_;
std::vector<RnnlmSimpleLooped> state_to_decodable_rnnlm_;

void ReadFstWordSymbolTableAndRnnWordlist(const std::string &rnn_in_wordlist,
// const std::string &rnn_out_wordlist,
Expand Down
Loading