nnet-randomizer.cc
Go to the documentation of this file.
1 // nnet/nnet-randomizer.cc
2 
3 // Copyright 2013 Brno University of Technology (author: Karel Vesely)
4 
5 // See ../../COPYING for clarification regarding multiple authors
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
15 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
16 // MERCHANTABLITY OR NON-INFRINGEMENT.
17 // See the Apache 2 License for the specific language governing permissions and
18 // limitations under the License.
19 
20 #include "nnet/nnet-randomizer.h"
21 
22 #include <vector>
23 #include <algorithm>
24 #include <utility>
25 
26 namespace kaldi {
27 namespace nnet1 {
28 
29 /* RandomizerMask:: */
30 
32  KALDI_LOG << "Seeding by srand with : " << conf.randomizer_seed;
33  srand(conf.randomizer_seed);
34 }
35 
36 const std::vector<int32>& RandomizerMask::Generate(int32 mask_size) {
37  mask_.resize(mask_size);
38  for (int32 i = 0; i < mask_size; i++) mask_[i] = i;
39  // shuffle using built-in random generator:
40  std::random_shuffle(mask_.begin(), mask_.end());
41  return mask_;
42 }
43 
44 
45 /* MatrixRandomizer:: */
46 
48  // pre-allocate before 1st use
49  if (data_.NumCols() == 0) {
50  data_.Resize(conf_.randomizer_size, m.NumCols());
51  }
52  // optionally put previous left-over to front
53  if (data_begin_ > 0) {
54  KALDI_ASSERT(data_begin_ <= data_end_); // sanity check,
55  int32 leftover = data_end_ - data_begin_;
56  KALDI_ASSERT(leftover < data_begin_); // no overlap,
57  if (leftover > 0) {
58  data_.RowRange(0, leftover).CopyFromMat(data_.RowRange(data_begin_, leftover));
59  }
60  data_begin_ = 0;
61  data_end_ = leftover;
62  // set zero to the rest of the buffer,
63  data_.RowRange(leftover, data_.NumRows() - leftover).SetZero();
64  }
65  // extend the buffer if necessary,
66  if (data_.NumRows() < data_end_ + m.NumRows()) {
67  // CuMatrix -> Matrix -> CuMatrix (needs less GPU memory),
68  Matrix<BaseFloat> data_aux(data_);
69  // Add extra 3% rows, so we don't reallocate soon:
70  int32 extra_rows = 0.03 * data_.NumRows();
71  data_.Resize(data_end_ + m.NumRows() + extra_rows, data_.NumCols());
72  data_.RowRange(0, data_aux.NumRows()).CopyFromMat(data_aux);
73  }
74  // copy the data
75  data_.RowRange(data_end_, m.NumRows()).CopyFromMat(m);
76  data_end_ += m.NumRows();
77 }
78 
79 void MatrixRandomizer::Randomize(const std::vector<int32>& mask) {
80  KALDI_ASSERT(data_begin_ == 0);
81  KALDI_ASSERT(data_end_ > 0);
82  KALDI_ASSERT(data_end_ == mask.size());
83  // Copy to auxiliary buffer for unshuffled data
84  data_aux_ = data_;
85  // Put the mask to GPU
86  CuArray<int32> mask_in_gpu(mask.size());
87  mask_in_gpu.CopyFromVec(mask);
88  // Randomize the data, mask is used to index rows in source matrix:
89  // (Here the vector 'mask_in_gpu' is typically shorter than number
90  // of rows in 'data_aux_', because the buffer 'data_aux_'
91  // is larger than capacity 'randomizer_size'.
92  // The extra rows in 'data_aux_' do not contain speech frames and
93  // are not copied from 'data_aux_', the extra rows in 'data_' are
94  // unchanged by cu::Randomize.)
95  cu::Randomize(data_aux_, mask_in_gpu, &data_);
96 }
97 
99  data_begin_ += conf_.minibatch_size;
100 }
101 
103  // make sure we have data for next minibatch,
104  KALDI_ASSERT(data_end_ - data_begin_ >= conf_.minibatch_size);
105  // prepare the mini-batch buffer,
106  minibatch_.Resize(conf_.minibatch_size, data_.NumCols(), kUndefined);
107  minibatch_.CopyFromMat(data_.RowRange(data_begin_, conf_.minibatch_size));
108  return minibatch_;
109 }
110 
111 
112 /* VectorRandomizer */
113 
115  // pre-allocate before 1st use
116  if (data_.Dim() == 0) {
117  data_.Resize(conf_.randomizer_size);
118  }
119  // optionally put previous left-over to front
120  if (data_begin_ > 0) {
121  KALDI_ASSERT(data_begin_ <= data_end_); // sanity check
122  int32 leftover = data_end_ - data_begin_;
123  KALDI_ASSERT(leftover < data_begin_); // no overlap
124  if (leftover > 0) {
125  data_.Range(0, leftover).CopyFromVec(data_.Range(data_begin_, leftover));
126  }
127  data_begin_ = 0;
128  data_end_ = leftover;
129  data_.Range(leftover, data_.Dim()-leftover).SetZero(); // zeroing the rest
130  }
131  // extend the buffer if necessary
132  if (data_.Dim() < data_end_ + v.Dim()) {
133  Vector<BaseFloat> data_aux(data_);
134  data_.Resize(data_end_ + v.Dim() + 1000); // +1000 row surplus
135  data_.Range(0, data_aux.Dim()).CopyFromVec(data_aux);
136  }
137  // copy the data
138  data_.Range(data_end_, v.Dim()).CopyFromVec(v);
139  data_end_ += v.Dim();
140 }
141 
142 void VectorRandomizer::Randomize(const std::vector<int32>& mask) {
143  KALDI_ASSERT(data_begin_ == 0);
144  KALDI_ASSERT(data_end_ > 0);
145  KALDI_ASSERT(data_end_ == mask.size());
146  // Use auxiliary buffer for unshuffled data
147  Vector<BaseFloat> data_aux(data_);
148  // randomize the data, mask is used to index elements in source vector
149  for (int32 i = 0; i < mask.size(); i++) {
150  data_(i) = data_aux(mask.at(i));
151  }
152 }
153 
155  data_begin_ += conf_.minibatch_size;
156 }
157 
159  // make sure we have data for next minibatch,
160  KALDI_ASSERT(data_end_ - data_begin_ >= conf_.minibatch_size);
161  // prepare the mini-batch buffer,
162  minibatch_.Resize(conf_.minibatch_size, kUndefined);
163  minibatch_.CopyFromVec(data_.Range(data_begin_, conf_.minibatch_size));
164  return minibatch_;
165 }
166 
167 
168 /* StdVectorRandomizer */
169 
170 template<typename T>
171 void StdVectorRandomizer<T>::AddData(const std::vector<T>& v) {
172  // pre-allocate before 1st use
173  if (data_.size() == 0) {
174  data_.resize(conf_.randomizer_size);
175  }
176  // optionally put previous left-over to front
177  if (data_begin_ > 0) {
178  KALDI_ASSERT(data_begin_ <= data_end_); // sanity check
179  int32 leftover = data_end_ - data_begin_;
180  KALDI_ASSERT(leftover < data_begin_); // no overlap
181  if (leftover > 0) {
182  typename std::vector<T>::iterator leftover_begin = data_.begin() + data_begin_;
183  std::copy(leftover_begin, leftover_begin + leftover, data_.begin());
184  }
185  data_begin_ = 0;
186  data_end_ = leftover;
187  }
188  // extend the buffer if necessary
189  if (data_.size() < data_end_ + v.size()) {
190  data_.resize(data_end_ + v.size() + 1000); // +1000 row surplus
191  }
192  // copy the data
193  std::copy(v.begin(), v.end(), data_.begin()+data_end_);
194  data_end_ += v.size();
195 }
196 
197 template<typename T>
198 void StdVectorRandomizer<T>::Randomize(const std::vector<int32>& mask) {
199  KALDI_ASSERT(data_begin_ == 0);
200  KALDI_ASSERT(data_end_ > 0);
201  KALDI_ASSERT(data_end_ == mask.size());
202  // Use auxiliary buffer for unshuffled data
203  std::vector<T> data_aux(data_);
204  // randomize the data, mask is used to index elements in source vector
205  for (int32 i = 0; i < mask.size(); i++) {
206  data_.at(i) = data_aux.at(mask.at(i));
207  }
208 }
209 
210 template<typename T>
212  data_begin_ += conf_.minibatch_size;
213 }
214 
215 template<typename T>
216 const std::vector<T>& StdVectorRandomizer<T>::Value() {
217  // make sure we have enough data for minibatch,
218  KALDI_ASSERT(data_end_ - data_begin_ >= conf_.minibatch_size);
219  // prepare the mini-batch buffer,
220  minibatch_.resize(conf_.minibatch_size);
221  typename std::vector<T>::iterator first = data_.begin() + data_begin_;
222  typename std::vector<T>::iterator last = first + conf_.minibatch_size;
223  std::copy(first, last, minibatch_.begin());
224  return minibatch_;
225 }
226 
227 // Instantiate template StdVectorRandomizer with types we expect to operate on,
228 // - Int32VectorRandomizer:
229 template class StdVectorRandomizer<int32>;
230 // - PosteriorRandomizer:
232 
233 } // namespace nnet1
234 } // namespace kaldi
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
void CopyFromVec(const std::vector< T > &src)
This function resizes if needed.
Definition: cu-array-inl.h:120
void Next()
Sets cursor to next mini-batch.
void Randomize(const CuMatrixBase< Real > &src, const CuArray< int32 > &copy_from_idx, CuMatrixBase< Real > *tgt)
Copies a permutation of src into tgt.
Definition: cu-math.cc:80
void Next()
Sets cursor to next mini-batch.
kaldi::int32 int32
uint64 data_
const std::vector< T > & Value()
Returns matrix-window with next mini-batch.
void Randomize(const std::vector< int32 > &mask)
Randomize matrix row-order using mask.
void AddData(const Vector< BaseFloat > &v)
Add data to randomization buffer.
void Next()
Sets cursor to next mini-batch.
std::vector< int32 > mask_
Configuration variables that affect how frame-level shuffling is done.
void Init(const NnetDataRandomizerOptions &conf)
Init, call srand,.
void Randomize(const std::vector< int32 > &mask)
Randomize matrix row-order using mask.
MatrixIndexT Dim() const
Returns the dimension of the vector.
Definition: kaldi-vector.h:64
const CuMatrixBase< BaseFloat > & Value()
Returns matrix-window with next mini-batch.
void Randomize(const std::vector< int32 > &mask)
Randomize matrix row-order using mask.
Matrix for CUDA computing.
Definition: matrix-common.h:69
MatrixIndexT NumCols() const
Definition: cu-matrix.h:216
const std::vector< int32 > & Generate(int32 mask_size)
Generate randomly ordered vector of integers 0..[mask_size -1],.
A class representing a vector.
Definition: kaldi-vector.h:406
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
Definition: kaldi-matrix.h:64
void AddData(const std::vector< T > &v)
Add data to randomization buffer.
Randomizes elements of a vector according to a mask.
MatrixIndexT NumRows() const
Dimensions.
Definition: cu-matrix.h:215
#define KALDI_LOG
Definition: kaldi-error.h:153
void AddData(const CuMatrixBase< BaseFloat > &m)
Add data to randomization buffer.
const Vector< BaseFloat > & Value()
Returns matrix-window with next mini-batch.