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

trunk: for splicing component: adding tests, bug-fix in backprop of splice...

trunk: for splicing component: adding tests, bug-fix in backprop of splice component (should not affect current scripts)

git-svn-id: https://svn.code.sf.net/p/kaldi/code/trunk@4594 5e6a8d80-dfce-4ca6-a32a-6e07a63d50c8
parent 971c266c
......@@ -34,25 +34,15 @@ namespace kaldi {
namespace nnet2 {
void UnitTestGenericComponentInternal(const Component &component) {
int32 input_dim = component.InputDim(),
output_dim = component.OutputDim();
KALDI_LOG << component.Info();
CuVector<BaseFloat> objf_vec(output_dim); // objective function is linear function of output.
objf_vec.SetRandn(); // set to Gaussian noise.
void UnitTestGenericComponentInternal(const Component &component,
const ChunkInfo in_info,
const ChunkInfo out_info) {
int32 num_egs = 10 + Rand() % 5;
CuMatrix<BaseFloat> input(num_egs, input_dim),
output(num_egs, output_dim);
CuMatrix<BaseFloat> input(in_info.NumRows(), in_info.NumCols()),
output(out_info.NumRows(), out_info.NumCols());
input.SetRandn();
int32 num_chunks = 1,
first_offset = 0,
last_offset = num_egs-1;
ChunkInfo in_info(input_dim, num_chunks, first_offset, last_offset);
ChunkInfo out_info(output_dim, num_chunks, first_offset, last_offset);
CuVector<BaseFloat> objf_vec(out_info.NumCols()); // objective function is linear function of output.
objf_vec.SetRandn(); // set to Gaussian noise.
int32 rand_seed = Rand();
......@@ -77,7 +67,7 @@ void UnitTestGenericComponentInternal(const Component &component) {
unlink("tmpf");
{ // Test backward derivative is correct.
CuVector<BaseFloat> output_objfs(num_egs);
CuVector<BaseFloat> output_objfs(out_info.NumRows());
output_objfs.AddMatVec(1.0, output, kNoTrans, objf_vec, 0.0);
BaseFloat objf = output_objfs.Sum();
......@@ -95,7 +85,6 @@ void UnitTestGenericComponentInternal(const Component &component) {
&output_ref =
(component_copy->BackpropNeedsOutput() ? output : empty_mat);
component_copy->Backprop(in_info, out_info, input_ref, output_ref,
output_deriv, NULL, &input_deriv);
......@@ -128,7 +117,7 @@ void UnitTestGenericComponentInternal(const Component &component) {
}
}
component.Propagate(in_info, out_info, perturbed_input, &perturbed_output);
CuVector<BaseFloat> perturbed_output_objfs(num_egs);
CuVector<BaseFloat> perturbed_output_objfs(out_info.NumRows());
perturbed_output_objfs.AddMatVec(1.0, perturbed_output, kNoTrans,
objf_vec, 0.0);
BaseFloat perturbed_objf = perturbed_output_objfs.Sum(),
......@@ -170,7 +159,7 @@ void UnitTestGenericComponentInternal(const Component &component) {
BaseFloat perturb_stddev = 5.0e-04;
perturbed_ucomponent->PerturbParams(perturb_stddev);
CuVector<BaseFloat> output_objfs(num_egs);
CuVector<BaseFloat> output_objfs(out_info.NumRows());
output_objfs.AddMatVec(1.0, output, kNoTrans, objf_vec, 0.0);
BaseFloat objf = output_objfs.Sum();
......@@ -196,7 +185,7 @@ void UnitTestGenericComponentInternal(const Component &component) {
}
}
perturbed_ucomponent->Propagate(in_info, out_info, input, &output_perturbed);
CuVector<BaseFloat> output_objfs_perturbed(num_egs);
CuVector<BaseFloat> output_objfs_perturbed(out_info.NumRows());
output_objfs_perturbed.AddMatVec(1.0, output_perturbed,
kNoTrans, objf_vec, 0.0);
objf_perturbed = output_objfs_perturbed.Sum();
......@@ -227,6 +216,22 @@ void UnitTestGenericComponentInternal(const Component &component) {
delete component_copy; // No longer needed.
}
void UnitTestGenericComponentInternal(const Component &component) {
int32 input_dim = component.InputDim(),
output_dim = component.OutputDim();
KALDI_LOG << component.Info();
int32 num_egs = 10 + Rand() % 5;
int32 num_chunks = 1,
first_offset = 0,
last_offset = num_egs-1;
ChunkInfo in_info(input_dim, num_chunks, first_offset, last_offset);
ChunkInfo out_info(output_dim, num_chunks, first_offset, last_offset);
UnitTestGenericComponentInternal(component, in_info, out_info);
}
void UnitTestSigmoidComponent() {
// We're testing that the gradients are computed correctly:
......@@ -681,51 +686,67 @@ void UnitTestParsing() {
}
void BasicDebugTestForSplice(bool output=false) {
int32 C = 5,
K = 4,
context_len = 1,
R = 3 + 2 * context_len;
SpliceComponent *c = new SpliceComponent();
std::vector<int32> context(2 * context_len + 1);
for (int32 i = -context_len; i <= context_len; i++)
context[i + context_len] = i;
c->Init(C, context, K);
ChunkInfo in_info = ChunkInfo(C, 1, 0, R - 1),
out_info = ChunkInfo((C - K) * context.size() + K, 1, context_len, R - 1 - context_len);
CuMatrix<BaseFloat> in(R, C), in_deriv(R, C);
CuMatrix<BaseFloat> out(R - 2 * context_len, c->OutputDim());
in_info.Check();
out_info.Check();
in.SetRandn();
if (output)
KALDI_LOG << in;
c->Propagate(in_info, out_info, in, &out);
if (output)
KALDI_LOG << out;
out.Set(1);
if (K > 0) {
CuSubMatrix<BaseFloat> k(out, 0, out.NumRows(), c->OutputDim() - K, K);
k.Set(-2);
out.Row(1).Scale(10.0);
void UnitTestSpliceComponent() {
int32 feat_dim = RandInt(1, 20),
const_dim = RandInt(0, 10),
left_context = RandInt(-5, 0),
right_context = RandInt(0, 5),
num_chunks = RandInt(0, 20);
// multiple chunks are required as splice component
// has separate index computation logic for more than one chunks
KALDI_LOG << " Feat_dim :" << feat_dim << " const_dim: " << const_dim ;
std::vector<bool> contiguous(2);
contiguous[0] = true;
contiguous[1] = false;
for (int32 i = 0; i < contiguous.size(); i++) {
std::vector<int32> splice_indexes;
if (contiguous[i]) {
// create contiguous set of splice indexes in the range
// (-left_context, right_context)
KALDI_LOG << "Testing contiguous splice component";
splice_indexes.reserve(right_context - left_context + 1);
for (int32 i = left_context; i <= right_context; i++)
splice_indexes.push_back(i);
} else {
// generate random splice indexes in range (-left_context, right_context)
KALDI_LOG << "Testing non-contiguous splice component";
int32 num_left_splice_indexes = RandInt(0, -left_context) + 1;
int32 num_right_splice_indexes = RandInt(0, right_context);
splice_indexes.reserve(num_left_splice_indexes + num_right_splice_indexes);
while (splice_indexes.size() < num_left_splice_indexes) {
int32 new_index = RandInt(left_context, 0);
// check if the index already exists in the vector
if (std::find(splice_indexes.begin(), splice_indexes.end(), new_index)
== splice_indexes.end()) {
splice_indexes.push_back(new_index);
}
}
while (splice_indexes.size() < num_left_splice_indexes + num_right_splice_indexes) {
int32 new_index = RandInt(0, right_context);
// check if the index already exists in the vector
if (std::find(splice_indexes.begin(), splice_indexes.end(), new_index)
== splice_indexes.end()) {
splice_indexes.push_back(new_index);
}
}
sort(splice_indexes.begin(), splice_indexes.end());
if (splice_indexes.back() < 0) // will fail assertion in init of component
splice_indexes.push_back(0);
}
std::vector<int32> input_offsets;
for (int32 i = 0; i < splice_indexes.size(); i++) {
input_offsets.push_back(splice_indexes[i] - splice_indexes.front());
KALDI_LOG << i << " : " << splice_indexes[i] << " : " << input_offsets[i] ;
}
int32 output_offset = -splice_indexes.front();
SpliceComponent *component = new SpliceComponent();
component->Init(feat_dim + const_dim, splice_indexes, const_dim);
ChunkInfo in_info = ChunkInfo(feat_dim + const_dim, num_chunks,
input_offsets),
out_info = ChunkInfo(feat_dim * splice_indexes.size() + const_dim,
num_chunks, output_offset, output_offset);
UnitTestGenericComponentInternal(*component, in_info, out_info);
}
if (output)
KALDI_LOG << out;
c->Backprop(in_info, out_info, in, in, out, c, &in_deriv);
if (output)
KALDI_LOG << in_deriv;
delete c;
}
void BasicDebugTestForSpliceMax(bool output=false) {
......@@ -785,7 +806,6 @@ int main() {
CuDevice::Instantiate().SelectGpuId("optional"); // -2 .. automatic selection
#endif
BasicDebugTestForSplice(true);
BasicDebugTestForSpliceMax(true);
for (int32 i = 0; i < 3; i++) {
UnitTestGenericComponent<SigmoidComponent>();
......@@ -796,6 +816,7 @@ int main() {
UnitTestGenericComponent<SoftmaxComponent>();
UnitTestGenericComponent<RectifiedLinearComponent>();
UnitTestGenericComponent<SoftHingeComponent>();
UnitTestSpliceComponent();
UnitTestMaxoutComponent();
UnitTestPnormComponent();
UnitTestGenericComponent<NormalizeComponent>();
......
......@@ -2593,9 +2593,10 @@ void SpliceComponent::Propagate(const ChunkInfo &in_info,
} else { // just copy the indices from the previous chunk
// and offset these by input chunk size
for (int32 c = 0; c < num_splice; c++) {
for (int32 out_index = 0; out_index < out_chunk_size; out_index++) {
for (int32 out_index = 0; out_index < out_chunk_size; out_index++) {
int32 last_value = indexes[c][(chunk-1) * out_chunk_size + out_index];
indexes[c][chunk * out_chunk_size + out_index] =
indexes[c][(chunk-1) * out_chunk_size + out_index] + in_chunk_size;
(last_value == -1 ? -1 : last_value + in_chunk_size);
}
}
}
......@@ -2644,8 +2645,8 @@ void SpliceComponent::Backprop(const ChunkInfo &in_info,
int32 out_chunk_size = out_info.ChunkSize(),
in_chunk_size = in_info.ChunkSize(),
output_dim = out_deriv.NumCols(),
input_dim = InputDim();
output_dim = out_deriv.NumCols(),
input_dim = InputDim();
KALDI_ASSERT(OutputDim() == output_dim);
......@@ -2681,8 +2682,9 @@ void SpliceComponent::Backprop(const ChunkInfo &in_info,
} else { // just copy the indexes from the previous chunk
for (int32 c = 0; c < num_splice; c++) {
for (int32 in_index = 0; in_index < in_chunk_size; in_index++) {
int32 last_value = indexes[c][(chunk-1) * in_chunk_size + in_index];
indexes[c][chunk * in_chunk_size + in_index] =
indexes[c][(chunk-1) * in_chunk_size + in_index] + out_chunk_size;
(last_value == -1 ? -1 : last_value + out_chunk_size);
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment