25 namespace time_height_convolution {
35 max_height_offset =
RandInt(0, 2),
36 min_time_offset =
RandInt(-2, 0),
37 max_time_offset =
RandInt(0, 2);
50 std::vector<int32> all_time_offsets;
54 for (
int32 i = 0;
i < max_offsets;
i++) {
63 std::random_shuffle(all_time_offsets.begin(), all_time_offsets.end());
64 int32 num_required_offsets =
RandInt(1, all_time_offsets.size());
65 for (
int32 i = 0;
i < num_required_offsets;
i++)
69 if (!model->
Check()) {
70 KALDI_WARN <<
"Regenerating model because it didn't pass the check: " 79 std::vector<Index> *input_indexes,
80 std::vector<Index> *output_indexes) {
83 std::vector<std::pair<int32, int32> > n_x_pairs;
85 for (
int32 i = 0;
i < num_n_x_pairs;
i++) {
87 n_x_pairs.push_back(std::pair<int32, int32>(n, x));
90 num_n_x_pairs = n_x_pairs.size();
95 std::vector<int32> output_t_values;
100 for (
int32 i = 0;
i < num_t_out;
i++)
101 output_t_values.push_back(out_t_start +
i * out_t_step);
104 input_indexes->clear();
105 output_indexes->clear();
106 for (
size_t i = 0;
i < n_x_pairs.size();
i++) {
107 std::vector<int32> chosen_output_t_values;
108 while (chosen_output_t_values.empty()) {
109 for (
size_t j = 0;
j < output_t_values.size();
j++)
111 chosen_output_t_values.push_back(output_t_values[
j]);
115 std::set<int32> required_input_t_values,
116 usable_input_t_values;
117 for (
size_t j = 0;
j < chosen_output_t_values.size();
j++) {
118 std::set<int32>::const_iterator iter;
119 int32 t_out = chosen_output_t_values[
j];
122 int32 offset = *iter;
123 required_input_t_values.insert(t_out + offset);
127 int32 offset = *iter;
128 usable_input_t_values.insert(t_out + offset);
133 for (
size_t j = 0;
j < chosen_output_t_values.size();
j++) {
134 int32 t_out = chosen_output_t_values[
j];
136 index.
n = n_x_pairs[
i].first;
137 index.
x = n_x_pairs[
i].second;
139 output_indexes->push_back(index);
142 std::vector<int32> chosen_input_t_values(required_input_t_values.begin(),
143 required_input_t_values.end());
144 for (std::set<int32>::const_iterator iter = usable_input_t_values.begin();
145 iter != usable_input_t_values.end(); ++iter) {
148 chosen_input_t_values.push_back(t);
153 for (
size_t j = 0;
j < chosen_input_t_values.size();
j++) {
154 int32 t_in = chosen_input_t_values[
j];
156 index.
n = n_x_pairs[
i].first;
157 index.
x = n_x_pairs[
i].second;
159 input_indexes->push_back(index);
171 std::ostringstream os1, os2;
172 bool binary = (
RandInt(0, 1) == 0);
173 conv_model.
Write(os1, binary);
174 std::istringstream is(os1.str());
176 conv_model2.
Read(is, binary);
177 conv_model2.Write(os2, binary);
178 KALDI_ASSERT(os1.str() == os2.str() && conv_model2.Check());
183 std::ostringstream os1, os2;
184 bool binary = (
RandInt(0, 1) == 0);
185 computation.
Write(os1, binary);
186 std::istringstream is(os1.str());
188 computation2.
Read(is, binary);
189 computation2.Write(os2, binary);
191 computation2.Check();
202 if (num_rows == 0)
return;
205 const Index *indexes_ptr = &(indexes[0]);
207 for (
int32 r = 0; r < num_rows; r++) {
208 if (indexes_ptr[r].t ==
kNoTime)
220 const std::vector<Index> &input_indexes,
221 const std::vector<Index> &output_indexes,
228 std::unordered_map<Index, int32, IndexHasher> index_to_row;
229 int32 input_rows = input.NumRows(),
230 output_rows = output.
NumRows();
231 for (
int32 r_in = 0; r_in < input_rows; r_in++) {
232 if (input_indexes[r_in].t !=
kNoTime) {
233 index_to_row[input_indexes[r_in]] = r_in;
242 for (
int32 r_out = 0; r_out < output_rows; r_out++) {
243 Index index_out = output_indexes[r_out];
247 for (
int32 o = 0; o < num_offsets; o++) {
249 height_offset = model.
offsets[o].height_offset;
250 Index index_in(index_out);
251 index_in.
t += time_offset;
252 std::unordered_map<Index, int32, IndexHasher>::const_iterator iter =
253 index_to_row.find(index_in);
254 if (iter != index_to_row.end()) {
256 o * num_filters_in, num_filters_in);
257 int32 r_in = iter->second;
259 for (
int32 h_out_subsampled = 0;
260 h_out_subsampled < height_out;
261 h_out_subsampled++) {
262 int32 h_out = h_out_subsampled * height_subsample_out,
263 h_in = h_out + height_offset;
264 if (h_in < 0 || h_in >= height_in)
267 h_out_subsampled * num_filters_out,
269 input_part(input_row, h_in * num_filters_in, num_filters_in);
270 output_part.AddMatVec(1.0, params_part,
kNoTrans, input_part, 1.0);
281 const std::vector<Index> &input_indexes,
282 const std::vector<Index> &output_indexes,
286 output(output_indexes.size(), conv_model.
OutputDim(),
297 input, params, &output2);
298 KALDI_LOG <<
"Tested convolution for model: " 299 << conv_model.
Info();
300 if (!output.ApproxEqual(output2, 0.001)) {
303 KALDI_ERR <<
"Convolution test failure.";
309 const std::vector<Index> &input_indexes,
310 const std::vector<Index> &output_indexes,
313 input_deriv(input_indexes.size(), conv_model.
InputDim(),
315 input(input_indexes.size(), conv_model.
InputDim(),
317 output(output_indexes.size(), conv_model.
OutputDim(),
319 output_deriv(output_indexes.size(), conv_model.
OutputDim(),
325 output_deriv.SetRandn();
341 KALDI_LOG <<
"Expected objf = " << expected_objf
342 <<
", observed objf = " << observed_objf;
343 if (!
ApproxEqual(expected_objf, observed_objf, 0.1) &&
344 fabs(expected_objf) < 1.0) {
345 KALDI_ERR <<
"Difference in objf too large.";
351 const std::vector<Index> &input_indexes,
352 const std::vector<Index> &output_indexes,
355 input(input_indexes.size(), conv_model.
InputDim(),
357 output(output_indexes.size(), conv_model.
OutputDim(),
359 output_deriv(output_indexes.size(), conv_model.
OutputDim(),
366 output_deriv.SetRandn();
384 KALDI_LOG <<
"Expected objf = " << expected_objf
385 <<
", observed objf = " << observed_objf;
386 if (!
ApproxEqual(expected_objf, observed_objf, 0.1) &&
387 fabs(expected_objf) < 1.0) {
388 KALDI_ERR <<
"Difference in objf too large.";
400 std::vector<Index> input_indexes, output_indexes;
405 std::vector<Index> input_indexes_modified, output_indexes_modified;
408 &input_indexes_modified,
409 &output_indexes_modified);
412 input_indexes_modified,
413 output_indexes_modified,
416 input_indexes_modified,
417 output_indexes_modified,
420 input_indexes_modified,
421 output_indexes_modified,
423 std::ostringstream os;
424 os <<
"\nInput-indexes: ";
426 os <<
"\nInput-indexes-modified: ";
428 os <<
"\nOutput-indexes: ";
430 os <<
"\nOutput-indexes-modified: ";
450 using namespace kaldi;
453 for (
int32 loop = 0; loop < 2; loop++) {
455 CuDevice::Instantiate().SetDebugStrideMode(
true);
457 CuDevice::Instantiate().SelectGpuId(
"no");
459 CuDevice::Instantiate().SelectGpuId(
"optional");
void CopyFromMat(const MatrixBase< OtherReal > &src, MatrixTransposeType trans=kNoTrans)
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
int32 height_subsample_out
void WriteIndexVector(std::ostream &os, bool binary, const std::vector< Index > &vec)
void Write(std::ostream &os, bool binary) const
void ConvolveBackwardParams(const ConvolutionComputation &cc, const CuMatrixBase< BaseFloat > &input, const CuMatrixBase< BaseFloat > &output_deriv, BaseFloat alpha, CuMatrixBase< BaseFloat > *params_deriv)
This does the part of the backward derivative computation of convolution, that computes derivatives w...
bool Check(bool check_heights_used=true, bool allow_height_padding=true) const
void Read(std::istream &is, bool binary)
void UnitTestTimeHeightConvolutionCompile()
This comment explains the basic framework used for everything related to time-height convolution...
This class represents a matrix that's stored on the GPU if we have one, and in memory if not...
static void GetRandomConvolutionIndexes(const ConvolutionModel &model, std::vector< Index > *input_indexes, std::vector< Index > *output_indexes)
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq's (removes duplicates) from a vector.
struct Index is intended to represent the various indexes by which we number the rows of the matrices...
std::set< int32 > all_time_offsets
void UnitTestTimeHeightConvolutionIo()
This file contains some fairly low-level utilities for implementing convolutional neural networks and...
void UnitTestTimeHeightConvolution()
void ConvolveBackwardData(const ConvolutionComputation &cc, const CuMatrixBase< BaseFloat > ¶ms, const CuMatrixBase< BaseFloat > &output_deriv, CuMatrixBase< BaseFloat > *input_deriv)
This does the part of the backward derivative computation of convolution, that propagates derivatives...
void Read(std::istream &is, bool binary)
void ZeroBlankRows(const std::vector< Index > &indexes, CuMatrix< BaseFloat > *matrix)
void TestRunningComputation(const ConvolutionModel &conv_model, const std::vector< Index > &input_indexes, const std::vector< Index > &output_indexes, const ConvolutionComputation &computation)
void TestComputationIo(const ConvolutionComputation &computation)
void ConvolveForwardSimple(const ConvolutionModel &model, const std::vector< Index > &input_indexes, const std::vector< Index > &output_indexes, const CuMatrixBase< BaseFloat > &input_cu, const CuMatrixBase< BaseFloat > ¶ms_cu, CuMatrixBase< BaseFloat > *output_cu)
void CompileConvolutionComputation(const ConvolutionModel &model, const std::vector< Index > &input_indexes, const std::vector< Index > &output_indexes, const ConvolutionComputationOptions &opts, ConvolutionComputation *computation, std::vector< Index > *input_indexes_modified, std::vector< Index > *output_indexes_modified)
This function does the compilation for a convolution computation; it's a wrapper for the functions be...
Real TraceMatMat(const MatrixBase< Real > &A, const MatrixBase< Real > &B, MatrixTransposeType trans)
We need to declare this here as it will be a friend function.
Real * Data()
Returns a pointer to the start of the vector's data.
std::vector< Offset > offsets
This struct represents the structure of a convolution computation.
Matrix for CUDA computing.
A class representing a vector.
#define KALDI_ASSERT(cond)
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
void Set(Real f)
Set all members of a vector to a specified value.
void TestParamsBackprop(const ConvolutionModel &conv_model, const std::vector< Index > &input_indexes, const std::vector< Index > &output_indexes, const ConvolutionComputation &computation)
This struct contains options for compiling the convolutional computation.
std::set< int32 > required_time_offsets
void Write(std::ostream &os, bool binary) const
static void GetRandomConvolutionModel(ConvolutionModel *model)
void Swap(CuVector< Real > *vec)
void TestDataBackprop(const ConvolutionModel &conv_model, const std::vector< Index > &input_indexes, const std::vector< Index > &output_indexes, const ConvolutionComputation &computation)
MatrixIndexT NumRows() const
Dimensions.
bool IsSortedAndUniq(const std::vector< T > &vec)
Returns true if the vector is sorted and contains each element only once.
void MulRowsVec(const CuVectorBase< Real > &scale)
scale i'th row by scale[i]
Sub-matrix representation.
void ConvolveForward(const ConvolutionComputation &cc, const CuMatrixBase< BaseFloat > &input, const CuMatrixBase< BaseFloat > ¶ms, CuMatrixBase< BaseFloat > *output)
This does the forward computation of convolution.
Represents a non-allocating general vector which can be defined as a sub-vector of higher-level vecto...
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)