Commit a1d837d2 authored by Dan Povey's avatar Dan Povey
Browse files

trunk: finish example script for nnet1->nnet2 model conversion, see demo in...

trunk: finish example script for nnet1->nnet2 model conversion, see demo in egs/rm/s5/local/run_dnn.sh

git-svn-id: https://svn.code.sf.net/p/kaldi/code/trunk@4257 5e6a8d80-dfce-4ca6-a32a-6e07a63d50c8
parent 7398f6ea
......@@ -7,6 +7,4 @@ for x in exp/*/decode_dev; do grep WER $x/wer_* | utils/best_wer.sh; done
%WER 31.07 [ 12163 / 39141, 1869 ins, 2705 del, 7589 sub ] exp/tri5a/decode_dev/wer_13
%WER 31.13 [ 12184 / 39141, 1939 ins, 2584 del, 7661 sub ] exp/tri5a_0.1/decode_dev/wer_12
%WER 23.66 [ 9259 / 39141, 1495 ins, 2432 del, 5332 sub ] exp/nnet6c4_gpu/decode_dev/wer_11
#!/bin/bash
# This script shows how you can do data-cleaning, and exclude data that has a
# higher likelihood of being wrongly transcribed. see the RESULTS file; this
# made essentially no difference in our case-- indicating, perhaps, that Fisher
# transcripts are already clean enough.
. cmd.sh
. path.sh
set -e
steps/cleanup/find_bad_utts.sh --nj 200 --cmd "$train_cmd" data/train data/lang \
exp/tri5a exp/tri5a_cleanup
# with threshold of 0.05 we keep 1.1 million out of 1.6 million utterances, and
# around 8.7 million out of 18.1 million words
# with threshold of 0.1 we keep 1.3 out of 1.6 million utterances, and around
# 13.2 million out of 18.1 million words.
thresh=0.1
cat exp/tri5a_cleanup/all_info.txt | awk -v threshold=$thresh '{ errs=$2;ref=$3; if (errs <= threshold*ref) { print $1; } }' > uttlist
utils/subset_data_dir.sh --utt-list uttlist data/train data/train.thresh$thresh
steps/align_fmllr.sh --nj 30 --cmd "$train_cmd" \
data/train.thresh$thresh data/lang exp/tri4a exp/tri4a_ali_$thresh
steps/train_sat.sh --cmd "$train_cmd" \
10000 300000 data/train data/lang exp/tri4a_ali_$thresh exp/tri5a_$thresh || exit 1;
utils/mkgraph.sh data/lang_test exp/tri5a_$thresh exp/tri5a_$thresh/graph
steps/decode_fmllr.sh --nj 25 --cmd "$decode_cmd" --config conf/decode.config \
exp/tri5a_$thresh/graph data/dev exp/tri5a_$thresh/decode_dev
......@@ -163,33 +163,10 @@ steps/train_sat.sh --cmd "$train_cmd" \
)&
# The step below won't run by default; it demonstrates a data-cleaning method.
# It doesn't seem to help in this setup; maybe the data was clean enough already.
false && (
steps/cleanup/find_bad_utts.sh --nj 200 --cmd "$train_cmd" data/train data/lang \
exp/tri5a exp/tri5a_cleanup
# with threshold of 0.05 we keep 1.1 million out of 1.6 million utterances, and
# around 8.7 million out of 18.1 million words
# with threshold of 0.1 we keep 1.3 out of 1.6 million utterances, and around
# 13.2 million out of 18.1 million words.
thresh=0.1
cat exp/tri5a_cleanup/all_info.txt | awk -v threshold=$thresh '{ errs=$2;ref=$3; if (errs <= threshold*ref) { print $1; } }' > uttlist
utils/subset_data_dir.sh --utt-list uttlist data/train data/train.thresh$thresh
steps/align_fmllr.sh --nj 30 --cmd "$train_cmd" \
data/train.thresh$thresh data/lang exp/tri4a exp/tri4a_ali_$thresh
steps/train_sat.sh --cmd "$train_cmd" \
10000 300000 data/train data/lang exp/tri4a_ali_$thresh exp/tri5a_$thresh || exit 1;
(
utils/mkgraph.sh data/lang_test exp/tri5a_$thresh exp/tri5a_$thresh/graph
steps/decode_fmllr.sh --nj 25 --cmd "$decode_cmd" --config conf/decode.config \
exp/tri5a_$thresh/graph data/dev exp/tri5a_$thresh/decode_dev
)&
)
# local/run_data_cleaning.sh
# local/run_for_spkid.sh
......
......@@ -161,6 +161,8 @@ exit 0
# last time I created this.
# Per-frame cross-entropy training
%WER 1.66 [ 208 / 12533, 27 ins, 49 del, 132 sub ] exp/dnn4b_pretrain-dbn_dnn/decode/wer_3
%WER 7.80 [ 978 / 12533, 83 ins, 151 del, 744 sub ] exp/dnn4b_pretrain-dbn_dnn/decode_ug/wer_6
# Sequence-based sMBR training
%WER 1.64 [ 206 / 12533, 24 ins, 49 del, 133 sub ] exp/dnn4b_pretrain-dbn_dnn_smbr/decode_it1/wer_4
%WER 1.62 [ 203 / 12533, 25 ins, 46 del, 132 sub ] exp/dnn4b_pretrain-dbn_dnn_smbr/decode_it2/wer_4
......
......@@ -7,8 +7,14 @@
train_cmd="queue.pl -l arch=*64"
decode_cmd="queue.pl -l arch=*64"
# cuda_cmd is used for nnet1 scripts e.g. local/run_dnn.sh, but
# in the nnet2 scripts e.g. local/run_nnet2.sh, this is not
# used and we append options to train_cmd.
cuda_cmd="queue.pl -l arch=*64 -l gpu=1"
#train_cmd="run.pl"
# Do training locally. Note: for jobs on smallish subsets,
# with run.pl we do training locally. Note: for jobs on smallish subsets,
# it's way faster to run on a single machine with a handful of CPUs, as
# you avoid the latency of starting GridEngine jobs.
......
......@@ -2,5 +2,3 @@
first_beam=16.0
beam=20.0
lattice_beam=10.0
min_lmwt=2
max_lmwt=10
......@@ -66,6 +66,8 @@ if [ $stage -le 2 ]; then
# Decode (reuse HCLG graph)
steps/nnet/decode.sh --nj 20 --cmd "$decode_cmd" --config conf/decode_dnn.config --acwt 0.1 \
$gmmdir/graph $data_fmllr/test $dir/decode || exit 1;
steps/nnet/decode.sh --nj 20 --cmd "$decode_cmd" --config conf/decode_dnn.config --acwt 0.1 \
$gmmdir/graph_ug $data_fmllr/test $dir/decode_ug || exit 1;
fi
......@@ -92,6 +94,9 @@ if [ $stage -le 4 ]; then
steps/nnet/decode.sh --nj 20 --cmd "$decode_cmd" --config conf/decode_dnn.config \
--nnet $dir/${ITER}.nnet --acwt $acwt \
$gmmdir/graph $data_fmllr/test $dir/decode_it${ITER} || exit 1
steps/nnet/decode.sh --nj 20 --cmd "$decode_cmd" --config conf/decode_dnn.config \
--nnet $dir/${ITER}.nnet --acwt $acwt \
$gmmdir/graph_ug $data_fmllr/test $dir/decode_ug_it${ITER} || exit 1
done
fi
......@@ -100,3 +105,16 @@ exit 0
# Getting results [see RESULTS file]
# for x in exp/*/decode*; do [ -d $x ] && grep WER $x/wer_* | utils/best_wer.sh; done
# Showing how model conversion to nnet2 works; note, we use the expanded variable
# names here so be careful in case the script changes.
# steps/nnet2/convert_nnet1_to_nnet2.sh exp/dnn4b_pretrain-dbn_dnn exp/dnn4b_nnet2
# cp exp/tri3b/splice_opts exp/tri3b/cmvn_opts exp/tri3b/final.mat exp/dnn4b_nnet2/
#
# steps/nnet2/decode.sh --nj 10 --cmd "$decode_cmd" --transform-dir exp/tri3b/decode \
# --config conf/decode.config exp/tri3b/graph data/test exp/dnn4b_nnet2/decode
# decoding results are essentially the same (any small difference is probably because
# decode.config != decode_dnn.config).
# %WER 1.58 [ 198 / 12533, 22 ins, 45 del, 131 sub ] exp/dnn4b_nnet2/decode/wer_3
# %WER 1.59 [ 199 / 12533, 23 ins, 45 del, 131 sub ] exp/dnn4b_pretrain-dbn_dnn/decode/wer_3
......@@ -20,7 +20,7 @@ max_active=750
transform_dir= # directory to find fMLLR transforms in.
top_n_words=100 # Number of common words that we compile into each graph (most frequent
# in $lang/text.
stage=0
stage=-1
cleanup=true
# End configuration options.
......@@ -65,14 +65,16 @@ cp $srcdir/{tree,final.mdl} $dir || exit 1;
cp $srcdir/final.occs $dir;
utils/sym2int.pl --map-oov $oov -f 2- $lang/words.txt <$data/text | \
awk '{for(x=2;x<=NF;x++) print $x;}' | sort | uniq -c | \
sort -rn > $dir/word_counts.int || exit 1;
num_words=$(awk '{x+=$1} END{print x}' < $dir/word_counts.int) || exit 1;
# print top-n words with their unigram probabilities.
head -n $top_n_words $dir/word_counts.int | awk -v tot=$num_words '{print $1/tot, $2;}' >$dir/top_words.int
utils/int2sym.pl -f 2 $lang/words.txt <$dir/top_words.int >$dir/top_words.txt
if [ $stage -le 0 ]; then
utils/sym2int.pl --map-oov $oov -f 2- $lang/words.txt <$data/text | \
awk '{for(x=2;x<=NF;x++) print $x;}' | sort | uniq -c | \
sort -rn > $dir/word_counts.int || exit 1;
num_words=$(awk '{x+=$1} END{print x}' < $dir/word_counts.int) || exit 1;
# print top-n words with their unigram probabilities.
head -n $top_n_words $dir/word_counts.int | awk -v tot=$num_words '{print $1/tot, $2;}' >$dir/top_words.int
utils/int2sym.pl -f 2 $lang/words.txt <$dir/top_words.int >$dir/top_words.txt
fi
if [ -f $srcdir/final.mat ]; then feat_type=lda; else feat_type=delta; fi
echo "$0: feature type is $feat_type"
......@@ -106,9 +108,9 @@ elif [ -f $srcdir/final.alimdl ]; then
fi
echo "$0: decoding $data using utterance-specific decoding graphs using model from $srcdir, output in $dir"
if [ $stage -le 1 ]; then
echo "$0: decoding $data using utterance-specific decoding graphs using model from $srcdir, output in $dir"
if [ $stage -le 0 ]; then
rm $dir/edits.*.txt $dir/aligned_ref.*.txt 2>/dev/null
$cmd JOB=1:$nj $dir/log/decode.JOB.log \
......@@ -126,15 +128,16 @@ if [ $stage -le 0 ]; then
fi
if [ $stage -le 1 ]; then
if [ $stage -le 2 ]; then
if [ -f $dir/edits.1.txt ]; then
for x in $(seq $nj); do cat $dir/edits.$x.txt; done > $dir/edits.txt
for x in $(seq $nj); do cat $dir/aligned_ref.$x.txt; done > $dir/aligned_ref.txt
# the awk commands below are to ensure that partially-written files don't confuse us.
for x in $(seq $nj); do cat $dir/edits.$x.txt; done | awk '{if(NF==2){print;}}' > $dir/edits.txt
for x in $(seq $nj); do cat $dir/aligned_ref.$x.txt; done | awk '{if(NF>=1){print;}}' > $dir/aligned_ref.txt
else
echo "$0: warning: no file $dir/edits.1.txt, using previously concatenated file if present."
fi
# in case any utterances failed to align, get filtered copy of $data/text that's filtered.
# in case any utterances failed to align, get filtered copy of $data/text
utils/filter_scp.pl $dir/edits.txt < $data/text > $dir/text
cat $dir/text | awk '{print $1, (NF-1);}' > $dir/length.txt
......@@ -159,9 +162,8 @@ if [ $stage -le 1 ]; then
<(awk '{$1="";print;}' <$dir/text) > $dir/all_info.txt
sort -nr -k2 $dir/all_info.txt > $dir/all_info.sorted.txt
# TEMP, will uncomment this later.
#if $cleanup; then
# rm $dir/edits.*.txt $dir/aligned_ref.*.txt
#fi
fi
if $cleanup; then
rm $dir/edits.*.txt $dir/aligned_ref.*.txt
fi
fi
#!/bin/bash
# Copyright 2014 Johns Hopkins University (Author: Daniel Povey).
# Apache 2.0.
# This script converts nnet1 into nnet2 models.
# Note, it doesn't support all possible types of nnet1 models.
# Begin configuration section
cleanup=true
cmd=run.pl
# End configuration section.
echo "$0 $@" # Print the command line for logging
[ -f ./path.sh ] && . ./path.sh; # source the path.
. parse_options.sh || exit 1;
if [ $# -ne 2 ]; then
echo "Usage: $0 [options] <src-nnet1-dir> <dest-nnet2-dir>"
echo "e.g.: $0 exp/dnn4b_pretrain-dbn_dnn_smbr exp/dnn4b_smbr_nnet2"
exit 1;
fi
src=$1
dir=$2
mkdir -p $dir/log || exit 1;
for f in $src/final.mdl $src/final.nnet $src/final.feature_transform $src/ali_train_pdf.counts; do
[ ! -f $f ] && echo "$0: expected file $f to exist" && exit 1
done
# We could do the following things all as one long piped command,
# but it will be easier to debug if we make them separate.
$cmd $dir/log/convert_feature_transform.log \
nnet1-to-raw-nnet $src/final.feature_transform $dir/0.raw || exit 1;
$cmd $dir/log/convert_model.log \
nnet1-to-raw-nnet $src/final.nnet $dir/1.raw || exit 1;
$cmd $dir/log/append_model.log \
raw-nnet-concat $dir/0.raw $dir/1.raw $dir/concat.raw || exit 1;
$cmd $dir/log/init_model.log \
nnet-am-init $src/final.mdl $dir/concat.raw $dir/final_noprior.mdl || exit 1;
$cmd $dir/log/set_priors.log \
nnet-adjust-priors $dir/final_noprior.mdl $src/ali_train_pdf.counts $dir/final.mdl || exit 1;
if $cleanup; then
rm $dir/0.raw $dir/1.raw $dir/concat.raw $dir/final_noprior.mdl
fi
......@@ -61,6 +61,7 @@ done
sdata=$data/split$nj;
splice_opts=`cat $srcdir/splice_opts 2>/dev/null`
cmvn_opts=`cat $srcdir/cmvn_opts 2>/dev/null`
thread_string=
[ $num_threads -gt 1 ] && thread_string="-parallel --num-threads=$num_threads"
......@@ -75,7 +76,6 @@ if [ -z "$feat_type" ]; then
echo "$0: feature type is $feat_type"
fi
cmvn_opts=`cat $srcdir/cmvn_opts 2>/dev/null`
case $feat_type in
raw) feats="ark,s,cs:apply-cmvn $cmvn_opts --utt2spk=ark:$sdata/JOB/utt2spk scp:$sdata/JOB/cmvn.scp scp:$sdata/JOB/feats.scp ark:- |";;
......@@ -85,16 +85,30 @@ case $feat_type in
esac
if [ ! -z "$transform_dir" ]; then
echo "$0: using transforms from $transform_dir"
if [ "$feat_type" == "lda" ]; then
[ ! -f $transform_dir/trans.1 ] && echo "$0: no such file $transform_dir/trans.1" && exit 1;
[ "$nj" -ne "`cat $transform_dir/num_jobs`" ] \
&& echo "$0: #jobs mismatch with transform-dir." && exit 1;
feats="$feats transform-feats --utt2spk=ark:$sdata/JOB/utt2spk ark,s,cs:$transform_dir/trans.JOB ark:- ark:- |"
[ ! -s $transform_dir/num_jobs ] && \
echo "$0: expected $transform_dir/num_jobs to contain the number of jobs." && exit 1;
nj_orig=$(cat $transform_dir/num_jobs)
if [ $feat_type == "raw" ]; then trans=raw_trans;
else trans=trans; fi
if [ $feat_type == "lda" ] && \
! cmp $transform_dir/../final.mat $srcdir/final.mat && \
! cmp $transform_dir/final.mat $srcdir/final.mat; then
echo "$0: LDA transforms differ between $srcdir and $transform_dir"
exit 1;
fi
if [ ! -f $transform_dir/$trans.1 ]; then
echo "$0: expected $transform_dir/$trans.1 to exist (--transform-dir option)"
exit 1;
fi
if [ $nj -ne $nj_orig ]; then
# Copy the transforms into an archive with an index.
for n in $(seq $nj_orig); do cat $transform_dir/$trans.$n; done | \
copy-feats ark:- ark,scp:$dir/$trans.ark,$dir/$trans.scp || exit 1;
feats="$feats transform-feats --utt2spk=ark:$sdata/JOB/utt2spk scp:$dir/$trans.scp ark:- ark:- |"
else
[ ! -f $transform_dir/raw_trans.1 ] && echo "$0: no such file $transform_dir/raw_trans.1" && exit 1;
[ "$nj" -ne "`cat $transform_dir/num_jobs`" ] \
&& echo "$0: #jobs mismatch with transform-dir." && exit 1;
feats="$feats transform-feats --utt2spk=ark:$sdata/JOB/utt2spk ark,s,cs:$transform_dir/raw_trans.JOB ark:- ark:- |"
# number of jobs matches with alignment dir.
feats="$feats transform-feats --utt2spk=ark:$sdata/JOB/utt2spk ark:$transform_dir/$trans.JOB ark:- ark:- |"
fi
elif grep 'transform-feats --utt2spk' $srcdir/log/train.1.log >&/dev/null; then
echo "$0: **WARNING**: you seem to be using a neural net system trained with transforms,"
......
......@@ -36,6 +36,7 @@ perspk=false
first_opt=""
speakers=false
spk_list_specified=false
utt_list_specified=false
if [ "$1" == "--per-spk" ]; then
perspk=true;
......@@ -55,6 +56,9 @@ elif [ "$1" == "--last" ]; then
elif [ "$1" == "--spk-list" ]; then
spk_list_specified=true
shift;
elif [ "$1" == "--utt-list" ]; then
utt_list_specified=true
shift;
fi
......@@ -64,6 +68,7 @@ if [ $# != 3 ]; then
echo "Usage: "
echo " subset_data_dir.sh [--speakers|--shortest|--first|--last|--per-spk] <srcdir> <num-utt> <destdir>"
echo " subset_data_dir.sh [--spk-list <speaker-list-file>] <srcdir> <destdir>"
echo " subset_data_dir.sh [--utt-list <utterance-list-file>] <srcdir> <destdir>"
echo "By default, randomly selects <num-utt> utterances from the data directory."
echo "With --speakers, randomly selects enough speakers that we have <num-utt> utterances"
echo "With --per-spk, selects <num-utt> utterances per speaker, if available."
......@@ -78,6 +83,10 @@ if $spk_list_specified; then
spk_list=$1
srcdir=$2
destdir=$3
elif $utt_list_specified; then
utt_list=$1
srcdir=$2
destdir=$3
else
srcdir=$1
numutt=$2
......@@ -127,7 +136,13 @@ if $spk_list_specified; then
utils/filter_scp.pl "$spk_list" $srcdir/spk2utt > $destdir/spk2utt || exit 1;
utils/spk2utt_to_utt2spk.pl < $destdir/spk2utt > $destdir/utt2spk || exit 1;
do_filtering; # bash function.
exit 0;
exit 0;
elif $utt_list_specified; then
mkdir -p $destdir
utils/filter_scp.pl "$utt_list" $srcdir/utt2spk > $destdir/utt2spk || exit 1;
utils/utt2spk_to_spk2utt.pl < $destdir/utt2spk > $destdir/spk2utt || exit 1;
do_filtering; # bash function.
exit 0;
elif $speakers; then
mkdir -p $destdir
utils/shuffle_list.pl < $srcdir/spk2utt | awk -v numutt=$numutt '{ if (tot < numutt){ print; } tot += (NF-1); }' | \
......
......@@ -128,8 +128,8 @@ void Randomize(const CuMatrixBase<Real> &src,
template<typename Real>
void Splice(const CuMatrix<Real> &src, const CuArray<int32> &frame_offsets,
CuMatrix<Real> *tgt) {
CuMatrixBase<Real> *tgt) {
KALDI_ASSERT(src.NumCols()*frame_offsets.Dim() == tgt->NumCols());
KALDI_ASSERT(src.NumRows() == tgt->NumRows());
......@@ -167,7 +167,8 @@ void Splice(const CuMatrix<Real> &src, const CuArray<int32> &frame_offsets,
template<typename Real>
void Copy(const CuMatrix<Real> &src, const CuArray<int32> &copy_from_indices, CuMatrix<Real> *tgt) {
void Copy(const CuMatrix<Real> &src, const CuArray<int32> &copy_from_indices,
CuMatrixBase<Real> *tgt) {
KALDI_ASSERT(copy_from_indices.Dim() == tgt->NumCols());
KALDI_ASSERT(src.NumRows() == tgt->NumRows());
......@@ -207,13 +208,17 @@ template
void RegularizeL1(CuMatrixBase<double> *weight, CuMatrixBase<double> *grad, double l1, double lr);
template
void Splice(const CuMatrix<float> &src, const CuArray<int32> &frame_offsets, CuMatrix<float> *tgt);
void Splice(const CuMatrix<float> &src, const CuArray<int32> &frame_offsets,
CuMatrixBase<float> *tgt);
template
void Splice(const CuMatrix<double> &src, const CuArray<int32> &frame_offsets, CuMatrix<double> *tgt);
void Splice(const CuMatrix<double> &src, const CuArray<int32> &frame_offsets,
CuMatrixBase<double> *tgt);
template
void Copy(const CuMatrix<float> &src, const CuArray<int32> &copy_from_indices, CuMatrix<float> *tgt);
void Copy(const CuMatrix<float> &src, const CuArray<int32> &copy_from_indices,
CuMatrixBase<float> *tgt);
template
void Copy(const CuMatrix<double> &src, const CuArray<int32> &copy_from_indices, CuMatrix<double> *tgt);
void Copy(const CuMatrix<double> &src, const CuArray<int32> &copy_from_indices,
CuMatrixBase<double> *tgt);
template
void Randomize(const CuMatrixBase<float> &src,
......
......@@ -61,7 +61,7 @@ void Randomize(const CuMatrixBase<Real> &src,
template<typename Real>
void Splice(const CuMatrix<Real> &src,
const CuArray<int32> &frame_offsets,
CuMatrix<Real> *tgt);
CuMatrixBase<Real> *tgt);
/// Copies elements from src into tgt as given by copy_from_indices.
/// The matrices src and tgt must have the same dimensions and
......@@ -71,7 +71,7 @@ void Splice(const CuMatrix<Real> &src,
template<typename Real>
void Copy(const CuMatrix<Real> &src,
const CuArray<int32> &copy_from_indices,
CuMatrix<Real> *tgt);
CuMatrixBase<Real> *tgt);
} // namespace cu
......
......@@ -78,10 +78,10 @@ class CuMatrixBase {
CuMatrixBase<Real> *grad, Real l1, Real lr);
friend void cu::Splice<Real>(const CuMatrix<Real> &src,
const CuArray<int32> &frame_offsets,
CuMatrix<Real> *tgt);
CuMatrixBase<Real> *tgt);
friend void cu::Copy<Real>(const CuMatrix<Real> &src,
const CuArray<int32> &copy_from_indices,
CuMatrix<Real> *tgt);
CuMatrixBase<Real> *tgt);
friend void cu::Randomize<Real>(const CuMatrixBase<Real> &src,
const CuArray<int32> &copy_from_idx,
CuMatrixBase<Real> *tgt);
......
......@@ -59,7 +59,7 @@ class CuVectorBase {
const CuVectorBase<OtherReal> &v2);
friend void cu::Splice<Real>(const CuMatrix<Real> &src,
const CuArray<int32> &frame_offsets,
CuMatrix<Real> *tgt);
CuMatrixBase<Real> *tgt);
friend class CuRand<Real>;
/// Dimensions
......
......@@ -119,7 +119,7 @@ std::string MomentStatistics(const CuMatrix<Real> &mat) {
* in N, out k*N, FrameOffset o_1,o_2,...,o_k
* FrameOffset example 11frames: -5 -4 -3 -2 -1 0 1 2 3 4 5
*/
class Splice : public Component {
class Splice: public Component {
public:
Splice(int32 dim_in, int32 dim_out)
: Component(dim_in, dim_out)
......
......@@ -294,6 +294,15 @@ Component *PermuteComponent::Copy() const {
ans->reorder_ = reorder_;
return ans;
}
void PermuteComponent::Init(const std::vector<int32> &reorder) {
reorder_ = reorder;
KALDI_ASSERT(!reorder.empty());
std::vector<int32> indexes(reorder);
std::sort(indexes.begin(), indexes.end());
for (int32 i = 0; i < static_cast<int32>(indexes.size()); i++)
KALDI_ASSERT(i == indexes[i] && "Not a permutation");
}
std::string Component::Info() const {
std::stringstream stream;
......@@ -1083,6 +1092,7 @@ AffineComponent::AffineComponent(const CuMatrix<BaseFloat> &linear_params,
bias_params_(bias_params) {
KALDI_ASSERT(linear_params.NumRows() == bias_params.Dim()&&
bias_params.Dim() != 0);
is_gradient_ = false;
}
......@@ -1209,11 +1219,16 @@ void AffineComponent::InitFromString(std::string args) {
void AffineComponent::Propagate(const CuMatrixBase<BaseFloat> &in,
int32, // num_chunks
CuMatrix<BaseFloat> *out) const {
KALDI_LOG << "First element of input is " << in(0, 0);
KALDI_LOG << "Input sum is " << in.Sum();
// No need for asserts as they'll happen within the matrix operations.
out->Resize(in.NumRows(), linear_params_.NumRows());
out->CopyRowsFromVec(bias_params_); // copies bias_params_ to each row
// of *out.
KALDI_LOG << "First element of output is " << (*out)(0, 0);
KALDI_LOG << "Linearity sum is " << linear_params_.Sum();
out->AddMatMat(1.0, in, kNoTrans, linear_params_, kTrans, 1.0);
KALDI_LOG << "First element of output is " << (*out)(0, 0);
}
void AffineComponent::UpdateSimple(const CuMatrixBase<BaseFloat> &in_value,
......@@ -3451,86 +3466,50 @@ void SpliceComponent::Propagate(const CuMatrixBase<BaseFloat> &in,
<< "Probably a code error.";
out->Resize(num_chunks * output_chunk_size, output_dim);
if (0) { // rand() % 2 == 0) { // Occasionally do the older code,
// this will flag any inconsistency in the tests.
for (int32 chunk = 0; chunk < num_chunks; chunk++) {
CuSubMatrix<BaseFloat> input_chunk(in,
chunk * input_chunk_size, input_chunk_size,
0, input_dim),
output_chunk(*out,
chunk * output_chunk_size, output_chunk_size,
0, output_dim);
for (int32 c = 0; c < left_context_ + right_context_ + 1; c++) {
CuSubMatrix<BaseFloat> input_part(input_chunk,
c, output_chunk_size,
0, input_dim - const_component_dim_),
output_part(output_chunk,
0, output_chunk_size,
(input_dim - const_component_dim_) * c,
input_dim - const_component_dim_);
output_part.CopyFromMat(input_part);
}
//Append the constant component at the end of the output vector
if (const_component_dim_ != 0) {
CuSubMatrix<BaseFloat> input_part(input_chunk,
0, output_chunk_size,
InputDim() - const_component_dim_,
const_component_dim_),
output_part(output_chunk,
0, output_chunk_size,
OutputDim() - const_component_dim_,
const_component_dim_);
output_part.CopyFromMat(input_part);
// 'indexes' is, for each index from 0 to (left_context_+right_context_+1)-1,
// then for each row of "out", the corresponding row of "in" that we copy from.
int32 num_splice = left_context_ + right_context_ + 1,
const_dim = const_component_dim_;
std::vector<std::vector<int32> > indexes(num_splice);
// const_component_dim_ != 0, "const_indexes" will be used to determine which
// row of "in" we copy the last part of each row of "out" from (this part is
// not subject to splicing, it's assumed constant for each frame of "input".
std::vector<int32> const_indexes(const_dim == 0 ? 0 : out->NumRows());
for (int32 c = 0; c < num_splice; c++)
indexes[c].resize(out->NumRows());
for (int32 chunk = 0; chunk < num_chunks; chunk++) {
for (int32 c = 0; c < num_splice; c++) {
for (int32 offset = 0; offset < output_chunk_size; offset++) {
indexes[c][chunk * output_chunk_size + offset] =
chunk * input_chunk_size + c + offset;
}
}
} else {
// 'indexes' is, for each index from 0 to (left_context_+right_context_+1)-1,
// then for each row of "out", the corresponding row of "in" that we copy from.
int32 num_splice = left_context_ + right_context_ + 1,
const_dim = const_component_dim_;
std::vector<std::vector<int32> > indexes(num_splice);
// const_component_dim_ != 0, "const_indexes" will be used to determine which
// row of "in" we copy the last part of each row of "out" from (this part is
// not subject to splicing, it's assumed constant for each frame of "input".
std::vector<int32> const_indexes(const_dim == 0 ? 0 : out->NumRows());
for (int32 c = 0; c < num_splice; c++)
indexes[c].resize(out->NumRows());
for (int32 chunk = 0; chunk < num_chunks; chunk++) {
for (int32 c = 0; c < num_splice; c++) {