kaldi::nnet3 Namespace Reference

Namespaces

 attention
 
 computation_graph
 
 time_height_convolution
 
 utterance_splitting
 This namespace contains things needed for the implementation of the function NnetBatchComputer::SplitUtteranceIntoTasks().
 

Classes

struct  Access
 
class  AffineComponent
 
class  AmNnetSimple
 
struct  Analyzer
 This struct exists to set up various pieces of analysis; it helps avoid the repetition of code where we compute all these things in sequence. More...
 
class  BackpropTruncationComponent
 
class  BackpropTruncationComponentPrecomputedIndexes
 
class  BatchedXvectorComputer
 
struct  BatchedXvectorComputerOptions
 
class  BatchNormComponent
 
class  BinarySumDescriptor
 BinarySumDescriptor can represent either A + B, or (A if defined, else B). More...
 
class  BlockAffineComponent
 This class implements an affine transform using a block diagonal matrix e.g., one whose weight matrix is all zeros except for blocks on the diagonal. More...
 
class  BlockFactorizedTdnnComponent
 BlockFactorizedTdnnComponent is a modified form of TdnnComponent (which inherits from TdnnComponent) that is inspired by quaternion-based neural networks, but is more general and trainable– the idea is that blocks of parameters are linear functions of a smaller number parameters, where the linear function itself is trainable. More...
 
class  CachingOptimizingCompiler
 This class enables you to do the compilation and optimization in one call, and also ensures that if the ComputationRequest is identical to the previous one, the compilation process is not repeated. More...
 
struct  CachingOptimizingCompilerOptions
 
class  ChainExampleMerger
 This class is responsible for arranging examples in groups that have the same strucure (i.e. More...
 
struct  ChainObjectiveInfo
 
struct  CheckComputationOptions
 
struct  ChunkInfo
 
struct  ChunkTimeInfo
 struct ChunkTimeInfo is used by class UtteranceSplitter to output information about how we split an utterance into chunks. More...
 
struct  CindexHasher
 
class  CindexSet
 
struct  CindexVectorHasher
 
class  ClipGradientComponent
 
struct  CollapseModelConfig
 Config class for the CollapseModel function. More...
 
struct  CommandAttributes
 
struct  CommandPairComparator
 
struct  ComparePair
 
class  Compiler
 This class creates an initial version of the NnetComputation, without any optimization or sharing of matrices. More...
 
struct  CompilerOptions
 
class  Component
 Abstract base-class for neural-net components. More...
 
class  ComponentPrecomputedIndexes
 
class  CompositeComponent
 CompositeComponent is a component representing a sequence of [simple] components. More...
 
class  ComputationAnalysis
 This class performs various kinds of specific analysis on top of what class Analyzer gives you immediately. More...
 
class  ComputationCache
 Class ComputationCache is used inside class CachingOptimizingCompiler to cache previously computed computations. More...
 
class  ComputationChecker
 
class  ComputationExpander
 
struct  ComputationGraph
 The first step in compilation is to turn the ComputationSpecification into a ComputationGraph, where for each Cindex we have a list of other Cindexes that it depends on. More...
 
class  ComputationGraphBuilder
 An abstract representation of a set of Cindexes. More...
 
class  ComputationLoopedOptimizer
 
class  ComputationRenumberer
 
struct  ComputationRequest
 
struct  ComputationRequestHasher
 
struct  ComputationRequestPtrEqual
 
class  ComputationStepsComputer
 This class arranges the cindex_ids of the computation into a sequence of lists called "steps", which will correspond roughly to the commands in the compiled computation. More...
 
class  ComputationVariables
 This class relates the matrices and sub-matrices in the computation to imaginary "variables", such that we can think of the operations as operating on sets of individual variables, and we can then do analysis that lets us do optimization. More...
 
class  ConstantComponent
 
class  ConstantFunctionComponent
 
class  ConstantSumDescriptor
 This is an alternative base-case of SumDescriptor (an alternative to SimpleSumDescriptor) which represents a constant term, e.g. More...
 
class  ConvolutionComponent
 WARNING, this component is deprecated in favor of TimeHeightConvolutionComponent, and will be deleted. More...
 
class  DecodableAmNnetLoopedOnline
 
class  DecodableAmNnetSimple
 
class  DecodableAmNnetSimpleLooped
 
class  DecodableAmNnetSimpleParallel
 
class  DecodableNnetLoopedOnline
 
class  DecodableNnetLoopedOnlineBase
 
class  DecodableNnetSimple
 
class  DecodableNnetSimpleLooped
 
class  DecodableNnetSimpleLoopedInfo
 When you instantiate class DecodableNnetSimpleLooped, you should give it a const reference to this class, that has been previously initialized. More...
 
class  DerivativeTimeLimiter
 
class  Descriptor
 
class  DiscriminativeExampleMerger
 This class is responsible for arranging examples in groups that have the same strucure (i.e. More...
 
struct  DiscriminativeObjectiveFunctionInfo
 
class  DistributeComponent
 This Component takes a larger input-dim than output-dim, where the input-dim must be a multiple of the output-dim, and distributes different blocks of the input dimension to different 'x' values. More...
 
class  DistributeComponentPrecomputedIndexes
 
class  DropoutComponent
 
class  DropoutMaskComponent
 
class  ElementwiseProductComponent
 
struct  ExampleGenerationConfig
 
class  ExampleMerger
 This class is responsible for arranging examples in groups that have the same strucure (i.e. More...
 
class  ExampleMergingConfig
 
class  ExampleMergingStats
 This class is responsible for storing, and displaying in log messages, statistics about how examples of different sizes (c.f. More...
 
class  FixedAffineComponent
 FixedAffineComponent is an affine transform that is supplied at network initialization time and is not trainable. More...
 
class  FixedBiasComponent
 FixedBiasComponent applies a fixed per-element bias; it's similar to the AddShift component in the nnet1 setup (and only needed for nnet1 model conversion. More...
 
class  FixedScaleComponent
 FixedScaleComponent applies a fixed per-element scale; it's similar to the Rescale component in the nnet1 setup (and only needed for nnet1 model conversion). More...
 
class  ForwardingDescriptor
 A ForwardingDescriptor describes how we copy data from another NetworkNode, or from multiple other NetworkNodes, possibly with a scalar weight. More...
 
struct  GeneralDescriptor
 This class is only used when parsing Descriptors. More...
 
class  GeneralDropoutComponent
 GeneralDropoutComponent implements dropout, including a continuous variant where the thing we multiply is not just zero or one, but may be a continuous value. More...
 
class  GeneralDropoutComponentPrecomputedIndexes
 
struct  ImageAugmentationConfig
 
struct  Index
 struct Index is intended to represent the various indexes by which we number the rows of the matrices that the Components process: mainly 'n', the index of the member of the minibatch, 't', used for the frame index in speech recognition, and 'x', which is a catch-all extra index which we might use in convolutional setups or for other reasons. More...
 
struct  IndexHasher
 
struct  IndexLessNxt
 
class  IndexSet
 An abstract representation of a set of Indexes. More...
 
struct  IndexVectorHasher
 
struct  IoSpecification
 
struct  IoSpecificationHasher
 
class  LinearComponent
 
class  LogSoftmaxComponent
 
class  LstmNonlinearityComponent
 
struct  MatrixAccesses
 
class  MatrixExtender
 
struct  MaxChangeStats
 
class  MaxpoolingComponent
 
class  MemoryCompressionOptimizer
 This class is used in the function OptimizeMemoryCompression(), once we determine that there is some potential to do memory compression for this computation. More...
 
struct  MiscComputationInfo
 
class  ModelCollapser
 
class  ModelUpdateConsolidator
 This class is responsible for consolidating the model-update part of backprop commands, for components in (e.g.) recurrent networks that need to have many separate backprop commands, into more efficient single commands operating on consolidated data in larger matrices. More...
 
class  NaturalGradientAffineComponent
 
class  NaturalGradientPerElementScaleComponent
 NaturalGradientPerElementScaleComponent is like PerElementScaleComponent but it uses a natural gradient update for the per-element scales. More...
 
class  NaturalGradientRepeatedAffineComponent
 
struct  NetworkNode
 NetworkNode is used to represent, three types of thing: either an input of the network (which pretty much just states the dimension of the input vector); a Component (e.g. More...
 
class  Nnet
 
class  NnetBatchComputer
 This class does neural net inference in a way that is optimized for GPU use: it combines chunks of multiple utterances into minibatches for more efficient computation. More...
 
struct  NnetBatchComputerOptions
 
class  NnetBatchDecoder
 Decoder object that uses multiple CPU threads for the graph search, plus a GPU for the neural net inference (that's done by a separate NnetBatchComputer object). More...
 
class  NnetBatchInference
 This class implements a simplified interface to class NnetBatchComputer, which is suitable for programs like 'nnet3-compute' where you want to support fast GPU-based inference on a sequence of utterances, and get them back from the object in the same order. More...
 
class  NnetChainComputeProb
 This class is for computing objective-function values in a nnet3+chain setup, for diagnostics. More...
 
struct  NnetChainExample
 NnetChainExample is like NnetExample, but specialized for lattice-free (chain) training. More...
 
struct  NnetChainExampleStructureCompare
 This comparator object compares just the structural aspects of the NnetChainExample without looking at the value of the features. More...
 
struct  NnetChainExampleStructureHasher
 This hashing object hashes just the structural aspects of the NnetExample without looking at the value of the features. More...
 
struct  NnetChainSupervision
 
class  NnetChainTrainer
 This class is for single-threaded training of neural nets using the 'chain' model. More...
 
struct  NnetChainTrainingOptions
 
struct  NnetComputation
 
struct  NnetComputationPrintInserter
 
struct  NnetComputeOptions
 
class  NnetComputeProb
 This class is for computing cross-entropy and accuracy values in a neural network, for diagnostics. More...
 
struct  NnetComputeProbOptions
 
class  NnetComputer
 class NnetComputer is responsible for executing the computation described in the "computation" object. More...
 
class  NnetComputerFromEg
 
class  NnetDiscriminativeComputeObjf
 This class is for computing objective-function values in a nnet3 discriminative training, for diagnostics. More...
 
struct  NnetDiscriminativeExample
 NnetDiscriminativeExample is like NnetExample, but specialized for sequence training. More...
 
struct  NnetDiscriminativeExampleStructureCompare
 This comparator object compares just the structural aspects of the NnetDiscriminativeExample without looking at the value of the features. More...
 
struct  NnetDiscriminativeExampleStructureHasher
 This hashing object hashes just the structural aspects of the NnetExample without looking at the value of the features. More...
 
struct  NnetDiscriminativeOptions
 
struct  NnetDiscriminativeSupervision
 
class  NnetDiscriminativeTrainer
 This class is for single-threaded discriminative training of neural nets. More...
 
struct  NnetExample
 NnetExample is the input data and corresponding label (or labels) for one or more frames of input, used for standard cross-entropy training of neural nets (and possibly for other objective functions). More...
 
struct  NnetExampleStructureCompare
 This comparator object compares just the structural aspects of the NnetExample without looking at the value of the features. More...
 
struct  NnetExampleStructureHasher
 This hashing object hashes just the structural aspects of the NnetExample without looking at the value of the features. More...
 
struct  NnetGenerationOptions
 
struct  NnetInferenceTask
 class NnetInferenceTask represents a chunk of an utterance that is requested to be computed. More...
 
struct  NnetIo
 
struct  NnetIoStructureCompare
 This comparison object compares just the structural aspects of the NnetIo object (name, indexes, feature dimension) without looking at the value of features. More...
 
struct  NnetIoStructureHasher
 This hashing object hashes just the structural aspects of the NnetIo object (name, indexes, feature dimension) without looking at the value of features. More...
 
class  NnetLdaStatsAccumulator
 
struct  NnetOptimizeOptions
 
struct  NnetSimpleComputationOptions
 
struct  NnetSimpleLoopedComputationOptions
 
class  NnetTrainer
 This class is for single-threaded training of neural nets using standard objective functions such as cross-entropy (implemented with logsoftmax nonlinearity and a linear objective function) and quadratic loss. More...
 
struct  NnetTrainerOptions
 
class  NonlinearComponent
 
class  NoOpComponent
 NoOpComponent just duplicates its input. More...
 
class  NormalizeComponent
 
struct  ObjectiveFunctionInfo
 
class  OffsetForwardingDescriptor
 Offsets in 't' and 'x' values of other ForwardingDescriptors. More...
 
class  OnlineNaturalGradient
 Keywords for search: natural gradient, naturalgradient, NG-SGD. More...
 
class  OnlineNaturalGradientSimple
 
class  OptionalSumDescriptor
 This is the case of class SumDescriptor, in which we contain just one term, and that term is optional (an IfDefined() expression). More...
 
struct  PairIsEqualComparator
 
struct  PerDimObjectiveInfo
 
class  PerElementOffsetComponent
 
class  PerElementScaleComponent
 PerElementScaleComponent scales each dimension of its input with a separate trainable scale; it's like a linear component with a diagonal matrix. More...
 
class  PermuteComponent
 PermuteComponent changes the order of the columns (i.e. More...
 
class  PnormComponent
 
class  RandomComponent
 
class  RectifiedLinearComponent
 
class  RepeatedAffineComponent
 
class  ReplaceIndexForwardingDescriptor
 This ForwardingDescriptor modifies the indexes (n, t, x) by replacing one of them (normally t) with a constant value and keeping the rest. More...
 
class  RestrictedAttentionComponent
 RestrictedAttentionComponent implements an attention model with restricted temporal context. More...
 
class  RoundingForwardingDescriptor
 For use in clockwork RNNs and the like, this forwarding-descriptor rounds the time-index t down to the the closest t' <= t that is an exact multiple of t_modulus_. More...
 
class  RowOpsSplitter
 
class  ScaleAndOffsetComponent
 
class  SigmoidComponent
 
class  SimpleForwardingDescriptor
 SimpleForwardingDescriptor is the base-case of ForwardingDescriptor, consisting of a source node in the graph with a given scalar weight (which will in the normal case be 1.0). More...
 
struct  SimpleObjectiveInfo
 
class  SimpleSumDescriptor
 This is the normal base-case of SumDescriptor which just wraps a ForwardingDescriptor. More...
 
class  SoftmaxComponent
 
class  SpecAugmentTimeMaskComponent
 SpecAugmentTimeMaskComponent implements the time part of SpecAugment. More...
 
class  SpecAugmentTimeMaskComponentPrecomputedIndexes
 
class  StatisticsExtractionComponent
 
class  StatisticsExtractionComponentPrecomputedIndexes
 
class  StatisticsPoolingComponent
 
class  StatisticsPoolingComponentPrecomputedIndexes
 
class  SumBlockComponent
 SumBlockComponent sums over blocks of its input: for instance, if you create one with the config "input-dim=400 output-dim=100", its output will be the sum over the 4 100-dimensional blocks of the input. More...
 
class  SumDescriptor
 This is an abstract base-class. More...
 
class  SumGroupComponent
 SumGroupComponent is used to sum up groups of posteriors. More...
 
class  SvdApplier
 
class  SwitchingForwardingDescriptor
 Chooses from different inputs based on the the time index modulo (the number of ForwardingDescriptors given as inputs). More...
 
class  TanhComponent
 
struct  TarjanNode
 
class  TdnnComponent
 TdnnComponent is a more memory-efficient alternative to manually splicing several frames of input and then using a NaturalGradientAffineComponent or a LinearComponent. More...
 
class  TimeHeightConvolutionComponent
 TimeHeightConvolutionComponent implements 2-dimensional convolution where one of the dimensions of convolution (which traditionally would be called the width axis) is identified with time (i.e. More...
 
class  UpdatableComponent
 Class UpdatableComponent is a Component which has trainable parameters; it extends the interface of Component. More...
 
class  UtteranceSplitter
 
class  VariableMergingOptimizer
 This class is responsible for merging matrices, although you probably want to access it via the the function VariableMergingOptimization(). More...
 

Typedefs

typedef TableWriter< KaldiObjectHolder< NnetChainExample > > NnetChainExampleWriter
 
typedef SequentialTableReader< KaldiObjectHolder< NnetChainExample > > SequentialNnetChainExampleReader
 
typedef RandomAccessTableReader< KaldiObjectHolder< NnetChainExample > > RandomAccessNnetChainExampleReader
 
typedef std::pair< int32, IndexCindex
 
typedef TableWriter< KaldiObjectHolder< NnetDiscriminativeExample > > NnetDiscriminativeExampleWriter
 
typedef SequentialTableReader< KaldiObjectHolder< NnetDiscriminativeExample > > SequentialNnetDiscriminativeExampleReader
 
typedef RandomAccessTableReader< KaldiObjectHolder< NnetDiscriminativeExample > > RandomAccessNnetDiscriminativeExampleReader
 
typedef TableWriter< KaldiObjectHolder< NnetExample > > NnetExampleWriter
 
typedef SequentialTableReader< KaldiObjectHolder< NnetExample > > SequentialNnetExampleReader
 
typedef RandomAccessTableReader< KaldiObjectHolder< NnetExample > > RandomAccessNnetExampleReader
 

Enumerations

enum  AccessType { kReadAccess, kWriteAccess, kReadWriteAccess }
 
enum  ComponentProperties {
  kSimpleComponent = 0x001, kUpdatableComponent = 0x002, kPropagateInPlace = 0x004, kPropagateAdds = 0x008,
  kReordersIndexes = 0x010, kBackpropAdds = 0x020, kBackpropNeedsInput = 0x040, kBackpropNeedsOutput = 0x080,
  kBackpropInPlace = 0x100, kStoresStats = 0x200, kInputContiguous = 0x400, kOutputContiguous = 0x800,
  kUsesMemo = 0x1000, kRandomComponent = 0x2000
}
 
enum  CommandType {
  kAllocMatrix, kDeallocMatrix, kSwapMatrix, kSetConst,
  kPropagate, kBackprop, kBackpropNoModelUpdate, kMatrixCopy,
  kMatrixAdd, kCopyRows, kAddRows, kCopyRowsMulti,
  kCopyToRowsMulti, kAddRowsMulti, kAddToRowsMulti, kAddRowRanges,
  kCompressMatrix, kDecompressMatrix, kAcceptInput, kProvideOutput,
  kNoOperation, kNoOperationPermanent, kNoOperationMarker, kNoOperationLabel,
  kGotoLabel
}
 CommandType is an enum that describes the category of the command used in the NnetComputation. More...
 
enum  ObjectiveType { kLinear, kQuadratic }
 This enum is for a kind of annotation we associate with output nodes of the network; it's for the convenience of calling code so that if the objective is one of a few standard types, we can compute it directly and know how to interpret the supervision labels. More...
 
enum  NodeType {
  kInput, kDescriptor, kComponent, kDimRange,
  kNone
}
 
enum  FillMode { kNearest, kReflect }
 

Functions

void UnitTestPreconditionDirectionsOnline ()
 
std::string PrintCommand (int32 num_commands, int32 command)
 
void UnitTestNnetAnalyze ()
 
static void IndexesMultiToSubmatrixIndexes (const std::vector< std::pair< int32, int32 > > &indexes_multi, std::vector< int32 > *submatrix_indexes)
 given a vector of pairs from computation.indexes_multi_indexes containing paris (submatrix-index, row-index), this function outputs to "submatrix_indexes" all (unique) submatrix indexes that appear; and it outputs to "contains_null_marker" true if the pair (-1, -1) appears anywhere in indexes_multi, and false otherwise. More...
 
void ComputeCommandAttributes (const Nnet &nnet, const NnetComputation &computation, const ComputationVariables &vars, std::vector< CommandAttributes > *attributes)
 
void ComputeVariableAccesses (const ComputationVariables &variables, const std::vector< CommandAttributes > &command_attributes, std::vector< std::vector< Access > > *variable_accesses)
 After the command-level attributes have been computed, this function organizes them per variable (see class ComputationVariables for how a variable is defined; it is part of a matrix). More...
 
void ComputeMatrixAccesses (const Nnet &nnet, const NnetComputation &computation, const ComputationVariables &variables, const std::vector< CommandAttributes > &command_attributes, std::vector< MatrixAccesses > *matrix_accesses)
 This function organizes information in the CommandAttributes in a way that is convenient to access per matrix. More...
 
static void CheckComputationOnline (const Nnet &nnet, NnetComputation computation, bool check_rewrite)
 
void CheckComputation (const Nnet &nnet, const NnetComputation &computation, bool check_rewrite=false)
 This is a convenience interface for class ComputationChecker. More...
 
void ComputeMatrixToSubmatrix (const NnetComputation &computation, std::vector< std::vector< int32 > > *mat_to_submat)
 This function computes a vector 'mat_to_submat', indexed by matrix index, such that (*mat_to_submat)[m] is a list of all the submatrix indexes that refer to matrix m. More...
 
void PrintMatrixAccesses (std::ostream &os, const std::vector< MatrixAccesses > &matrix_accesses)
 This function is to be used in debugging; it produces human-readable output. More...
 
void PrintCommandAttributes (std::ostream &os, const std::vector< CommandAttributes > &attributes)
 This function is to be used in debugging; it produces human-readable output. More...
 
void GetCommandsOfType (const NnetComputation &computation, CommandType t, std::vector< int32 > *command_indexes)
 This utility function works out from a computation, the command-indexes of the commands of the given type. More...
 
int64 GetMaxMemoryUse (const NnetComputation &computation)
 
int32 MaxMemoryUsage (const NnetComputation &computation)
 Returns the total memory, in bytes, used by the computation (just the temporary memory, not counting the memory used by the nnet itself). More...
 
void MergeTaskOutput (const std::vector< NnetInferenceTask > &tasks, Matrix< BaseFloat > *output)
 Merges together the 'output_cpu' (if the 'output_to_cpu' members are true) or the 'output' members of 'tasks' into a single CPU matrix 'output'. More...
 
void MergeTaskOutput (const std::vector< NnetInferenceTask > &tasks, CuMatrix< BaseFloat > *output)
 
static bool HasXentOutputs (const Nnet &nnet)
 
void RecomputeStats (const std::vector< NnetChainExample > &egs, const chain::ChainTrainingOptions &chain_config, const fst::StdVectorFst &den_fst, Nnet *nnet)
 This function zeros the stored component-level stats in the nnet using ZeroComponentStats(), then recomputes them with the supplied egs. More...
 
static void MergeSupervision (const std::vector< const NnetChainSupervision *> &inputs, NnetChainSupervision *output)
 
void MergeChainExamples (bool compress, std::vector< NnetChainExample > *input, NnetChainExample *output)
 This function merges a list of NnetChainExample objects into a single one– intended to be used when forming minibatches for neural net training. More...
 
void GetChainComputationRequest (const Nnet &nnet, const NnetChainExample &eg, bool need_model_derivative, bool store_component_stats, bool use_xent_regularization, bool use_xent_derivative, ComputationRequest *computation_request)
 This function takes a NnetChainExample and produces a ComputationRequest. More...
 
void ShiftChainExampleTimes (int32 frame_shift, const std::vector< std::string > &exclude_names, NnetChainExample *eg)
 Shifts the time-index t of everything in the input of "eg" by adding "t_offset" to all "t" values– but excluding those with names listed in "exclude_names", e.g. More...
 
int32 GetNnetChainExampleSize (const NnetChainExample &a)
 
int32 GetChainNnetExampleSize (const NnetChainExample &a)
 This function returns the 'size' of a chain example as defined for purposes of merging egs, which is defined as the largest number of Indexes in any of the inputs or outputs of the example. More...
 
int32 YzxVectorIndex (int32 x, int32 y, int32 z, int32 input_x_dim, int32 input_y_dim, int32 input_z_dim)
 
int32 ZyxVectorIndex (int32 x, int32 y, int32 z, int32 input_x_dim, int32 input_y_dim, int32 input_z_dim)
 
void RearrangeIndexes (const std::vector< std::vector< int32 > > &in, std::vector< std::vector< int32 > > *out)
 
void UnitTestIndexIo ()
 
void UnitTestCindexIo ()
 
static void WriteIndexVectorElementBinary (std::ostream &os, const std::vector< Index > &vec, int32 i)
 
static void ReadIndexVectorElementBinary (std::istream &is, int32 i, std::vector< Index > *vec)
 
void WriteIndexVector (std::ostream &os, bool binary, const std::vector< Index > &vec)
 
void ReadIndexVector (std::istream &is, bool binary, std::vector< Index > *vec)
 
static void WriteCindexVectorElementBinary (std::ostream &os, const std::vector< Cindex > &vec, int32 i)
 
static void ReadCindexVectorElementBinary (std::istream &is, int32 i, std::vector< Cindex > *vec)
 
void WriteCindexVector (std::ostream &os, bool binary, const std::vector< Cindex > &vec)
 
void ReadCindexVector (std::istream &is, bool binary, std::vector< Cindex > *vec)
 
std::ostream & operator<< (std::ostream &ostream, const Index &index)
 
std::ostream & operator<< (std::ostream &ostream, const Cindex &cindex)
 
void PrintCindex (std::ostream &os, const Cindex &cindex, const std::vector< std::string > &node_names)
 
void PrintIndexes (std::ostream &ostream, const std::vector< Index > &indexes)
 this will only be used for pretty-printing. More...
 
void PrintCindexes (std::ostream &ostream, const std::vector< Cindex > &cindexes, const std::vector< std::string > &node_names)
 this will only be used for pretty-printing. More...
 
void PrintIntegerVector (std::ostream &os, const std::vector< int32 > &ints)
 
void AppendCindexes (int32 node, const std::vector< Index > &indexes, std::vector< Cindex > *out)
 Appends to 'out' the pairs (node, indexes[0]), (node, indexes[1]), ... More...
 
void ModifyNnetIvectorPeriod (int32 ivector_period, Nnet *nnet)
 This function modifies the descriptors in the neural network to change the periodicity with which it expects to read an iVector at its input. More...
 
int32 GetChunkSize (const Nnet &nnet, int32 frame_subsampling_factor, int32 advised_chunk_size)
 
template<class I >
Mod (I m, I n)
 Mod(m, n), defined for integers m and n where n > 0, returns the modulus m % n, defined as the integer 0 <= i < n such that i and m are congruent modulo n; for instance, Mod(13, 10) = 3. More...
 
static void CreateComputationRequestInternal (int32 begin_input_t, int32 end_input_t, int32 begin_output_t, int32 end_output_t, int32 num_sequences, int32 frame_subsampling_factor, const std::set< int32 > &ivector_times, ComputationRequest *request)
 
void CreateLoopedComputationRequest (const Nnet &nnet, int32 chunk_size, int32 frame_subsampling_factor, int32 ivector_period, int32 left_context_begin, int32 right_context, int32 num_sequences, ComputationRequest *request1, ComputationRequest *request2, ComputationRequest *request3)
 This function creates computation request suitable for giving to ComputeLooped(). More...
 
void AddTimeOffsetToComputationRequest (int32 t_offset, ComputationRequest *request)
 
static bool ExtrapolateComputationRequest (const ComputationRequest &request1, const ComputationRequest &request2, ComputationRequest *request3)
 
static bool CompileLoopedInternal (const Nnet &nnet, NnetOptimizeOptions optimize_opts, const ComputationRequest &request1, const ComputationRequest &request2, const ComputationRequest &request3, int32 num_requests, NnetComputation *computation)
 
void CompileLooped (const Nnet &nnet, const NnetOptimizeOptions &optimize_opts, const ComputationRequest &request1, const ComputationRequest &request2, const ComputationRequest &request3, NnetComputation *computation)
 CompileLooped() provides an internal interface for 'looped' computation. More...
 
void CreateLoopedComputationRequestSimple (const Nnet &nnet, int32 chunk_size, int32 frame_subsampling_factor, int32 ivector_period, int32 extra_left_context_begin, int32 extra_right_context, int32 num_sequences, ComputationRequest *request1, ComputationRequest *request2, ComputationRequest *request3)
 This function is deprecated. More...
 
void UnitTestNnetCompile ()
 
void UnitTestNnetCompileMulti ()
 
void UnitTestNnetCompileLooped ()
 
void PrintVectorVectorPair (std::vector< std::vector< std::pair< int32, int32 > > > vec_vec_pair)
 
void UnitTestSplitLocationsBackward (bool verbose)
 
void UnitTestHasContiguousProperty ()
 
void UnitTestEnsureContiguousProperty ()
 
void UnitTestSplitLocations (bool verbose)
 
void GetSubmatCounts (const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::unordered_map< int32, int32 > *submat_counts, std::vector< int32 > *submats_with_large_counts)
 Gets counts of submatrices (the 1st members of pairs) in submat_lists. More...
 
void SeparateSubmatsWithLargeCounts (const std::vector< int32 > &submats_to_separate, const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *reduced_submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
 This function, used in SplitLocations(), is used to make separate 'split lists' for certain high-count submatrix indexes, specified by the user in 'submats_to_separate'. More...
 
void SplitLocations (const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
 The input to this function is a vector (indexed by matrix-row-index) of lists of pairs (submat_index, row_index), and this function splits it up into a list of vectors of pairs, where those vectors are indexed by matrix-row-index. More...
 
bool ConvertToIndexes (const std::vector< std::pair< int32, int32 > > &location_vector, int32 *first_value, std::vector< int32 > *second_values)
 If it is the case for some i >= 0 that all the .first elements of "location_vector" are either i or -1, then output i to first_value and the .second elements into "second_values", and return true. More...
 
void EnsureContiguousProperty (const std::vector< int32 > &indexes, std::vector< std::vector< int32 > > *indexes_out)
 This function takes a vector of indexes and splits it up into as separate vectors of the same size, as needed to ensure that the 'contiguous property' holds. More...
 
void SplitPairList (std::vector< std::pair< int32, int32 > > &list, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
 This function splits a vector of pairs into a list of vectors of pairs. More...
 
void SplitLocationsBackward (const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
 This function has the same interface as SplitLocations(); however, it ensures certain additional properties of the output "split_lists", which are necessary because of the way it is used in backprop code. More...
 
bool HasContiguousProperty (const std::vector< int32 > &indexes, std::vector< std::pair< int32, int32 > > *reverse_indexes)
 This function returns true if for each integer i != -1, all the indexes j at which indexes[j] == i are consecutive with no gaps (more formally: if j1 < j2 < j3 and indexes[j1] != -1 and indexes[j1] == indexes[j3], then indexes[j1] == indexes[j2]). More...
 
void GetNxList (const std::vector< Index > &indexes, std::vector< std::pair< int32, int32 > > *pairs)
 This function outputs a unique, lexicographically sorted list of the pairs of (n, x) values that are encountered in the provided list of Indexes. More...
 
void GetTList (const std::vector< Index > &indexes, std::vector< int32 > *t_values)
 This function outputs a sorted, unique list of the 't' values that are encountered in the provided list of Indexes If 't' values equal to kNoTime are encountered, they are ignored and are not output. More...
 
static void ResetSeed (int32 rand_seed, const Component &c)
 
bool CheckStringsApproxEqual (const std::string &a, const std::string &b, int32 tolerance=3)
 
void TestNnetComponentIo (Component *c)
 
void TestNnetComponentCopy (Component *c)
 
void TestNnetComponentAddScale (Component *c)
 
void TestNnetComponentVectorizeUnVectorize (Component *c)
 
void TestNnetComponentUpdatable (Component *c)
 
ComponentPrecomputedIndexesGetPrecomputedIndexes (const Component &c, int32 num_rows)
 
void TestSimpleComponentPropagateProperties (const Component &c)
 
bool TestSimpleComponentDataDerivative (const Component &c, BaseFloat perturb_delta)
 
bool TestSimpleComponentModelDerivative (const Component &c, BaseFloat perturb_delta, bool test_derivative)
 
void UnitTestNnetComponent ()
 
std::ostream & operator<< (std::ostream &os, const ComputationGraphBuilder::ComputableInfo &info)
 This is to be used in logging only. More...
 
void ComputeComputationGraph (const Nnet &nnet, const ComputationRequest &request, ComputationGraph *graph)
 
static int32 SumVectorSizes (const std::vector< std::vector< int32 > > &vec)
 
static int32 SumVectorSizes (const std::vector< std::vector< std::vector< int32 > > > &vec)
 
static void ComputeComputationPhasesForEpoch (const Nnet &nnet, const ComputationGraph &graph, const std::vector< int32 > &this_epoch, const std::vector< std::vector< int32 > > &dependencies_subset, const std::vector< std::vector< int32 > > &depend_on_subset, bool epoch_is_trivial, std::vector< int32 > *phase_indexes, std::vector< std::vector< int32 > > *phases)
 
void ComputeComputationPhases (const Nnet &nnet, const ComputationGraph &computation_graph, std::vector< std::vector< std::vector< int32 > > > *phases_per_segment)
 This function divides a computation into 'phases', where a 'phase' is a collection of cindexes which can (as far as the computation graph is concerned) all be computed at the same time, and depend only on cindexes previously computed in earlier phases. More...
 
static void GetIndexesStrings (const Nnet &nnet, const NnetComputation &computation, std::vector< std::string > *indexes_strings)
 
static void GetIndexesMultiStrings (const Nnet &nnet, const NnetComputation &computation, std::vector< std::string > *indexes_multi_strings)
 
static void PrintCommand (std::ostream &os_out, const Nnet &nnet, const NnetComputation &computation, int32 command_index, const std::vector< std::string > &submatrix_strings, const std::vector< std::string > &indexes_strings, const std::vector< std::string > &indexes_multi_strings)
 
static void PrintComputationPreamble (std::ostream &os, const NnetComputation &c, const Nnet &nnet, const std::vector< std::string > &submatrix_strings, const std::vector< std::string > &indexes_strings, const std::vector< std::string > &indexes_multi_strings)
 
void UnitTestNnetComputationIo (NnetComputation *computation)
 
void UnitTestComputationRequestIo (ComputationRequest *request)
 
void TestNnetDecodable (Nnet *nnet)
 
void UnitTestNnetCompute ()
 
void ComputeMinAndMaxTimes (const std::vector< Index > &indexes, int32 *min_t, int32 *max_t)
 
void SetDerivTimesOptions (const ComputationRequest &request, NnetOptimizeOptions *opt_config)
 
void UnitTestNnetModelDerivatives ()
 
void UnitTestNnetInputDerivatives ()
 
ForwardingDescriptorGenRandForwardingDescriptor (int32 num_nodes)
 
SumDescriptorGenRandSumDescriptor (int32 num_nodes)
 
void GenRandDescriptor (int32 num_nodes, Descriptor *desc)
 
void UnitTestDescriptorIo ()
 
void UnitTestGeneralDescriptor ()
 
std::string NormalizeTextDescriptor (const std::vector< std::string > &node_names, const std::string &desc_str)
 
void UnitTestGeneralDescriptorSpecial ()
 
static std::string ParsingContext (const std::string *token_ptr)
 
static void ExpectToken (const std::string &token, const std::string &what_we_are_parsing, const std::string **next_token)
 
static int32 ReadIntegerToken (const std::string &what_we_are_parsing, const std::string **next_token)
 
void ComputeAccuracy (const GeneralMatrix &supervision, const CuMatrixBase< BaseFloat > &nnet_output, BaseFloat *tot_weight, BaseFloat *tot_accuracy, VectorBase< BaseFloat > *tot_weight_vec=NULL, VectorBase< BaseFloat > *tot_accuracy_vec=NULL)
 This function computes the frame accuracy for this minibatch. More...
 
void MergeSupervision (const std::vector< const NnetDiscriminativeSupervision *> &inputs, NnetDiscriminativeSupervision *output)
 
void MergeDiscriminativeExamples (bool compress, std::vector< NnetDiscriminativeExample > *input, NnetDiscriminativeExample *output)
 
void GetDiscriminativeComputationRequest (const Nnet &nnet, const NnetDiscriminativeExample &eg, bool need_model_derivative, bool store_component_stats, bool use_xent_regularization, bool use_xent_derivative, ComputationRequest *computation_request)
 This function takes a NnetDiscriminativeExample and produces a ComputationRequest. More...
 
void ShiftDiscriminativeExampleTimes (int32 frame_shift, const std::vector< std::string > &exclude_names, NnetDiscriminativeExample *eg)
 Shifts the time-index t of everything in the input of "eg" by adding "t_offset" to all "t" values– but excluding those with names listed in "exclude_names", e.g. More...
 
int32 GetNnetDiscriminativeExampleSize (const NnetDiscriminativeExample &a)
 
void MergeDiscriminativeExamples (std::vector< NnetDiscriminativeExample > *input, bool compress, NnetDiscriminativeExample *output)
 Appends the given vector of examples (which must be non-empty) into a single output example. More...
 
int32 GetDiscriminativeNnetExampleSize (const NnetDiscriminativeExample &a)
 This function returns the 'size' of a discriminative example as defined for purposes of merging egs, which is defined as the largest number of Indexes in any of the inputs or outputs of the example. More...
 
void UnitTestNnetExample ()
 
void UnitTestNnetMergeExamples ()
 
static void GetIoNames (const std::vector< NnetExample > &src, std::vector< std::string > *names_vec)
 
static void GetIoSizes (const std::vector< NnetExample > &src, const std::vector< std::string > &names, std::vector< int32 > *sizes)
 
static void MergeIo (const std::vector< NnetExample > &src, const std::vector< std::string > &names, const std::vector< int32 > &sizes, bool compress, NnetExample *merged_eg)
 
void MergeExamples (const std::vector< NnetExample > &src, bool compress, NnetExample *dest)
 Merge a set of input examples into a single example (typically the size of "src" will be the minibatch size). More...
 
void ShiftExampleTimes (int32 t_offset, const std::vector< std::string > &exclude_names, NnetExample *eg)
 Shifts the time-index t of everything in the "eg" by adding "t_offset" to all "t" values. More...
 
void GetComputationRequest (const Nnet &nnet, const NnetExample &eg, bool need_model_derivative, bool store_component_stats, ComputationRequest *computation_request)
 This function takes a NnetExample (which should already have been frame-selected, if desired, and merged into a minibatch) and produces a ComputationRequest. More...
 
void WriteVectorAsChar (std::ostream &os, bool binary, const VectorBase< BaseFloat > &vec)
 
void ReadVectorAsChar (std::istream &is, bool binary, Vector< BaseFloat > *vec)
 
void RoundUpNumFrames (int32 frame_subsampling_factor, int32 *num_frames, int32 *num_frames_overlap)
 
int32 GetNnetExampleSize (const NnetExample &a)
 This function returns the 'size' of a nnet-example as defined for purposes of merging egs, which is defined as the largest number of Indexes in any of the inputs or outputs of the example. More...
 
static void CopyPairVector (const CuArray< Int32Pair > &in, std::vector< std::pair< int32, int32 > > *out)
 
static void CopyPairVector (const std::vector< std::pair< int32, int32 > > &in, CuArray< Int32Pair > *out)
 
bool AssertGraphEqual (const std::vector< std::vector< int32 > > &graph1, const std::vector< std::vector< int32 > > &graph2)
 
bool AssertVectorEqual (const std::vector< int32 > &vec1, const std::vector< int32 > &vec2)
 
void BuildTestGraph (std::vector< std::vector< int32 > > *graph)
 
void BuildTestGraphTranspose (std::vector< std::vector< int32 > > *graph)
 
void BuildTestSccs (std::vector< std::vector< int32 > > *sccs)
 
void BuildTestSccGraph (std::vector< std::vector< int32 > > *scc_graph)
 
void BuildTestTopSortOrder (std::vector< int32 > *node_to_order)
 
void UnitTestComputeGraphTranspose ()
 
void UnitTestFindSccs ()
 
void UnitTestMakeSccGraph ()
 
void UnitTestComputeTopSortOrder ()
 
void UnitTestComputeTopSortOrder2 ()
 
void NnetToDirectedGraph (const Nnet &nnet, std::vector< std::vector< int32 > > *graph)
 This function takes an nnet and turns it to a directed graph on nodes. More...
 
void ComputeGraphTranspose (const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *graph_transpose)
 Outputs a graph in which the order of arcs is reversed. More...
 
void TarjanSccRecursive (int32 node, const std::vector< std::vector< int32 > > &graph, int32 *global_index, std::vector< TarjanNode > *tarjan_nodes, std::vector< int32 > *tarjan_stack, std::vector< std::vector< int32 > > *sccs)
 
void FindSccsTarjan (const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *sccs)
 
void FindSccs (const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *sccs)
 Given a directed graph (where each std::vector<int32> is a list of destination-nodes of arcs coming from the current node), partition it into strongly connected components (i.e. More...
 
void MakeSccGraph (const std::vector< std::vector< int32 > > &graph, const std::vector< std::vector< int32 > > &sccs, std::vector< std::vector< int32 > > *scc_graph)
 Given a list of sccs of a graph (e.g. More...
 
void ComputeTopSortOrderRecursive (int32 node, const std::vector< std::vector< int32 > > &graph, std::vector< bool > *cycle_detector, std::vector< bool > *is_visited, std::vector< int32 > *reversed_orders)
 
void ComputeTopSortOrder (const std::vector< std::vector< int32 > > &graph, std::vector< int32 > *node_to_order)
 Given an acyclic graph (where each std::vector<int32> is a list of destination-nodes of arcs coming from the current node), compute a topological ordering of the graph nodes. More...
 
std::string PrintGraphToString (const std::vector< std::vector< int32 > > &graph)
 Prints a graph to a string in a pretty way for human readability, e.g. More...
 
void ComputeNnetComputationEpochs (const Nnet &nnet, std::vector< int32 > *node_to_epoch)
 This function computes the order in which we need to compute each node in the graph, where each node-index n maps to an epoch-index t = 0, 1, ... More...
 
bool GraphHasCycles (const std::vector< std::vector< int32 > > &graph)
 This function returns 'true' if the graph represented in 'graph' contains cycles (including cycles where a single node has an arc to itself). More...
 
void UnitTestNnetIo ()
 
static bool UnitTestNnetOptimizeWithOptions (int32 srand_seed, NnetOptimizeOptions opt_config, CachingOptimizingCompilerOptions compiler_config)
 
static void UnitTestNnetOptimizeInternal (int32 srand_seed)
 
static void UnitTestNnetOptimize ()
 
void IdentifySubmatrixArgs (NnetComputation::Command *command, std::vector< int32 * > *submatrix_args)
 This function outputs to "submatrix_args" the addresses of a subset of arguments arg1 through arg6 in "command", that correspond to the indexes of submatrices. More...
 
void IdentifySubmatrixArgs (std::vector< NnetComputation::Command > *commands, std::vector< int32 * > *submatrix_args)
 This function outputs to "submatrix_args" the addresses of the args (arguments arg1 through arg6) in the vector "commands", that correspond to the indexes of submatrices. More...
 
void IdentifyMatrixArgsInComputation (NnetComputation *computation, std::vector< int32 *> *matrix_args)
 
void IdentifyIndexesMultiArgs (std::vector< NnetComputation::Command > *commands, std::vector< int32 * > *indexes_multi_args)
 Identifies in the vector of commands, arguments that correspond to indexes into the computation's indexes_multi array, and outputs a list of pointers to those arguments to 'indexes_multi_args'. More...
 
void IdentifyIndexesRangesArgs (std::vector< NnetComputation::Command > *commands, std::vector< int32 * > *indexes_ranges_args)
 Identifies in the vector of commands, arguments that correspond to indexes into the computation's 'indexes_ranges' array, and outputs a list of pointers to those arguments to 'indexes_ranges_args'. More...
 
void IdentifyIndexesArgs (std::vector< NnetComputation::Command > *commands, std::vector< int32 * > *indexes_args)
 Identifies in the vector of commands, arguments that correspond to indexes into the computation's 'indexes' array, and outputs a list of pointers to those arguments to 'indexes_args'. More...
 
void IdentifySubmatrixArgsInComputation (NnetComputation *computation, std::vector< int32 * > *submatrix_args)
 This function outputs to "submatrix_args" the addresses of integers in 'computation' that correspond to submatrices. More...
 
void RenumberComputation (NnetComputation *computation)
 This function detects submatrices and matrices that are never used (e.g. More...
 
static bool IsNoop (const NnetComputation::Command &command)
 
void RemoveNoOps (NnetComputation *computation)
 Removes commands of type kNoOperation in the computation. More...
 
static NnetComputation::SubMatrixInfo GetSubMatrixOfSubMatrix (const NnetComputation &computation, int32 submat_a, int32 submat_b)
 This static function returns a SubMatrixInfo corresponding to replacing the matrix-index in a's "matrix_index" with, essentially, sub-matrix b. More...
 
void ExtendMatrices (NnetComputation *computation)
 This is not really an optimization in itself but it can make things easier for class VariableMergingOptimizer (usually called by its wrapper VariableMergingOptimization()). More...
 
void ConsolidateModelUpdate (const Nnet &nnet, NnetComputation *computation)
 This optimization consolidates the model-update part of backprop commands, for components in (e.g.) recurrent networks that need to have many separate backprop commands, into more efficient single commands operating on consolidated data in larger matrices. More...
 
void LimitDerivativeTimes (const Nnet &nnet, int32 min_deriv_time, int32 max_deriv_time, NnetComputation *computation)
 
static bool IndexesHaveSpecialStructure (const std::vector< int32 > &indexes, int32 *first_nonnegative_pos, int32 *first_nonnegative_value, int32 *num_nonnegative_indexes)
 
bool ReplaceRowWithMatrixOps (NnetComputation *computation)
 This function detects cases where commands of type kCopyRows, kAddRows or kAddToRows can be converted to commands of type kMatrixCopy or kMatrixAdd, and converts them (this may involve adding submatrices). More...
 
static void FindNumLeadingAndTrailingNegatives (const std::vector< int32 > &vec, int32 *num_leading_negatives, int32 *num_trailing_negatives)
 
static bool SnipSingleRowOp (NnetComputation *computation, int32 command_index)
 
static void FindNumLeadingAndTrailingNegatives (const std::vector< std::pair< int32, int32 > > &vec, int32 *num_leading_negatives, int32 *num_trailing_negatives)
 
static bool SnipMultiRowOp (NnetComputation *computation, int32 command_index)
 
static void FindNumLeadingAndTrailingIdenticals (const std::vector< std::pair< int32, int32 > > &vec, int32 *num_leading_identicals, int32 *num_trailing_identicals)
 
static bool SnipRangesRowOp (NnetComputation *computation, int32 command_index)
 
bool SnipRowOps (NnetComputation *computation)
 This function detects cases where commands of type kCopyRows, kAddRows, kAddRowsMulti, kAddToRowsMulti, kCopyRowsMulti, kCopyToRowsMulti or kAddRowRanges use indexes that start or end with -1's or equivalents, and replace them with similar commands that act on a sub-matrix of the matrices they are currently acting on. More...
 
bool SplitRowOps (NnetComputation *computation)
 This function detects cases where commands of type kAddRowsMulti, kAddToRowsMulti, kCopyRowsMulti, kCopyToRowsMulti use indexes that correspond to at most two submatrices, in two distinct ranges without gaps filled by -1's, and could be converted to at most two commands of type kMatrixAdd, kMatrixCopy, kAddRows or kCopyRows. More...
 
static int32 FindNStride (const std::vector< Index > &indexes, bool full_check)
 
static int32 FindNStride (const std::vector< Cindex > &cindexes, bool full_check)
 
static void ConvertNumNValues (int32 n_stride, int32 old_N, int32 new_N, const std::vector< Index > &indexes_in, std::vector< Index > *indexes_out)
 
void ExpandComputation (const Nnet &nnet, const MiscComputationInfo &misc_info, const NnetComputation &computation, bool need_debug_info, int32 num_n_values, NnetComputation *expanded_computation)
 This function is used in 'shortcut' compilation to expand a computation that has been compiled for exactly 2 'n' values, to one that is suitable for some num_n_values > 2. More...
 
static bool IoSpecificationIsDecomposable (const IoSpecification &io_spec, IoSpecification *mini_io_spec, int32 *num_n_values_out)
 
bool RequestIsDecomposable (const ComputationRequest &request, ComputationRequest *mini_request, int32 *num_n_values)
 This function, used in 'shortcut' compilation where we first compile a smaller computation with the same structure but only 2 distinct 'n' values, works out whether a computation is 'decomposable'; if so, it returns true and outputs the 'mini_request' with the same structure, and the number of 'n' values. More...
 
void OptimizeLoopedComputation (const Nnet &nnet, NnetComputation *computation)
 This function tries to optimize computation 'computation' for an 'looped' computation. More...
 
void FixGotoLabel (NnetComputation *computation)
 This function ensures that the arg1 of a final command of type kGotoLabel is the same as the command with type kNoOperationLabel. More...
 
bool MatrixIsUnused (const Analyzer &analyzer, const NnetComputation &computation, int32 m)
 This function returns true if matrix 1 <= m < computation->matrices.size() is unused, defined as: it is not an input or an output, and is not accessed other than via commands of type kAllocMatrix, kDeallocMatrix, and kSetConst. More...
 
void RemoveCommandsForUnusedMatrix (const Analyzer &analyzer, int32 m, NnetComputation *computation)
 This function removes from 'computation' the commands accessing matrix 'm', which is assumed to be unused according to the MatrixIsUnused() command above. More...
 
void InsertCommands (std::vector< std::pair< int32, NnetComputation::Command > > *commands, NnetComputation *computation)
 Inserts commands into the computation at the requested places. More...
 
void OptimizeMemoryCompression (const Nnet &nnet, int32 memory_compression_level, NnetComputation *computation)
 Performs optimization to reduce memory usage where possible, making use of the kCompressMatrix and kDecompressMatrix commands. More...
 
int32 MaxOutputTimeInRequest (const ComputationRequest &request)
 
void MoveSizingCommands (const Nnet &nnet, NnetComputation *computation)
 This optimization moves commands that allocate and zero matrices to as late as possible, and moves commands that deallocate matrices to as early as possible. More...
 
void RemoveUnnecessaryZeroing (const Nnet &nnet, NnetComputation *computation)
 This optimization function removes, where possible, commands of type type kSetConst. More...
 
static void ComputeCommandPairs (const std::pair< std::vector< int32 >, std::vector< int32 > > &lists, std::vector< std::pair< int32, int32 > > *pairs)
 
void RemoveUnnecessaryAllocation (const Nnet &nnet, NnetComputation *computation)
 This optimization detects cases where we deallocate a matrix, and then later allocate another matrix of the same size; and replaces them with commands of type kAllocFromOther or kAllocFromOtherZeroed. More...
 
void VariableMergingOptimization (const NnetOptimizeOptions &config, const Nnet &nnet, NnetComputation *computation)
 This wraps class VariableMergingOptimizer in a simplified interface. More...
 
void ConvertAdditionToAssignment (const Nnet &nnet, NnetComputation *computation)
 This converts addition operations (things with Add in their names) to copy operations (things with Copy in their names). More...
 
void Optimize (const NnetOptimizeOptions &config, const Nnet &nnet, int32 max_output_time_in_request, NnetComputation *computation)
 This is the top-level function for optimizing a computation. More...
 
static void SplitComputationIntoSegments (const NnetComputation &computation, std::vector< std::pair< int32, int32 > > *segments)
 Split the computation up into segments bounded by kNoOperationMarker. More...
 
void ConsolidateIoOperations (const Nnet &nnet, NnetComputation *computation)
 This optimization puts the input operations (kAcceptInput) and output operations (kProvideOutput) at the very beginning or end of segments of computation, respectively. More...
 
void LimitDerivativeTimes (const Nnet &nnet, const ComputationRequest &request, const NnetOptimizeOptions &opts, NnetComputation *computation)
 This optimization, which has no effect unless you set –min-deriv-time or –max-deriv-time, modifies the backprop operations for efficiency based on the assumption that derivatives for any Cindex with t < min_deriv_time or t > max_deriv_time are zero. More...
 
void UnitTestDescriptorTokenize ()
 
void UnitTestSummarizeVector ()
 
void UnitTestNameMatchesPattern ()
 
bool DescriptorTokenize (const std::string &input, std::vector< std::string > *tokens)
 This function tokenizes input when parsing Descriptor configuration values. More...
 
std::string ErrorContext (std::istream &is)
 Return a string used in error messages. More...
 
std::string ErrorContext (const std::string &str)
 
static void PrintFloatSuccinctly (std::ostream &os, BaseFloat f)
 
std::string SummarizeVector (const VectorBase< float > &vec)
 Returns a string that summarizes a vector fairly succintly, for printing stats in info lines. More...
 
std::string SummarizeVector (const VectorBase< double > &vec)
 
std::string SummarizeVector (const CuVectorBase< BaseFloat > &cu_vec)
 
void PrintParameterStats (std::ostringstream &os, const std::string &name, const CuVectorBase< BaseFloat > &params, bool include_mean=false)
 Print to 'os' some information about the mean and standard deviation of some parameters, used in Info() functions in nnet-simple-component.cc. More...
 
void PrintParameterStats (std::ostringstream &os, const std::string &name, const CuMatrix< BaseFloat > &params, bool include_mean=false, bool include_row_norms=false, bool include_column_norms=false, bool include_singular_values=false)
 Print to 'os' some information about the mean and standard deviation of some parameters, used in Info() functions in nnet-simple-component.cc. More...
 
void ParseConfigLines (const std::vector< std::string > &lines, std::vector< ConfigLine > *config_lines)
 
bool NameMatchesPattern (const char *name, const char *pattern)
 
void GenerateConfigSequenceSimplest (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceSimpleContext (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceSimple (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceStatistics (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceRnn (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceRnnClockwork (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceLstm (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceLstmWithTruncation (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceLstmType2 (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceCnn (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceCnnNew (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceRestrictedAttention (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceDistribute (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 
void GenerateConfigSequenceCompositeBlock (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 Generate a config string with a composite component composed only of block affine, repeated affine, and natural gradient repeated affine components. More...
 
void GenerateConfigSequence (const NnetGenerationOptions &opts, std::vector< std::string > *configs)
 Generates a sequence of at least one config files, output as strings, where the first in the sequence is the initial nnet, and the remaining ones may do things like add layers. More...
 
void ComputeExampleComputationRequestSimple (const Nnet &nnet, ComputationRequest *request, std::vector< Matrix< BaseFloat > > *inputs)
 This function computes an example computation request, for testing purposes. More...
 
static void GenerateRandomComponentConfig (std::string *component_type, std::string *config)
 
ComponentGenerateRandomSimpleComponent ()
 Generates random simple component for testing. More...
 
bool NnetParametersAreIdentical (const Nnet &nnet1, const Nnet &nnet2, BaseFloat threshold)
 Used for testing that the updatable parameters in two networks are the same. More...
 
void GenerateSimpleNnetTrainingExample (int32 num_supervised_frames, int32 left_context, int32 right_context, int32 input_dim, int32 output_dim, int32 ivector_dim, NnetExample *example)
 Low-level function that generates an nnet training example. More...
 
bool ExampleApproxEqual (const NnetExample &eg1, const NnetExample &eg2, BaseFloat delta)
 Returns true if the examples are approximately equal (only intended to be used in testing). More...
 
void ComputeObjectiveFunction (const GeneralMatrix &supervision, ObjectiveType objective_type, const std::string &output_name, bool supply_deriv, NnetComputer *computer, BaseFloat *tot_weight, BaseFloat *tot_objf)
 This function computes the objective function, and if supply_deriv = true, supplies its derivative to the NnetComputation object. More...
 
void UnitTestNnetContext ()
 
void UnitTestConvertRepeatedToBlockAffine ()
 
void UnitTestConvertRepeatedToBlockAffineComposite ()
 
int32 NumOutputNodes (const Nnet &nnet)
 returns the number of output nodes of this nnet. More...
 
int32 NumInputNodes (const Nnet &nnet)
 returns the number of input nodes of this nnet. More...
 
bool IsSimpleNnet (const Nnet &nnet)
 This function returns true if the nnet has the following properties: It has an output called "output" (other outputs are allowed but may be ignored). More...
 
void EvaluateComputationRequest (const Nnet &nnet, const ComputationRequest &request, std::vector< std::vector< bool > > *is_computable)
 Given an nnet and a computation request, this function works out which requested outputs in the computation request are computable; it outputs this information as a vector "is_computable" indexed by the same indexes as request.outputs. More...
 
static bool ComputeSimpleNnetContextForShift (const Nnet &nnet, int32 input_start, int32 window_size, int32 *left_context, int32 *right_context)
 
void ComputeSimpleNnetContext (const Nnet &nnet, int32 *left_context, int32 *right_context)
 ComputeSimpleNnetContext computes the left-context and right-context of a nnet. More...
 
void PerturbParams (BaseFloat stddev, Nnet *nnet)
 Calls PerturbParams (with the given stddev) on all updatable components of the nnet. More...
 
void ComponentDotProducts (const Nnet &nnet1, const Nnet &nnet2, VectorBase< BaseFloat > *dot_prod)
 Returns dot products between two networks of the same structure (calls the DotProduct functions of the Updatable components and fill in the output vector). More...
 
std::string PrintVectorPerUpdatableComponent (const Nnet &nnet, const VectorBase< BaseFloat > &vec)
 This function is for printing, to a string, a vector with one element per updatable component of the nnet (e.g. More...
 
BaseFloat DotProduct (const Nnet &nnet1, const Nnet &nnet2)
 Returns dot product between two networks of the same structure (calls the DotProduct functions of the Updatable components and sums up the return values). More...
 
void ZeroComponentStats (Nnet *nnet)
 Zeroes the component stats in all nonlinear components in the nnet. More...
 
void SetLearningRate (BaseFloat learning_rate, Nnet *nnet)
 Sets the underlying learning rate for all the components in the nnet to this value. More...
 
void SetNnetAsGradient (Nnet *nnet)
 Sets nnet as gradient by Setting is_gradient_ to true and learning_rate_ to 1 for each UpdatableComponent in nnet. More...
 
void SetRequireDirectInput (bool b, Nnet *nnet)
 Calls the corresponding function in any component of type StatisticsPoolingComponent; used as a way to compute the 'real' left-right context of networks including SatisticsPoolingComponent, which will give you the minimum chunk size they can consume. More...
 
void ScaleNnet (BaseFloat scale, Nnet *nnet)
 Scales the nnet parameters and stats by this scale. More...
 
void AddNnetComponents (const Nnet &src, const Vector< BaseFloat > &alphas, BaseFloat scale, Nnet *dest)
 Does *dest += alpha * src for updatable components (affects nnet parameters), and *dest += scale * src for other components (affects stored stats). More...
 
void AddNnet (const Nnet &src, BaseFloat alpha, Nnet *dest)
 Does *dest += alpha * src (affects nnet parameters and stored stats). More...
 
int32 NumParameters (const Nnet &src)
 Returns the total of the number of parameters in the updatable components of the nnet. More...
 
void VectorizeNnet (const Nnet &src, VectorBase< BaseFloat > *params)
 Copies the nnet parameters to *params, whose dimension must be equal to NumParameters(src). More...
 
void UnVectorizeNnet (const VectorBase< BaseFloat > &params, Nnet *dest)
 Copies the parameters from params to *dest. More...
 
int32 NumUpdatableComponents (const Nnet &dest)
 Returns the number of updatable components in the nnet. More...
 
void FreezeNaturalGradient (bool freeze, Nnet *nnet)
 Controls if natural gradient will be updated. More...
 
void ConvertRepeatedToBlockAffine (CompositeComponent *c_component)
 
void ConvertRepeatedToBlockAffine (Nnet *nnet)
 Convert all components of type RepeatedAffineComponent or NaturalGradientRepeatedAffineComponent to BlockAffineComponent in nnet. More...
 
std::string NnetInfo (const Nnet &nnet)
 This function returns various info about the neural net. More...
 
void SetDropoutProportion (BaseFloat dropout_proportion, Nnet *nnet)
 This function sets the dropout proportion in all dropout components to dropout_proportion value. More...
 
bool HasBatchnorm (const Nnet &nnet)
 Returns true if nnet has at least one component of type BatchNormComponent. More...
 
void ScaleBatchnormStats (BaseFloat batchnorm_stats_scale, Nnet *nnet)
 This function scales the batchorm stats of any batchnorm components (components of type BatchNormComponent) in 'nnet' by the scale 'batchnorm_stats_scale'. More...
 
void RecomputeStats (const std::vector< NnetExample > &egs, Nnet *nnet)
 This function zeros the stored component-level stats in the nnet using ZeroComponentStats(), then recomputes them with the supplied egs. More...
 
void SetBatchnormTestMode (bool test_mode, Nnet *nnet)
 This function affects only components of type BatchNormComponent. More...
 
void SetDropoutTestMode (bool test_mode, Nnet *nnet)
 This function affects components of child-classes of RandomComponent. More...
 
void ResetGenerators (Nnet *nnet)
 This function calls 'ResetGenerator()' on all components in 'nnet' that inherit from class RandomComponent. More...
 
void FindOrphanComponents (const Nnet &nnet, std::vector< int32 > *components)
 This function finds a list of components that are never used, and outputs the integer comopnent indexes (you can use these to index nnet.GetComponentNames() to get their names). More...
 
void FindOrphanNodes (const Nnet &nnet, std::vector< int32 > *nodes)
 This function finds a list of nodes that are never used to compute any output, and outputs the integer node indexes (you can use these to index nnet.GetNodeNames() to get their names). More...
 
void ConstrainOrthonormalInternal (BaseFloat scale, CuMatrixBase< BaseFloat > *M)
 
void ConstrainOrthonormal (Nnet *nnet)
 This function, to be called after processing every minibatch, is responsible for enforcing the orthogonality constraint for any components of type LinearComponent or inheriting from AffineComponent that have the "orthonormal_constraint" value set. More...
 
void ConsolidateMemory (Nnet *nnet)
 This just calls ConsolidateMemory() on all the components of the nnet. More...
 
void ReduceRankOfComponents (const std::string component_name_pattern, int32 rank, Nnet *nnet)
 
void ReadEditConfig (std::istream &config_file, Nnet *nnet)
 ReadEditConfig() reads a file with a similar-looking format to the config file read by Nnet::ReadConfig(), but this consists of a sequence of operations to perform on an existing network, mostly modifying components. More...
 
bool NnetIsRecurrent (const Nnet &nnet)
 Returns true if 'nnet' has some kind of recurrency. More...
 
void CollapseModel (const CollapseModelConfig &config, Nnet *nnet)
 This function modifies the neural net for efficiency, in a way that suitable to be done in test time. More...
 
bool UpdateNnetWithMaxChange (const Nnet &delta_nnet, BaseFloat max_param_change, BaseFloat max_change_scale, BaseFloat scale, Nnet *nnet, std::vector< int32 > *num_max_change_per_component_applied, int32 *num_max_change_global_applied)
 This function does the operation '*nnet += scale * delta_nnet', while respecting any max-parameter-change (max-param-change) specified in the updatable components, and also the global max-param-change specified as 'max_param_change'. More...
 
int32 GetNumNvalues (const std::vector< NnetIo > &io_vec, bool exhaustive)
 This utility function can be used to obtain the number of distinct 'n' values in a training example. More...
 
void ApplyL2Regularization (const Nnet &nnet, BaseFloat l2_regularize_scale, Nnet *delta_nnet)
 This function is used as part of the regular training workflow, prior to UpdateNnetWithMaxChange(). More...
 
bool UpdateNnetWithMaxChange (const Nnet &delta_nnet, BaseFloat max_param_change, BaseFloat max_change_scale, BaseFloat scale, Nnet *nnet, MaxChangeStats *stats)
 
BaseFloat KlDivergence (const Vector< BaseFloat > &p, const Vector< BaseFloat > &q)
 
void PrintPriorDiagnostics (const Vector< BaseFloat > &old_priors, const Vector< BaseFloat > &new_priors)
 
void SetPriors (const TransitionModel &tmodel, const Vector< double > &transition_accs, double prior_floor, AmNnetSimple *am_nnet)
 
double ComputeObjf (bool batchnorm_test_mode, bool dropout_test_mode, const std::vector< NnetExample > &egs, const Nnet &nnet, NnetComputeProb *prob_computer)
 
void UpdateNnetMovingAverage (int32 num_models, const Nnet &nnet, Nnet *moving_average_nnet)
 
void RenameOutputs (const std::string &new_name, NnetExample *eg)
 
void ScaleSupervisionWeight (BaseFloat weight, NnetExample *eg)
 
int32 GetCount (double expected_count)
 
bool ContainsSingleExample (const NnetExample &eg, int32 *min_input_t, int32 *max_input_t, int32 *min_output_t, int32 *max_output_t)
 Returns true if the "eg" contains just a single example, meaning that all the "n" values in the indexes are zero, and the example has NnetIo members named both "input" and "output". More...
 
void FilterExample (const NnetExample &eg, int32 min_input_t, int32 max_input_t, int32 min_output_t, int32 max_output_t, NnetExample *eg_out)
 This function filters the indexes (and associated feature rows) in a NnetExample, removing any index/row in an NnetIo named "input" with t < min_input_t or t > max_input_t and any index/row in an NnetIo named "output" with t < min_output_t or t > max_output_t. More...
 
bool SelectFromExample (const NnetExample &eg, std::string frame_str, int32 left_context, int32 right_context, int32 frame_shift, NnetExample *eg_out)
 This function is responsible for possibly selecting one frame from multiple supervised frames, and reducing the left and right context as specified. More...
 
static bool ProcessFile (const discriminative::SplitDiscriminativeSupervisionOptions &config, const TransitionModel &tmodel, const MatrixBase< BaseFloat > &feats, const MatrixBase< BaseFloat > *ivector_feats, int32 ivector_period, const discriminative::DiscriminativeSupervision &supervision, const std::string &utt_id, bool compress, UtteranceSplitter *utt_splitter, NnetDiscriminativeExampleWriter *example_writer)
 
void ApplyAffineTransform (MatrixBase< BaseFloat > &transform, int32 num_channels, MatrixBase< BaseFloat > *image, FillMode fill_mode)
 This function applies a geometric transformation 'transform' to the image. More...
 
void PerturbImage (const ImageAugmentationConfig &config, MatrixBase< BaseFloat > *image)
 This function randomly modifies (perturbs) the image by applying different geometric transformations according to the options in 'config'. More...
 
void PerturbImageInNnetExample (const ImageAugmentationConfig &config, NnetExample *eg)
 This function does image perturbation as directed by 'config' The example 'eg' is expected to contain a NnetIo member with the name 'input', representing an image. More...
 
static bool ProcessFile (const GeneralMatrix &feats, const MatrixBase< BaseFloat > *ivector_feats, int32 ivector_period, const MatrixBase< BaseFloat > &targets, const std::string &utt_id, bool compress, int32 num_targets, int32 length_tolerance, UtteranceSplitter *utt_splitter, NnetExampleWriter *example_writer)
 
static bool ProcessFile (const GeneralMatrix &feats, const MatrixBase< BaseFloat > *ivector_feats, int32 ivector_period, const Posterior &pdf_post, const std::string &utt_id, bool compress, int32 num_pdfs, int32 length_tolerance, UtteranceSplitter *utt_splitter, NnetExampleWriter *example_writer)
 
int32 NumOutputIndexes (const NnetExample &eg)
 
void DivideIntoPieces (int32 a, int32 b, std::vector< int32 > *pieces)
 This function divides the number 'a' into 'b' pieces, such that the sum of the pieces equals 'a' and no two pieces differ by more than 1. More...
 
static void RunNnetComputation (const MatrixBase< BaseFloat > &features, const Nnet &nnet, CachingOptimizingCompiler *compiler, Vector< BaseFloat > *xvector)
 
static void ProcessRangeFile (const std::string &range_rxfilename, unordered_map< std::string, std::vector< ChunkInfo *> > *utt_to_chunks)
 
static void WriteExamples (const MatrixBase< BaseFloat > &feats, const std::vector< ChunkInfo *> &chunks, const std::string &utt, bool compress, int32 num_pdfs, int32 *num_egs_written, std::vector< NnetExampleWriter *> *example_writers)
 

Variables

static bool computation_checker_warned_unused_input = false
 Checks that we never use variables before they are allocated or after they are deallocated, and some other checks that can be done from the MatrixAccesses. More...
 
const int kNoTime = std::numeric_limits<int32>::min()
 

Typedef Documentation

◆ Cindex

typedef std::pair<int32, Index> Cindex

Definition at line 115 of file nnet-common.h.

◆ NnetChainExampleWriter

◆ NnetDiscriminativeExampleWriter

◆ NnetExampleWriter

◆ RandomAccessNnetChainExampleReader

◆ RandomAccessNnetDiscriminativeExampleReader

◆ RandomAccessNnetExampleReader

◆ SequentialNnetChainExampleReader

◆ SequentialNnetDiscriminativeExampleReader

◆ SequentialNnetExampleReader

Enumeration Type Documentation

◆ AccessType

enum AccessType
Enumerator
kReadAccess 
kWriteAccess 
kReadWriteAccess 

Definition at line 75 of file nnet-analyze.h.

◆ CommandType

CommandType is an enum that describes the category of the command used in the NnetComputation.

We declare it outside that class because it's so frequently used and we got tired of typing NnetComputation:: everywhere. We document the commands here. Note: for operations that naturally need to operate on entire matrices (i.e. allocation commands and input and output commands), we use the submatrix indexes of them, which turns out to be more convenient for optimization; but these submatrix indexes must refer to the whole of a matrix.

  • kAllocMatrix. Allocate a matrix (its values will be undefined). arg1 = submatrix index, which must refer to a whole matrix.
  • kDeallocMatrix: Deallocate a matrix. arg1 = submatrix index.
  • kSwapMatrix: initialize matrix with submatrix index arg1 using memory from matrix with submatrix index arg2 (using shallow swap). Both submatrices must refer to whole matrices. The expectation is that prior to the swap, arg1 was empty and arg2 was nonempty, but the execution code does not enforce this.
  • kSetConst: set all elements of submatrix index 'arg1' to the value 'alpha'.
  • kPropagate: Forward computation of neural net, see Component::Propagate()
    • arg1 is is component-index in neural net
    • arg2 is index into ComponentPrecomputedIndexes (0 if NULL; always 0 for simple Components)
    • arg3 is sub-matrix index of input
    • arg4 is sub-matrix index of output
    • arg5 is the index of the memo saved from Propagate()'s return value, or 0 if it saves no memo.
    • arg6 is 1 if we need to call StoreStats() after the Propagate, or 0 if we don't. We used to have a separate command for storing the stats, but that has been removed.
  • kBackprop: Do the back-propagation operation, see Component::Backprop()
    • arg1 is index of component in neural net
    • arg2 is index into ComponentPrecomputedIndexes (0 if NULL; always 0 for simple Components)
    • arg3 is submatrix-index of input value (input to Propagate()); 0 if unused
    • arg4 is submatrix-index of output value (output of Propagate()); 0 if unused
    • arg5 is submatrix-index of output derivative
    • arg6 is submatrix-index of input derivative; 0 if unused.
    • arg7 is the index of the memo which is generated from the corresponding Propagate() function if the flag kUsesMemo is set; 0 if unused.
  • kBackpropNoModelUpdate: as kBackprop, but does not set the 'to_update' argument to the Backprop call, even if the model is updatable, so it skips the model-update phase of backprop.
  • kMatrixCopy: Copy (alpha times contents of sub-matrix arg2) to sub-matrix arg1, currently implemented as copy then scale. Note: to implement scaling a matrix, you can use kMatrixCopy with arg1 == arg2 and it won't do any redundant copying.
  • kMatrixAdd: Add (alpha times contents of sub-matrix arg2) to sub-matrix arg1
  • kCopyRows: call CopyRows() on sub-matrix arg1 with sub-matrix arg2 and indexes[arg3] as arguments, then if alpha != 1.0, scale sub-matrix arg1 by alpha.
  • kAddRows: call AddRows() on sub-matrix arg1 with alpha, sub-matrix arg2 and indexes[arg3] as arguments.
  • kAddRowsMulti, kAddToRowsMulti, kCopyRowsMulti, kCopyToRowsMulti: Call the corresponding function in class CuMatrix (Actually the names do not have 'Multi' in them, but they are the ones that accept a vector of 'Real*'.
    • arg1 is sub-matrix index of *this matrix in operation
    • arg2 is index into "indexes_multi", of which each pair is (sub-matrix index, row index) (or (-1,-1) for NULL marker), which is turned into a vector of BaseFloat* (pointers to matrix rows) before being given as the argument to the function. In the 'Add' functions 'alpha' is provided as an argument; for the 'Copy' functions, we scale the destination by 'alpha' after the copy, if alpha != 1.0. (However, for implementation reasons, kCopyToRowsMulti does not currently support alpha != 1.0 and will crash, so we avoid generating this code).
  • kAddRowRanges: call AddRowRanges() on sub-matrix arg1, with arg2 as source sub-matrix, and indexes given indexes_ranges[arg3]. We use the "alpha" as if AddRowRanges() accepted that argument, even though it doesn't (we fake it using other calls, if alpha != 1.0).
  • kCompressMatrix: Compresses the matrix which should be referred to by submatrix-index arg1. arg2 is a number that determines the compression type (it's converted from the enum CuCompressedMatrixType; 1=int8, 2=uint8, 3=int16, 4=uint16), and alpha determines the 'range' parameter (c.f. NewCuCompressedMatrix()). arg3 will be converted to the 'truncate' argument to the class CuCompressedMatrix; it should be false (0) if you know that the input is limited to the allowed range, and true (1) if the input may exceed that range (see docs for CuCompresedMatrix).
  • kDecompressMatrix: Decompresses the matrix which is referred to by submatrix-index arg1 (it should previously have been compressed).
  • kAcceptInput: accepts a matrix of input from the user, which may be either features, or derivatives w.r.t. the output. arg1 is the submatrix index of a whole matrix that the input goes to, and arg2 is the index of the network node associated with it (e.g. the node of "input" or "ivector"), for puroses of double checking.
  • kProvideOutput: outputs a matrix to the user: either a network output, or a matrix of derivatives w.r.t. an input. arg1 is the submatrix index of the output (which we expect to be a whole matrix), arg2 is the index of the network node associated with it (e.g. the node for "output").
  • kNoOperation: does nothing, and will be removed by optimization code (sometimes useful during optimization)
  • kNoOperationPermanent: like kNoOperation, but won't be removed by optimization code. This is used to ensure that for 'trivial' computations, which just copy the input to the output, the block of commands for the forward or backward propagation is nonempty (to avoid confusing the computation code).
  • kNoOperationMarker: does nothing, but used to mark end of a block of commands (like forward commands).
  • kNoOperationLabel: does nothing, but is the destination for the kGotoLabel command.
  • kGotoLabel: jumps to the kNoOperationLabel command. arg1 must be set to the location of that command. Since there are no conditionals, the kGotoLabel command should be the last command, as remaining commands will be unreachable.
Enumerator
kAllocMatrix 
kDeallocMatrix 
kSwapMatrix 
kSetConst 
kPropagate 
kBackprop 
kBackpropNoModelUpdate 
kMatrixCopy 
kMatrixAdd 
kCopyRows 
kAddRows 
kCopyRowsMulti 
kCopyToRowsMulti 
kAddRowsMulti 
kAddToRowsMulti 
kAddRowRanges 
kCompressMatrix 
kDecompressMatrix 
kAcceptInput 
kProvideOutput 
kNoOperation 
kNoOperationPermanent 
kNoOperationMarker 
kNoOperationLabel 
kGotoLabel 

Definition at line 288 of file nnet-computation.h.

288  {
296  kGotoLabel };

◆ ComponentProperties

Enumerator
kSimpleComponent 
kUpdatableComponent 
kPropagateInPlace 
kPropagateAdds 
kReordersIndexes 
kBackpropAdds 
kBackpropNeedsInput 
kBackpropNeedsOutput 
kBackpropInPlace 
kStoresStats 
kInputContiguous 
kOutputContiguous 
kUsesMemo 
kRandomComponent 

Definition at line 37 of file nnet-component-itf.h.

37  {
38  kSimpleComponent = 0x001, // true if number of rows of input equals number of rows
39  // of output and this component doesn't care about the indexes
40  // (i.e. it maps each row of input to each row of output without
41  // regard to the index values). Will normally be true.
42  kUpdatableComponent = 0x002, // true if the component has parameters that can
43  // be updated. Components that return this flag
44  // must be dynamic_castable to type
45  // UpdatableComponent (but components of type
46  // UpdatableComponent do not have to return this
47  // flag, e.g. if this instance is not really
48  // updatable).
49  kPropagateInPlace = 0x004, // true if we can do the propagate operation in-place
50  // (input and output matrices are the same).
51  // Note: if doing backprop, you'd also need to check
52  // that the kBackpropNeedsInput property is not true.
53  kPropagateAdds = 0x008, // true if the Propagate function adds to, rather
54  // than setting, its output, for non-in-place
55  // propagation. The Component chooses whether to add
56  // or set, and the calling code has to accommodate
57  // it.
58  kReordersIndexes = 0x010, // true if the ReorderIndexes function might reorder
59  // the indexes (otherwise we can skip calling it).
60  // Must not be set for simple components.
61  kBackpropAdds = 0x020, // true if the Backprop function adds to, rather than
62  // setting, the "in_deriv" output for non-in-place
63  // backprop. The Component chooses whether to add or
64  // set, and the calling code has to accommodate it.
65  kBackpropNeedsInput = 0x040, // true if backprop operation needs access to
66  // forward-pass input.
67  kBackpropNeedsOutput = 0x080, // true if backprop operation needs access to
68  // forward-pass output (e.g. true for Sigmoid).
69  kBackpropInPlace = 0x100, // true if we can do the backprop operation in-place
70  // (input and output matrices may be the same).
71  kStoresStats = 0x200, // true if the StoreStats operation stores
72  // statistics e.g. on average node activations and
73  // derivatives of the nonlinearity, (as it does for
74  // Tanh, Sigmoid, ReLU and Softmax).
75  kInputContiguous = 0x400, // true if the component requires its input data (and
76  // input derivatives) to have Stride()== NumCols().
77  kOutputContiguous = 0x800, // true if the component requires its input data (and
78  // output derivatives) to have Stride()== NumCols().
79  kUsesMemo = 0x1000, // true if the component returns a void* pointer from its
80  // Propagate() function that needs to be passed into the
81  // corresponding Backprop function.
82  kRandomComponent = 0x2000 // true if the component has some kind of
83  // randomness, like DropoutComponent (these should
84  // inherit from class RandomComponent.
85 };

◆ FillMode

enum FillMode
Enumerator
kNearest 
kReflect 

Definition at line 31 of file nnet3-egs-augment-image.cc.

◆ NodeType

enum NodeType
Enumerator
kInput 
kDescriptor 
kComponent 
kDimRange 
kNone 

Definition at line 55 of file nnet-nnet.h.

◆ ObjectiveType

This enum is for a kind of annotation we associate with output nodes of the network; it's for the convenience of calling code so that if the objective is one of a few standard types, we can compute it directly and know how to interpret the supervision labels.

However, the core of the framework never makes use of the objective types, other than making them available to calling code which then supplies the derivatives.

  • Objective type kLinear is intended for Neural nets where the final component is a LogSoftmaxComponent, so the log-prob (negative cross-entropy) objective is just a linear function of the input.
  • Objective type kQuadratic is used to mean the objective function f(x, y) = -0.5 (x-y).(x-y), which is to be maximized, as in the kLinear case.
Enumerator
kLinear 
kQuadratic 

Definition at line 52 of file nnet-nnet.h.

Function Documentation

◆ AddNnet()

void AddNnet ( const Nnet src,
BaseFloat  alpha,
Nnet dest 
)

Does *dest += alpha * src (affects nnet parameters and stored stats).

Definition at line 349 of file nnet-utils.cc.

References Component::Add(), Nnet::GetComponent(), KALDI_ERR, and Nnet::NumComponents().

Referenced by main(), kaldi::ReadModels(), NnetDiscriminativeTrainer::Train(), and UpdateNnetMovingAverage().

349  {
350  if (src.NumComponents() != dest->NumComponents())
351  KALDI_ERR << "Trying to add incompatible nnets.";
352  for (int32 c = 0; c < src.NumComponents(); c++) {
353  const Component *src_comp = src.GetComponent(c);
354  Component *dest_comp = dest->GetComponent(c);
355  dest_comp->Add(alpha, *src_comp);
356  }
357 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ AddNnetComponents()

void AddNnetComponents ( const Nnet src,
const Vector< BaseFloat > &  alphas,
BaseFloat  scale,
Nnet dest 
)

Does *dest += alpha * src for updatable components (affects nnet parameters), and *dest += scale * src for other components (affects stored stats).

Here, alphas is a vector of size equal to the number of updatable components

Definition at line 322 of file nnet-utils.cc.

References Component::Add(), VectorBase< Real >::Dim(), Nnet::GetComponent(), rnnlm::i, KALDI_ASSERT, KALDI_ERR, kUpdatableComponent, Nnet::NumComponents(), and Component::Properties().

Referenced by UpdateNnetWithMaxChange().

323  {
324  if (src.NumComponents() != dest->NumComponents())
325  KALDI_ERR << "Trying to add incompatible nnets.";
326  int32 i = 0;
327  for (int32 c = 0; c < src.NumComponents(); c++) {
328  const Component *src_comp = src.GetComponent(c);
329  Component *dest_comp = dest->GetComponent(c);
330  if (src_comp->Properties() & kUpdatableComponent) {
331  // For now all updatable components inherit from class UpdatableComponent.
332  // If that changes in future, we will change this code.
333  const UpdatableComponent *src_uc =
334  dynamic_cast<const UpdatableComponent*>(src_comp);
335  UpdatableComponent *dest_uc =
336  dynamic_cast<UpdatableComponent*>(dest_comp);
337  if (src_uc == NULL || dest_uc == NULL)
338  KALDI_ERR << "Updatable component does not inherit from class "
339  "UpdatableComponent; change this code.";
340  KALDI_ASSERT(i < alphas.Dim());
341  dest_uc->Add(alphas(i++), *src_uc);
342  } else { // add stored stats
343  dest_comp->Add(scale, *src_comp);
344  }
345  }
346  KALDI_ASSERT(i == alphas.Dim());
347 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ AddTimeOffsetToComputationRequest()

void kaldi::nnet3::AddTimeOffsetToComputationRequest ( int32  t_offset,
ComputationRequest request 
)

Definition at line 235 of file nnet-compile-looped.cc.

References rnnlm::i, ComputationRequest::inputs, rnnlm::j, and ComputationRequest::outputs.

Referenced by ExtrapolateComputationRequest().

236  {
237  for (size_t i = 0; i < request->inputs.size(); i++) {
238  size_t size = request->inputs[i].indexes.size();
239  for (size_t j = 0; j < size; j++)
240  request->inputs[i].indexes[j].t += t_offset;
241  }
242  for (size_t i = 0; i < request->outputs.size(); i++) {
243  size_t size = request->outputs[i].indexes.size();
244  for (size_t j = 0; j < size; j++)
245  request->outputs[i].indexes[j].t += t_offset;
246  }
247 }

◆ AppendCindexes()

void AppendCindexes ( int32  node,
const std::vector< Index > &  indexes,
std::vector< Cindex > *  out 
)

Appends to 'out' the pairs (node, indexes[0]), (node, indexes[1]), ...

Definition at line 1384 of file nnet-compile.cc.

References rnnlm::i.

Referenced by Compiler::OutputDebugInfo().

1385  {
1386  size_t indexes_size = indexes.size();
1387  if (indexes_size > out->size())
1388  out->reserve(out->size() + indexes_size);
1389  for (size_t i = 0; i < indexes_size; i++)
1390  out->push_back(Cindex(node, indexes[i]));
1391 }
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115

◆ ApplyAffineTransform()

void kaldi::nnet3::ApplyAffineTransform ( MatrixBase< BaseFloat > &  transform,
int32  num_channels,
MatrixBase< BaseFloat > *  image,
FillMode  fill_mode 
)

This function applies a geometric transformation 'transform' to the image.

Reference: Digital Image Processing book by Gonzalez and Woods.

Parameters
[in]transformThe 3x3 geometric transformation matrix to apply.
[in]num_channelsNumber of channels (i.e. colors) of the image
[in,out]imageThe image matrix to be modified. image->NumRows() is the width (number of x values) in the image; image->NumCols() is the height times number of channels (channel varies the fastest).

Definition at line 110 of file nnet3-egs-augment-image.cc.

References KALDI_ASSERT, kNearest, ImageAugmentationConfig::num_channels, MatrixBase< Real >::NumCols(), and MatrixBase< Real >::NumRows().

Referenced by PerturbImage().

113  {
114  int32 num_rows = image->NumRows(),
115  num_cols = image->NumCols(),
116  height = num_cols / num_channels,
117  width = num_rows;
118  KALDI_ASSERT(num_cols % num_channels == 0);
119  Matrix<BaseFloat> original_image(*image);
120  for (int32 r = 0; r < width; r++) {
121  for (int32 c = 0; c < height; c++) {
122  // (r_old, c_old) is the coordinate of the pixel in the original image
123  // while (r, c) is the coordinate in the new (transformed) image.
124  BaseFloat r_old = transform(0, 0) * r +
125  transform(0, 1) * c + transform(0, 2);
126  BaseFloat c_old = transform(1, 0) * r +
127  transform(1, 1) * c + transform(1, 2);
128  // We are going to do bilinear interpolation between 4 closest points
129  // to the point (r_old, c_old) of the original image. We have:
130  // r1 <= r_old <= r2
131  // c1 <= c_old <= c2
132  int32 r1 = static_cast<int32>(floor(r_old));
133  int32 c1 = static_cast<int32>(floor(c_old));
134  int32 r2 = r1 + 1;
135  int32 c2 = c1 + 1;
136 
137  // These weights determine how much each of the 4 points contributes
138  // to the final interpolated value:
139  BaseFloat weight_11 = (r2 - r_old) * (c2 - c_old),
140  weight_12 = (r2 - r_old) * (c_old - c1),
141  weight_21 = (r_old - r1) * (c2 - c_old),
142  weight_22 = (r_old - r1) * (c_old - c1);
143  // Handle edge conditions:
144  if (fill_mode == kNearest) {
145  if (r1 < 0) {
146  r1 = 0;
147  if (r2 < 0) r2 = 0;
148  }
149  if (r2 >= width) {
150  r2 = width - 1;
151  if (r1 >= width) r1 = width - 1;
152  }
153  if (c1 < 0) {
154  c1 = 0;
155  if (c2 < 0) c2 = 0;
156  }
157  if (c2 >= height) {
158  c2 = height - 1;
159  if (c1 >= height) c1 = height - 1;
160  }
161  } else {
162  KALDI_ASSERT(fill_mode == kReflect);
163  if (r1 < 0) {
164  r1 = - r1;
165  if (r2 < 0) r2 = - r2;
166  }
167  if (r2 >= width) {
168  r2 = 2 * width - 2 - r2;
169  if (r1 >= width) r1 = 2 * width - 2 - r1;
170  }
171  if (c1 < 0) {
172  c1 = - c1;
173  if (c2 < 0) c2 = -c2;
174  }
175  if (c2 >= height) {
176  c2 = 2 * height - 2 - c2;
177  if (c1 >= height) c1 = 2 * height - 2 - c1;
178  }
179  }
180  for (int32 ch = 0; ch < num_channels; ch++) {
181  // find the values at the 4 points
182  BaseFloat p11 = original_image(r1, num_channels * c1 + ch),
183  p12 = original_image(r1, num_channels * c2 + ch),
184  p21 = original_image(r2, num_channels * c1 + ch),
185  p22 = original_image(r2, num_channels * c2 + ch);
186  (*image)(r, num_channels * c + ch) = weight_11 * p11 + weight_12 * p12 +
187  weight_21 * p21 + weight_22 * p22;
188  }
189  }
190  }
191 }
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Definition: kaldi-matrix.h:67
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
#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

◆ ApplyL2Regularization()

void ApplyL2Regularization ( const Nnet nnet,
BaseFloat  l2_regularize_scale,
Nnet delta_nnet 
)

This function is used as part of the regular training workflow, prior to UpdateNnetWithMaxChange().

For each updatable component c in the neural net, suppose it has a l2-regularization constant alpha set at the component level (see UpdatableComponent::L2Regularization()), and a learning-rate eta, then this function does (and this is not real code):

delta_nnet->c -= 2.0 * l2_regularize_scale * alpha * eta * nnet.c

The factor of -1.0 comes from the fact that we are maximizing, and we'd add the l2 regularization term (of the form ||||_2^2, i.e. squared l2 norm) in the objective function with negative sign; the factor of 2.0 comes from the derivative of the squared parameters. The factor 'l2_regularize_scale' is provided to this function, see below for an explanation.

Note: the way we do it is a little bit approximate, due to the interaction with natural gradient. The issue is that the regular gradients are multiplied by the inverse of the approximated, smoothed and factored inverse Fisher matrix, but the l2 gradients are not. This means that what we're optimizing is not exactly the (regular objective plus the L2 term)– we could view it as optimizing (regular objective plus the l2 term times the Fisher matrix)– with the proviso that the Fisher matrix has been scaled in such a way that the amount of parameter change is not affected, so this is not an issue of affecting the overall strength of l2, just an issue of the direction-wise weighting. In effect, the l2 term will be larger, relative to the gradient contribution, in directions where the Fisher matrix is large. This is probably not ideal– but it's hard to judge without experiments. Anyway the l2 effect is small enough, and the Fisher matrix sufficiently smoothed with the identity, that I doubt this makes much of a difference.

Parameters
[in]nnetThe neural net that is being trained; expected to be different from delta_nnet
[in]l2_regularize_scaleA scale on the l2 regularization. Usually this will be equal to the number of distinct examples (e.g. the number of chunks of speech– more precisely, the number of distinct 'n' values) in the minibatch, but this is multiplied by a configuration value –l2-regularize-factor passed in from the command line. The reason for making l2 proportional to the number of elements in the minibatch is that we add the parameter gradients over the minibatch (we don't average), so multiplying the l2 factor by the number of elements in the minibatch is necessary to make the amount of l2 vs. gradient contribution stay the same when we vary the minibatch size. The –l2-regularize-factor option is provided so that the calling script can correct for the effects of parallelization via model-averaging (we'd normally set this to 1/num-parallel-jobs).
[out]delta_nnetThe neural net containing the parameter updates; this is a copy of 'nnet' that is used for purposes of momentum and applying max-change values. This is what this code adds to.

Definition at line 2244 of file nnet-utils.cc.

References Component::Add(), Nnet::GetComponent(), KALDI_ASSERT, kUpdatableComponent, UpdatableComponent::L2Regularization(), UpdatableComponent::LearningRate(), Nnet::NumComponents(), and Component::Properties().

Referenced by CollapseModelConfig::CollapseModelConfig(), NnetChainTrainer::TrainInternal(), NnetTrainer::TrainInternal(), NnetChainTrainer::TrainInternalBackstitch(), and NnetTrainer::TrainInternalBackstitch().

2246  {
2247  if (l2_regularize_scale == 0.0)
2248  return;
2249  for (int32 c = 0; c < nnet.NumComponents(); c++) {
2250  const Component *src_component_in = nnet.GetComponent(c);
2251  if (src_component_in->Properties() & kUpdatableComponent) {
2252  const UpdatableComponent *src_component =
2253  dynamic_cast<const UpdatableComponent*>(src_component_in);
2254  UpdatableComponent *dest_component =
2255  dynamic_cast<UpdatableComponent*>(delta_nnet->GetComponent(c));
2256  // The following code will segfault if they aren't both updatable, which
2257  // would be a bug in the calling code.
2258  BaseFloat lrate = dest_component->LearningRate(),
2259  l2_regularize = dest_component->L2Regularization();
2260  KALDI_ASSERT(lrate >= 0 && l2_regularize >= 0);
2261  BaseFloat scale = -2.0 * l2_regularize_scale * lrate * l2_regularize;
2262  if (scale != 0.0)
2263  dest_component->Add(scale, *src_component);
2264  }
2265  }
2266 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ AssertGraphEqual()

bool kaldi::nnet3::AssertGraphEqual ( const std::vector< std::vector< int32 > > &  graph1,
const std::vector< std::vector< int32 > > &  graph2 
)

Definition at line 26 of file nnet-graph-test.cc.

References rnnlm::i, and rnnlm::j.

Referenced by UnitTestComputeGraphTranspose(), UnitTestFindSccs(), and UnitTestMakeSccGraph().

27  {
28  if (graph1.size() != graph2.size()) { return false; }
29  for (int32 i = 0; i < graph1.size(); ++i) {
30  if (graph1[i].size() != graph2[i].size()) { return false; }
31  for (int32 j = 0; j < graph1[i].size(); ++j) {
32  if (graph1[i][j] != graph2[i][j]) { return false; }
33  }
34  }
35  return true;
36 }
kaldi::int32 int32

◆ AssertVectorEqual()

bool kaldi::nnet3::AssertVectorEqual ( const std::vector< int32 > &  vec1,
const std::vector< int32 > &  vec2 
)

Definition at line 38 of file nnet-graph-test.cc.

References rnnlm::i.

Referenced by UnitTestComputeTopSortOrder(), and UnitTestComputeTopSortOrder2().

39  {
40  if (vec1.size() != vec2.size()) { return false; }
41  for (int32 i = 0; i < vec1.size(); ++i) {
42  if (vec1[i] != vec2[i]) { return false; }
43  }
44  return true;
45 }
kaldi::int32 int32

◆ BuildTestGraph()

void kaldi::nnet3::BuildTestGraph ( std::vector< std::vector< int32 > > *  graph)

Definition at line 47 of file nnet-graph-test.cc.

References KALDI_ASSERT.

Referenced by UnitTestComputeGraphTranspose(), UnitTestFindSccs(), and UnitTestMakeSccGraph().

47  {
48  KALDI_ASSERT(graph != NULL);
49  graph->clear();
50  graph->resize(8);
51 
52  // We create the following graph for testing.
53  // 0 --> 4
54  // 1 --> 0
55  // 2 --> 1 3
56  // 3 --> 2
57  // 4 --> 1
58  // 5 --> 1 4 6
59  // 6 --> 5
60  // 7 --> 7 3 6
61  std::vector<int32> tmp;
62  tmp.resize(1); tmp[0] = 4; (*graph)[0] = tmp;
63  tmp.resize(1); tmp[0] = 0; (*graph)[1] = tmp;
64  tmp.resize(2); tmp[0] = 1; tmp[1] = 3; (*graph)[2] = tmp;
65  tmp.resize(1); tmp[0] = 2; (*graph)[3] = tmp;
66  tmp.resize(1); tmp[0] = 1; (*graph)[4] = tmp;
67  tmp.resize(3); tmp[0] = 1; tmp[1] = 4; tmp[2] = 6; (*graph)[5] = tmp;
68  tmp.resize(1); tmp[0] = 5; (*graph)[6] = tmp;
69  tmp.resize(3); tmp[0] = 7; tmp[1] = 3; tmp[2] = 6; (*graph)[7] = tmp;
70 }
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ BuildTestGraphTranspose()

void kaldi::nnet3::BuildTestGraphTranspose ( std::vector< std::vector< int32 > > *  graph)

Definition at line 72 of file nnet-graph-test.cc.

References KALDI_ASSERT.

Referenced by UnitTestComputeGraphTranspose().

72  {
73  KALDI_ASSERT(graph != NULL);
74  graph->clear();
75  graph->resize(8);
76 
77  // We create the following graph for testing.
78  // 0 --> 1
79  // 1 --> 2 4 5
80  // 2 --> 3
81  // 3 --> 2 7
82  // 4 --> 0 5
83  // 5 --> 6
84  // 6 --> 5 7
85  // 7 --> 7
86  std::vector<int32> tmp;
87  tmp.resize(1); tmp[0] = 1; (*graph)[0] = tmp;
88  tmp.resize(3); tmp[0] = 2; tmp[1] = 4; tmp[2] = 5; (*graph)[1] = tmp;
89  tmp.resize(1); tmp[0] = 3; (*graph)[2] = tmp;
90  tmp.resize(2); tmp[0] = 2; tmp[1] = 7; (*graph)[3] = tmp;
91  tmp.resize(2); tmp[0] = 0; tmp[1] = 5; (*graph)[4] = tmp;
92  tmp.resize(1); tmp[0] = 6; (*graph)[5] = tmp;
93  tmp.resize(2); tmp[0] = 5; tmp[1] = 7; (*graph)[6] = tmp;
94  tmp.resize(1); tmp[0] = 7; (*graph)[7] = tmp;
95 }
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ BuildTestSccGraph()

void kaldi::nnet3::BuildTestSccGraph ( std::vector< std::vector< int32 > > *  scc_graph)

Definition at line 114 of file nnet-graph-test.cc.

References KALDI_ASSERT.

Referenced by UnitTestComputeTopSortOrder(), and UnitTestMakeSccGraph().

114  {
115  KALDI_ASSERT(scc_graph != NULL);
116  scc_graph->clear();
117  scc_graph->resize(4);
118 
119  // We create the following SCC graph for testing.
120  // 0 -->
121  // 1 --> 0
122  // 2 --> 0
123  // 3 --> 1 2
124  std::vector<int32> tmp;
125  tmp.resize(0); (*scc_graph)[0] = tmp;
126  tmp.resize(1); tmp[0] = 0; (*scc_graph)[1] = tmp;
127  tmp.resize(1); tmp[0] = 0; (*scc_graph)[2] = tmp;
128  tmp.resize(2); tmp[0] = 1; tmp[1] = 2; (*scc_graph)[3] = tmp;
129 }
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ BuildTestSccs()

void kaldi::nnet3::BuildTestSccs ( std::vector< std::vector< int32 > > *  sccs)

Definition at line 97 of file nnet-graph-test.cc.

References KALDI_ASSERT.

Referenced by UnitTestFindSccs(), and UnitTestMakeSccGraph().

97  {
98  KALDI_ASSERT(sccs != NULL);
99  sccs->clear();
100  sccs->resize(4);
101 
102  // We create the following SCCs for testing.
103  // 0 --> 1 4 0
104  // 1 --> 3 2
105  // 2 --> 6 5
106  // 3 --> 7
107  std::vector<int32> tmp;
108  tmp.resize(3); tmp[0] = 1; tmp[1] = 4; tmp[2] = 0; (*sccs)[0] = tmp;
109  tmp.resize(2); tmp[0] = 3; tmp[1] = 2; (*sccs)[1] = tmp;
110  tmp.resize(2); tmp[0] = 6; tmp[1] = 5; (*sccs)[2] = tmp;
111  tmp.resize(1); tmp[0] = 7; (*sccs)[3] = tmp;
112 }
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ BuildTestTopSortOrder()

void kaldi::nnet3::BuildTestTopSortOrder ( std::vector< int32 > *  node_to_order)

Definition at line 131 of file nnet-graph-test.cc.

References KALDI_ASSERT.

Referenced by UnitTestComputeTopSortOrder().

131  {
132  KALDI_ASSERT(node_to_order != NULL);
133  node_to_order->clear();
134  node_to_order->resize(4);
135 
136  // The topological sorting order of the above SCC graph is as follows (from
137  // our particular algorithm):
138  // 0 --> 3
139  // 1 --> 2
140  // 2 --> 1
141  // 3 --> 0
142  (*node_to_order)[0] = 3;
143  (*node_to_order)[1] = 2;
144  (*node_to_order)[2] = 1;
145  (*node_to_order)[3] = 0;
146 }
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ CheckComputation()

void CheckComputation ( const Nnet nnet,
const NnetComputation computation,
bool  check_rewrite = false 
)

This is a convenience interface for class ComputationChecker.

Call it with check_rewrite = true only if the computation is pre-optimization. If the computation is an 'online' computation, this function treats it specially.

Definition at line 1145 of file nnet-analyze.cc.

References ComputationChecker::Check(), CheckComputationOptions::check_rewrite, CheckComputationOnline(), NnetComputation::commands, KALDI_ERR, kGotoLabel, and NnetComputation::Print().

Referenced by CachingOptimizingCompiler::CompileViaShortcut(), and Optimize().

1147  {
1148  try {
1149  if (!computation.commands.empty() &&
1150  computation.commands.back().command_type == kGotoLabel) {
1151  // Online computations need to be treated specially.
1152  CheckComputationOnline(nnet, computation, check_rewrite);
1153  } else {
1154  CheckComputationOptions opts;
1155  opts.check_rewrite = check_rewrite;
1156  ComputationChecker checker(opts, nnet, computation);
1157  checker.Check();
1158  }
1159  } catch (...) {
1160  computation.Print(std::cerr, nnet);
1161  KALDI_ERR << "Computation check failed for computation printed above "
1162  "(actual error message is above computation)";
1163  }
1164 }
#define KALDI_ERR
Definition: kaldi-error.h:147
static void CheckComputationOnline(const Nnet &nnet, NnetComputation computation, bool check_rewrite)

◆ CheckComputationOnline()

static void kaldi::nnet3::CheckComputationOnline ( const Nnet nnet,
NnetComputation  computation,
bool  check_rewrite 
)
static

Definition at line 1118 of file nnet-analyze.cc.

References ComputationChecker::Check(), CheckComputationOptions::check_rewrite, CheckComputationOptions::check_unused_variables, NnetComputation::commands, KALDI_ASSERT, kDeallocMatrix, kGotoLabel, kSwapMatrix, and kaldi::swap().

Referenced by CheckComputation().

1120  {
1121  int32 num_commands = computation.commands.size();
1122  KALDI_ASSERT(computation.commands[num_commands-1].command_type == kGotoLabel);
1123  for (int32 c = num_commands - 2;
1124  c >= 0 && computation.commands[c].command_type == kSwapMatrix;
1125  c--) {
1126  // this command can be interpreted as "initialize matrix referred to by
1127  // c.arg2 with the matrix referred to by c.arg2".
1128  // Because this would be interpreted by the analysis code as initializing a
1129  // matrix that has already been initialized, we turn this into a command
1130  // that just deallocates the matrix in c.arg2. [note: all these indexes
1131  // are actually submatrix indexes].
1132  computation.commands[c].command_type = kDeallocMatrix;
1133  std::swap(computation.commands[c].arg1, computation.commands[c].arg2);
1134  }
1135 
1136  CheckComputationOptions opts;
1137  opts.check_rewrite = check_rewrite;
1138  opts.check_unused_variables = false;
1139  // We can always do this check with online computations, since they do not
1140  // have the RemoveUnnecessaryAllocation() optimization applied.
1141  ComputationChecker checker(opts, nnet, computation);
1142  checker.Check();
1143 }
void swap(basic_filebuf< CharT, Traits > &x, basic_filebuf< CharT, Traits > &y)
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ CheckStringsApproxEqual()

bool kaldi::nnet3::CheckStringsApproxEqual ( const std::string &  a,
const std::string &  b,
int32  tolerance = 3 
)

Definition at line 39 of file nnet-component-test.cc.

References KALDI_WARN, and kaldi::StringsApproxEqual().

Referenced by TestNnetComponentAddScale(), TestNnetComponentIo(), TestNnetComponentUpdatable(), and TestNnetComponentVectorizeUnVectorize().

41  {
42  if (!StringsApproxEqual(a, b, tolerance)) {
43  KALDI_WARN << "Strings differ: " << a
44  << "\nvs.\n" << b;
45  return false;
46  } else {
47  return true;
48  }
49 }
bool StringsApproxEqual(const std::string &a, const std::string &b, int32 decimal_places_tolerance)
This function returns true when two text strings are approximately equal, and false when they are not...
Definition: text-utils.cc:335
#define KALDI_WARN
Definition: kaldi-error.h:150

◆ CollapseModel()

void CollapseModel ( const CollapseModelConfig config,
Nnet nnet 
)

This function modifies the neural net for efficiency, in a way that suitable to be done in test time.

For example, it tries to get rid of dropout, batchnorm and fixed-scale components, and to collapse subsequent affine components if doing so won't hurt speed.

Definition at line 2100 of file nnet-utils.cc.

References ModelCollapser::Collapse().

Referenced by CollapseModelConfig::CollapseModelConfig(), main(), and UnitTestNnetCompute().

2101  {
2102  ModelCollapser c(config, nnet);
2103  c.Collapse();
2104 }

◆ CompileLooped()

void CompileLooped ( const Nnet nnet,
const NnetOptimizeOptions optimize_opts,
const ComputationRequest request1,
const ComputationRequest request2,
const ComputationRequest request3,
NnetComputation computation 
)

CompileLooped() provides an internal interface for 'looped' computation.

It's usable for inference only (not training), meaning that backprop is not supported (for now, at least). CompileLooped() allows you to do the neural net computation for small chunks with increasing 't' values, and naturally cache the intermediate activations (rather than recomputing them every time you see new input data).

This function does both compilation and optimization, so it's like a combination of Compiler::CreateComputation() [nnet-compile.h] and Optimize() [nnet-optimize.h].

You provide 3 computation requests. request1 is the first computation request of an utterance (or other type of segment) that contains any required extra left context in the input. request2 and request3 are the second and third computation request, and must have exactly the same structure, except for a fixed time offset (change in 't' index) between them. This will be extrapolated to an infinite sequence of further requests (request4, request5, etc.). In practice the way it's done is that we extrapolate to a small finite number of requests (like 10), and then attempt to identify a common structure in the computation where, after processing, as an example, the 3nd computation request, the active variables can be identified with those present at, say, the 7th computation request, and we then cut and splice the computation together at this points, like making a tape loop, by adding a goto statement that jumps from the end of the 7th computation request to the end of the 3rd computation request. We also have to identify the variables with each other (merge variables).

That's done in the optimization code.

Definition at line 329 of file nnet-compile-looped.cc.

References CompileLoopedInternal(), Timer::Elapsed(), KALDI_ERR, KALDI_LOG, and KALDI_VLOG.

Referenced by DecodableNnetSimpleLoopedInfo::Init(), and UnitTestNnetCompileLooped().

334  {
335  int32 num_requests1 = 5, factor = 2, max_requests = 100,
336  num_requests;
337 
338  Timer timer;
339 
340  for (num_requests = num_requests1; num_requests <= max_requests;
341  num_requests *= factor) {
342  if (CompileLoopedInternal(nnet, optimize_opts,
343  request1, request2, request3,
344  num_requests, computation)) {
345  KALDI_LOG << "Spent " << timer.Elapsed()
346  << " seconds in looped compilation.";
347  return;
348  } else {
349  KALDI_VLOG(2) << "Looped compilation failed with "
350  << num_requests << " requests, trying "
351  << (num_requests * factor);
352  }
353  }
354  KALDI_ERR << "Looped compilation failed with "
355  << (num_requests/factor) << " requests, which "
356  << "we expect should be enough... something "
357  << "went wrong.";
358 }
kaldi::int32 int32
static bool CompileLoopedInternal(const Nnet &nnet, NnetOptimizeOptions optimize_opts, const ComputationRequest &request1, const ComputationRequest &request2, const ComputationRequest &request3, int32 num_requests, NnetComputation *computation)
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ CompileLoopedInternal()

static bool kaldi::nnet3::CompileLoopedInternal ( const Nnet nnet,
NnetOptimizeOptions  optimize_opts,
const ComputationRequest request1,
const ComputationRequest request2,
const ComputationRequest request3,
int32  num_requests,
NnetComputation computation 
)
static

Definition at line 284 of file nnet-compile-looped.cc.

References NnetComputation::commands, Compiler::CreateComputation(), ExtrapolateComputationRequest(), rnnlm::i, KALDI_ASSERT, KALDI_ERR, KALDI_LOG, kGotoLabel, MaxOutputTimeInRequest(), Optimize(), NnetOptimizeOptions::optimize_looped_computation, and ComputationRequest::Print().

Referenced by CompileLooped().

291  {
292 
293  KALDI_ASSERT(num_requests >= 3);
294  std::vector<ComputationRequest> extra_requests(num_requests - 3);
295  const ComputationRequest *prev_request = &request2;
296  const ComputationRequest *cur_request = &request3;
297  for (int32 i = 0; i < num_requests - 3; i++) {
298  if (!ExtrapolateComputationRequest(*prev_request, *cur_request,
299  &(extra_requests[i]))) {
300  KALDI_LOG << "prev_request is:";
301  prev_request->Print(std::cerr);
302  KALDI_LOG << "cur_request is:";
303  cur_request->Print(std::cerr);
304  KALDI_ERR << "Computation requests do not have the right relationship";
305  }
306  prev_request = cur_request;
307  cur_request = &(extra_requests[i]);
308  }
309 
310  std::vector<const ComputationRequest*> requests;
311  requests.push_back(&request1);
312  requests.push_back(&request2);
313  requests.push_back(&request3);
314  for (int32 i = 0; i < num_requests - 3; i++)
315  requests.push_back(&(extra_requests[i]));
316  Compiler compiler(requests, nnet);
317  CompilerOptions compiler_opts;
318  compiler.CreateComputation(compiler_opts, computation);
319  optimize_opts.optimize_looped_computation = true;
320 
321  int32 dont_really_care = MaxOutputTimeInRequest(request3);
322  Optimize(optimize_opts, nnet,
323  dont_really_care, computation);
324 
325  return computation->commands.size() != 0 &&
326  computation->commands.back().command_type == kGotoLabel;
327 }
static bool ExtrapolateComputationRequest(const ComputationRequest &request1, const ComputationRequest &request2, ComputationRequest *request3)
kaldi::int32 int32
int32 MaxOutputTimeInRequest(const ComputationRequest &request)
#define KALDI_ERR
Definition: kaldi-error.h:147
void Optimize(const NnetOptimizeOptions &config, const Nnet &nnet, int32 max_output_time_in_request, NnetComputation *computation)
This is the top-level function for optimizing a computation.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ ComponentDotProducts()

void ComponentDotProducts ( const Nnet nnet1,
const Nnet nnet2,
VectorBase< BaseFloat > *  dot_prod 
)

Returns dot products between two networks of the same structure (calls the DotProduct functions of the Updatable components and fill in the output vector).

Definition at line 211 of file nnet-utils.cc.

References VectorBase< Real >::Data(), VectorBase< Real >::Dim(), UpdatableComponent::DotProduct(), Nnet::GetComponent(), KALDI_ASSERT, kUpdatableComponent, Nnet::NumComponents(), and Component::Properties().

Referenced by main().

213  {
214  KALDI_ASSERT(nnet1.NumComponents() == nnet2.NumComponents());
215  int32 updatable_c = 0;
216  for (int32 c = 0; c < nnet1.NumComponents(); c++) {
217  const Component *comp1 = nnet1.GetComponent(c),
218  *comp2 = nnet2.GetComponent(c);
219  if (comp1->Properties() & kUpdatableComponent) {
220  const UpdatableComponent
221  *u_comp1 = dynamic_cast<const UpdatableComponent*>(comp1),
222  *u_comp2 = dynamic_cast<const UpdatableComponent*>(comp2);
223  KALDI_ASSERT(u_comp1 != NULL && u_comp2 != NULL);
224  dot_prod->Data()[updatable_c] = u_comp1->DotProduct(*u_comp2);
225  updatable_c++;
226  }
227  }
228  KALDI_ASSERT(updatable_c == dot_prod->Dim());
229 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeAccuracy()

void ComputeAccuracy ( const GeneralMatrix supervision,
const CuMatrixBase< BaseFloat > &  nnet_output,
BaseFloat tot_weight,
BaseFloat tot_accuracy,
VectorBase< BaseFloat > *  tot_weight_vec = NULL,
VectorBase< BaseFloat > *  tot_accuracy_vec = NULL 
)

This function computes the frame accuracy for this minibatch.

It interprets the supervision information in "supervision" as labels or soft labels; it picks the maximum element in each row and treats that as the label for purposes of computing the accuracy (in situations where you would care about the accuracy, there will normally be just one nonzero label). The hypothesized labels are computed by taking the neural net output (supplied as a CuMatrix), and finding the maximum element in each row. See also the function ComputeObjectiveFunction, declared in nnet-training.h.

Parameters
[in]supervisionThe supervision information (no elements may be negative); only the maximum in each row matters (although we expect that usually there will be just one nonzero element in each row); and the sum of each row is interpreted as a weighting factor (although we expect that this sum will usually be one).
[in]nnet_outputThe neural net output must have the same dimensions as the supervision. Only the index of the maximum value in each row matters. Ties will be broken in an unspecified way.
[out]tot_weightThe sum of the values in the supervision matrix
[out]tot_accuracyThe total accuracy, equal to the sum over all row indexes r such that the maximum column index of row r of supervision and nnet_output is the same, of the sum of the r'th row of supervision (i.e. the row's weight).
[out]tot_weight_vecIf non-NULL, we write to this location the counts per-class in the supervision matrix. This is expected to have the same dimension as the corresponding output in the network.
[out]tot_accuracy_vecIf non-NULL, we write to this location the accuracy per-class. For index j, the value is equal to the sum over all row indexes r such that the maximum column index of row r of supervision is j and nnet_output is also j, of the sum of the r'th row of supervision (i.e. the row's weight)

Definition at line 206 of file nnet-diagnostics.cc.

References CuArrayBase< T >::CopyToVec(), VectorBase< Real >::Dim(), CuMatrixBase< Real >::FindRowMaxId(), GeneralMatrix::GetFullMatrix(), GeneralMatrix::GetMatrix(), GeneralMatrix::GetSparseMatrix(), KALDI_ASSERT, KALDI_ERR, kaldi::kCompressedMatrix, kaldi::kFullMatrix, kaldi::kSparseMatrix, SparseVector< Real >::Max(), VectorBase< Real >::Max(), CuMatrixBase< Real >::NumCols(), GeneralMatrix::NumCols(), CuMatrixBase< Real >::NumRows(), GeneralMatrix::NumRows(), SparseMatrix< Real >::Row(), VectorBase< Real >::Set(), SparseVector< Real >::Sum(), VectorBase< Real >::Sum(), and GeneralMatrix::Type().

Referenced by NnetComputeProb::ProcessOutputs().

211  {
212  int32 num_rows = nnet_output.NumRows(),
213  num_cols = nnet_output.NumCols();
214  KALDI_ASSERT(supervision.NumRows() == num_rows &&
215  supervision.NumCols() == num_cols);
216 
217  if (tot_accuracy_vec || tot_weight_vec)
218  KALDI_ASSERT(tot_accuracy_vec && tot_weight_vec &&
219  tot_accuracy_vec->Dim() == num_cols &&
220  tot_weight_vec->Dim() == num_cols);
221  if (tot_accuracy_vec) tot_accuracy_vec->Set(0.0);
222  if (tot_weight_vec) tot_weight_vec->Set(0.0);
223 
224  CuArray<int32> best_index(num_rows);
225  nnet_output.FindRowMaxId(&best_index);
226  std::vector<int32> best_index_cpu;
227  // wasteful copy, but doesn't dominate.
228  best_index.CopyToVec(&best_index_cpu);
229 
230 
231  double tot_weight = 0.0,
232  tot_accuracy = 0.0;
233 
234  // note: we expect that in most cases where this code is called,
235  // supervision.Type() will be kSparseMatrix.
236  switch (supervision.Type()) {
237  case kCompressedMatrix: {
238  Matrix<BaseFloat> mat;
239  supervision.GetMatrix(&mat);
240  for (int32 r = 0; r < num_rows; r++) {
241  SubVector<BaseFloat> vec(mat, r);
242  BaseFloat row_sum = vec.Sum();
243  int32 best_index;
244  vec.Max(&best_index); // discard max value.
245  tot_weight += row_sum;
246  if (tot_weight_vec)
247  (*tot_weight_vec)(best_index) += row_sum;
248  if (best_index == best_index_cpu[r]) {
249  tot_accuracy += row_sum;
250  if (tot_accuracy_vec)
251  (*tot_accuracy_vec)(best_index) += row_sum;
252  }
253  }
254  break;
255  }
256  case kFullMatrix: {
257  const Matrix<BaseFloat> &mat = supervision.GetFullMatrix();
258  for (int32 r = 0; r < num_rows; r++) {
259  SubVector<BaseFloat> vec(mat, r);
260  BaseFloat row_sum = vec.Sum();
261  int32 best_index;
262  vec.Max(&best_index); // discard max value.
263  tot_weight += row_sum;
264  if (tot_weight_vec)
265  (*tot_weight_vec)(best_index) += row_sum;
266  if (best_index == best_index_cpu[r]) {
267  tot_accuracy += row_sum;
268  if (tot_accuracy_vec)
269  (*tot_accuracy_vec)(best_index) += row_sum;
270  }
271  }
272  break;
273  }
274  case kSparseMatrix: {
275  const SparseMatrix<BaseFloat> &smat = supervision.GetSparseMatrix();
276  for (int32 r = 0; r < num_rows; r++) {
277  const SparseVector<BaseFloat> &row = smat.Row(r);
278  BaseFloat row_sum = row.Sum();
279  int32 best_index;
280  row.Max(&best_index);
281  KALDI_ASSERT(best_index < num_cols);
282  tot_weight += row_sum;
283  if (tot_weight_vec)
284  (*tot_weight_vec)(best_index) += row_sum;
285  if (best_index == best_index_cpu[r]) {
286  tot_accuracy += row_sum;
287  if (tot_accuracy_vec)
288  (*tot_accuracy_vec)(best_index) += row_sum;
289  }
290  }
291  break;
292  }
293  default: KALDI_ERR << "Bad general-matrix type.";
294  }
295  *tot_weight_out = tot_weight;
296  *tot_accuracy_out = tot_accuracy;
297 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeCommandAttributes()

void ComputeCommandAttributes ( const Nnet nnet,
const NnetComputation computation,
const ComputationVariables vars,
std::vector< CommandAttributes > *  attributes 
)

Definition at line 284 of file nnet-analyze.cc.

References NnetComputation::Command::arg1, NnetComputation::Command::arg2, NnetComputation::Command::arg3, NnetComputation::Command::arg4, NnetComputation::Command::arg5, NnetComputation::Command::arg6, NnetComputation::Command::command_type, NnetComputation::commands, count, Nnet::GetComponent(), CommandAttributes::has_side_effects, rnnlm::i, NnetComputation::indexes, NnetComputation::indexes_multi, IndexesMultiToSubmatrixIndexes(), kAcceptInput, kAddRowRanges, kAddRows, kAddRowsMulti, kAddToRowsMulti, KALDI_ERR, kAllocMatrix, kBackprop, kBackpropAdds, kBackpropNoModelUpdate, kCompressMatrix, kCopyRows, kCopyRowsMulti, kCopyToRowsMulti, kDeallocMatrix, kDecompressMatrix, kGotoLabel, kMatrixAdd, kMatrixCopy, kNoOperation, kNoOperationLabel, kNoOperationMarker, kNoOperationPermanent, kPropagate, kPropagateAdds, kProvideOutput, kReadAccess, kReadWriteAccess, kSetConst, kSwapMatrix, kUpdatableComponent, kWriteAccess, CommandAttributes::matrices_read, CommandAttributes::matrices_written, Component::Properties(), ComputationVariables::RecordAccessForSubmatrix(), kaldi::SortAndUniq(), CommandAttributes::submatrices_read, CommandAttributes::submatrices_written, CommandAttributes::variables_read, and CommandAttributes::variables_written.

Referenced by NnetComputer::Init(), Analyzer::Init(), and MoveSizingCommands().

288  {
289  int32 num_commands = computation.commands.size();
290  attributes->clear();
291  attributes->resize(num_commands);
292  for (int32 command_index = 0; command_index < num_commands; command_index++) {
293  const NnetComputation::Command &c = computation.commands[command_index];
294  CommandAttributes &attr = (*attributes)[command_index];
295  switch (c.command_type) {
296  case kAllocMatrix:
297  case kDeallocMatrix:
298  case kSwapMatrix:
299  break; // the commands above leave the matrix undefined.
300  case kSetConst:
301  vars.RecordAccessForSubmatrix(c.arg1, kWriteAccess, &attr);
302  break;
303  case kPropagate:
304  vars.RecordAccessForSubmatrix(c.arg3, kReadAccess, &attr);
305  if (nnet.GetComponent(c.arg1)->Properties() & kPropagateAdds)
306  vars.RecordAccessForSubmatrix(c.arg4, kReadWriteAccess, &attr);
307  else
308  vars.RecordAccessForSubmatrix(c.arg4, kWriteAccess, &attr);
309  break;
310  case kBackprop:
312  vars.RecordAccessForSubmatrix(c.arg3, kReadAccess, &attr);
313  vars.RecordAccessForSubmatrix(c.arg4, kReadAccess, &attr);
314  vars.RecordAccessForSubmatrix(c.arg5, kReadAccess, &attr);
315  if (nnet.GetComponent(c.arg1)->Properties() & kBackpropAdds)
316  vars.RecordAccessForSubmatrix(c.arg6, kReadWriteAccess, &attr);
317  else
318  vars.RecordAccessForSubmatrix(c.arg6, kWriteAccess, &attr);
319  if (c.command_type == kBackprop &&
320  nnet.GetComponent(c.arg1)->Properties() & kUpdatableComponent)
321  attr.has_side_effects = true;
322  break;
323  case kMatrixCopy:
324  vars.RecordAccessForSubmatrix(c.arg1, kWriteAccess, &attr);
325  vars.RecordAccessForSubmatrix(c.arg2, kReadAccess, &attr);
326  break;
327  case kMatrixAdd:
328  vars.RecordAccessForSubmatrix(c.arg1, kReadWriteAccess, &attr);
329  vars.RecordAccessForSubmatrix(c.arg2, kReadAccess, &attr);
330  break;
331  case kAddRows:
332  vars.RecordAccessForSubmatrix(c.arg1, kReadWriteAccess, &attr);
333  vars.RecordAccessForSubmatrix(c.arg2, kReadAccess, &attr);
334  break;
335  case kCopyRows: {
336  const std::vector<int32> &indexes = computation.indexes[c.arg3];
337  // if there are -1's in "indexes", then the result of the operation
338  // will depend on the initial value of the matrix, so it's
339  // a "rw" operation, not a "write" operation.
340  if (std::count(indexes.begin(), indexes.end(), -1) > 0)
341  vars.RecordAccessForSubmatrix(c.arg1, kReadWriteAccess, &attr);
342  else
343  vars.RecordAccessForSubmatrix(c.arg1, kWriteAccess, &attr);
344  vars.RecordAccessForSubmatrix(c.arg2, kReadAccess, &attr);
345  break;
346  }
347  case kAddRowsMulti: {
348  vars.RecordAccessForSubmatrix(c.arg1, kReadWriteAccess, &attr);
349  std::vector<int32> submatrix_indexes;
350  IndexesMultiToSubmatrixIndexes(computation.indexes_multi[c.arg2],
351  &submatrix_indexes);
352  for (size_t i = 0; i < submatrix_indexes.size(); i++)
353  vars.RecordAccessForSubmatrix(submatrix_indexes[i],
354  kReadAccess, &attr);
355  break;
356  }
357  case kCopyRowsMulti: {
358  std::vector<int32> submatrix_indexes;
359  IndexesMultiToSubmatrixIndexes(computation.indexes_multi[c.arg2],
360  &submatrix_indexes);
361  // note: the CopyRows command assigns zero in cases where
362  // there is no source for some row
363  vars.RecordAccessForSubmatrix(c.arg1, kWriteAccess, &attr);
364  for (size_t i = 0; i < submatrix_indexes.size(); i++)
365  vars.RecordAccessForSubmatrix(submatrix_indexes[i],
366  kReadAccess, &attr);
367  break;
368  }
369  case kAddToRowsMulti:
370  case kCopyToRowsMulti: {
371  vars.RecordAccessForSubmatrix(c.arg1, kReadAccess, &attr);
372  // if the submatrixes we're writing to (in kCopyToRowsMulti) had all
373  // rows covered, it would be a pure write operation.
374  std::vector<int32> submatrix_indexes;
375  IndexesMultiToSubmatrixIndexes(computation.indexes_multi[c.arg2],
376  &submatrix_indexes);
377  for (size_t i = 0; i < submatrix_indexes.size(); i++)
378  vars.RecordAccessForSubmatrix(submatrix_indexes[i], kReadWriteAccess,
379  &attr);
380  break;
381  }
382  case kAddRowRanges: {
383  vars.RecordAccessForSubmatrix(c.arg1, kReadWriteAccess, &attr);
384  vars.RecordAccessForSubmatrix(c.arg2, kReadAccess, &attr);
385  break;
386  }
387  case kCompressMatrix: {
388  vars.RecordAccessForSubmatrix(c.arg1, kReadWriteAccess, &attr);
389  break;
390  }
391  case kDecompressMatrix: {
392  vars.RecordAccessForSubmatrix(c.arg1, kWriteAccess, &attr);
393  break;
394  }
395  case kAcceptInput: {
396  vars.RecordAccessForSubmatrix(c.arg1, kWriteAccess, &attr);
397  break;
398  }
399  case kProvideOutput: {
400  vars.RecordAccessForSubmatrix(c.arg1, kReadAccess, &attr);
401  break;
402  }
403  case kNoOperation:
405  case kNoOperationMarker:
406  case kNoOperationLabel:
407  case kGotoLabel:
408  break;
409  default:
410  KALDI_ERR << "Unknown command type.";
411  }
412  SortAndUniq(&attr.variables_read);
413  SortAndUniq(&attr.variables_written);
414  SortAndUniq(&attr.submatrices_read);
415  SortAndUniq(&attr.submatrices_written);
416  SortAndUniq(&attr.matrices_read);
417  SortAndUniq(&attr.matrices_written);
418  }
419 }
kaldi::int32 int32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
static void IndexesMultiToSubmatrixIndexes(const std::vector< std::pair< int32, int32 > > &indexes_multi, std::vector< int32 > *submatrix_indexes)
given a vector of pairs from computation.indexes_multi_indexes containing paris (submatrix-index, row-index), this function outputs to "submatrix_indexes" all (unique) submatrix indexes that appear; and it outputs to "contains_null_marker" true if the pair (-1, -1) appears anywhere in indexes_multi, and false otherwise.
const size_t count
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ ComputeCommandPairs()

static void kaldi::nnet3::ComputeCommandPairs ( const std::pair< std::vector< int32 >, std::vector< int32 > > &  lists,
std::vector< std::pair< int32, int32 > > *  pairs 
)
static

Definition at line 328 of file nnet-optimize.cc.

References kaldi::CopyVectorToSet(), rnnlm::d, and KALDI_PARANOID_ASSERT.

Referenced by RemoveUnnecessaryAllocation().

330  {
331  std::vector<int32> d_list = lists.first;
332 
333  std::set<int32> a_set;
334  CopyVectorToSet(lists.second, &a_set);
335 
336  std::vector<int32>::reverse_iterator iter = d_list.rbegin(),
337  end = d_list.rend();
338 
339  // from the latest to the earliest deallocation command...
340  for (; iter != end; ++iter) {
341  int32 d = *iter;
342  std::set<int32>::iterator a_iter = a_set.upper_bound(d);
343  // a_iter is an iterator to the first element a of the set 'a_set' such
344  // that a > d, or a_set.end() if no such element exists.
345  if (a_iter == a_set.end())
346  continue; // we will output no pair for this d.
347  int32 a = *a_iter;
348  KALDI_PARANOID_ASSERT(a > d); // or code error
349  a_set.erase(a_iter); // remove this a from 'a_set' so it doesn't get used
350  // twice
351  pairs->push_back(std::pair<int32,int32>(d, a));
352  }
353 }
kaldi::int32 int32
void CopyVectorToSet(const std::vector< A > &v, std::set< A > *s)
Copies the contents of a vector to a set.
Definition: stl-utils.h:172
#define KALDI_PARANOID_ASSERT(cond)
Definition: kaldi-error.h:206

◆ ComputeComputationGraph()

void kaldi::nnet3::ComputeComputationGraph ( const Nnet nnet,
const ComputationRequest request,
ComputationGraph graph 
)

Definition at line 1152 of file nnet-computation-graph.cc.

References kaldi::nnet3::computation_graph::AddInputToGraph(), kaldi::nnet3::computation_graph::AddOutputToGraph(), ComputationGraph::cindexes, NetworkNode::component_index, ComputationGraph::dependencies, NetworkNode::descriptor, ComputationGraph::GetCindexId(), Nnet::GetComponent(), Descriptor::GetDependencies(), Component::GetInputIndexes(), Nnet::GetNode(), rnnlm::i, ComputationGraph::is_input, KALDI_ASSERT, KALDI_ERR, kComponent, kDescriptor, kDimRange, kInput, ComputationRequest::misc_info, rnnlm::n, NetworkNode::node_index, NetworkNode::node_type, kaldi::SortAndUniq(), and NetworkNode::u.

1154  {
1155  using namespace computation_graph;
1156  // make sure graph is empty at the start.
1157  KALDI_ASSERT(graph->cindexes.empty());
1158 
1159  AddInputToGraph(request, nnet, graph);
1160  AddOutputToGraph(request, nnet, graph);
1161 
1162  // queue of cindex_ids to process.
1163  std::vector<int32> queue(graph->cindexes.size());
1164  for (int32 i = 0; i < graph->cindexes.size(); i++)
1165  queue.push_back(i);
1166 
1167  while (!queue.empty()) {
1168  int32 cindex_id = queue.back();
1169  queue.pop_back();
1170  if (static_cast<int32>(graph->dependencies.size()) <= cindex_id)
1171  graph->dependencies.resize(cindex_id + 1);
1172 
1173  if (graph->is_input[cindex_id])
1174  continue;
1175  Cindex cindex = graph->cindexes[cindex_id];
1176 
1177  // find the dependencies of this cindex.
1178  int32 n = cindex.first;
1179  const Index &index = cindex.second;
1180  const NetworkNode &node = nnet.GetNode(n);
1181 
1182  std::vector<Cindex> input_cindexes;
1183 
1184  // the following switch statement sets up "input_cindexes".
1185  switch (node.node_type) {
1186  case kDescriptor: {
1187  // desc describes how this node obtains its input from other nodes.
1188  const Descriptor &desc = node.descriptor;
1189  desc.GetDependencies(index, &input_cindexes);
1190  break;
1191  }
1192  case kComponent: {
1193  int32 c = node.u.component_index;
1194  const Component *component = nnet.GetComponent(c);
1195  std::vector<Index> input_indexes;
1196  component->GetInputIndexes(request.misc_info, index,
1197  &input_indexes);
1198  // each Component node should be preceded by a node that describes its
1199  // input, of type kDescriptor
1200  KALDI_ASSERT(nnet.GetNode(n-1).node_type ==
1201  kDescriptor);
1202 
1203  input_cindexes.resize(input_indexes.size());
1204  for (size_t i = 0; i < input_indexes.size(); i++) {
1205  input_cindexes[i].first = n - 1; // preceding node.
1206  input_cindexes[i].second = input_indexes[i];
1207  }
1208  break;
1209  }
1210  case kDimRange: {
1211  input_cindexes.resize(1);
1212  input_cindexes[0] = Cindex(node.u.node_index, index);
1213  break;
1214  }
1215  case kInput: default:
1216  // for kInput, you should have hit the "continue" statement above.
1217  KALDI_ERR << "Invalid node type";
1218  }
1219  std::vector<int32> &this_dep = graph->dependencies[cindex_id];
1220 
1221  int32 num_dependencies = input_cindexes.size();
1222  this_dep.resize(num_dependencies);
1223  for (size_t i = 0; i < num_dependencies; i++) {
1224  bool is_input = false, is_new;
1225  int32 dep_cindex_id = graph->GetCindexId(input_cindexes[i],
1226  is_input, &is_new);
1227  this_dep[i] = dep_cindex_id;
1228  if (is_new)
1229  queue.push_back(dep_cindex_id);
1230  }
1231 
1232  // remove duplicates of dependencies.
1233  SortAndUniq(&this_dep);
1234  }
1235 }
kaldi::int32 int32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
void AddInputToGraph(const ComputationRequest &request, const Nnet &nnet, ComputationGraph *graph)
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115
void AddOutputToGraph(const ComputationRequest &request, const Nnet &nnet, ComputationGraph *graph)
struct rnnlm::@11::@12 n
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeComputationPhases()

void ComputeComputationPhases ( const Nnet nnet,
const ComputationGraph computation_graph,
std::vector< std::vector< std::vector< int32 > > > *  phases_per_segment 
)

This function divides a computation into 'phases', where a 'phase' is a collection of cindexes which can (as far as the computation graph is concerned) all be computed at the same time, and depend only on cindexes previously computed in earlier phases.

So the phases are an ordering of the Cindexes in the computation, but an ordering that depends on graph-theoretic considerations only, and not practical concerns like whether the cindexes belong to the same node [for that, see the notion of steps].

Parameters
[in]nnetThe neural network this computation is for
[in]graphThe computation graph that we're computing phases for.
[out]phases_per_segmentThe phases, listed separately for each segment of the computation [there will be just one segment in the normal case, more in the online-recognition case]. Consider just one segment for now. Suppose the computation can be completed in 20 phases, then (*phases)[0].size() will be 20 at exit, and (*phases)[0][0] will be a sorted list of cindex_ids. that belong to the first phase, and so on. (Remember, a cindex_id is an index into graph->cindexes; it compactly identifies a cindex.) The sets represented by the int32's in 'phases_per_segment' will be disjoint and will cover all elements in [0 .. computation.cindexes.size() - 1].

Note: we assume you have called PruneComputationGraph() before this function. Even so, this function will be crash if the computation cannot actually be computed– there are some mal-formed computations where you can build the computation graph but not the ordering of cindexes because there are dependencies forward and backward in time that intertwine.

Definition at line 1406 of file nnet-computation-graph.cc.

References ComputationGraph::cindexes, ComputeComputationPhasesForEpoch(), kaldi::nnet3::computation_graph::ComputeDependenciesSubset(), kaldi::nnet3::computation_graph::ComputeEpochInfo(), ComputeGraphTranspose(), KALDI_ASSERT, ComputationGraph::segment_ends, and SumVectorSizes().

Referenced by Compiler::CreateComputation().

1409  {
1410  using namespace computation_graph;
1411  int32 num_cindex_ids = graph.cindexes.size();
1412 
1413  std::vector<int32> cindex_id_to_segment_and_epoch;
1414  std::vector<std::vector<std::vector<int32 > > > epochs_per_segment;
1415  std::vector<bool> epoch_is_trivial;
1416  ComputeEpochInfo(nnet, graph, &cindex_id_to_segment_and_epoch,
1417  &epochs_per_segment, &epoch_is_trivial);
1418 
1419  KALDI_ASSERT(SumVectorSizes(epochs_per_segment) == num_cindex_ids);
1420 
1421  // dependencies_subset contains just the subset of dependencies
1422  // of each cindex_id, that have the same epoch index as
1423  // cindex_id itself. This will be used to correctly order
1424  // cindexes within a certain epoch (relevant for things like
1425  // LSTMs).
1426  std::vector<std::vector<int32> > dependencies_subset;
1427  ComputeDependenciesSubset(graph, cindex_id_to_segment_and_epoch,
1428  &dependencies_subset);
1429  // destroy cindex_id_to_segment_and_epoch, it's no longer needed.
1430  { std::vector<int32> temp; temp.swap(cindex_id_to_segment_and_epoch); }
1431 
1432  // depend_on_subset is a subset of the normal "depend_on" list (i.e. a list of
1433  // all cindex_ids that depend on the current cindex_id), limited to just those
1434  // cindex_ids that have the same epoch index.
1435  std::vector<std::vector<int32> > depend_on_subset;
1436  ComputeGraphTranspose(dependencies_subset, &depend_on_subset);
1437 
1438  int32 num_epoch_indexes = epoch_is_trivial.size(),
1439  num_segments = graph.segment_ends.size();
1440 
1441  // "phase_indexes" is used inside ComputeComputationPhasesForEpoch.
1442  std::vector<int32> phase_indexes(num_cindex_ids, -1);
1443 
1444  phases_per_segment->clear();
1445  phases_per_segment->resize(num_segments);
1446 
1447  for (int32 segment = 0; segment < num_segments; segment++) {
1448  phases_per_segment->reserve(50); // minimize unnecessary copies. 50 is
1449  // very arbitrarily chosen.
1450  for (int32 epoch = 0; epoch < num_epoch_indexes; epoch++)
1452  epochs_per_segment[segment][epoch],
1453  dependencies_subset,
1454  depend_on_subset,
1455  epoch_is_trivial[epoch],
1456  &phase_indexes,
1457  &((*phases_per_segment)[segment]));
1458  }
1459 
1460 
1461  // make sure everything was computable. If the next assert fails it's likely
1462  // a bug in this function or in PruneComputataionGraph.
1463  KALDI_ASSERT(SumVectorSizes(*phases_per_segment) == num_cindex_ids);
1464 }
static void ComputeEpochInfo(const Nnet &nnet, const ComputationGraph &graph, std::vector< int32 > *cindex_id_to_segment_and_epoch, std::vector< std::vector< std::vector< int32 > > > *epochs_per_segment, std::vector< bool > *epoch_is_trivial)
This function computes certain information about "epochs" of cindex_ids.
static int32 SumVectorSizes(const std::vector< std::vector< std::vector< int32 > > > &vec)
kaldi::int32 int32
void ComputeGraphTranspose(const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *graph_transpose)
Outputs a graph in which the order of arcs is reversed.
Definition: nnet-graph.cc:63
static void ComputeComputationPhasesForEpoch(const Nnet &nnet, const ComputationGraph &graph, const std::vector< int32 > &this_epoch, const std::vector< std::vector< int32 > > &dependencies_subset, const std::vector< std::vector< int32 > > &depend_on_subset, bool epoch_is_trivial, std::vector< int32 > *phase_indexes, std::vector< std::vector< int32 > > *phases)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static void ComputeDependenciesSubset(const ComputationGraph &graph, const std::vector< int32 > &cindex_id_to_segment_and_epoch, std::vector< std::vector< int32 > > *dependencies_subset)
This function outputs to dependencies_subset[c], for each cindex_id c, the subset of elements d of gr...

◆ ComputeComputationPhasesForEpoch()

static void kaldi::nnet3::ComputeComputationPhasesForEpoch ( const Nnet nnet,
const ComputationGraph graph,
const std::vector< int32 > &  this_epoch,
const std::vector< std::vector< int32 > > &  dependencies_subset,
const std::vector< std::vector< int32 > > &  depend_on_subset,
bool  epoch_is_trivial,
std::vector< int32 > *  phase_indexes,
std::vector< std::vector< int32 > > *  phases 
)
inlinestatic

Definition at line 1307 of file nnet-computation-graph.cc.

References rnnlm::d, KALDI_ASSERT, KALDI_ERR, and kaldi::SortAndUniq().

Referenced by ComputeComputationPhases().

1315  {
1316  std::vector<int32> this_phase, next_phase_candidates;
1317 
1318  if (this_epoch.empty())
1319  return;
1320 
1321  if (epoch_is_trivial) { // an optimization
1322  this_phase = this_epoch;
1323  } else {
1324  // Start out with all elements of this epoch that have no
1325  // dependencies within the same epoch (i.e. those that
1326  // can be computed first).
1327  std::vector<int32>::const_iterator iter = this_epoch.begin(),
1328  end = this_epoch.end();
1329  for (; iter != end; ++iter) {
1330  int32 cindex_id = *iter;
1331  if (dependencies_subset[cindex_id].empty())
1332  this_phase.push_back(cindex_id);
1333  }
1334  }
1335 
1336  // if the next assert fails, the graph at the level of cindex_ids is not acyclic.
1337  KALDI_ASSERT(!this_phase.empty() &&
1338  "Trying to process computation with cycles");
1339 
1340  while (!this_phase.empty()) {
1341  // The next two lines are a more efficient version of:
1342  // phases->push_back(this_phase);
1343  phases->resize(phases->size() + 1);
1344  phases->back().swap(this_phase);
1345  // The next if-statement is an optimization: if for this epoch index
1346  // there is just one node, we can skip the rest of this loop. Note: if
1347  // epoch == 0, even if there is just one node, cindex_ids from
1348  // multiple nodes may be put here because of the rule that cindex_ids which
1349  // are inputs always get epoch 0. But it's still true that they
1350  // will have no dependencies, so we can still skip the code below.
1351  if (epoch_is_trivial)
1352  return;
1353 
1354  int32 cur_phase_index = phases->size() - 1;
1355 
1356  // next_phases_candidates is a list of cindexes that we should check
1357  // whether they are computable now, because one of the things they depend
1358  // on just became computable.
1359  next_phase_candidates.clear();
1360  std::vector<int32>::const_iterator this_phase_iter = phases->back().begin(),
1361  this_phase_end = phases->back().end();
1362 
1363  for (; this_phase_iter != this_phase_end; ++this_phase_iter) {
1364  int32 c = *this_phase_iter; // c is a cindex_id with phase cur_phase_index.
1365  (*phase_indexes)[c] = cur_phase_index;
1366  std::vector<int32>::const_iterator iter = depend_on_subset[c].begin(),
1367  end = depend_on_subset[c].end();
1368  for (; iter != end; ++iter) {
1369  int32 d = *iter; // cindex_id that depends on c.
1370  next_phase_candidates.push_back(d);
1371  }
1372  }
1373  SortAndUniq(&next_phase_candidates);
1374  // note, at this point 'this_phase' will be the empty vector [see the 'swap'
1375  // above].
1376  this_phase.reserve(next_phase_candidates.size());
1377  // now check the candidates that might be in the next phase, and put any
1378  // members that we are currently able to compute into "this_phase".
1379  std::vector<int32>::const_iterator iter = next_phase_candidates.begin(),
1380  end = next_phase_candidates.end();
1381  for (; iter != end; ++iter) {
1382  int32 c = *iter;
1383  std::vector<int32>::const_iterator
1384  dep_iter = dependencies_subset[c].begin(),
1385  dep_end = dependencies_subset[c].end();
1386  for (; dep_iter != dep_end; ++dep_iter) {
1387  int32 d = *dep_iter; // d is cindex_id that c depends on.
1388  if ((*phase_indexes)[d] < 0) // we can't compute c yet because something we depend
1389  break; // on has not yet been computed.
1390  }
1391  if (dep_iter == dep_end) {
1392  // we reached the end and did not break -> all dependencies satisfied
1393  this_phase.push_back(c);
1394  }
1395  }
1396  if (!next_phase_candidates.empty() && this_phase.empty()) {
1397  // this should have been caught earlier so likely a code error rather than
1398  // a problem with user input.
1399  KALDI_ERR << "Your model has a type of recurrence that cannot be computed. "
1400  << "E.g. if x[t] depends on both x[t+1] and x[t-1]... no order "
1401  << "of computation will work.";
1402  }
1403  }
1404 }
kaldi::int32 int32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeExampleComputationRequestSimple()

void ComputeExampleComputationRequestSimple ( const Nnet nnet,
ComputationRequest request,
std::vector< Matrix< BaseFloat > > *  inputs 
)

This function computes an example computation request, for testing purposes.

The "Simple" in the name means that it currently only supports neural nets that satisfy IsSimple(nnet) (defined in nnet-utils.h). If there are 2 inputs, the "input" will be first, followed by "ivector".

In order to expand the range of things you can test with this (mainly to stop crashes with statistics-pooling/statistics-extraction components), this function always generates computation-requests where at least 3 successive frames of input are requested.

Definition at line 1338 of file nnet-test-utils.cc.

References ComputeSimpleNnetContext(), Nnet::InputDim(), ComputationRequest::inputs, IsSimpleNnet(), KALDI_ASSERT, rnnlm::n, ComputationRequest::need_model_derivative, ComputationRequest::outputs, kaldi::Rand(), and ComputationRequest::store_component_stats.

Referenced by NnetGenerationOptions::NnetGenerationOptions(), UnitTestNnetAnalyze(), UnitTestNnetCompile(), UnitTestNnetCompileMulti(), UnitTestNnetCompute(), UnitTestNnetInputDerivatives(), UnitTestNnetModelDerivatives(), and UnitTestNnetOptimizeWithOptions().

1341  {
1342  KALDI_ASSERT(IsSimpleNnet(nnet));
1343 
1344  int32 left_context, right_context;
1345  ComputeSimpleNnetContext(nnet, &left_context, &right_context);
1346 
1347  int32 num_output_frames = 1 + Rand() % 10,
1348  output_start_frame = Rand() % 10,
1349  num_examples = 1 + Rand() % 4,
1350  output_end_frame = output_start_frame + num_output_frames,
1351  input_start_frame = output_start_frame - left_context - (Rand() % 3),
1352  input_end_frame = output_end_frame + right_context + (Rand() % 3),
1353  n_offset = Rand() % 2;
1354  bool need_deriv = (Rand() % 2 == 0);
1355  // make sure there are at least 3 frames of input available. this makes a
1356  // difference for our tests of statistics-pooling and statistics-extraction
1357  // component.
1358  if (input_end_frame < input_start_frame + 3)
1359  input_end_frame = input_start_frame + 3;
1360 
1361  request->inputs.clear();
1362  request->outputs.clear();
1363  inputs->clear();
1364 
1365  std::vector<Index> input_indexes, ivector_indexes, output_indexes;
1366  for (int32 n = n_offset; n < n_offset + num_examples; n++) {
1367  for (int32 t = input_start_frame; t < input_end_frame; t++)
1368  input_indexes.push_back(Index(n, t, 0));
1369  for (int32 t = output_start_frame; t < output_end_frame; t++)
1370  output_indexes.push_back(Index(n, t, 0));
1371  ivector_indexes.push_back(Index(n, 0, 0));
1372  }
1373  request->outputs.push_back(IoSpecification("output", output_indexes));
1374  if (need_deriv || (Rand() % 3 == 0))
1375  request->outputs.back().has_deriv = true;
1376  request->inputs.push_back(IoSpecification("input", input_indexes));
1377  if (need_deriv && (Rand() % 2 == 0))
1378  request->inputs.back().has_deriv = true;
1379  int32 input_dim = nnet.InputDim("input");
1380  KALDI_ASSERT(input_dim > 0);
1381  inputs->push_back(
1382  Matrix<BaseFloat>((input_end_frame - input_start_frame) * num_examples,
1383  input_dim));
1384  inputs->back().SetRandn();
1385  int32 ivector_dim = nnet.InputDim("ivector"); // may not exist.
1386  if (ivector_dim != -1) {
1387  request->inputs.push_back(IoSpecification("ivector", ivector_indexes));
1388  inputs->push_back(Matrix<BaseFloat>(num_examples, ivector_dim));
1389  inputs->back().SetRandn();
1390  if (need_deriv && (Rand() % 2 == 0))
1391  request->inputs.back().has_deriv = true;
1392  }
1393  if (Rand() % 2 == 0)
1394  request->need_model_derivative = need_deriv;
1395  if (Rand() % 2 == 0)
1396  request->store_component_stats = true;
1397 }
kaldi::int32 int32
void ComputeSimpleNnetContext(const Nnet &nnet, int32 *left_context, int32 *right_context)
ComputeSimpleNnetContext computes the left-context and right-context of a nnet.
Definition: nnet-utils.cc:146
struct rnnlm::@11::@12 n
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
bool IsSimpleNnet(const Nnet &nnet)
This function returns true if the nnet has the following properties: It has an output called "output"...
Definition: nnet-utils.cc:52
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeGraphTranspose()

void ComputeGraphTranspose ( const std::vector< std::vector< int32 > > &  graph,
std::vector< std::vector< int32 > > *  graph_transpose 
)

Outputs a graph in which the order of arcs is reversed.

Definition at line 63 of file nnet-graph.cc.

References rnnlm::n.

Referenced by ComputeComputationPhases(), FindOrphanNodes(), and UnitTestComputeGraphTranspose().

64  {
65  int32 size = graph.size();
66  graph_transpose->clear();
67  graph_transpose->resize(size);
68  for (int32 n = 0; n < size; n++) {
69  const std::vector<int32> &nodes = graph[n];
70  std::vector<int32>::const_iterator iter = nodes.begin(), end = nodes.end();
71  for (; iter != end; ++iter) {
72  int32 dest = *iter;
73  (*graph_transpose)[dest].push_back(n);
74  }
75  }
76 }
kaldi::int32 int32
struct rnnlm::@11::@12 n

◆ ComputeMatrixAccesses()

void ComputeMatrixAccesses ( const Nnet nnet,
const NnetComputation computation,
const ComputationVariables variables,
const std::vector< CommandAttributes > &  command_attributes,
std::vector< MatrixAccesses > *  matrix_accesses 
)

This function organizes information in the CommandAttributes in a way that is convenient to access per matrix.

See the declaration of struct MatrixAccesses for the output format; the output "matrix_accesses" is indexed by matrix index (the same index as computation.matrices).

Definition at line 467 of file nnet-analyze.cc.

References NnetComputation::Command::arg1, NnetComputation::Command::arg2, NnetComputation::Command::command_type, NnetComputation::commands, kaldi::IsSortedAndUniq(), NnetComputation::IsWholeMatrix(), kAcceptInput, KALDI_ASSERT, KALDI_ERR, kAllocMatrix, kDeallocMatrix, kProvideOutput, kReadAccess, kReadWriteAccess, kSwapMatrix, kWriteAccess, NnetComputation::matrices, CommandAttributes::matrices_read, CommandAttributes::matrices_written, kaldi::SortAndUniq(), and NnetComputation::submatrices.

Referenced by Analyzer::Init(), MatrixAccesses::MatrixAccesses(), and MoveSizingCommands().

472  {
473  int32 num_matrices = computation.matrices.size(),
474  num_commands = command_attributes.size();
475  matrix_accesses->clear();
476  matrix_accesses->resize(num_matrices);
477  for (int32 c = 0; c < num_commands; c++) {
478  const CommandAttributes &attr = command_attributes[c];
479  KALDI_ASSERT(IsSortedAndUniq(attr.matrices_read));
480  KALDI_ASSERT(IsSortedAndUniq(attr.matrices_written));
481  std::vector<int32> all_matrices;
482  all_matrices.reserve(attr.matrices_read.size() +
483  attr.matrices_written.size());
484  all_matrices.insert(all_matrices.end(), attr.matrices_read.begin(),
485  attr.matrices_read.end());
486  all_matrices.insert(all_matrices.end(), attr.matrices_written.begin(),
487  attr.matrices_written.end());
488  SortAndUniq(&all_matrices);
489 
490  std::vector<int32>::const_iterator iter = all_matrices.begin(),
491  end = all_matrices.end();
492  for (; iter != end; ++iter) {
493  int32 matrix_index = *iter;
494  bool is_read = std::binary_search(attr.matrices_read.begin(),
495  attr.matrices_read.end(),
496  matrix_index),
497  is_written = (!is_read ? true :
498  std::binary_search(attr.matrices_written.begin(),
499  attr.matrices_written.end(),
500  matrix_index));
501  if (is_read && is_written) {
502  (*matrix_accesses)[matrix_index].accesses.push_back(
503  Access(c, kReadWriteAccess));
504  } else if (is_read) {
505  (*matrix_accesses)[matrix_index].accesses.push_back(
506  Access(c, kReadAccess));
507  } else {
508  (*matrix_accesses)[matrix_index].accesses.push_back(
509  Access(c, kWriteAccess));
510  }
511  }
512  // Now set up allocate_command, deallocate_command,
513  // is_input and is_output.
514  const NnetComputation::Command &command = computation.commands[c];
515  int32 matrix_index1, matrix_index2;
516 
517  switch (command.command_type) {
518  case kAllocMatrix:
519  if (!computation.IsWholeMatrix(command.arg1))
520  KALDI_ERR << "Command does not operate on whole matrix";
521  matrix_index1 = computation.submatrices[command.arg1].matrix_index;
522  if ((*matrix_accesses)[matrix_index1].allocate_command != -1)
523  KALDI_ERR << "Matrix " << matrix_index1 << " initialized twice.";
524  (*matrix_accesses)[matrix_index1].allocate_command = c;
525  break;
526  case kSwapMatrix:
527  if (!computation.IsWholeMatrix(command.arg1))
528  KALDI_ERR << "Command does not operate on whole matrix";
529  matrix_index1 = computation.submatrices[command.arg1].matrix_index;
530  KALDI_ASSERT(computation.IsWholeMatrix(command.arg2));
531  matrix_index2 = computation.submatrices[command.arg2].matrix_index;
532  if ((*matrix_accesses)[matrix_index1].allocate_command != -1)
533  KALDI_ERR << "Matrix " << matrix_index1 << " initialized twice.";
534  (*matrix_accesses)[matrix_index1].allocate_command = c;
535  if ((*matrix_accesses)[matrix_index2].deallocate_command != -1)
536  KALDI_ERR << "Matrix " << matrix_index2 << " destroyed twice.";
537  (*matrix_accesses)[matrix_index2].deallocate_command = c;
538  break;
539  case kDeallocMatrix:
540  if (!computation.IsWholeMatrix(command.arg1))
541  KALDI_ERR << "Command does not operate on whole matrix";
542  matrix_index1 = computation.submatrices[command.arg1].matrix_index;
543  if ((*matrix_accesses)[matrix_index1].deallocate_command != -1)
544  KALDI_ERR << "Matrix " << matrix_index1 << " destroyed twice.";
545  (*matrix_accesses)[matrix_index1].deallocate_command = c;
546  break;
547  case kAcceptInput:
548  if (!computation.IsWholeMatrix(command.arg1))
549  KALDI_ERR << "Command does not operate on whole matrix";
550  matrix_index1 = computation.submatrices[command.arg1].matrix_index;
551  (*matrix_accesses)[matrix_index1].is_input = true;
552  // If a certain matrix is accepted as input multiple times, we
553  // count the first one as allocating it (the second will just
554  // allocate it again, which is harmless).
555  if ((*matrix_accesses)[matrix_index1].allocate_command == -1)
556  (*matrix_accesses)[matrix_index1].allocate_command = c;
557  break;
558  case kProvideOutput:
559  if (!computation.IsWholeMatrix(command.arg1))
560  KALDI_ERR << "Command does not operate on whole matrix";
561  matrix_index1 = computation.submatrices[command.arg1].matrix_index;
562  (*matrix_accesses)[matrix_index1].is_output = true;
563  break;
564  default:
565  ;
566  }
567  }
568 }
kaldi::int32 int32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
bool IsSortedAndUniq(const std::vector< T > &vec)
Returns true if the vector is sorted and contains each element only once.
Definition: stl-utils.h:63

◆ ComputeMatrixToSubmatrix()

void ComputeMatrixToSubmatrix ( const NnetComputation computation,
std::vector< std::vector< int32 > > *  mat_to_submat 
)

This function computes a vector 'mat_to_submat', indexed by matrix index, such that (*mat_to_submat)[m] is a list of all the submatrix indexes that refer to matrix m.

Note, (*mat_to_submat)[0] will be the empty vector.

Definition at line 1166 of file nnet-analyze.cc.

References KALDI_ASSERT, NnetComputation::matrices, and NnetComputation::submatrices.

Referenced by VariableMergingOptimizer::VariableMergingOptimizer().

1168  {
1169  int32 num_matrices = computation.matrices.size(),
1170  num_submatrices = computation.submatrices.size();
1171  mat_to_submat->clear();
1172  mat_to_submat->resize(num_matrices);
1173  for (int32 submatrix_index = 1;
1174  submatrix_index < num_submatrices;
1175  submatrix_index++) {
1176  int32 matrix_index = computation.submatrices[submatrix_index].matrix_index;
1177  KALDI_ASSERT(matrix_index > 0 && matrix_index < num_matrices);
1178  (*mat_to_submat)[matrix_index].push_back(submatrix_index);
1179  }
1180 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeMinAndMaxTimes()

void kaldi::nnet3::ComputeMinAndMaxTimes ( const std::vector< Index > &  indexes,
int32 min_t,
int32 max_t 
)

Definition at line 31 of file nnet-derivative-test.cc.

References KALDI_ASSERT, and rnnlm::n.

Referenced by SetDerivTimesOptions().

33  {
34  KALDI_ASSERT(!indexes.empty());
35  *min_t = indexes[0].t;
36  *max_t = *min_t;
37  for (int32 n = 1; n < static_cast<int32>(indexes.size()); n++) {
38  *min_t = std::min(*min_t, indexes[n].t);
39  *max_t = std::max(*max_t, indexes[n].t);
40  }
41 }
kaldi::int32 int32
struct rnnlm::@11::@12 n
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeNnetComputationEpochs()

void ComputeNnetComputationEpochs ( const Nnet nnet,
std::vector< int32 > *  node_to_epoch 
)

This function computes the order in which we need to compute each node in the graph, where each node-index n maps to an epoch-index t = 0, 1, ...

that says when we should compute it. Nodes that are part of a strongly connected component (SCC) will all be computed at the same time, but any two nodes that are not part of an SCC will have different epoch-index, and these epoch-indexes will be such that a node computed at a larger epoch-index may depend on a node computed at a smaller epoch-index, but not vice versa.

Internally it calls NnetToDirectedGraph, FindSccs, MakeSccGraph and ComputeTopSortOrder.

Definition at line 265 of file nnet-graph.cc.

References ComputeTopSortOrder(), FindSccs(), kaldi::GetVerboseLevel(), rnnlm::i, rnnlm::j, KALDI_ASSERT, KALDI_VLOG, MakeSccGraph(), NnetToDirectedGraph(), and PrintGraphToString().

Referenced by kaldi::nnet3::computation_graph::ComputeEpochInfo().

266  {
267  KALDI_ASSERT(node_to_epoch != NULL);
268 
269  std::vector<std::vector<int32> > graph;
270  NnetToDirectedGraph(nnet, &graph);
271  KALDI_VLOG(6) << "graph is: " << PrintGraphToString(graph);
272 
273  std::vector<std::vector<int32> > sccs;
274  FindSccs(graph, &sccs);
275 
276  std::vector<std::vector<int32> > scc_graph;
277  MakeSccGraph(graph, sccs, &scc_graph);
278  KALDI_VLOG(6) << "scc graph is: " << PrintGraphToString(scc_graph);
279 
280  std::vector<int32> scc_node_to_epoch;
281  ComputeTopSortOrder(scc_graph, &scc_node_to_epoch);
282  if (GetVerboseLevel() >= 6) {
283  std::ostringstream os;
284  for (int32 i = 0; i < scc_node_to_epoch.size(); i++)
285  os << scc_node_to_epoch[i] << ", ";
286  KALDI_VLOG(6) << "scc_node_to_epoch is: " << os.str();
287  }
288 
289  node_to_epoch->clear();
290  node_to_epoch->resize(graph.size());
291  for (int32 i = 0; i < sccs.size(); ++i) {
292  for (int32 j = 0; j < sccs[i].size(); ++j) {
293  int32 node = sccs[i][j];
294  KALDI_ASSERT(node >= 0 && node < graph.size());
295  (*node_to_epoch)[node] = scc_node_to_epoch[i];
296  }
297  }
298 }
void NnetToDirectedGraph(const Nnet &nnet, std::vector< std::vector< int32 > > *graph)
This function takes an nnet and turns it to a directed graph on nodes.
Definition: nnet-graph.cc:30
int32 GetVerboseLevel()
Get verbosity level, usually set via command line &#39;–verbose=&#39; switch.
Definition: kaldi-error.h:60
kaldi::int32 int32
void ComputeTopSortOrder(const std::vector< std::vector< int32 > > &graph, std::vector< int32 > *node_to_order)
Given an acyclic graph (where each std::vector<int32> is a list of destination-nodes of arcs coming f...
Definition: nnet-graph.cc:223
void FindSccs(const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *sccs)
Given a directed graph (where each std::vector<int32> is a list of destination-nodes of arcs coming f...
Definition: nnet-graph.cc:156
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void MakeSccGraph(const std::vector< std::vector< int32 > > &graph, const std::vector< std::vector< int32 > > &sccs, std::vector< std::vector< int32 > > *scc_graph)
Given a list of sccs of a graph (e.g.
Definition: nnet-graph.cc:164
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156
std::string PrintGraphToString(const std::vector< std::vector< int32 > > &graph)
Prints a graph to a string in a pretty way for human readability, e.g.
Definition: nnet-graph.cc:248

◆ ComputeObjectiveFunction()

void ComputeObjectiveFunction ( const GeneralMatrix supervision,
ObjectiveType  objective_type,
const std::string &  output_name,
bool  supply_deriv,
NnetComputer computer,
BaseFloat tot_weight,
BaseFloat tot_objf 
)

This function computes the objective function, and if supply_deriv = true, supplies its derivative to the NnetComputation object.

See also the function ComputeAccuracy(), declared in nnet-diagnostics.h.

Parameters
[in]supervisionA GeneralMatrix, typically derived from a NnetExample, containing the supervision posteriors or features.
[in]objective_typeThe objective function type: kLinear = output * supervision, or kQuadratic = -0.5 * (output - supervision)^2. kLinear is used for softmax objectives; the network contains a LogSoftmax layer which correctly normalizes its output.
[in]output_nameThe name of the output node (e.g. "output"), used to look up the output in the NnetComputer object.
[in]supply_derivIf this is true, this function will compute the derivative of the objective function and supply it to the network using the function NnetComputer::AcceptOutputDeriv
[in,out]computerThe NnetComputer object, from which we get the output using GetOutput and to which we may supply the derivatives using AcceptOutputDeriv.
[out]tot_weightThe total weight of the training examples. In the kLinear case, this is the sum of the supervision matrix; in the kQuadratic case, it is the number of rows of the supervision matrix. In order to make it possible to weight samples with quadratic objective functions, we may at some point make it possible for the supervision matrix to have an extra column containing weights. At the moment, this is not supported.
[out]tot_objfThe total objective function; divide this by the tot_weight to get the normalized objective function.

Definition at line 339 of file nnet-training.cc.

References NnetComputer::AcceptInput(), CuMatrixBase< Real >::CopyFromGeneralMat(), CuSparseMatrix< Real >::CopyToMat(), GeneralMatrix::GetFullMatrix(), GeneralMatrix::GetMatrix(), NnetComputer::GetOutput(), GeneralMatrix::GetSparseMatrix(), KALDI_ERR, kaldi::kCompressedMatrix, kaldi::kFullMatrix, kLinear, kQuadratic, kaldi::kSparseMatrix, kaldi::kTrans, kaldi::kUndefined, CuMatrixBase< Real >::NumCols(), GeneralMatrix::NumCols(), CuMatrixBase< Real >::NumRows(), GeneralMatrix::NumRows(), CuSparseMatrix< Real >::Sum(), CuMatrixBase< Real >::Sum(), CuMatrix< Real >::Swap(), kaldi::TraceMatMat(), kaldi::TraceMatSmat(), and GeneralMatrix::Type().

Referenced by NnetComputeProb::ProcessOutputs(), and NnetTrainer::ProcessOutputs().

345  {
346  const CuMatrixBase<BaseFloat> &output = computer->GetOutput(output_name);
347 
348  if (output.NumCols() != supervision.NumCols())
349  KALDI_ERR << "Nnet versus example output dimension (num-classes) "
350  << "mismatch for '" << output_name << "': " << output.NumCols()
351  << " (nnet) vs. " << supervision.NumCols() << " (egs)\n";
352 
353  switch (objective_type) {
354  case kLinear: {
355  // objective is x * y.
356  switch (supervision.Type()) {
357  case kSparseMatrix: {
358  const SparseMatrix<BaseFloat> &post = supervision.GetSparseMatrix();
359  CuSparseMatrix<BaseFloat> cu_post(post);
360  // The cross-entropy objective is computed by a simple dot product,
361  // because after the LogSoftmaxLayer, the output is already in the form
362  // of log-likelihoods that are normalized to sum to one.
363  *tot_weight = cu_post.Sum();
364  *tot_objf = TraceMatSmat(output, cu_post, kTrans);
365  if (supply_deriv) {
366  CuMatrix<BaseFloat> output_deriv(output.NumRows(), output.NumCols(),
367  kUndefined);
368  cu_post.CopyToMat(&output_deriv);
369  computer->AcceptInput(output_name, &output_deriv);
370  }
371  break;
372  }
373  case kFullMatrix: {
374  // there is a redundant matrix copy in here if we're not using a GPU
375  // but we don't anticipate this code branch being used in many cases.
376  CuMatrix<BaseFloat> cu_post(supervision.GetFullMatrix());
377  *tot_weight = cu_post.Sum();
378  *tot_objf = TraceMatMat(output, cu_post, kTrans);
379  if (supply_deriv)
380  computer->AcceptInput(output_name, &cu_post);
381  break;
382  }
383  case kCompressedMatrix: {
384  Matrix<BaseFloat> post;
385  supervision.GetMatrix(&post);
386  CuMatrix<BaseFloat> cu_post;
387  cu_post.Swap(&post);
388  *tot_weight = cu_post.Sum();
389  *tot_objf = TraceMatMat(output, cu_post, kTrans);
390  if (supply_deriv)
391  computer->AcceptInput(output_name, &cu_post);
392  break;
393  }
394  }
395  break;
396  }
397  case kQuadratic: {
398  // objective is -0.5 (x - y)^2
399  CuMatrix<BaseFloat> diff(supervision.NumRows(),
400  supervision.NumCols(),
401  kUndefined);
402  diff.CopyFromGeneralMat(supervision);
403  diff.AddMat(-1.0, output);
404  *tot_weight = diff.NumRows();
405  *tot_objf = -0.5 * TraceMatMat(diff, diff, kTrans);
406  if (supply_deriv)
407  computer->AcceptInput(output_name, &diff);
408  break;
409  }
410  default:
411  KALDI_ERR << "Objective function type " << objective_type
412  << " not handled.";
413  }
414 }
#define KALDI_ERR
Definition: kaldi-error.h:147
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 TraceMatSmat(const MatrixBase< Real > &A, const SparseMatrix< Real > &B, MatrixTransposeType trans)

◆ ComputeObjf()

double kaldi::nnet3::ComputeObjf ( bool  batchnorm_test_mode,
bool  dropout_test_mode,
const std::vector< NnetExample > &  egs,
const Nnet nnet,
NnetComputeProb prob_computer 
)

Definition at line 35 of file nnet3-combine.cc.

References NnetComputeProb::Compute(), NnetComputeProb::GetTotalObjective(), KALDI_ASSERT, NnetComputeProb::Reset(), SetBatchnormTestMode(), and SetDropoutTestMode().

Referenced by main().

37  {
38  if (batchnorm_test_mode || dropout_test_mode) {
39  Nnet nnet_copy(nnet);
40  if (batchnorm_test_mode)
41  SetBatchnormTestMode(true, &nnet_copy);
42  if (dropout_test_mode)
43  SetDropoutTestMode(true, &nnet_copy);
44  NnetComputeProbOptions compute_prob_opts;
45  NnetComputeProb prob_computer_test(compute_prob_opts, nnet_copy);
46  return ComputeObjf(false, false, egs, nnet_copy, &prob_computer_test);
47  } else {
48  prob_computer->Reset();
49  std::vector<NnetExample>::const_iterator iter = egs.begin(),
50  end = egs.end();
51  for (; iter != end; ++iter)
52  prob_computer->Compute(*iter);
53  double tot_weights,
54  tot_objf = prob_computer->GetTotalObjective(&tot_weights);
55  KALDI_ASSERT(tot_weights > 0.0);
56  // inf/nan tot_objf->return -inf objective.
57  if (!(tot_objf == tot_objf && tot_objf - tot_objf == 0))
58  return -std::numeric_limits<double>::infinity();
59  // we prefer to deal with normalized objective functions.
60  return tot_objf / tot_weights;
61  }
62 }
void Compute(const NnetExample &eg)
void SetBatchnormTestMode(bool test_mode, Nnet *nnet)
This function affects only components of type BatchNormComponent.
Definition: nnet-utils.cc:564
This class is for computing cross-entropy and accuracy values in a neural network, for diagnostics.
double ComputeObjf(bool batchnorm_test_mode, bool dropout_test_mode, const std::vector< NnetExample > &egs, const Nnet &nnet, NnetComputeProb *prob_computer)
void SetDropoutTestMode(bool test_mode, Nnet *nnet)
This function affects components of child-classes of RandomComponent.
Definition: nnet-utils.cc:573
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
double GetTotalObjective(double *tot_weight) const

◆ ComputeSimpleNnetContext()

void ComputeSimpleNnetContext ( const Nnet nnet,
int32 left_context,
int32 right_context 
)

ComputeSimpleNnetContext computes the left-context and right-context of a nnet.

The nnet must satisfy IsSimpleNnet(nnet).

It does this by constructing a ComputationRequest with a certain number of inputs available, outputs can be computed.. It does the same after shifting the time index of the output to all values 0, 1, ... n-1, where n is the output of nnet.Modulus(). Then it returns the largest left context and the largest right context that it infers from any of these computation requests.

Definition at line 146 of file nnet-utils.cc.

References ComputeSimpleNnetContextForShift(), IsSimpleNnet(), KALDI_ASSERT, KALDI_ERR, and Nnet::Modulus().

Referenced by ComputeExampleComputationRequestSimple(), CreateLoopedComputationRequestSimple(), CachingOptimizingCompiler::GetSimpleNnetContext(), Nnet::Info(), DecodableNnetSimpleLoopedInfo::Init(), main(), NnetBatchComputer::NnetBatchComputer(), NnetInfo(), AmNnetSimple::SetContext(), and UnitTestNnetContext().

148  {
149  KALDI_ASSERT(IsSimpleNnet(nnet));
150  int32 modulus = nnet.Modulus();
151  // modulus >= 1 is a number such that the network ought to be
152  // invariant to time shifts (of both the input and output) that
153  // are a multiple of this number. We need to test all shifts modulo
154  // this number in case the left and right context vary at all within
155  // this range.
156 
157  std::vector<int32> left_contexts(modulus + 1);
158  std::vector<int32> right_contexts(modulus + 1);
159 
160  // window_size is a number which needs to be greater than the total context
161  // of the nnet, else we won't be able to work out the context. Large window
162  // size will make this code slow, so we start off with small window size, and
163  // if it isn't enough, we keep doubling it up to a maximum.
164  int32 window_size = 40, max_window_size = 800;
165 
166  while (window_size < max_window_size) {
167 
168  // by going "<= modulus" instead of "< modulus" we do one more computation
169  // than we really need; it becomes a sanity check.
170  int32 input_start;
171  for (input_start = 0; input_start <= modulus; input_start++) {
172  if (!ComputeSimpleNnetContextForShift(nnet, input_start, window_size,
173  &(left_contexts[input_start]),
174  &(right_contexts[input_start])))
175  break;
176  }
177  if (input_start <= modulus) {
178  // We broke from the loop over 'input_start', which means there was
179  // a failure in ComputeSimpleNnextContextForShift-- we assume at
180  // this point that it was because window_size was too small.
181  window_size *= 2;
182  continue;
183  }
184 
185  KALDI_ASSERT(left_contexts[0] == left_contexts[modulus] &&
186  "nnet does not have the properties we expect.");
187  KALDI_ASSERT(right_contexts[0] == right_contexts[modulus] &&
188  "nnet does not have the properties we expect.");
189  *left_context =
190  *std::max_element(left_contexts.begin(), left_contexts.end());
191  *right_context =
192  *std::max_element(right_contexts.begin(), right_contexts.end());
193  // Success.
194  return;
195  }
196  KALDI_ERR << "Failure in ComputeSimpleNnetContext (perhaps not a simple nnet?)";
197 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
static bool ComputeSimpleNnetContextForShift(const Nnet &nnet, int32 input_start, int32 window_size, int32 *left_context, int32 *right_context)
Definition: nnet-utils.cc:92
bool IsSimpleNnet(const Nnet &nnet)
This function returns true if the nnet has the following properties: It has an output called "output"...
Definition: nnet-utils.cc:52
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeSimpleNnetContextForShift()

static bool kaldi::nnet3::ComputeSimpleNnetContextForShift ( const Nnet nnet,
int32  input_start,
int32  window_size,
int32 left_context,
int32 right_context 
)
static

Definition at line 92 of file nnet-utils.cc.

References EvaluateComputationRequest(), Nnet::GetNodeIndex(), IoSpecification::indexes, ComputationRequest::inputs, KALDI_ASSERT, Nnet::Modulus(), rnnlm::n, IoSpecification::name, and ComputationRequest::outputs.

Referenced by ComputeSimpleNnetContext().

97  {
98 
99  int32 input_end = input_start + window_size;
100  IoSpecification input;
101  input.name = "input";
102  IoSpecification output;
103  output.name = "output";
104  IoSpecification ivector; // we might or might not use this.
105  ivector.name = "ivector";
106 
107  int32 n = rand() % 10;
108  // in the IoSpecification for now we we will request all the same indexes at
109  // output that we requested at input.
110  for (int32 t = input_start; t < input_end; t++) {
111  input.indexes.push_back(Index(n, t));
112  output.indexes.push_back(Index(n, t));
113  }
114 
115  // most networks will just require the ivector at time t = 0,
116  // but this might not always be the case, and some might use rounding
117  // descriptors with the iVector which might require it at an earlier
118  // frame than the regular input, so we provide the iVector in as wide a range
119  // as it might possibly be needed.
120  for (int32 t = input_start - nnet.Modulus(); t < input_end; t++) {
121  ivector.indexes.push_back(Index(n, t));
122  }
123 
124  ComputationRequest request;
125  request.inputs.push_back(input);
126  request.outputs.push_back(output);
127  if (nnet.GetNodeIndex("ivector") != -1)
128  request.inputs.push_back(ivector);
129  std::vector<std::vector<bool> > computable;
130  EvaluateComputationRequest(nnet, request, &computable);
131 
132  KALDI_ASSERT(computable.size() == 1);
133  std::vector<bool> &output_ok = computable[0];
134  std::vector<bool>::iterator iter =
135  std::find(output_ok.begin(), output_ok.end(), true);
136  int32 first_ok = iter - output_ok.begin();
137  int32 first_not_ok = std::find(iter, output_ok.end(), false) -
138  output_ok.begin();
139  if (first_ok == window_size || first_not_ok <= first_ok)
140  return false;
141  *left_context = first_ok;
142  *right_context = window_size - first_not_ok;
143  return true;
144 }
void EvaluateComputationRequest(const Nnet &nnet, const ComputationRequest &request, std::vector< std::vector< bool > > *is_computable)
Given an nnet and a computation request, this function works out which requested outputs in the compu...
Definition: nnet-utils.cc:71
kaldi::int32 int32
struct rnnlm::@11::@12 n
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeTopSortOrder()

void ComputeTopSortOrder ( const std::vector< std::vector< int32 > > &  graph,
std::vector< int32 > *  node_to_order 
)

Given an acyclic graph (where each std::vector<int32> is a list of destination-nodes of arcs coming from the current node), compute a topological ordering of the graph nodes.

The output format is that node_to_order[n] contains an integer t = 0, 1, ... which is the order of node n in a topological sorting. node_to_order should contain some permutation of the numbers 0 ... graph.size() - 1. This function should crash if the graph contains cycles.

Definition at line 223 of file nnet-graph.cc.

References ComputeTopSortOrderRecursive(), rnnlm::i, and KALDI_ASSERT.

Referenced by ComputeNnetComputationEpochs(), UnitTestComputeTopSortOrder(), and UnitTestComputeTopSortOrder2().

224  {
225  // Internally we use DFS, but we only put the node to <node_to_order> when all
226  // its parents have been visited.
227  KALDI_ASSERT(node_to_order != NULL);
228  node_to_order->resize(graph.size());
229 
230  std::vector<bool> cycle_detector(graph.size(), false);
231  std::vector<bool> is_visited(graph.size(), false);
232 
233  std::vector<int32> reversed_orders;
234  for(int32 i = 0; i < graph.size(); ++i) {
235  if (!is_visited[i]) {
236  ComputeTopSortOrderRecursive(i, graph, &cycle_detector,
237  &is_visited, &reversed_orders);
238  }
239  }
240 
241  KALDI_ASSERT(node_to_order->size() == reversed_orders.size());
242  for (int32 i = 0; i < reversed_orders.size(); ++i) {
243  KALDI_ASSERT(reversed_orders[i] >= 0 && reversed_orders[i] < graph.size());
244  (*node_to_order)[reversed_orders[i]] = graph.size() - i - 1;
245  }
246 }
void ComputeTopSortOrderRecursive(int32 node, const std::vector< std::vector< int32 > > &graph, std::vector< bool > *cycle_detector, std::vector< bool > *is_visited, std::vector< int32 > *reversed_orders)
Definition: nnet-graph.cc:196
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeTopSortOrderRecursive()

void kaldi::nnet3::ComputeTopSortOrderRecursive ( int32  node,
const std::vector< std::vector< int32 > > &  graph,
std::vector< bool > *  cycle_detector,
std::vector< bool > *  is_visited,
std::vector< int32 > *  reversed_orders 
)

Definition at line 196 of file nnet-graph.cc.

References rnnlm::i, KALDI_ASSERT, and KALDI_ERR.

Referenced by ComputeTopSortOrder().

200  {
201  KALDI_ASSERT(node >= 0 && node < graph.size());
202  KALDI_ASSERT(cycle_detector != NULL);
203  KALDI_ASSERT(is_visited != NULL);
204  KALDI_ASSERT(reversed_orders != NULL);
205  if ((*cycle_detector)[node]) {
206  KALDI_ERR << "Cycle detected when computing the topological sorting order";
207  }
208 
209  if (!(*is_visited)[node]) {
210  (*cycle_detector)[node] = true;
211  for (int32 i = 0; i < graph[node].size(); ++i) {
212  ComputeTopSortOrderRecursive(graph[node][i], graph,
213  cycle_detector, is_visited, reversed_orders);
214  }
215  (*cycle_detector)[node] = false;
216  (*is_visited)[node] = true;
217  // At this point we have added all the children to <reversed_orders>, so we
218  // can add the current now.
219  reversed_orders->push_back(node);
220  }
221 }
void ComputeTopSortOrderRecursive(int32 node, const std::vector< std::vector< int32 > > &graph, std::vector< bool > *cycle_detector, std::vector< bool > *is_visited, std::vector< int32 > *reversed_orders)
Definition: nnet-graph.cc:196
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ComputeVariableAccesses()

void ComputeVariableAccesses ( const ComputationVariables variables,
const std::vector< CommandAttributes > &  command_attributes,
std::vector< std::vector< Access > > *  variable_accesses 
)

After the command-level attributes have been computed, this function organizes them per variable (see class ComputationVariables for how a variable is defined; it is part of a matrix).

Parameters
[in]variablesThe definition of variables for this computation
[in]command_attributesA vector of attributes, one per command, as obtained from ComputeCommandAttributes().
[out]variable_accessesThe output will have a size equal to the number of variables, and each element will be a vector of accesses, sorted by command index; each command will only be listed once in this vector.

Definition at line 421 of file nnet-analyze.cc.

References kaldi::IsSortedAndUniq(), KALDI_ASSERT, kReadAccess, kReadWriteAccess, kWriteAccess, ComputationVariables::NumVariables(), kaldi::SortAndUniq(), CommandAttributes::variables_read, and CommandAttributes::variables_written.

Referenced by Analyzer::Init(), MoveSizingCommands(), and Access::operator<().

424  {
425  int32 num_variables = variables.NumVariables(),
426  num_commands = command_attributes.size();
427  variable_accesses->clear();
428  variable_accesses->resize(num_variables);
429  for (int32 c = 0; c < num_commands; c++) {
430  const CommandAttributes &attr = command_attributes[c];
431  KALDI_ASSERT(IsSortedAndUniq(attr.variables_read));
432  KALDI_ASSERT(IsSortedAndUniq(attr.variables_written));
433  std::vector<int32> all_variables;
434  all_variables.reserve(attr.variables_read.size() +
435  attr.variables_written.size());
436  all_variables.insert(all_variables.end(), attr.variables_read.begin(),
437  attr.variables_read.end());
438  all_variables.insert(all_variables.end(), attr.variables_written.begin(),
439  attr.variables_written.end());
440  SortAndUniq(&all_variables);
441 
442  std::vector<int32>::const_iterator iter = all_variables.begin(),
443  end = all_variables.end();
444  for (; iter != end; ++iter) {
445  int32 variable_index = *iter;
446  bool is_read = std::binary_search(attr.variables_read.begin(),
447  attr.variables_read.end(),
448  variable_index),
449  is_written = (!is_read ? true :
450  std::binary_search(attr.variables_written.begin(),
451  attr.variables_written.end(),
452  variable_index));
453  if (is_read && is_written) {
454  (*variable_accesses)[variable_index].push_back(
455  Access(c, kReadWriteAccess));
456  } else if (is_read) {
457  (*variable_accesses)[variable_index].push_back(
458  Access(c, kReadAccess));
459  } else {
460  (*variable_accesses)[variable_index].push_back(
461  Access(c, kWriteAccess));
462  }
463  }
464  }
465 }
kaldi::int32 int32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
bool IsSortedAndUniq(const std::vector< T > &vec)
Returns true if the vector is sorted and contains each element only once.
Definition: stl-utils.h:63

◆ ConsolidateIoOperations()

void ConsolidateIoOperations ( const Nnet nnet,
NnetComputation computation 
)

This optimization puts the input operations (kAcceptInput) and output operations (kProvideOutput) at the very beginning or end of segments of computation, respectively.

This is actually necessary for computations to be run easily, because if these commands were interspersed with the regular commands, you'd have to call computer.Run() between the individual AcceptInput() and GetOutput() function calls.

Definition at line 869 of file nnet-optimize.cc.

References NnetComputation::commands, kAcceptInput, KALDI_ASSERT, kNoOperationMarker, kProvideOutput, and SplitComputationIntoSegments().

Referenced by Compiler::CreateComputation(), and Optimize().

870  {
871  // These segments, represented as (start-index, end-index),
872  // are segments of the computation separated by kNoOperationMarker.
873  std::vector<std::pair<int32, int32> > segments;
874  SplitComputationIntoSegments(*computation, &segments);
875 
876  int32 num_commands = computation->commands.size();
877  std::vector<NnetComputation::Command> reordered_commands(num_commands);
878  // put kNoOperationMarker between all segments in the reordered commands.
879  for (size_t s = 0; s + 1 < segments.size(); s++)
880  reordered_commands[segments[s].second].command_type = kNoOperationMarker;
881 
882  // for each segment we'll divide the commands up into those that must appear
883  // at the left of the segment (kAcceptInput for inputs and output-derivs), those
884  // that must appear in the middle (most commands), those that must appear
885  // on the right (kProvideOutput for output nodes and input derivatives).
886  std::vector<int32> left_commands, middle_commands, right_commands;
887 
888  for (size_t s = 0; s < segments.size(); s++) {
889  int32 segment_start = segments[s].first,
890  segment_end = segments[s].second;
891  left_commands.clear();
892  middle_commands.clear();
893  right_commands.clear();
894  for (int32 c = segment_start; c < segment_end; c++) {
895  if (computation->commands[c].command_type == kProvideOutput) {
896  right_commands.push_back(c);
897  } else if (computation->commands[c].command_type == kAcceptInput) {
898  left_commands.push_back(c);
899  } else {
900  middle_commands.push_back(c);
901  }
902  }
903  std::vector<int32>::const_iterator iter = left_commands.begin(),
904  end = left_commands.end();
905  int32 c = segment_start;
906  for (; iter != end; ++iter, ++c)
907  reordered_commands[c] = computation->commands[*iter];
908  iter = middle_commands.begin();
909  end = middle_commands.end();
910  for (; iter != end; ++iter, ++c)
911  reordered_commands[c] = computation->commands[*iter];
912  iter = right_commands.begin();
913  end = right_commands.end();
914  for (; iter != end; ++iter, ++c)
915  reordered_commands[c] = computation->commands[*iter];
916  KALDI_ASSERT(c == segment_end);
917  }
918  computation->commands.swap(reordered_commands);
919 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static void SplitComputationIntoSegments(const NnetComputation &computation, std::vector< std::pair< int32, int32 > > *segments)
Split the computation up into segments bounded by kNoOperationMarker.

◆ ConsolidateMemory()

void ConsolidateMemory ( Nnet nnet)

This just calls ConsolidateMemory() on all the components of the nnet.

This is called by the training code after processing the first minibatch. On some components this will do nothing; on some components it will reallocate certain quantities that have been allocated during training (mostly the contents of NaturalGradientOnline objects, and stats for NonlinearComponents) so that they can be put into low memory. This will tend to minimize memory fragmentation. Read comments in ../cudamatrix/cu-allocator.h for more explanation.

Definition at line 1147 of file nnet-utils.cc.

References Component::ConsolidateMemory(), Nnet::GetComponent(), kaldi::GetVerboseLevel(), KALDI_VLOG, and Nnet::NumComponents().

Referenced by CollapseModelConfig::CollapseModelConfig(), NonlinearComponent::OutputDim(), NnetChainTrainer::Train(), and NnetTrainer::Train().

1147  {
1148 #if HAVE_CUDA == 1
1149  if (CuDevice::Instantiate().Enabled()) {
1150  bool print_memory_info = (GetVerboseLevel() >= 1);
1151  if (print_memory_info) {
1152  KALDI_VLOG(1) << "Consolidating memory; will print memory usage before "
1153  "and after consolidating:";
1154  g_cuda_allocator.PrintMemoryUsage();
1155  }
1156  for (int32 c = 0; c < nnet->NumComponents(); c++) {
1157  Component *comp = nnet->GetComponent(c);
1158  comp->ConsolidateMemory();
1159  }
1160  if (print_memory_info) {
1161  g_cuda_allocator.PrintMemoryUsage();
1162  }
1163  }
1164 #endif
1165 }
int32 GetVerboseLevel()
Get verbosity level, usually set via command line &#39;–verbose=&#39; switch.
Definition: kaldi-error.h:60
kaldi::int32 int32
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156

◆ ConsolidateModelUpdate()

void ConsolidateModelUpdate ( const Nnet nnet,
NnetComputation computation 
)

This optimization consolidates the model-update part of backprop commands, for components in (e.g.) recurrent networks that need to have many separate backprop commands, into more efficient single commands operating on consolidated data in larger matrices.

This consolidates the model-update parts of the backprop into larger operations (applicable mostly to recurrent setups)– internally it uses class ModelUpdateConsolidator.

This is useful for recurrent networks. The resulting computation separates the backprop for data-derivatives from the model-update part of backprop.

Will fail if called a second time.

Definition at line 1551 of file nnet-optimize-utils.cc.

References ModelUpdateConsolidator::ConsolidateModelUpdate(), and NnetComputation::need_model_derivative.

Referenced by Optimize().

1552  {
1553  // This following if-statement is an optimization: if the computation
1554  // request(s) had need_model_derivative == false, there would be nothing to
1555  // optimize, so don't bother trying.
1556  if (!computation->need_model_derivative)
1557  return;
1558  ModelUpdateConsolidator consolidator(nnet, computation);
1559  consolidator.ConsolidateModelUpdate();
1560 }

◆ ConstrainOrthonormal()

void ConstrainOrthonormal ( Nnet nnet)

This function, to be called after processing every minibatch, is responsible for enforcing the orthogonality constraint for any components of type LinearComponent or inheriting from AffineComponent that have the "orthonormal_constraint" value set.

This function, to be called after processing every minibatch, is responsible for enforcing the orthogonality constraint for any components of type LinearComponent or inheriting from AffineComponent that have the "orthonormal-constraint" value set to a nonzero value.

Technically what we are doing is constraining the parameter matrix M to be a "semi-orthogonal" matrix times a constant alpha. That is: if num-rows > num-cols, this amounts to asserting that M M^T == alpha^2 I; otherwise, that M^T M == alpha^2 I.

If, for a particular component, orthonormal-constraint > 0.0, then that value becomes the "alpha" mentioned above. If orthonormal-constraint == 0.0, then nothing is done. If orthonormal-constraint < 0.0, then it's like letting alpha "float", i.e. we try to make M closer to (any constant alpha) times a semi-orthogonal matrix.

In order to make it efficient on GPU, it doesn't make it completely orthonormal, it just makes it closer to being orthonormal (times the 'orthonormal_constraint' value). Over multiple iterations this rapidly makes it almost exactly orthonormal.

See http://www.danielpovey.com/files/2018_interspeech_tdnnf.pdf

Definition at line 1108 of file nnet-utils.cc.

References ConstrainOrthonormalInternal(), CuMatrixBase< Real >::CopyFromMat(), Nnet::GetComponent(), kaldi::kTrans, AffineComponent::LinearParams(), TdnnComponent::LinearParams(), CuMatrixBase< Real >::NumCols(), Nnet::NumComponents(), CuMatrixBase< Real >::NumRows(), AffineComponent::OrthonormalConstraint(), TdnnComponent::OrthonormalConstraint(), LinearComponent::OrthonormalConstraint(), LinearComponent::Params(), and kaldi::RandInt().

Referenced by CollapseModelConfig::CollapseModelConfig(), NnetChainTrainer::TrainInternal(), NnetTrainer::TrainInternal(), NnetChainTrainer::TrainInternalBackstitch(), and NnetTrainer::TrainInternalBackstitch().

1108  {
1109 
1110  for (int32 c = 0; c < nnet->NumComponents(); c++) {
1111  Component *component = nnet->GetComponent(c);
1112  CuMatrixBase<BaseFloat> *params = NULL;
1113  BaseFloat orthonormal_constraint = 0.0;
1114 
1115  LinearComponent *lc = dynamic_cast<LinearComponent*>(component);
1116  if (lc != NULL && lc->OrthonormalConstraint() != 0.0) {
1117  orthonormal_constraint = lc->OrthonormalConstraint();
1118  params = &(lc->Params());
1119  }
1120  AffineComponent *ac = dynamic_cast<AffineComponent*>(component);
1121  if (ac != NULL && ac->OrthonormalConstraint() != 0.0) {
1122  orthonormal_constraint = ac->OrthonormalConstraint();
1123  params = &(ac->LinearParams());
1124  }
1125  TdnnComponent *tc = dynamic_cast<TdnnComponent*>(component);
1126  if (tc != NULL && tc->OrthonormalConstraint() != 0.0) {
1127  orthonormal_constraint = tc->OrthonormalConstraint();
1128  params = &(tc->LinearParams());
1129  }
1130  if (orthonormal_constraint == 0.0 || RandInt(0, 3) != 0) {
1131  // For efficiency, only do this every 4 or so minibatches-- it won't have
1132  // time stray far from the constraint in between.
1133  continue;
1134  }
1135 
1136  int32 rows = params->NumRows(), cols = params->NumCols();
1137  if (rows <= cols) {
1138  ConstrainOrthonormalInternal(orthonormal_constraint, params);
1139  } else {
1140  CuMatrix<BaseFloat> params_trans(*params, kTrans);
1141  ConstrainOrthonormalInternal(orthonormal_constraint, &params_trans);
1142  params->CopyFromMat(params_trans, kTrans);
1143  }
1144  }
1145 }
kaldi::int32 int32
void ConstrainOrthonormalInternal(BaseFloat scale, CuMatrixBase< BaseFloat > *M)
Definition: nnet-utils.cc:982
float BaseFloat
Definition: kaldi-types.h:29
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ ConstrainOrthonormalInternal()

void kaldi::nnet3::ConstrainOrthonormalInternal ( BaseFloat  scale,
CuMatrixBase< BaseFloat > *  M 
)

Definition at line 982 of file nnet-utils.cc.

References CuMatrixBase< Real >::AddMat(), CuMatrixBase< Real >::AddMatMat(), CuMatrixBase< Real >::AddToDiag(), CuMatrixBase< Real >::CopyLowerToUpper(), CuMatrixBase< Real >::FrobeniusNorm(), kaldi::GetVerboseLevel(), KALDI_ASSERT, KALDI_VLOG, kaldi::kNoTrans, kaldi::kTrans, CuMatrixBase< Real >::NumCols(), CuMatrixBase< Real >::NumRows(), CuMatrixBase< Real >::SymAddMat2(), CuMatrixBase< Real >::Trace(), and kaldi::TraceMatMat().

Referenced by ConstrainOrthonormal().

982  {
983  KALDI_ASSERT(scale != 0.0);
984 
985  // We'd like to enforce the rows of M to be orthonormal.
986  // define P = M M^T. If P is unit then M has orthonormal rows.
987  // We actually want P to equal scale^2 * I, so that M's rows are
988  // orthogonal with 2-norms equal to 'scale'.
989  // We (notionally) add to the objective function, the value
990  // -alpha times the sum of squared elements of Q = (P - scale^2 * I).
991  int32 rows = M->NumRows(), cols = M->NumCols();
992  CuMatrix<BaseFloat> M_update(rows, cols);
993  CuMatrix<BaseFloat> P(rows, rows);
994  P.SymAddMat2(1.0, *M, kNoTrans, 0.0);
995  P.CopyLowerToUpper();
996 
997  // The 'update_speed' is a constant that determines how fast we approach a
998  // matrix with the desired properties (larger -> faster). Larger values will
999  // update faster but will be more prone to instability. 0.125 (1/8) is the
1000  // value that gives us the fastest possible convergence when we are already
1001  // close to be a semi-orthogonal matrix (in fact, it will lead to quadratic
1002  // convergence).
1003  // See http://www.danielpovey.com/files/2018_interspeech_tdnnf.pdf
1004  // for more details.
1005  BaseFloat update_speed = 0.125;
1006  bool floating_scale = (scale < 0.0);
1007 
1008 
1009  if (floating_scale) {
1010  // This (letting the scale "float") is described in Sec. 2.3 of
1011  // http://www.danielpovey.com/files/2018_interspeech_tdnnf.pdf,
1012  // where 'scale' here is written 'alpha' in the paper.
1013  //
1014  // We pick the scale that will give us an update to M that is
1015  // orthogonal to M (viewed as a vector): i.e., if we're doing
1016  // an update M := M + X, then we want to have tr(M X^T) == 0.
1017  // The following formula is what gives us that.
1018  // With P = M M^T, our update formula is doing to be:
1019  // M := M + (-4 * alpha * (P - scale^2 I) * M).
1020  // (The math below explains this update formula; for now, it's
1021  // best to view it as an established fact).
1022  // So X (the change in M) is -4 * alpha * (P - scale^2 I) * M,
1023  // where alpha == update_speed / scale^2.
1024  // We want tr(M X^T) == 0. First, forget the -4*alpha, because
1025  // we don't care about constant factors. So we want:
1026  // tr(M * M^T * (P - scale^2 I)) == 0.
1027  // Since M M^T == P, that means:
1028  // tr(P^2 - scale^2 P) == 0,
1029  // or scale^2 = tr(P^2) / tr(P).
1030  // Note: P is symmetric so it doesn't matter whether we use tr(P P) or
1031  // tr(P^T P); we use tr(P^T P) because I believe it's faster to compute.
1032 
1033  BaseFloat trace_P = P.Trace(), trace_P_P = TraceMatMat(P, P, kTrans);
1034 
1035  scale = std::sqrt(trace_P_P / trace_P);
1036 
1037  // The following is a tweak to avoid divergence when the eigenvalues aren't
1038  // close to being the same. trace_P is the sum of eigenvalues of P, and
1039  // trace_P_P is the sum-square of eigenvalues of P. Treat trace_P as a sum
1040  // of positive values, and trace_P_P as their sumsq. Then mean = trace_P /
1041  // dim, and trace_P_P cannot be less than dim * (trace_P / dim)^2,
1042  // i.e. trace_P_P >= trace_P^2 / dim. If ratio = trace_P_P * dim /
1043  // trace_P^2, then ratio >= 1.0, and the excess above 1.0 is a measure of
1044  // how far we are from convergence. If we're far from convergence, we make
1045  // the learning rate slower to reduce the risk of divergence, since the
1046  // update may not be stable for starting points far from equilibrium.
1047  BaseFloat ratio = (trace_P_P * P.NumRows() / (trace_P * trace_P));
1048  KALDI_ASSERT(ratio > 0.99);
1049  if (ratio > 1.02) {
1050  update_speed *= 0.5; // Slow down the update speed to reduce the risk of divergence.
1051  if (ratio > 1.1) update_speed *= 0.5; // Slow it down even more.
1052  }
1053  }
1054 
1055  P.AddToDiag(-1.0 * scale * scale);
1056 
1057  // We may want to un-comment the following code block later on if we have a
1058  // problem with instability in setups with a non-floating orthonormal
1059  // constraint.
1060  /*
1061  if (!floating_scale) {
1062  // This is analogous to the stuff with 'ratio' above, but when we don't have
1063  // a floating scale. It reduces the chances of divergence when we have
1064  // a bad initialization.
1065  BaseFloat error = P.FrobeniusNorm(),
1066  error_proportion = error * error / P.NumRows();
1067  // 'error_proportion' is the sumsq of elements in (P - I) divided by the
1068  // sumsq of elements of I. It should be much less than one (i.e. close to
1069  // zero) if the error is small.
1070  if (error_proportion > 0.02) {
1071  update_speed *= 0.5;
1072  if (error_proportion > 0.1)
1073  update_speed *= 0.5;
1074  }
1075  }
1076  */
1077 
1078  if (GetVerboseLevel() >= 1) {
1079  BaseFloat error = P.FrobeniusNorm();
1080  KALDI_VLOG(2) << "Error in orthogonality is " << error;
1081  }
1082 
1083  // see Sec. 2.2 of http://www.danielpovey.com/files/2018_interspeech_tdnnf.pdf
1084  // for explanation of the 1/(scale*scale) factor, but there is a difference in
1085  // notation; 'scale' here corresponds to 'alpha' in the paper, and
1086  // 'update_speed' corresponds to 'nu' in the paper.
1087  BaseFloat alpha = update_speed / (scale * scale);
1088 
1089  // At this point, the matrix P contains what, in the math, would be Q =
1090  // P-scale^2*I. The derivative of the objective function w.r.t. an element q(i,j)
1091  // of Q is now equal to -2*alpha*q(i,j), i.e. we could write q_deriv(i,j)
1092  // = -2*alpha*q(i,j) This is also the derivative of the objective function
1093  // w.r.t. p(i,j): i.e. p_deriv(i,j) = -2*alpha*q(i,j).
1094  // Suppose we have define this matrix as 'P_deriv'.
1095  // The derivative of the objective w.r.t M equals
1096  // 2 * P_deriv * M, which equals -4*alpha*(P-scale^2*I)*M.
1097  // (Currently the matrix P contains what, in the math, is P-scale^2*I).
1098  M_update.AddMatMat(-4.0 * alpha, P, kNoTrans, *M, kNoTrans, 0.0);
1099  M->AddMat(1.0, M_update);
1100 }
int32 GetVerboseLevel()
Get verbosity level, usually set via command line &#39;–verbose=&#39; switch.
Definition: kaldi-error.h:60
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
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.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156

◆ ContainsSingleExample()

bool kaldi::nnet3::ContainsSingleExample ( const NnetExample eg,
int32 min_input_t,
int32 max_input_t,
int32 min_output_t,
int32 max_output_t 
)

Returns true if the "eg" contains just a single example, meaning that all the "n" values in the indexes are zero, and the example has NnetIo members named both "input" and "output".

Also computes the minimum and maximum "t" values in the "input" and "output" NnetIo members.

Definition at line 82 of file nnet3-copy-egs.cc.

References rnnlm::i, NnetIo::indexes, NnetExample::io, KALDI_ASSERT, KALDI_WARN, and NnetIo::name.

Referenced by SelectFromExample().

86  {
87  bool done_input = false, done_output = false;
88  int32 num_indexes = eg.io.size();
89  for (int32 i = 0; i < num_indexes; i++) {
90  const NnetIo &io = eg.io[i];
91  std::vector<Index>::const_iterator iter = io.indexes.begin(),
92  end = io.indexes.end();
93  // Should not have an empty input/output type.
94  KALDI_ASSERT(!io.indexes.empty());
95  if (io.name == "input" || io.name == "output") {
96  int32 min_t = iter->t, max_t = iter->t;
97  for (; iter != end; ++iter) {
98  int32 this_t = iter->t;
99  min_t = std::min(min_t, this_t);
100  max_t = std::max(max_t, this_t);
101  if (iter->n != 0) {
102  KALDI_WARN << "Example does not contain just a single example; "
103  << "too late to do frame selection or reduce context.";
104  return false;
105  }
106  }
107  if (io.name == "input") {
108  done_input = true;
109  *min_input_t = min_t;
110  *max_input_t = max_t;
111  } else {
112  KALDI_ASSERT(io.name == "output");
113  done_output = true;
114  *min_output_t = min_t;
115  *max_output_t = max_t;
116  }
117  } else {
118  for (; iter != end; ++iter) {
119  if (iter->n != 0) {
120  KALDI_WARN << "Example does not contain just a single example; "
121  << "too late to do frame selection or reduce context.";
122  return false;
123  }
124  }
125  }
126  }
127  if (!done_input) {
128  KALDI_WARN << "Example does not have any input named 'input'";
129  return false;
130  }
131  if (!done_output) {
132  KALDI_WARN << "Example does not have any output named 'output'";
133  return false;
134  }
135  return true;
136 }
kaldi::int32 int32
std::vector< Index > indexes
"indexes" is a vector the same length as features.NumRows(), explaining the meaning of each row of th...
Definition: nnet-example.h:42
#define KALDI_WARN
Definition: kaldi-error.h:150
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
std::string name
the name of the input in the neural net; in simple setups it will just be "input".
Definition: nnet-example.h:36
std::vector< NnetIo > io
"io" contains the input and output.
Definition: nnet-example.h:116

◆ ConvertAdditionToAssignment()

void ConvertAdditionToAssignment ( const Nnet nnet,
NnetComputation computation 
)

This converts addition operations (things with Add in their names) to copy operations (things with Copy in their names).

This is slightly more efficient, and it may later allow us to remove unnecessary zeroing.

Definition at line 430 of file nnet-optimize.cc.

References NnetComputation::Command::alpha, Analyzer::command_attributes, NnetComputation::Command::command_type, NnetComputation::commands, ComputationAnalysis::FirstNontrivialAccess(), Analyzer::Init(), kAddRows, kAddRowsMulti, kAddToRowsMulti, KALDI_ASSERT, KALDI_ERR, kCopyRows, kCopyRowsMulti, kCopyToRowsMulti, kMatrixAdd, and kMatrixCopy.

Referenced by Optimize().

431  {
432  Analyzer analyzer;
433  analyzer.Init(nnet, *computation);
434  ComputationAnalysis analysis(*computation, analyzer);
435  int32 num_commands = computation->commands.size();
436  for (int32 command = 0; command < num_commands; command++) {
437  NnetComputation::Command &c = computation->commands[command];
438  switch (c.command_type) {
439  case kMatrixAdd: case kAddRows: case kAddRowsMulti:
440  case kAddToRowsMulti: {
441  const std::vector<int32> &submatrices_written =
442  analyzer.command_attributes[command].submatrices_written;
443  KALDI_ASSERT(!submatrices_written.empty());
444  std::vector<int32>::const_iterator iter = submatrices_written.begin(),
445  end = submatrices_written.end();
446  bool can_convert = true;
447  for (; iter != end; ++iter) {
448  int32 submatrix_written = *iter;
449  int32 first_access_command = analysis.FirstNontrivialAccess(
450  submatrix_written);
451  // first_access_command is first command other than zeroing and
452  // allocation that accesses this submatrix. It can be assumed to be a
453  // write command, since it makes no sense to read a variable before
454  // it's written to. If it's before this command then we need to add
455  // rather than copy; we can't do the conversion to a copy command.
456  if (first_access_command != command) {
457  can_convert = false;
458  break;
459  }
460  }
461  if (can_convert) { // convert to a copy command.
462  switch (c.command_type) {
463  case kMatrixAdd: c.command_type = kMatrixCopy;
464  break;
465  case kAddRows: c.command_type = kCopyRows;
466  break;
467  case kAddRowsMulti: c.command_type = kCopyRowsMulti;
468  break;
469  // note: kCopyToRowsMulti does not currently support alpha != 1.0.
470  case kAddToRowsMulti: if (c.alpha == 1.0) c.command_type = kCopyToRowsMulti;
471  break;
472  default: KALDI_ERR << "Unexpected command type.";
473  }
474  }
475  break;
476  }
477  default:
478  break;
479  }
480  }
481 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ConvertNumNValues()

static void kaldi::nnet3::ConvertNumNValues ( int32  n_stride,
int32  old_N,
int32  new_N,
const std::vector< Index > &  indexes_in,
std::vector< Index > *  indexes_out 
)
static

Definition at line 3106 of file nnet-optimize-utils.cc.

References KALDI_ASSERT, Index::n, and rnnlm::n.

Referenced by ComputationExpander::ExpandIndexes(), and IoSpecificationIsDecomposable().

3108  {
3109  int32 size_in = indexes_in.size();
3110  KALDI_ASSERT(size_in > 0 && indexes_in[size_in - 1].n == old_N - 1);
3111  int32 block_size_in = n_stride * old_N,
3112  block_size_out = n_stride * new_N;
3113 
3114  indexes_out->resize((size_in / old_N) * new_N);
3115  for (int32 i_in = 0; i_in < size_in; i_in++) {
3116  if (indexes_in[i_in].n != 0)
3117  continue;
3118  Index index(indexes_in[i_in]);
3119  int32 block_index = i_in / block_size_in,
3120  offset_within_block = i_in % block_size_in;
3121 
3122 
3123  int32 i_out = block_index * block_size_out +
3124  offset_within_block;
3125  for (int32 n = 0; n < new_N; n++, i_out += n_stride) {
3126  index.n = n;
3127  (*indexes_out)[i_out] = index;
3128  }
3129  }
3130 }
kaldi::int32 int32
struct rnnlm::@11::@12 n
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ConvertRepeatedToBlockAffine() [1/2]

void kaldi::nnet3::ConvertRepeatedToBlockAffine ( CompositeComponent c_component)

Definition at line 447 of file nnet-utils.cc.

References CompositeComponent::GetComponent(), rnnlm::i, KALDI_ASSERT, CompositeComponent::NumComponents(), CompositeComponent::SetComponent(), and Component::Type().

Referenced by ConvertRepeatedToBlockAffine(), main(), UnitTestConvertRepeatedToBlockAffine(), and UnitTestConvertRepeatedToBlockAffineComposite().

447  {
448  for(int32 i = 0; i < c_component->NumComponents(); i++) {
449  const Component *c = c_component->GetComponent(i);
450  KALDI_ASSERT(c->Type() != "CompositeComponent" &&
451  "Nesting CompositeComponent within CompositeComponent is not allowed.\n"
452  "(We may change this as more complicated components are introduced.)");
453 
454  if(c->Type() == "RepeatedAffineComponent" ||
455  c->Type() == "NaturalGradientRepeatedAffineComponent") {
456  // N.B.: NaturalGradientRepeatedAffineComponent is a subclass of
457  // RepeatedAffineComponent.
458  const RepeatedAffineComponent *rac =
459  dynamic_cast<const RepeatedAffineComponent*>(c);
460  KALDI_ASSERT(rac != NULL);
461  BlockAffineComponent *bac = new BlockAffineComponent(*rac);
462  // following call deletes rac
463  c_component->SetComponent(i, bac);
464  }
465  }
466 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ConvertRepeatedToBlockAffine() [2/2]

void ConvertRepeatedToBlockAffine ( Nnet nnet)

Convert all components of type RepeatedAffineComponent or NaturalGradientRepeatedAffineComponent to BlockAffineComponent in nnet.

Definition at line 468 of file nnet-utils.cc.

References ConvertRepeatedToBlockAffine(), Nnet::GetComponent(), rnnlm::i, KALDI_ASSERT, Nnet::NumComponents(), Nnet::SetComponent(), and Component::Type().

468  {
469  for(int32 i = 0; i < nnet->NumComponents(); i++) {
470  const Component *const_c = nnet->GetComponent(i);
471  if(const_c->Type() == "RepeatedAffineComponent" ||
472  const_c->Type() == "NaturalGradientRepeatedAffineComponent") {
473  // N.B.: NaturalGradientRepeatedAffineComponent is a subclass of
474  // RepeatedAffineComponent.
475  const RepeatedAffineComponent *rac =
476  dynamic_cast<const RepeatedAffineComponent*>(const_c);
477  KALDI_ASSERT(rac != NULL);
478  BlockAffineComponent *bac = new BlockAffineComponent(*rac);
479  // following call deletes rac
480  nnet->SetComponent(i, bac);
481  } else if (const_c->Type() == "CompositeComponent") {
482  // We must modify the composite component, so we use the
483  // non-const GetComponent() call here.
484  Component *c = nnet->GetComponent(i);
485  CompositeComponent *cc = dynamic_cast<CompositeComponent*>(c);
486  KALDI_ASSERT(cc != NULL);
488  }
489  }
490 }
void ConvertRepeatedToBlockAffine(Nnet *nnet)
Convert all components of type RepeatedAffineComponent or NaturalGradientRepeatedAffineComponent to B...
Definition: nnet-utils.cc:468
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ConvertToIndexes()

bool ConvertToIndexes ( const std::vector< std::pair< int32, int32 > > &  location_vector,
int32 first_value,
std::vector< int32 > *  second_values 
)

If it is the case for some i >= 0 that all the .first elements of "location_vector" are either i or -1, then output i to first_value and the .second elements into "second_values", and return true.

Otherwise return false and the outputs are don't-cares.

Definition at line 190 of file nnet-compile-utils.cc.

Referenced by Compiler::CompileBackwardFromSubmatLocations(), Compiler::CompileForwardFromSubmatLocations(), SplitLocationsBackward(), UnitTestSplitLocations(), and UnitTestSplitLocationsBackward().

193  {
194  *first_value = -1;
195  second_values->clear();
196  second_values->reserve(location_vector.size());
197  std::vector<std::pair<int32, int32> >::const_iterator iter;
198  for (iter = location_vector.begin(); iter < location_vector.end(); ++iter) {
199  if (iter->first != -1) {
200  if (*first_value == -1)
201  *first_value = iter->first;
202  if (iter->first != *first_value)
203  return false;
204  second_values->push_back(iter->second);
205  } else {
206  second_values->push_back(-1);
207  }
208  }
209  return true;
210 }

◆ CopyPairVector() [1/2]

static void kaldi::nnet3::CopyPairVector ( const CuArray< Int32Pair > &  in,
std::vector< std::pair< int32, int32 > > *  out 
)
static

Definition at line 31 of file nnet-general-component.cc.

References CuArrayBase< T >::CopyToVec().

Referenced by StatisticsExtractionComponentPrecomputedIndexes::Read(), StatisticsPoolingComponentPrecomputedIndexes::Read(), StatisticsExtractionComponentPrecomputedIndexes::Write(), and StatisticsPoolingComponentPrecomputedIndexes::Write().

32  {
33  in.CopyToVec(reinterpret_cast<std::vector<Int32Pair>*>(out));
34 }
void CopyToVec(std::vector< T > *dst) const
This function resizes *dst if needed.
Definition: cu-array-inl.h:177

◆ CopyPairVector() [2/2]

static void kaldi::nnet3::CopyPairVector ( const std::vector< std::pair< int32, int32 > > &  in,
CuArray< Int32Pair > *  out 
)
static

Definition at line 36 of file nnet-general-component.cc.

References CuArray< T >::CopyFromVec().

37  {
38  const std::vector<Int32Pair> *in_cast =
39  reinterpret_cast<const std::vector<Int32Pair>*>(&in);
40  out->CopyFromVec(*in_cast);
41 }
void CopyFromVec(const std::vector< T > &src)
This function resizes if needed.
Definition: cu-array-inl.h:120

◆ CreateComputationRequestInternal()

static void kaldi::nnet3::CreateComputationRequestInternal ( int32  begin_input_t,
int32  end_input_t,
int32  begin_output_t,
int32  end_output_t,
int32  num_sequences,
int32  frame_subsampling_factor,
const std::set< int32 > &  ivector_times,
ComputationRequest request 
)
static

Definition at line 113 of file nnet-compile-looped.cc.

References ComputationRequest::inputs, rnnlm::n, and ComputationRequest::outputs.

Referenced by CreateLoopedComputationRequest().

119  {
120  request->inputs.reserve(2);
121  request->inputs.clear();
122  request->inputs.resize(1 + (ivector_times.empty() ? 0 : 1));
123  request->inputs[0].name = "input";
124  request->inputs[0].has_deriv = false;
125  request->outputs.clear();
126  request->outputs.resize(1);
127  request->outputs[0].name = "output";
128  request->outputs[0].has_deriv = false;
129  if (!ivector_times.empty()) {
130  request->inputs[1].name = "ivector";
131  request->inputs[1].has_deriv = false;
132  }
133 
134  // in the computation request the 'n' indexes (the sequence/utterance indexes)
135  // have the larger stride than 't', although this is opposite to the way it's
136  // done inside the computation. This is for user convenience where it may be
137  // easier to deal with submatrixes per sequence.
138  for (int32 n = 0; n < num_sequences; n++) {
139  int32 x = 0;
140  for (int32 t = begin_input_t; t < end_input_t; t++) {
141  request->inputs[0].indexes.push_back(Index(n, t, x));
142  }
143  for (int32 t = begin_output_t;
144  t < end_output_t;
145  t += frame_subsampling_factor)
146  request->outputs[0].indexes.push_back(Index(n, t, x));
147  }
148  if (!ivector_times.empty()) {
149  request->inputs.resize(2);
150  request->inputs[1].name = "ivector";
151  request->inputs[1].has_deriv = false;
152  for (int32 n = 0; n < num_sequences; n++) {
153  // note: std::sets store things in sorted order.
154  for (std::set<int32>::const_iterator iter = ivector_times.begin();
155  iter != ivector_times.end(); ++iter) {
156  int32 t = *iter, x = 0;
157  request->inputs[1].indexes.push_back(Index(n, t, x));
158  }
159  }
160  }
161 }
kaldi::int32 int32
struct rnnlm::@11::@12 n

◆ CreateLoopedComputationRequest()

void CreateLoopedComputationRequest ( const Nnet nnet,
int32  chunk_size,
int32  frame_subsampling_factor,
int32  ivector_period,
int32  left_context_begin,
int32  right_context,
int32  num_sequences,
ComputationRequest request1,
ComputationRequest request2,
ComputationRequest request3 
)

This function creates computation request suitable for giving to ComputeLooped().

It's intended for use with a 'simple' nnet (one satisfying IsSimpleNnet()), and this basically means that the inputs must be named "input" and possibly "ivector", and that there is an output named "output", and that those are the ones you care about (it won't generate any other outputs or use any other inputs).

If you want to use looped computation for different types of neural net, you should use the deeper interface, CompileLooped().

Parameters
[in]nnetThe neural net this computation request is to be used with. This is used to check whether the neural net accepts iVectors, and to work out the left-context and right-context required by the network.
[in]chunk_sizeThe number of frames of output that will be generated for each chunk (note: this is the shift in the t-index, which will not equal the number of output frames if frame_subsampling_factor != 1). Note: it is required that chunk_size be a multiple of ivector_period, frame_subsampling_factor, and nnet.Modulus(). You should use GetChunkSize() to compute the chunk size, giving it an advisory/ minimum chunksize, to make sure it satisfies these properties.
[in]frame_subsampling_factorThis will normally be 1, but may be more than 1 (e.g. 3) in chain systems; it determines the frame-skipping on the output, so we evaluate the output with 't' at multiples of this value.
[in]ivector_periodThe period with which iVectors are to be supplied to the network (if you're using iVectors). Not necessarily the same as the period with which the ivectors are extracted or stored on disk (–online-ivector-period). You will normally set this to the chunk size. It must divide the chunk size (if you're using iVectors) Note: you should call ModifyNnetIvectorPeriod on 'nnet' before calling this function; otherwise the neural net will most likely not actually be able to consume the iVector with this frequency.
[in]left_context_beginThis should be the left-context of the network plus any additional left-context (provided via the option –extra-left-context-begin) that should be supplied to the network on top of the minimum that the network requires. We call this left_context_begin because this only relates to the start of the utterance (t=0).
[in]right_contextThis should be the right-context of the network, plus any additional right-context ("extra-right-context") that should be supplied to the network on top of the minimum that the network requires (currently extra-right-context != 0 is is not supported at the command-line level).
[in]num_sequencesThe number of separate 'n' values to put in the computation; normally this will be just 1, but it can be increased to allow simultaneous operation on multiple streams of input.
[out]request1The first of the 3 requests that this function generates, that the user should then supply to CompileLooped(). Note: this will tend to be the largest computation request in terms of input, because we have to provide enough left and right context that it can evaluate the first chunk. Note: as elsewhere, the job of duplicating first and last frames enough to provide the required left/right context to the network, is left to the caller (at runtime, not during compilation).
[out]request2The second of the 3 requests that this function generates. Caution: none of the inputs and outputs should overlap.
[out]request3The third of the 3 requests that this function generates. It will be the same as request2, except for a time offset.

Definition at line 164 of file nnet-compile-looped.cc.

References CreateComputationRequestInternal(), Nnet::InputDim(), KALDI_ASSERT, Mod(), and Nnet::Modulus().

Referenced by CreateLoopedComputationRequestSimple(), and DecodableNnetSimpleLoopedInfo::Init().

173  {
174  bool has_ivector = (nnet.InputDim("ivector") > 0);
175  KALDI_ASSERT(chunk_size % frame_subsampling_factor == 0 &&
176  chunk_size % nnet.Modulus() == 0 &&
177  chunk_size % ivector_period == 0);
178  KALDI_ASSERT(left_context_begin >= 0 && right_context >= 0);
179  // note, 'end' is one past the last one.
180  int32 chunk1_input_begin_t = - left_context_begin,
181  chunk1_input_end_t = chunk_size + right_context,
182  chunk2_input_begin_t = chunk1_input_end_t,
183  chunk2_input_end_t = chunk2_input_begin_t + chunk_size,
184  chunk3_input_begin_t = chunk2_input_end_t,
185  chunk3_input_end_t = chunk3_input_begin_t + chunk_size;
186 
187 
188  // work out the times at which i-vectors are required.
189  std::set<int32> ivector_times1, ivector_times2, ivector_times3;
190  if (has_ivector) {
191  for (int32 t = chunk1_input_begin_t; t < chunk1_input_end_t; t++) {
192  int32 ivector_t = t - Mod(t, ivector_period);
193  ivector_times1.insert(ivector_t);
194  }
195  for (int32 t = chunk2_input_begin_t; t < chunk2_input_end_t; t++) {
196  int32 ivector_t = t - Mod(t, ivector_period);
197  if (ivector_times2.count(ivector_t) == 0 &&
198  ivector_times1.count(ivector_t) == 0)
199  ivector_times2.insert(ivector_t);
200  }
201  for (int32 t = chunk3_input_begin_t; t < chunk3_input_end_t; t++) {
202  int32 ivector_t = t - Mod(t, ivector_period);
203  if (ivector_times3.count(ivector_t) == 0 &&
204  ivector_times2.count(ivector_t) == 0 &&
205  ivector_times1.count(ivector_t) == 0)
206  ivector_times3.insert(ivector_t);
207  }
208  }
209 
211  chunk1_input_begin_t, chunk1_input_end_t,
212  0, chunk_size,
213  num_sequences, frame_subsampling_factor,
214  ivector_times1,
215  request1);
216 
218  chunk2_input_begin_t, chunk2_input_end_t,
219  chunk_size, chunk_size * 2,
220  num_sequences, frame_subsampling_factor,
221  ivector_times2,
222  request2);
223 
225  chunk3_input_begin_t, chunk3_input_end_t,
226  chunk_size * 2, chunk_size * 3,
227  num_sequences, frame_subsampling_factor,
228  ivector_times3,
229  request3);
230 
231 }
static void CreateComputationRequestInternal(int32 begin_input_t, int32 end_input_t, int32 begin_output_t, int32 end_output_t, int32 num_sequences, int32 frame_subsampling_factor, const std::set< int32 > &ivector_times, ComputationRequest *request)
kaldi::int32 int32
I Mod(I m, I n)
Mod(m, n), defined for integers m and n where n > 0, returns the modulus m % n, defined as the intege...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ CreateLoopedComputationRequestSimple()

void CreateLoopedComputationRequestSimple ( const Nnet nnet,
int32  chunk_size,
int32  frame_subsampling_factor,
int32  ivector_period,
int32  extra_left_context_begin,
int32  extra_right_context,
int32  num_sequences,
ComputationRequest request1,
ComputationRequest request2,
ComputationRequest request3 
)

This function is deprecated.

It has the same interface as CreateLoopedComputationRequest(), except that the left and right context are specified in a different way (as just the 'extra' part). It is deprecated because this function has to work out the left and right context of the network, which turns out to be quite slow if it's done after you call ModifyNnetIvectorPeriod().

Definition at line 361 of file nnet-compile-looped.cc.

References ComputeSimpleNnetContext(), and CreateLoopedComputationRequest().

Referenced by UnitTestNnetCompileLooped().

370  {
371  int32 left_context, right_context;
372  ComputeSimpleNnetContext(nnet, &left_context, &right_context);
373 
374  CreateLoopedComputationRequest(nnet, chunk_size, frame_subsampling_factor,
375  ivector_period,
376  extra_left_context_begin + left_context,
377  extra_right_context + right_context,
378  num_sequences, request1, request2, request3);
379 }
void CreateLoopedComputationRequest(const Nnet &nnet, int32 chunk_size, int32 frame_subsampling_factor, int32 ivector_period, int32 left_context_begin, int32 right_context, int32 num_sequences, ComputationRequest *request1, ComputationRequest *request2, ComputationRequest *request3)
This function creates computation request suitable for giving to ComputeLooped(). ...
kaldi::int32 int32
void ComputeSimpleNnetContext(const Nnet &nnet, int32 *left_context, int32 *right_context)
ComputeSimpleNnetContext computes the left-context and right-context of a nnet.
Definition: nnet-utils.cc:146

◆ DescriptorTokenize()

bool DescriptorTokenize ( const std::string &  input,
std::vector< std::string > *  tokens 
)

This function tokenizes input when parsing Descriptor configuration values.

A token in this context is not the same as a generic Kaldi token, e.g. as defined in IsToken() in util/text_utils.h, which just means a non-empty whitespace-free string. Here a token is more like a programming-language token, and currently the following are allowed as tokens: "(" ")" ","

  • A nonempty string beginning with A-Za-z_, and containing only -_A-Za-z0-9.
  • An integer, optionally beginning with - or + and then a nonempty sequence of 0-9.

This function should return false and print an informative error with local context if it can't tokenize the input.

Definition at line 30 of file nnet-parse.cc.

References kaldi::ConvertStringToReal(), ErrorContext(), kaldi::IsValidName(), KALDI_ASSERT, and KALDI_WARN.

Referenced by NormalizeTextDescriptor(), Nnet::ProcessComponentNodeConfigLine(), Nnet::ProcessOutputNodeConfigLine(), Nnet::RemoveSomeNodes(), ModelCollapser::ReplaceNodeInDescriptor(), UnitTestDescriptorIo(), UnitTestDescriptorTokenize(), and UnitTestGeneralDescriptor().

31  {
32  KALDI_ASSERT(tokens != NULL);
33  size_t start = input.find_first_not_of(" \t"), size = input.size();
34  tokens->clear();
35  while (start < size) {
36  KALDI_ASSERT(!isspace(input[start]));
37  if (input[start] == '(' || input[start] == ')' || input[start] == ',') {
38  tokens->push_back(std::string(input, start, 1));
39  start = input.find_first_not_of(" \t", start + 1);
40  } else {
41  size_t found = input.find_first_of(" \t(),", start);
42  KALDI_ASSERT(found != start);
43  if (found == std::string::npos) {
44  std::string str(input, start, input.size() - start);
45  BaseFloat tmp;
46  if (!IsValidName(str) && !ConvertStringToReal(str, &tmp)) {
47  KALDI_WARN << "Could not tokenize line " << ErrorContext(std::string(input, start));
48  return false;
49  }
50  tokens->push_back(str);
51  break;
52  } else {
53  if (input[found] == '(' || input[found] == ')' || input[found] == ',') {
54  std::string str(input, start, found - start);
55  BaseFloat tmp;
56  if (!IsValidName(str) && !ConvertStringToReal(str, &tmp)) {
57  KALDI_WARN << "Could not tokenize line " << ErrorContext(std::string(input, start));
58  return false;
59  }
60  tokens->push_back(str);
61  start = found;
62  } else {
63  std::string str(input, start, found - start);
64  BaseFloat tmp;
65  if (!IsValidName(str) && !ConvertStringToReal(str, &tmp)) {
66  KALDI_WARN << "Could not tokenize line " << ErrorContext(std::string(input, start));
67  return false;
68  }
69  tokens->push_back(str);
70  start = input.find_first_not_of(" \t", found);
71  }
72  }
73  }
74  }
75  return true;
76 }
bool IsValidName(const std::string &name)
Returns true if &#39;name&#39; would be a valid name for a component or node in a nnet3Nnet.
Definition: text-utils.cc:553
float BaseFloat
Definition: kaldi-types.h:29
std::string ErrorContext(const std::string &str)
Definition: nnet-parse.cc:88
bool ConvertStringToReal(const std::string &str, T *out)
ConvertStringToReal converts a string into either float or double and returns false if there was any ...
Definition: text-utils.cc:238
#define KALDI_WARN
Definition: kaldi-error.h:150
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ DivideIntoPieces()

void kaldi::nnet3::DivideIntoPieces ( int32  a,
int32  b,
std::vector< int32 > *  pieces 
)

This function divides the number 'a' into 'b' pieces, such that the sum of the pieces equals 'a' and no two pieces differ by more than 1.

Parameters
[in]aA number, may be positive or negative
[in]bThe number of pieces, b >= 1.
[out]piecesThe pieces will be written to here. At exit, their sum will equal a, and none of them will differ from any other by more than 1. Otherwise they are arbitrarily chosen.

Definition at line 72 of file nnet3-xvector-compute-batched.cc.

References rnnlm::i, and KALDI_ASSERT.

Referenced by BatchedXvectorComputer::SplitUtteranceIntoChunks().

72  {
73  KALDI_ASSERT(b > 0);
74  pieces->clear();
75  pieces->reserve(b);
76  int32 a_sign = 1;
77  // Make sure a is positive before division, because the behavior of division
78  // with negative operands is not fully defined in C.
79  if (a < 0) {
80  a_sign = -1;
81  a *= -1;
82  }
83  int32 piece_size1 = a / b,
84  piece_size2 = piece_size1 + 1,
85  remainder = a % b;
86  int32 num_pieces_of_size1 = b - remainder,
87  num_pieces_of_size2 = remainder;
88  KALDI_ASSERT(a == num_pieces_of_size1 * piece_size1 +
89  num_pieces_of_size2 * piece_size2);
90 
91  for (int32 i = 0; i < num_pieces_of_size1; i++)
92  pieces->push_back(piece_size1 * a_sign);
93  for (int32 i = 0; i < num_pieces_of_size2; i++)
94  pieces->push_back(piece_size2 * a_sign);
95 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ DotProduct()

BaseFloat DotProduct ( const Nnet nnet1,
const Nnet nnet2 
)

Returns dot product between two networks of the same structure (calls the DotProduct functions of the Updatable components and sums up the return values).

Definition at line 250 of file nnet-utils.cc.

References UpdatableComponent::DotProduct(), Nnet::GetComponent(), KALDI_ASSERT, kUpdatableComponent, Nnet::NumComponents(), and Component::Properties().

Referenced by AffineComponent::BackpropNeedsOutput(), BlockAffineComponent::BackpropNeedsOutput(), Convolutional1dComponent::BackpropNeedsOutput(), LstmNonlinearityComponent::ConsolidateMemory(), ScaleAndOffsetComponent::Copy(), ConstantComponent::IsComputable(), LinearComponent::LinearComponent(), AffineComponent::Properties(), BlockAffineComponent::Properties(), RepeatedAffineComponent::Properties(), PerElementScaleComponent::Properties(), PerElementOffsetComponent::Properties(), ConstantFunctionComponent::Properties(), NnetDiscriminativeTrainer::Train(), CompositeComponent::Type(), UnitTestNnetModelDerivatives(), and UpdatableComponent::~UpdatableComponent().

251  {
252  KALDI_ASSERT(nnet1.NumComponents() == nnet2.NumComponents());
253  BaseFloat ans = 0.0;
254  for (int32 c = 0; c < nnet1.NumComponents(); c++) {
255  const Component *comp1 = nnet1.GetComponent(c),
256  *comp2 = nnet2.GetComponent(c);
257  if (comp1->Properties() & kUpdatableComponent) {
258  const UpdatableComponent
259  *u_comp1 = dynamic_cast<const UpdatableComponent*>(comp1),
260  *u_comp2 = dynamic_cast<const UpdatableComponent*>(comp2);
261  KALDI_ASSERT(u_comp1 != NULL && u_comp2 != NULL);
262  ans += u_comp1->DotProduct(*u_comp2);
263  }
264  }
265  return ans;
266 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ EnsureContiguousProperty()

void EnsureContiguousProperty ( const std::vector< int32 > &  indexes,
std::vector< std::vector< int32 > > *  indexes_out 
)

This function takes a vector of indexes and splits it up into as separate vectors of the same size, as needed to ensure that the 'contiguous property' holds.

This is done via padding with -1's. An example will clarify this. Suppose the input is: [ -1 1 1 1 2 2 1 1 ] which lacks the contiguous property because 1's appear in 2 different places, it would split it up as [ -1 1 1 1 2 2 -1 -1 ] [ -1 -1 -1 -1 -1 -1 1 1 ] If 'indexes' is empty or only contains -1's, 'indexes_out' will be empty.

Definition at line 214 of file nnet-compile-utils.cc.

References rnnlm::i.

Referenced by SplitLocationsBackward(), and UnitTestEnsureContiguousProperty().

216  {
217  indexes_out->clear();
218  indexes_out->reserve(3);
219  if (indexes.empty()) return;
220  int32 max_value = *std::max_element(indexes.begin(), indexes.end());
221  if (max_value == -1) return;
222  std::vector<int32> num_segments_seen(max_value + 1, 0);
223  int32 dim = indexes.size(), num_output_vectors = 0;
224  for (int32 i = 0; i < dim;) {
225  // note, we increment i within the loop.
226  if (indexes[i] == -1) {
227  i++;
228  continue;
229  }
230  int32 value = indexes[i], start_index = i;
231  for (; i < dim && indexes[i] == value; i++);
232  int32 end_index = i; // one past the end.
233  // the input 'indexes' contains a sequence of possibly-repeated instances of
234  // the value 'value', starting at index 'start_index', with 'end_index' as
235  // one past the end.
236  int32 this_num_segments_seen = num_segments_seen[value]++;
237  if (this_num_segments_seen >= num_output_vectors) { // we have nowhere to
238  // put it.
239  indexes_out->resize(++num_output_vectors);
240  indexes_out->back().resize(dim, -1); // fill newly added vector with -1's.
241  }
242  std::vector<int32> &this_out_vec((*indexes_out)[this_num_segments_seen]);
243  std::vector<int32>::iterator iter = this_out_vec.begin() + start_index,
244  end = this_out_vec.begin() + end_index;
245  // Fill the appropriate range of the output vector with 'value'
246  for (; iter != end; ++iter) *iter = value;
247  }
248 }
kaldi::int32 int32

◆ ErrorContext() [1/2]

std::string ErrorContext ( std::istream &  is)

Return a string used in error messages.

Here, "is" will be from an istringstream derived from a single line or part of a line. If "is" is at EOF or in error state, this should just say "end of line", else if the contents of "is" before EOF is <20 characters it should return it all, else it should return the first 20 characters followed by "...".

Definition at line 78 of file nnet-parse.cc.

Referenced by DescriptorTokenize().

78  {
79  if (!is.good()) return "end of line";
80  char buf[21];
81  is.read(buf, 21);
82  if (is) {
83  return (std::string(buf, 20) + "...");
84  }
85  return std::string(buf, is.gcount());
86 }

◆ ErrorContext() [2/2]

std::string ErrorContext ( const std::string &  str)

Definition at line 88 of file nnet-parse.cc.

88  {
89  if (str.size() == 0) return "end of line";
90  if (str.size() <= 20) return str;
91  return std::string(str, 0, 20) + "...";
92 }

◆ EvaluateComputationRequest()

void EvaluateComputationRequest ( const Nnet nnet,
const ComputationRequest request,
std::vector< std::vector< bool > > *  is_computable 
)

Given an nnet and a computation request, this function works out which requested outputs in the computation request are computable; it outputs this information as a vector "is_computable" indexed by the same indexes as request.outputs.

It does this by executing some of the early stages of compilation.

Definition at line 71 of file nnet-utils.cc.

References ComputationGraphBuilder::Compute(), ComputationGraphBuilder::GetComputableInfo(), Nnet::GetNodeNames(), kaldi::GetVerboseLevel(), KALDI_VLOG, and ComputationGraph::Print().

Referenced by ComputeSimpleNnetContextForShift().

74  {
75  ComputationGraph graph;
76  ComputationGraphBuilder builder(nnet, &graph);
77  builder.Compute(request);
78  builder.GetComputableInfo(is_computable);
79  if (GetVerboseLevel() >= 4) {
80  std::ostringstream graph_pretty;
81  graph.Print(graph_pretty, nnet.GetNodeNames());
82  KALDI_VLOG(4) << "Graph is " << graph_pretty.str();
83  }
84 }
int32 GetVerboseLevel()
Get verbosity level, usually set via command line &#39;–verbose=&#39; switch.
Definition: kaldi-error.h:60
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156

◆ ExampleApproxEqual()

bool ExampleApproxEqual ( const NnetExample eg1,
const NnetExample eg2,
BaseFloat  delta 
)

Returns true if the examples are approximately equal (only intended to be used in testing).

Definition at line 1885 of file nnet-test-utils.cc.

References kaldi::ApproxEqual(), NnetIo::features, GeneralMatrix::GetMatrix(), rnnlm::i, NnetIo::indexes, NnetExample::io, and NnetIo::name.

Referenced by NnetGenerationOptions::NnetGenerationOptions(), and UnitTestNnetExample().

1887  {
1888  if (eg1.io.size() != eg2.io.size())
1889  return false;
1890  for (size_t i = 0; i < eg1.io.size(); i++) {
1891  NnetIo io1 = eg1.io[i], io2 = eg2.io[i];
1892  if (io1.name != io2.name || io1.indexes != io2.indexes)
1893  return false;
1894  Matrix<BaseFloat> feat1, feat2;
1895  io1.features.GetMatrix(&feat1);
1896  io2.features.GetMatrix(&feat2);
1897  if (!ApproxEqual(feat1, feat2, delta))
1898  return false;
1899  }
1900  return true;
1901 }
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
Definition: kaldi-math.h:265

◆ ExpandComputation()

void ExpandComputation ( const Nnet nnet,
const MiscComputationInfo misc_info,
const NnetComputation computation,
bool  need_debug_info,
int32  num_n_values,
NnetComputation expanded_computation 
)

This function is used in 'shortcut' compilation to expand a computation that has been compiled for exactly 2 'n' values, to one that is suitable for some num_n_values > 2.

Parameters
[in]nnetThe neural network for which this computation is being built.
[in]misc_infoThe same MiscComputationInfo object that was present in the ComputationRequests that were originally used to generate the computation (required to generated the PrecomputedIndexes)
[in]computationThe computation that was compiled for exactly 2 'n' values (n=0 and n=1)
[in]need_debug_infoTrue if we want to retain the 'debug_info' in the output 'expanded_computation'. In any case, the 'debug_info' is required in the input computation.
[in]num_n_valuesThe number of 'n' values we want in the output computation
[out]expanded_computationThe expanded computation.

Definition at line 3804 of file nnet-optimize-utils.cc.

References ComputationExpander::Expand().

Referenced by CachingOptimizingCompiler::CompileViaShortcut().

3809  {
3810  ComputationExpander expander(nnet, misc_info, computation,
3811  need_debug_info, num_n_values,
3812  expanded_computation);
3813  expander.Expand();
3814 }

◆ ExpectToken()

static void kaldi::nnet3::ExpectToken ( const std::string &  token,
const std::string &  what_we_are_parsing,
const std::string **  next_token 
)
static

Definition at line 45 of file nnet-descriptor.cc.

References KALDI_ERR, and ParsingContext().

Referenced by LstmNonlinearityComponent::ConsolidateMemory(), GeneralDescriptor::Parse(), GeneralDescriptor::ParseConst(), GeneralDescriptor::ParseFailover(), GeneralDescriptor::ParseIfDefined(), GeneralDescriptor::ParseOffset(), GeneralDescriptor::ParseReplaceIndex(), GeneralDescriptor::ParseRound(), GeneralDescriptor::ParseScale(), AmNnetSimple::Read(), PnormComponent::Read(), Index::Read(), DistributeComponent::Read(), NnetIo::Read(), NnetDiscriminativeSupervision::Read(), IoSpecification::Read(), NormalizeComponent::Read(), NnetChainSupervision::Read(), NnetDiscriminativeExample::Read(), NnetExample::Read(), DropoutComponent::Read(), NnetChainExample::Read(), NnetOptimizeOptions::Read(), DistributeComponentPrecomputedIndexes::Read(), RestrictedAttentionComponent::Read(), ComputationRequest::Read(), ConvolutionComponent::Read(), ElementwiseProductComponent::Read(), RestrictedAttentionComponent::PrecomputedIndexes::Read(), BatchNormComponent::Read(), Nnet::Read(), StatisticsExtractionComponent::Read(), ConvolutionModel::Read(), TimeHeightConvolutionComponent::Read(), TimeHeightConvolutionComponent::PrecomputedIndexes::Read(), StatisticsExtractionComponentPrecomputedIndexes::Read(), NnetComputation::MatrixInfo::Read(), NnetComputation::MatrixDebugInfo::Read(), NnetComputation::SubMatrixInfo::Read(), ConvolutionComputation::Read(), LstmNonlinearityComponent::Read(), NnetComputation::Command::Read(), StatisticsPoolingComponent::Read(), ConvolutionComputationIo::Read(), AffineComponent::Read(), StatisticsPoolingComponentPrecomputedIndexes::Read(), NnetComputation::Read(), TdnnComponent::Read(), BackpropTruncationComponent::Read(), MaxpoolingComponent::Read(), BlockAffineComponent::Read(), TdnnComponent::PrecomputedIndexes::Read(), BackpropTruncationComponentPrecomputedIndexes::Read(), RepeatedAffineComponent::Read(), NonlinearComponent::Read(), ComputationCache::Read(), ConstantComponent::Read(), DropoutMaskComponent::Read(), NaturalGradientAffineComponent::Read(), GeneralDropoutComponent::Read(), LinearComponent::Read(), GeneralDropoutComponentPrecomputedIndexes::Read(), FixedAffineComponent::Read(), SpecAugmentTimeMaskComponent::Read(), SpecAugmentTimeMaskComponentPrecomputedIndexes::Read(), FixedScaleComponent::Read(), FixedBiasComponent::Read(), NoOpComponent::Read(), SumBlockComponent::Read(), ClipGradientComponent::Read(), PermuteComponent::Read(), PerElementScaleComponent::Read(), PerElementOffsetComponent::Read(), ConstantFunctionComponent::Read(), NaturalGradientPerElementScaleComponent::Read(), ScaleAndOffsetComponent::Read(), CompositeComponent::Read(), ReadCindexVector(), and ReadIndexVector().

47  {
48  if (**next_token != token)
49  KALDI_ERR << "Expected '" << token << "' while parsing "
50  << what_we_are_parsing << ", got "
51  << **next_token << ParsingContext(*next_token);
52  else // advance token pointer.
53  (*next_token)++;
54 }
static std::string ParsingContext(const std::string *token_ptr)
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ ExtendMatrices()

void ExtendMatrices ( NnetComputation computation)

This is not really an optimization in itself but it can make things easier for class VariableMergingOptimizer (usually called by its wrapper VariableMergingOptimization()).

It looks for a case where most of a matrix (but not its final rows) are copied to some submatrix of another matrix, where the row-range of that submatrix extends to the last row of the other matrix; and it extends the other matrix with additional rows so that the entire source matrix can be copied to the destination.

Definition at line 1270 of file nnet-optimize-utils.cc.

References MatrixExtender::ExtendMatrices().

Referenced by Optimize().

1270  {
1271  MatrixExtender ext(computation);
1272  ext.ExtendMatrices();
1273 }

◆ ExtrapolateComputationRequest()

static bool kaldi::nnet3::ExtrapolateComputationRequest ( const ComputationRequest request1,
const ComputationRequest request2,
ComputationRequest request3 
)
static

Definition at line 251 of file nnet-compile-looped.cc.

References AddTimeOffsetToComputationRequest(), ComputationRequest::inputs, and KALDI_ASSERT.

Referenced by CompileLoopedInternal().

254  {
255  // accepts two computation requests 'request1' and 'request2' that
256  // must be identical except for a time offset, and creates 'request3'
257  // that is the extrapolation of the next term in sequence.
258  *request3 = request2;
259  KALDI_ASSERT(!request1.inputs.empty() && !request1.inputs[0].indexes.empty() &&
260  !request2.inputs.empty() && !request2.inputs[0].indexes.empty());
261  int32 t_offset = request2.inputs[0].indexes[0].t -
262  request1.inputs[0].indexes[0].t;
263  // the following is just to make sure that the inputs are structurally
264  // equivalent.
265  AddTimeOffsetToComputationRequest(-t_offset, request3);
266  if (!(*request3 == request1))
267  return false; // there is somse structural difference, or
268  // the time offset is not consistent.
269  // the following reverses the last call to AddTimeOffsetToComputationRequest,
270  // then adds the offset we want.
271  AddTimeOffsetToComputationRequest(2 * t_offset, request3);
272  return true;
273 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void AddTimeOffsetToComputationRequest(int32 t_offset, ComputationRequest *request)

◆ FilterExample()

void kaldi::nnet3::FilterExample ( const NnetExample eg,
int32  min_input_t,
int32  max_input_t,
int32  min_output_t,
int32  max_output_t,
NnetExample eg_out 
)

This function filters the indexes (and associated feature rows) in a NnetExample, removing any index/row in an NnetIo named "input" with t < min_input_t or t > max_input_t and any index/row in an NnetIo named "output" with t < min_output_t or t > max_output_t.

Will crash if filtering removes all Indexes of "input" or "output".

Definition at line 145 of file nnet3-copy-egs.cc.

References NnetIo::features, kaldi::FilterGeneralMatrixRows(), rnnlm::i, NnetIo::indexes, NnetExample::io, KALDI_ASSERT, KALDI_ERR, NnetIo::name, and GeneralMatrix::NumRows().

Referenced by SelectFromExample().

150  {
151  eg_out->io.clear();
152  eg_out->io.resize(eg.io.size());
153  for (size_t i = 0; i < eg.io.size(); i++) {
154  bool is_input_or_output;
155  int32 min_t, max_t;
156  const NnetIo &io_in = eg.io[i];
157  NnetIo &io_out = eg_out->io[i];
158  const std::string &name = io_in.name;
159  io_out.name = name;
160  if (name == "input") {
161  min_t = min_input_t;
162  max_t = max_input_t;
163  is_input_or_output = true;
164  } else if (name == "output") {
165  min_t = min_output_t;
166  max_t = max_output_t;
167  is_input_or_output = true;
168  } else {
169  is_input_or_output = false;
170  }
171  if (!is_input_or_output) { // Just copy everything.
172  io_out.indexes = io_in.indexes;
173  io_out.features = io_in.features;
174  } else {
175  const std::vector<Index> &indexes_in = io_in.indexes;
176  std::vector<Index> &indexes_out = io_out.indexes;
177  indexes_out.reserve(indexes_in.size());
178  int32 num_indexes = indexes_in.size(), num_kept = 0;
179  KALDI_ASSERT(io_in.features.NumRows() == num_indexes);
180  std::vector<bool> keep(num_indexes, false);
181  std::vector<Index>::const_iterator iter_in = indexes_in.begin(),
182  end_in = indexes_in.end();
183  std::vector<bool>::iterator iter_out = keep.begin();
184  for (; iter_in != end_in; ++iter_in,++iter_out) {
185  int32 t = iter_in->t;
186  bool is_within_range = (t >= min_t && t <= max_t);
187  *iter_out = is_within_range;
188  if (is_within_range) {
189  indexes_out.push_back(*iter_in);
190  num_kept++;
191  }
192  }
193  KALDI_ASSERT(iter_out == keep.end());
194  if (num_kept == 0)
195  KALDI_ERR << "FilterExample removed all indexes for '" << name << "'";
196 
197  FilterGeneralMatrixRows(io_in.features, keep,
198  &io_out.features);
199  KALDI_ASSERT(io_out.features.NumRows() == num_kept &&
200  indexes_out.size() == static_cast<size_t>(num_kept));
201  }
202  }
203 }
kaldi::int32 int32
GeneralMatrix features
The features or labels.
Definition: nnet-example.h:46
std::vector< Index > indexes
"indexes" is a vector the same length as features.NumRows(), explaining the meaning of each row of th...
Definition: nnet-example.h:42
void FilterGeneralMatrixRows(const GeneralMatrix &in, const std::vector< bool > &keep_rows, GeneralMatrix *out)
Outputs a GeneralMatrix containing only the rows r of "in" such that keep_rows[r] == true...
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
MatrixIndexT NumRows() const
std::string name
the name of the input in the neural net; in simple setups it will just be "input".
Definition: nnet-example.h:36
std::vector< NnetIo > io
"io" contains the input and output.
Definition: nnet-example.h:116

◆ FindNStride() [1/2]

static int32 kaldi::nnet3::FindNStride ( const std::vector< Index > &  indexes,
bool  full_check 
)
static

Definition at line 2942 of file nnet-optimize-utils.cc.

References rnnlm::i, rnnlm::j, KALDI_ASSERT, Index::n, rnnlm::n, kaldi::RandInt(), and kaldi::SortAndUniq().

Referenced by ComputationExpander::ExpandIndexes(), ComputationExpander::InitStrideInfo(), and IoSpecificationIsDecomposable().

2943  {
2944  // First find candidate stride. Later we'll check for consistency.
2945  int32 size = indexes.size();
2946  KALDI_ASSERT(size > 0);
2947  int32 N = indexes[size-1].n + 1,
2948  n_stride = -1;
2949  if (N <= 1) {
2950  // we wouldn't be able to determine the stride if N <= 1.
2951  return 0;
2952  }
2953  Index index(indexes[0]);
2954  if (index.n != 0 || size % N != 0) {
2955  // for the n stride to be positive, we must start with an index with n == 0.
2956  // if indexes.size() is not divisible by N, we have no hope of finding the
2957  // regular structure.
2958  return 0;
2959  }
2960  index.n = 1;
2961  // First check the two most common strides, which are 1
2962  // and size / N.
2963  if (indexes[1] == index) {
2964  n_stride = 1;
2965  } else if (indexes[size / N] == index) {
2966  n_stride = size / N;
2967  } else {
2968  int32 stride;
2969  // try the other possible strides one by one (for subsampling
2970  // layers of convnets, we might see strides of 2, for instance).
2971  for (stride = 2; stride < size / N; stride++) {
2972  if (size % stride == 0 && indexes[stride] == index) {
2973  n_stride = stride;
2974  break;
2975  }
2976  }
2977  if (n_stride == -1) {
2978  // if we fell off the loop then we found no candidates, which is strange
2979  // and means we did not find the expected structure; we'll return 0 as we
2980  // failed.
2981  return 0;
2982  }
2983  }
2984  // Now is the checking phase.
2985 
2986  // to understand block_size, see the comment above this functcion.
2987  int32 block_size = n_stride * N;
2988 
2989  std::vector<int32> indexes_to_check;
2990  if (full_check) {
2991  indexes_to_check.resize(size);
2992  for (int32 i = 0; i < size; i++)
2993  indexes_to_check[i] = i;
2994  } else {
2995  int32 num_to_check = std::min<int32>(5, size);
2996  indexes_to_check.resize(num_to_check);
2997  for (int32 j = 0; j < num_to_check; j++)
2998  indexes_to_check[j] = RandInt(0, size - 1);
2999  SortAndUniq(&indexes_to_check);
3000  }
3001  for (std::vector<int32>::iterator iter = indexes_to_check.begin();
3002  iter != indexes_to_check.end(); ++iter) {
3003  int32 i = *iter;
3004  Index index = indexes[i];
3005  int32 n = index.n;
3006  if (n < N - 1) {
3007  index.n = n + 1;
3008  if (i + n_stride >= size || indexes[i + n_stride] != index)
3009  return 0;
3010  }
3011  if (n == 0) {
3012  if (i / block_size != (i + n_stride * (N-1)) / block_size) {
3013  // this is a check that the input divides into blocks of size n_stride *
3014  // N and the N different versions of the same Index are always within a
3015  // block (i.e. that the n stride never crosses over the block; having
3016  // the same Index repeated within different blocks actually would not
3017  // matter).
3018  return 0;
3019  }
3020  } else { // n > 0
3021  index.n = n - 1;
3022  if (i - n_stride < 0 || indexes[i - n_stride] != index)
3023  return 0;
3024  }
3025  }
3026  return n_stride;
3027 }
kaldi::int32 int32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
struct rnnlm::@11::@12 n
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ FindNStride() [2/2]

static int32 kaldi::nnet3::FindNStride ( const std::vector< Cindex > &  cindexes,
bool  full_check 
)
static

Definition at line 3033 of file nnet-optimize-utils.cc.

References rnnlm::i, rnnlm::j, KALDI_ASSERT, rnnlm::n, kaldi::RandInt(), and kaldi::SortAndUniq().

3034  {
3035  int32 size = cindexes.size();
3036  KALDI_ASSERT(size > 0);
3037  int32 N = cindexes[size-1].second.n + 1,
3038  n_stride = 0;
3039  if (N <= 1)
3040  return 0;
3041  Cindex cindex(cindexes[0]);
3042  if (cindex.second.n != 0 || size % N != 0)
3043  return 0;
3044  cindex.second.n = 1;
3045  if (cindexes[1] == cindex) {
3046  n_stride = 1;
3047  } else if (cindexes[size / N] == cindex) {
3048  n_stride = size / N;
3049  } else {
3050  int32 stride;
3051  for (stride = 2; stride < size / N; stride++) {
3052  if (size % stride == 0 && cindexes[stride] == cindex) {
3053  n_stride = stride;
3054  break;
3055  }
3056  }
3057  if (stride == size / N)
3058  return 0;
3059  }
3060  int32 block_size = n_stride * N;
3061  std::vector<int32> indexes_to_check;
3062  if (full_check) {
3063  indexes_to_check.resize(size);
3064  for (int32 i = 0; i < size; i++)
3065  indexes_to_check[i] = i;
3066  } else {
3067  int32 num_to_check = std::min<int32>(5, size);
3068  indexes_to_check.resize(num_to_check);
3069  for (int32 j = 0; j < num_to_check; j++)
3070  indexes_to_check[j] = RandInt(0, size - 1);
3071  SortAndUniq(&indexes_to_check);
3072  }
3073  for (std::vector<int32>::iterator iter = indexes_to_check.begin();
3074  iter != indexes_to_check.end(); ++iter) {
3075  int32 i = *iter;
3076  Cindex cindex = cindexes[i];
3077  int32 n = cindex.second.n;
3078  if (n < N - 1) {
3079  cindex.second.n = n + 1;
3080  if (i + n_stride >= size || cindexes[i + n_stride] != cindex)
3081  return 0;
3082  }
3083  if (n == 0) {
3084  if (i / block_size != (i + n_stride * (N-1)) / block_size)
3085  return 0;
3086  } else {
3087  cindex.second.n = n - 1;
3088  if (i - n_stride < 0 || cindexes[i - n_stride] != cindex)
3089  return 0;
3090  }
3091  }
3092  return n_stride;
3093 }
kaldi::int32 int32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115
struct rnnlm::@11::@12 n
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ FindNumLeadingAndTrailingIdenticals()

static void kaldi::nnet3::FindNumLeadingAndTrailingIdenticals ( const std::vector< std::pair< int32, int32 > > &  vec,
int32 num_leading_identicals,
int32 num_trailing_identicals 
)
static

Definition at line 2477 of file nnet-optimize-utils.cc.

References KALDI_ASSERT.

Referenced by SnipRangesRowOp().

2480  {
2481  KALDI_ASSERT(!vec.empty());
2482  const std::pair<int32, int32> *begin = &(vec[0]), *ptr = begin,
2483  *end = ptr + vec.size();
2484  while (ptr != end && ptr->first == ptr->second)
2485  ptr++;
2486  // note regarding error message: we assume all pairs of identical numbers are
2487  // -1, due to the way this is called, but it only affects how we describe the
2488  // error.
2489  KALDI_ASSERT(ptr != end && "Vector consists entirely of -1's.");
2490  *num_leading_identicals = ptr - begin;
2491  const std::pair<int32, int32> *ptr2 = end - 1;
2492  // the following while loop should terminate before falling off the vector,
2493  // because we've established above (in the assertion) that the vector contains
2494  // at least one nonnegative number.
2495  while (ptr2->first == ptr2->second)
2496  ptr2--;
2497  KALDI_ASSERT(ptr2 >= begin); // would be code error.
2498  *num_trailing_identicals = end - 1 - ptr2;
2499 }
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ FindNumLeadingAndTrailingNegatives() [1/2]

static void kaldi::nnet3::FindNumLeadingAndTrailingNegatives ( const std::vector< int32 > &  vec,
int32 num_leading_negatives,
int32 num_trailing_negatives 
)
static

Definition at line 2339 of file nnet-optimize-utils.cc.

References KALDI_ASSERT.

Referenced by SnipMultiRowOp(), and SnipSingleRowOp().

2341  {
2342  KALDI_ASSERT(!vec.empty());
2343  const int32 *begin = &(vec[0]), *ptr = begin, *end = ptr + vec.size();
2344  while (ptr != end && *ptr < 0)
2345  ptr++;
2346  // note regarding error message: we assume all negative numbers are -1, due to
2347  // the way this is called, but it only affects how we describe the error.
2348  KALDI_ASSERT(ptr != end && "Vector consists entirely of -1's.");
2349  *num_leading_negatives = ptr - begin;
2350  const int32 *ptr2 = end - 1;
2351  // the following while loop should terminate before falling off the vector,
2352  // because we've established above (in the assertion) that the vector contains
2353  // at least one nonnegative number.
2354  while (*ptr2 < 0)
2355  ptr2--;
2356  KALDI_ASSERT(ptr2 >= begin); // or would be code error.
2357  *num_trailing_negatives = end - 1 - ptr2;
2358 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ FindNumLeadingAndTrailingNegatives() [2/2]

static void kaldi::nnet3::FindNumLeadingAndTrailingNegatives ( const std::vector< std::pair< int32, int32 > > &  vec,
int32 num_leading_negatives,
int32 num_trailing_negatives 
)
static

Definition at line 2406 of file nnet-optimize-utils.cc.

References KALDI_ASSERT.

2409  {
2410  KALDI_ASSERT(!vec.empty());
2411  const std::pair<int32, int32> *begin = &(vec[0]), *ptr = begin,
2412  *end = ptr + vec.size();
2413  while (ptr != end && ptr->first < 0)
2414  ptr++;
2415  // note regarding error message: we assume all negative numbers are -1, due to
2416  // the way this is called, but it only affects how we describe the error.
2417  KALDI_ASSERT(ptr != end && "Vector consists entirely of -1's.");
2418  *num_leading_negatives = ptr - begin;
2419  const std::pair<int32, int32> *ptr2 = end - 1;
2420  // the following while loop should terminate before falling off the vector,
2421  // because we've established above (in the assertion) that the vector contains
2422  // at least one nonnegative number.
2423  while (ptr2->first < 0)
2424  ptr2--;
2425  KALDI_ASSERT(ptr2 >= begin); // would be code error.
2426  *num_trailing_negatives = end - 1 - ptr2;
2427 }
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ FindOrphanComponents()

void FindOrphanComponents ( const Nnet nnet,
std::vector< int32 > *  components 
)

This function finds a list of components that are never used, and outputs the integer comopnent indexes (you can use these to index nnet.GetComponentNames() to get their names).

Definition at line 591 of file nnet-utils.cc.

References NetworkNode::component_index, Nnet::GetNode(), rnnlm::i, Nnet::IsComponentNode(), KALDI_ASSERT, Nnet::NumComponents(), Nnet::NumNodes(), and NetworkNode::u.

Referenced by Nnet::Check(), and Nnet::RemoveOrphanComponents().

591  {
592  int32 num_components = nnet.NumComponents(), num_nodes = nnet.NumNodes();
593  std::vector<bool> is_used(num_components, false);
594  for (int32 i = 0; i < num_nodes; i++) {
595  if (nnet.IsComponentNode(i)) {
596  int32 c = nnet.GetNode(i).u.component_index;
597  KALDI_ASSERT(c >= 0 && c < num_components);
598  is_used[c] = true;
599  }
600  }
601  components->clear();
602  for (int32 i = 0; i < num_components; i++)
603  if (!is_used[i])
604  components->push_back(i);
605 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ FindOrphanNodes()

void FindOrphanNodes ( const Nnet nnet,
std::vector< int32 > *  nodes 
)

This function finds a list of nodes that are never used to compute any output, and outputs the integer node indexes (you can use these to index nnet.GetNodeNames() to get their names).

Definition at line 607 of file nnet-utils.cc.

References ComputeGraphTranspose(), rnnlm::i, Nnet::IsOutputNode(), rnnlm::j, NnetToDirectedGraph(), and Nnet::NumNodes().

Referenced by Nnet::Check(), and Nnet::RemoveOrphanNodes().

607  {
608 
609  std::vector<std::vector<int32> > depend_on_graph, dependency_graph;
610  NnetToDirectedGraph(nnet, &depend_on_graph);
611  // depend_on_graph[i] is a list of all the nodes that depend on i.
612  ComputeGraphTranspose(depend_on_graph, &dependency_graph);
613  // dependency_graph[i] is a list of all the nodes that i depends on,
614  // to be computed.
615 
616  // Find all nodes required to produce the outputs.
617  int32 num_nodes = nnet.NumNodes();
618  assert(num_nodes == static_cast<int32>(dependency_graph.size()));
619  std::vector<bool> node_is_required(num_nodes, false);
620  std::vector<int32> queue;
621  for (int32 i = 0; i < num_nodes; i++) {
622  if (nnet.IsOutputNode(i))
623  queue.push_back(i);
624  }
625  while (!queue.empty()) {
626  int32 i = queue.back();
627  queue.pop_back();
628  if (!node_is_required[i]) {
629  node_is_required[i] = true;
630  for (size_t j = 0; j < dependency_graph[i].size(); j++)
631  queue.push_back(dependency_graph[i][j]);
632  }
633  }
634  nodes->clear();
635  for (int32 i = 0; i < num_nodes; i++) {
636  if (!node_is_required[i])
637  nodes->push_back(i);
638  }
639 }
void NnetToDirectedGraph(const Nnet &nnet, std::vector< std::vector< int32 > > *graph)
This function takes an nnet and turns it to a directed graph on nodes.
Definition: nnet-graph.cc:30
kaldi::int32 int32
void ComputeGraphTranspose(const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *graph_transpose)
Outputs a graph in which the order of arcs is reversed.
Definition: nnet-graph.cc:63

◆ FindSccs()

void FindSccs ( const std::vector< std::vector< int32 > > &  graph,
std::vector< std::vector< int32 > > *  sccs 
)

Given a directed graph (where each std::vector<int32> is a list of destination-nodes of arcs coming from the current node), partition it into strongly connected components (i.e.

within each SCC, all nodes are reachable from all other nodes). Each element of 'sccs' is a list of node indexes that are in that scc.

Definition at line 156 of file nnet-graph.cc.

References FindSccsTarjan(), and KALDI_ASSERT.

Referenced by ComputeNnetComputationEpochs(), GraphHasCycles(), and UnitTestFindSccs().

157  {
158  // Internally we call Tarjan's SCC algorithm, as it only requires one DFS. We
159  // can change this to other methods later on if necessary.
160  KALDI_ASSERT(sccs != NULL);
161  FindSccsTarjan(graph, sccs);
162 }
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void FindSccsTarjan(const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *sccs)
Definition: nnet-graph.cc:138

◆ FindSccsTarjan()

void kaldi::nnet3::FindSccsTarjan ( const std::vector< std::vector< int32 > > &  graph,
std::vector< std::vector< int32 > > *  sccs 
)

Definition at line 138 of file nnet-graph.cc.

References TarjanNode::index, KALDI_ASSERT, rnnlm::n, and TarjanSccRecursive().

Referenced by FindSccs().

139  {
140  KALDI_ASSERT(sccs != NULL);
141 
142  // Initialization.
143  std::vector<TarjanNode> tarjan_nodes(graph.size());
144  std::vector<int32> tarjan_stack;
145  int32 global_index = 0;
146 
147  // Calls the recursive function.
148  for (int32 n = 0; n < graph.size(); ++n) {
149  if (tarjan_nodes[n].index == -1) {
150  TarjanSccRecursive(n, graph,
151  &global_index, &tarjan_nodes, &tarjan_stack, sccs);
152  }
153  }
154 }
kaldi::int32 int32
struct rnnlm::@11::@12 n
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void TarjanSccRecursive(int32 node, const std::vector< std::vector< int32 > > &graph, int32 *global_index, std::vector< TarjanNode > *tarjan_nodes, std::vector< int32 > *tarjan_stack, std::vector< std::vector< int32 > > *sccs)
Definition: nnet-graph.cc:85

◆ FixGotoLabel()

void FixGotoLabel ( NnetComputation computation)

This function ensures that the arg1 of a final command of type kGotoLabel is the same as the command with type kNoOperationLabel.

This is necessary if you do any other type of optimization after 'OptimizeLoopedComputation()'.

Definition at line 4552 of file nnet-optimize-utils.cc.

References NnetComputation::commands, rnnlm::d, KALDI_ERR, kGotoLabel, kNoOperationLabel, and kProvideOutput.

Referenced by InsertCommands(), Optimize(), ComputationLoopedOptimizer::Optimize(), and RemoveUnnecessaryAllocation().

4552  {
4553  int32 num_commands = computation->commands.size();
4554  if (num_commands == 0)
4555  return;
4556  for (int32 c = num_commands - 1; c >= 0; c--) {
4557  if (computation->commands[c].command_type == kGotoLabel) {
4558  int32 dest_command = computation->commands[c].arg1;
4559  if (static_cast<size_t>(dest_command) < computation->commands.size() &&
4560  computation->commands[dest_command].command_type == kNoOperationLabel)
4561  return; // nothing to fix.
4562  for (int32 d = 0; d + 1 < num_commands; d++) {
4563  if (computation->commands[d].command_type == kNoOperationLabel) {
4564  computation->commands[c].arg1 = d;
4565  return;
4566  }
4567  }
4568  KALDI_ERR << "Label not found.";
4569  } else if (computation->commands[c].command_type == kProvideOutput) {
4570  // sometimes kProvideOutput commands are temporarily ordered after
4571  // the kGotoLabel command, and we need to work in that case.
4572  continue;
4573  } else {
4574  // it loks like there is no 'goto' command in this computation-
4575  // if there were, it would be right at the end, possibly followed by
4576  // kProvideOutput commands.
4577  break;
4578  }
4579  }
4580 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ FreezeNaturalGradient()

void FreezeNaturalGradient ( bool  freeze,
Nnet nnet 
)

Controls if natural gradient will be updated.

Definition at line 432 of file nnet-utils.cc.

References UpdatableComponent::FreezeNaturalGradient(), Nnet::GetComponent(), KALDI_ERR, kUpdatableComponent, Nnet::NumComponents(), and Component::Properties().

Referenced by LstmNonlinearityComponent::ConsolidateMemory(), LinearComponent::LinearComponent(), NaturalGradientAffineComponent::NaturalGradientAffineComponent(), NnetChainTrainer::Train(), NnetTrainer::Train(), NaturalGradientPerElementScaleComponent::Type(), and CompositeComponent::Type().

432  {
433  for (int32 c = 0; c < nnet->NumComponents(); c++) {
434  Component *comp = nnet->GetComponent(c);
435  if (comp->Properties() & kUpdatableComponent) {
436  // For now all updatable components inherit from class UpdatableComponent.
437  // If that changes in future, we will change this code.
438  UpdatableComponent *uc = dynamic_cast<UpdatableComponent*>(comp);
439  if (uc == NULL)
440  KALDI_ERR << "Updatable component does not inherit from class "
441  "UpdatableComponent; change this code.";
442  uc->FreezeNaturalGradient(freeze);
443  }
444  }
445 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ GenerateConfigSequence()

void GenerateConfigSequence ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Generates a sequence of at least one config files, output as strings, where the first in the sequence is the initial nnet, and the remaining ones may do things like add layers.

Definition at line 1252 of file nnet-test-utils.cc.

References NnetGenerationOptions::allow_context, NnetGenerationOptions::allow_nonlinearity, NnetGenerationOptions::allow_recursion, NnetGenerationOptions::allow_statistics_pooling, NnetGenerationOptions::allow_use_of_x_dim, GenerateConfigSequenceCnn(), GenerateConfigSequenceCnnNew(), GenerateConfigSequenceCompositeBlock(), GenerateConfigSequenceDistribute(), GenerateConfigSequenceLstm(), GenerateConfigSequenceLstmWithTruncation(), GenerateConfigSequenceRestrictedAttention(), GenerateConfigSequenceRnn(), GenerateConfigSequenceRnnClockwork(), GenerateConfigSequenceSimple(), GenerateConfigSequenceSimpleContext(), GenerateConfigSequenceSimplest(), GenerateConfigSequenceStatistics(), KALDI_ASSERT, KALDI_ERR, and kaldi::RandInt().

Referenced by NnetGenerationOptions::NnetGenerationOptions(), UnitTestNnetAnalyze(), UnitTestNnetCompile(), UnitTestNnetCompileLooped(), UnitTestNnetCompileMulti(), UnitTestNnetCompute(), UnitTestNnetContext(), UnitTestNnetInputDerivatives(), UnitTestNnetIo(), UnitTestNnetModelDerivatives(), and UnitTestNnetOptimizeWithOptions().

1254  {
1255 start:
1256  int32 network_type = RandInt(0, 14);
1257  switch(network_type) {
1258  case 0:
1259  GenerateConfigSequenceSimplest(opts, configs);
1260  break;
1261  case 1:
1262  if (!opts.allow_context)
1263  goto start;
1264  GenerateConfigSequenceSimpleContext(opts, configs);
1265  break;
1266  case 2:
1267  if (!opts.allow_context || !opts.allow_nonlinearity)
1268  goto start;
1269  GenerateConfigSequenceSimple(opts, configs);
1270  break;
1271  case 3:
1272  if (!opts.allow_recursion || !opts.allow_context ||
1273  !opts.allow_nonlinearity)
1274  goto start;
1275  GenerateConfigSequenceRnn(opts, configs);
1276  break;
1277  case 4:
1278  if (!opts.allow_recursion || !opts.allow_context ||
1279  !opts.allow_nonlinearity)
1280  goto start;
1281  GenerateConfigSequenceRnnClockwork(opts, configs);
1282  break;
1283  case 5:
1284  if (!opts.allow_recursion || !opts.allow_context ||
1285  !opts.allow_nonlinearity)
1286  goto start;
1287  GenerateConfigSequenceLstm(opts, configs);
1288  break;
1289  case 6:
1290  if (!opts.allow_recursion || !opts.allow_context ||
1291  !opts.allow_nonlinearity)
1292  goto start;
1293  GenerateConfigSequenceLstm(opts, configs);
1294  break;
1295  case 7:
1296  if (!opts.allow_nonlinearity)
1297  goto start;
1298  GenerateConfigSequenceCnn(opts, configs);
1299  break;
1300  case 8:
1301  if (!opts.allow_use_of_x_dim)
1302  goto start;
1303  GenerateConfigSequenceDistribute(opts, configs);
1304  break;
1305  case 9:
1306  GenerateConfigSequenceCompositeBlock(opts, configs);
1307  break;
1308  case 10:
1309  if (!opts.allow_statistics_pooling)
1310  goto start;
1311  GenerateConfigSequenceStatistics(opts, configs);
1312  break;
1313  case 11:
1314  if (!opts.allow_recursion || !opts.allow_context ||
1315  !opts.allow_nonlinearity)
1316  goto start;
1318  break;
1319  // We're allocating more case statements to the most recently
1320  // added type of model, to give more thorough testing where
1321  // it's needed most.
1322  case 12:
1323  if (!opts.allow_nonlinearity || !opts.allow_context)
1324  goto start;
1325  GenerateConfigSequenceCnnNew(opts, configs);
1326  break;
1327  case 13: case 14:
1328  if (!opts.allow_nonlinearity || !opts.allow_context)
1329  goto start;
1331  break;
1332  default:
1333  KALDI_ERR << "Error generating config sequence.";
1334  }
1335  KALDI_ASSERT(!configs->empty());
1336 }
void GenerateConfigSequenceLstm(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
void GenerateConfigSequenceRnnClockwork(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
void GenerateConfigSequenceLstmWithTruncation(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
void GenerateConfigSequenceSimpleContext(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
kaldi::int32 int32
void GenerateConfigSequenceDistribute(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
void GenerateConfigSequenceRnn(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
void GenerateConfigSequenceCnn(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
void GenerateConfigSequenceCnnNew(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
#define KALDI_ERR
Definition: kaldi-error.h:147
void GenerateConfigSequenceStatistics(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
void GenerateConfigSequenceSimplest(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
void GenerateConfigSequenceRestrictedAttention(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void GenerateConfigSequenceSimple(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
void GenerateConfigSequenceCompositeBlock(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generate a config string with a composite component composed only of block affine, repeated affine, and natural gradient repeated affine components.
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateConfigSequenceCnn()

void kaldi::nnet3::GenerateConfigSequenceCnn ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 913 of file nnet-test-utils.cc.

References kaldi::Rand().

Referenced by GenerateConfigSequence().

915  {
916  std::ostringstream os;
917 
918 
919  int32 input_x_dim = 10 + Rand() % 20,
920  input_y_dim = 10 + Rand() % 20,
921  input_z_dim = 3 + Rand() % 10,
922  filt_x_dim = 1 + Rand() % input_x_dim,
923  filt_y_dim = 1 + Rand() % input_y_dim,
924  num_filters = 10 + Rand() % 20,
925  filt_x_step = (1 + Rand() % filt_x_dim),
926  filt_y_step = (1 + Rand() % filt_y_dim);
927  int32 remainder = (input_x_dim - filt_x_dim) % filt_x_step;
928  // adjusting input_x_dim to ensure divisibility
929  input_x_dim = input_x_dim - remainder;
930  remainder = (input_y_dim - filt_y_dim) % filt_y_step;
931  // adjusting input_x_dim to ensure divisibility
932  input_y_dim = input_y_dim - remainder;
933 
934  int32 input_vectorization = Rand() % 2;
935  std::string vectorization;
936  if (input_vectorization == 0) {
937  vectorization = "yzx";
938  } else {
939  vectorization = "zyx";
940  }
941 
942  os << "component name=conv type=ConvolutionComponent "
943  << " input-x-dim=" << input_x_dim
944  << " input-y-dim=" << input_y_dim
945  << " input-z-dim=" << input_z_dim
946  << " filt-x-dim=" << filt_x_dim
947  << " filt-y-dim=" << filt_y_dim
948  << " filt-x-step=" << filt_x_step
949  << " filt-y-step=" << filt_y_step
950  << " num-filters=" << num_filters
951  << " input-vectorization-order=" << vectorization
952  << std::endl;
953 
954  int32 conv_output_x_dim = (1 + (input_x_dim - filt_x_dim) / filt_x_step);
955  int32 conv_output_y_dim = (1 + (input_y_dim - filt_y_dim) / filt_y_step);
956  int32 conv_output_z_dim = num_filters;
957  int32 pool_x_size = 1 + Rand() % conv_output_x_dim;
958  int32 pool_y_size = 1 + Rand() % conv_output_y_dim;
959  int32 pool_z_size = 1 + Rand() % conv_output_z_dim;
960  int32 pool_x_step = 1;
961  int32 pool_y_step = 1;
962  int32 pool_z_step = 1;
963  do {
964  pool_x_step = (1 + Rand() % pool_x_size);
965  } while((conv_output_x_dim - pool_x_size) % pool_x_step);
966  do {
967  pool_y_step = (1 + Rand() % pool_y_size);
968  } while((conv_output_y_dim - pool_y_size) % pool_y_step);
969  do {
970  pool_z_step = (1 + Rand() % pool_z_size);
971  } while((conv_output_z_dim - pool_z_size) % pool_z_step);
972 
973  os << "component name=maxpooling type=MaxpoolingComponent "
974  << " input-x-dim=" << conv_output_x_dim
975  << " input-y-dim=" << conv_output_y_dim
976  << " input-z-dim=" << conv_output_z_dim
977  << " pool-x-size=" << pool_x_size
978  << " pool-y-size=" << pool_y_size
979  << " pool-z-size=" << pool_z_size
980  << " pool-x-step=" << pool_x_step
981  << " pool-y-step=" << pool_y_step
982  << " pool-z-step=" << pool_z_step
983  << std::endl;
984 
985  os << "input-node name=input dim=" << (input_x_dim * input_y_dim * input_z_dim) << std::endl;
986  os << "component-node name=conv_node component=conv input=input\n";
987  os << "component-node name=maxpooling_node component=maxpooling input=conv_node\n";
988  os << "output-node name=output input=conv_node\n";
989  configs->push_back(os.str());
990 }
kaldi::int32 int32
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45

◆ GenerateConfigSequenceCnnNew()

void kaldi::nnet3::GenerateConfigSequenceCnnNew ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 994 of file nnet-test-utils.cc.

References kaldi::RandInt().

Referenced by GenerateConfigSequence().

996  {
997  std::ostringstream ss;
998 
999 
1000  int32 cur_height = RandInt(5, 15),
1001  cur_num_filt = RandInt(1, 3),
1002  num_layers = RandInt(0, 3);
1003  // note: generating zero layers is a bit odd but it exercises some code that
1004  // we otherwise wouldn't exercise.
1005 
1006 
1007  std::string cur_layer_descriptor = "input";
1008 
1009  { // input layer.
1010  ss << "input-node name=input dim=" << (cur_height * cur_num_filt)
1011  << std::endl;
1012  }
1013 
1014 
1015  for (int32 l = 0; l < num_layers; l++) {
1016  int32 next_num_filt = RandInt(1, 10);
1017 
1018  bool height_padding = (cur_height < 5 || RandInt(0, 1) == 0);
1019  int32 height_subsampling_factor = RandInt(1, 2);
1020  if (cur_height < 4) {
1021  // output height of 1 causes a problem with unused height-offsets,
1022  // so don't subsample in that case.
1023  height_subsampling_factor = 1;
1024  }
1025 
1026  int32 next_height = cur_height;
1027  if (!height_padding) {
1028  next_height -= 2; // the kernel will have height 3.
1029  }
1030  next_height = (next_height + height_subsampling_factor - 1) /
1031  height_subsampling_factor;
1032 
1033  if (next_height == cur_height && RandInt(0, 1) == 0) {
1034  // ensure that with sufficient frequency, we have the
1035  // same height and num-filt out; this enables ResNet-style
1036  // addition.
1037  next_num_filt = cur_num_filt;
1038  }
1039 
1040  std::string time_offsets, required_time_offsets;
1041  if (RandInt(0, 3) == 0) {
1042  time_offsets = "0";
1043  required_time_offsets = (RandInt(0, 1) == 0 ? "" : "0");
1044  } else if (RandInt(0, 1) == 0) {
1045  time_offsets = "-1,0,1";
1046  required_time_offsets = (RandInt(0, 1) == 0 ? "" : "-1");
1047  } else {
1048  time_offsets = "-2,0,2";
1049  required_time_offsets = (RandInt(0, 1) == 0 ? "" : "0");
1050  }
1051 
1052  ss << "component type=TimeHeightConvolutionComponent name=layer" << l << "-conv "
1053  << "num-filters-in=" << cur_num_filt
1054  << " num-filters-out=" << next_num_filt
1055  << " height-in=" << cur_height
1056  << " height-out=" << next_height
1057  << " height-offsets=" << (height_padding ? "-1,0,1" : "0,1,2")
1058  << " time-offsets=" << time_offsets;
1059 
1060  if (RandInt(0, 1) == 0) {
1061  // this limits the 'temp memory' usage to 100
1062  // bytes, which will test another code path where
1063  // it breaks up the temporary matrix into pieces
1064  ss << " max-memory-mb=1.0e-04";
1065  }
1066 
1067  if (height_subsampling_factor != 1 || RandInt(0, 1) == 0)
1068  ss << " height-subsample-out=" << height_subsampling_factor;
1069  if (required_time_offsets == "" && RandInt(0, 1) == 0) {
1070  required_time_offsets = time_offsets;
1071  // it should default to this, but we're exercising more of the config
1072  // parsing code this way.
1073  }
1074  if (required_time_offsets != "")
1075  ss << " required-time-offsets=" << required_time_offsets;
1076  if (RandInt(0, 1) == 0)
1077  ss << " param-stddev=0.1 bias-stddev=1";
1078  if (RandInt(0, 1) == 0)
1079  ss << " use-natural-gradient=false";
1080  if (RandInt(0, 1) == 0)
1081  ss << " rank-in=4";
1082  if (RandInt(0, 1) == 0)
1083  ss << " rank-out=4";
1084  if (RandInt(0, 1) == 0)
1085  ss << " alpha-in=2.0";
1086  if (RandInt(0, 1) == 0)
1087  ss << " alpha-out=2.0";
1088  ss << std::endl;
1089 
1090  ss << "component-node name=layer" << l << "-conv component=layer"
1091  << l << "-conv input=" << cur_layer_descriptor << std::endl;
1092 
1093  bool use_relu = false;
1094  if (use_relu) {
1095  ss << "component type=RectifiedLinearComponent name=layer" << l
1096  << "-relu dim=" << (next_height * next_num_filt) << std::endl;
1097  ss << "component-node name=layer" << l << "-relu component=layer"
1098  << l << "-relu input=layer" << l << "-conv" << std::endl;
1099  }
1100 
1101  std::ostringstream desc_ss;
1102  if (next_height == cur_height && next_num_filt == cur_num_filt
1103  && RandInt(0, 1) == 0) {
1104  desc_ss << "Sum(" << cur_layer_descriptor << ", layer" << l
1105  << (use_relu ? "-relu)" : "-conv)");
1106  } else {
1107  desc_ss << "layer" << l << (use_relu ? "-relu" : "-conv");
1108  }
1109 
1110  if (RandInt(0, 3) == 0) {
1111  std::ostringstream round_desc_ss;
1112  int32 modulus = RandInt(2, 3);
1113  round_desc_ss << "Round(" << desc_ss.str() << ", " << modulus << ")";
1114  cur_layer_descriptor = round_desc_ss.str();
1115  } else {
1116  cur_layer_descriptor = desc_ss.str();
1117  }
1118  cur_height = next_height;
1119  cur_num_filt = next_num_filt;
1120  }
1121 
1122  ss << "output-node name=output input=" << cur_layer_descriptor << std::endl;
1123 
1124 
1125  configs->push_back(ss.str());
1126 }
kaldi::int32 int32
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateConfigSequenceCompositeBlock()

void GenerateConfigSequenceCompositeBlock ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Generate a config string with a composite component composed only of block affine, repeated affine, and natural gradient repeated affine components.

Definition at line 1213 of file nnet-test-utils.cc.

References rnnlm::i, KALDI_WARN, NnetGenerationOptions::output_dim, and kaldi::RandInt().

Referenced by GenerateConfigSequence(), NnetGenerationOptions::NnetGenerationOptions(), and UnitTestConvertRepeatedToBlockAffineComposite().

1214  {
1215  int32 num_components = RandInt(1,5);
1216  int32 input_dim = 10 * RandInt(1,10);
1217  if (opts.output_dim > 0) {
1218  KALDI_WARN << "This function doesn't take a requested output_dim due to "
1219  "implementation complications.";
1220  }
1221  int32 max_rows_process = 512 + 512 * RandInt(1,3);
1222  std::ostringstream os;
1223  os << "component name=composite1 type=CompositeComponent max-rows-process="
1224  << max_rows_process << " num-components=" << num_components;
1225 
1226  int32 types_length = 3;
1227  std::string types[] = {"BlockAffineComponent",
1228  "RepeatedAffineComponent",
1229  "NaturalGradientRepeatedAffineComponent"};
1230  int32 last_output_dim = input_dim;
1231  // components within a composite component are indexed from 1.
1232  for(int32 i = 1; i <= num_components; i++) {
1233  os << " component" << i << "=";
1234  int32 rand_index = RandInt(0, types_length - 1);
1235  std::string rand_type = types[rand_index];
1236  os << "'type=" << rand_type << " input-dim=" << last_output_dim;
1237  int32 current_output_dim = 10 * RandInt(1,10);
1238  // must be a divisor or current_output_dim and last_output_dim
1239  int32 num_repeats = 10;
1240  os << " output-dim=" << current_output_dim;
1241  std::string repeats_string = (rand_type == "BlockAffineComponent") ? "num-blocks": "num-repeats";
1242  os << " " << repeats_string << "=" << num_repeats << "'";
1243  last_output_dim = current_output_dim;
1244  }
1245  os << std::endl << std::endl;
1246  os << "input-node name=input dim=" << input_dim << std::endl;
1247  os << "component-node name=composite1 component=composite1 input=input\n";
1248  os << "output-node name=output input=composite1\n";
1249  configs->push_back(os.str());
1250 }
kaldi::int32 int32
#define KALDI_WARN
Definition: kaldi-error.h:150
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateConfigSequenceDistribute()

void kaldi::nnet3::GenerateConfigSequenceDistribute ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 1187 of file nnet-test-utils.cc.

References rnnlm::i, NnetGenerationOptions::output_dim, and kaldi::RandInt().

Referenced by GenerateConfigSequence().

1189  {
1190  int32 output_dim = (opts.output_dim > 0 ? opts.output_dim : 100);
1191  int32 x_expand = RandInt(1, 5), after_expand_dim = RandInt(10, 20),
1192  input_dim = x_expand * after_expand_dim;
1193  std::ostringstream os;
1194  os << "input-node name=input dim=" << input_dim << std::endl;
1195  os << "component name=distribute type=DistributeComponent input-dim="
1196  << input_dim << " output-dim=" << after_expand_dim << std::endl;
1197  os << "component-node name=distribute component=distribute input=input\n";
1198  os << "component name=affine type=AffineComponent input-dim="
1199  << after_expand_dim << " output-dim=" << output_dim << std::endl;
1200  os << "component-node name=affine component=affine input=distribute\n";
1201  os << "output-node name=output input=Sum(";
1202  for (int32 i = 0; i < x_expand; i++) {
1203  if (i > 0) os << ", ";
1204  os << "ReplaceIndex(affine, x, " << i << ")";
1205  }
1206  os << ")\n";
1207  configs->push_back(os.str());
1208 }
kaldi::int32 int32
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateConfigSequenceLstm()

void kaldi::nnet3::GenerateConfigSequenceLstm ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 414 of file nnet-test-utils.cc.

References rnnlm::i, NnetGenerationOptions::output_dim, and kaldi::Rand().

Referenced by GenerateConfigSequence().

416  {
417  std::ostringstream os;
418 
419  std::vector<int32> splice_context;
420  for (int32 i = -5; i < 4; i++)
421  if (Rand() % 3 == 0)
422  splice_context.push_back(i);
423  if (splice_context.empty())
424  splice_context.push_back(0);
425 
426  int32 input_dim = 10 + Rand() % 20,
427  spliced_dim = input_dim * splice_context.size(),
428  output_dim = (opts.output_dim > 0 ?
429  opts.output_dim :
430  100 + Rand() % 200),
431  cell_dim = 40 + Rand() % 50,
432  projection_dim = std::ceil(cell_dim / (Rand() % 10 + 1));
433 
434  os << "input-node name=input dim=" << input_dim << std::endl;
435 
436  // trainable cell value for start/end of file.
437  os << "component name=c0 type=ConstantComponent"
438  << " output-dim=" << cell_dim << std::endl;
439 
440 
441  // Parameter Definitions W*(* replaced by - to have valid names)
442  // Input gate control : Wi* matrices
443  os << "component name=Wi-xr type=NaturalGradientAffineComponent"
444  << " input-dim=" << spliced_dim + projection_dim
445  << " output-dim=" << cell_dim << std::endl;
446  os << "component name=Wic type=PerElementScaleComponent "
447  << " dim=" << cell_dim << std::endl;
448 
449  // Forget gate control : Wf* matrices
450  os << "component name=Wf-xr type=NaturalGradientAffineComponent"
451  << " input-dim=" << spliced_dim + projection_dim
452  << " output-dim=" << cell_dim << std::endl;
453  os << "component name=Wfc type=PerElementScaleComponent "
454  << " dim=" << cell_dim << std::endl;
455 
456  // Output gate control : Wo* matrices
457  os << "component name=Wo-xr type=NaturalGradientAffineComponent"
458  << " input-dim=" << spliced_dim + projection_dim
459  << " output-dim=" << cell_dim << std::endl;
460  os << "component name=Woc type=PerElementScaleComponent "
461  << " dim=" << cell_dim << std::endl;
462 
463  // Cell input matrices : Wc* matrices
464  os << "component name=Wc-xr type=NaturalGradientAffineComponent"
465  << " input-dim=" << spliced_dim + projection_dim
466  << " output-dim=" << cell_dim << std::endl;
467 
468 
469 
470  // projection matrices : Wrm and Wpm
471  os << "component name=W-m type=NaturalGradientAffineComponent "
472  << " input-dim=" << cell_dim
473  << " output-dim=" << 2 * projection_dim << std::endl;
474 
475  // Output : Wyr and Wyp
476  os << "component name=Wy- type=NaturalGradientAffineComponent "
477  << " input-dim=" << 2 * projection_dim
478  << " output-dim=" << cell_dim << std::endl;
479 
480  // Defining the diagonal matrices
481  // Defining the final affine transform
482  os << "component name=final_affine type=NaturalGradientAffineComponent "
483  << "input-dim=" << cell_dim << " output-dim=" << output_dim << std::endl;
484  os << "component name=logsoftmax type=LogSoftmaxComponent dim="
485  << output_dim << std::endl;
486 
487  // Defining the non-linearities
488  // declare a no-op component so that we can use a sum descriptor's output
489  // multiple times, and to make the config more readable given the equations
490  os << "component name=i type=SigmoidComponent dim="
491  << cell_dim << std::endl;
492  os << "component name=f type=SigmoidComponent dim="
493  << cell_dim << std::endl;
494  os << "component name=o type=SigmoidComponent dim="
495  << cell_dim << std::endl;
496  os << "component name=g type=TanhComponent dim="
497  << cell_dim << std::endl;
498  os << "component name=h type=TanhComponent dim="
499  << cell_dim << std::endl;
500  os << "component name=c1 type=ElementwiseProductComponent "
501  << " input-dim=" << 2 * cell_dim
502  << " output-dim=" << cell_dim << std::endl;
503  os << "component name=c2 type=ElementwiseProductComponent "
504  << " input-dim=" << 2 * cell_dim
505  << " output-dim=" << cell_dim << std::endl;
506  os << "component name=m type=ElementwiseProductComponent "
507  << " input-dim=" << 2 * cell_dim
508  << " output-dim=" << cell_dim << std::endl;
509 
510  // Defining the computations
511  std::ostringstream temp_string_stream;
512  for (size_t i = 0; i < splice_context.size(); i++) {
513  int32 offset = splice_context[i];
514  temp_string_stream << "Offset(input, " << offset << ")";
515  if (i + 1 < splice_context.size())
516  temp_string_stream << ", ";
517  }
518  std::string spliced_input = temp_string_stream.str();
519 
520  std::string c_tminus1 = "Sum(Failover(Offset(c1_t, -1), c0), IfDefined(Offset( c2_t, -1)))";
521 
522 
523  // c0. note: the input is never used as the component requires
524  // no input indexes; we just write itself as input to keep the
525  // structures happy.
526  os << "component-node name=c0 component=c0 input=c0\n";
527 
528  // i_t
529  os << "component-node name=i1 component=Wi-xr input=Append("
530  << spliced_input << ", IfDefined(Offset(r_t, -1)))\n";
531  os << "component-node name=i2 component=Wic "
532  << " input=" << c_tminus1 << std::endl;
533  os << "component-node name=i_t component=i input=Sum(i1, i2)\n";
534 
535  // f_t
536  os << "component-node name=f1 component=Wf-xr input=Append("
537  << spliced_input << ", IfDefined(Offset(r_t, -1)))\n";
538  os << "component-node name=f2 component=Wfc "
539  << " input=" << c_tminus1 << std::endl;
540  os << "component-node name=f_t component=f input=Sum(f1, f2)\n";
541 
542  // o_t
543  os << "component-node name=o1 component=Wo-xr input=Append("
544  << spliced_input << ", IfDefined(Offset(r_t, -1)))\n";
545  os << "component-node name=o2 component=Woc input=Sum(c1_t, c2_t)\n";
546  os << "component-node name=o_t component=o input=Sum(o1, o2)\n";
547 
548  // h_t
549  os << "component-node name=h_t component=h input=Sum(c1_t, c2_t)\n";
550 
551  // g_t
552  os << "component-node name=g1 component=Wc-xr input=Append("
553  << spliced_input << ", IfDefined(Offset(r_t, -1)))\n";
554  os << "component-node name=g_t component=g input=g1\n";
555 
556  // parts of c_t
557  os << "component-node name=c1_t component=c1 "
558  << " input=Append(f_t, " << c_tminus1 << ")\n";
559  os << "component-node name=c2_t component=c2 input=Append(i_t, g_t)\n";
560 
561  // m_t
562  os << "component-node name=m_t component=m input=Append(o_t, h_t)\n";
563 
564  // r_t and p_t
565  os << "component-node name=rp_t component=W-m input=m_t\n";
566  // Splitting outputs of Wy- node
567  os << "dim-range-node name=r_t input-node=rp_t dim-offset=0 "
568  << "dim=" << projection_dim << std::endl;
569 
570  // y_t
571  os << "component-node name=y_t component=Wy- input=rp_t\n";
572 
573  // Final affine transform
574  os << "component-node name=final_affine component=final_affine input=y_t\n";
575  os << "component-node name=posteriors component=logsoftmax input=final_affine\n";
576  os << "output-node name=output input=posteriors\n";
577  configs->push_back(os.str());
578 }
kaldi::int32 int32
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45

◆ GenerateConfigSequenceLstmType2()

void kaldi::nnet3::GenerateConfigSequenceLstmType2 ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 767 of file nnet-test-utils.cc.

References rnnlm::i, KALDI_ERR, NnetGenerationOptions::output_dim, kaldi::Rand(), and kaldi::RandInt().

769  {
770  KALDI_ERR << "Not Implemented";
771  std::ostringstream os;
772 
773  std::vector<int32> splice_context;
774  for (int32 i = -5; i < 4; i++)
775  if (Rand() % 3 == 0)
776  splice_context.push_back(i);
777  if (splice_context.empty())
778  splice_context.push_back(0);
779 
780  int32 input_dim = 10 + Rand() % 20,
781  spliced_dim = input_dim * splice_context.size(),
782  output_dim = (opts.output_dim > 0 ?
783  opts.output_dim :
784  100 + Rand() % 200),
785  cell_dim = 40 + Rand() % 50,
786  projection_dim = std::ceil(cell_dim / (Rand() % 10 + 2));
787 
788  int32 offset = RandInt(-3, 3);
789  if (offset == 0)
790  offset = -1;
791 
792  os << "input-node name=input dim=" << input_dim << std::endl;
793  // Parameter Definitions W*(* replaced by - to have valid names)
794  os << "component name=W-x type=NaturalGradientAffineComponent input-dim="
795  << spliced_dim << " output-dim=" << 4 * cell_dim << std::endl;
796  os << "component name=W-r type=NaturalGradientAffineComponent input-dim="
797  << projection_dim << " output-dim=" << 4 * cell_dim << std::endl;
798  os << "component name=W-m type=NaturalGradientAffineComponent input-dim="
799  << cell_dim << " output-dim=" << 2 * projection_dim << std::endl;
800  os << "component name=Wyr type=NaturalGradientAffineComponent input-dim="
801  << projection_dim << " output-dim=" << cell_dim << std::endl;
802  os << "component name=Wyp type=NaturalGradientAffineComponent input-dim="
803  << projection_dim << " output-dim=" << cell_dim << std::endl;
804  // Defining the diagonal matrices
805  os << "component name=Wic type=PerElementScaleComponent "
806  << " dim=" << cell_dim << std::endl;
807  os << "component name=Wfc type=PerElementScaleComponent "
808  << " dim=" << cell_dim << std::endl;
809  os << "component name=Woc type=PerElementScaleComponent "
810  << " dim=" << cell_dim << std::endl;
811  // Defining the final affine transform
812  os << "component name=final_affine type=NaturalGradientAffineComponent "
813  << "input-dim=" << cell_dim << " output-dim=" << output_dim << std::endl;
814  os << "component name=logsoftmax type=LogSoftmaxComponent dim="
815  << output_dim << std::endl;
816 
817  // Defining the non-linearities
818  // declare a no-op component so that we can use a sum descriptor's output
819  // multiple times, and to make the config more readable given the equations
820  os << "component name=c_t type=NoOpComponent dim="
821  << cell_dim << std::endl;
822  os << "component name=i_t type=SigmoidComponent dim="
823  << cell_dim << std::endl;
824  os << "component name=f_t type=SigmoidComponent dim="
825  << cell_dim << std::endl;
826  os << "component name=o_t type=SigmoidComponent dim="
827  << cell_dim << std::endl;
828  os << "component name=g type=TanhComponent dim="
829  << cell_dim << std::endl;
830  os << "component name=h type=TanhComponent dim="
831  << cell_dim << std::endl;
832  os << "component name=f_t-c_tminus1 type=ElementwiseProductComponent "
833  << " input-dim=" << 2 * cell_dim
834  << " output-dim=" << cell_dim << std::endl;
835  os << "component name=i_t-g type=ElementwiseProductComponent "
836  << " input-dim=" << 2 * cell_dim
837  << " output-dim=" << cell_dim << std::endl;
838  os << "component name=m_t type=ElementwiseProductComponent "
839  << " input-dim=" << 2 * cell_dim
840  << " output-dim=" << cell_dim << std::endl;
841 
842 
843  // Defining the computations
844  os << "component-node name=W-x component=W-x input=Append(";
845  for (size_t i = 0; i < splice_context.size(); i++) {
846  int32 offset = splice_context[i];
847  os << "Offset(input, " << offset << ")";
848  if (i + 1 < splice_context.size())
849  os << ", ";
850  }
851  os << ")\n";
852 
853  os << "component-node name=W-r component=W-r input=IfDefined(Offset(r_t"
854  << offset << "))\n";
855  os << "component-node name=W-m component=W-m input=m_t \n";
856  os << "component-node name=Wic component=Wic input=IfDefined(Offset(c_t"
857  << offset << "))\n";
858  os << "component-node name=Wfc component=Wfc input=IfDefined(Offset(c_t"
859  << offset << "))\n";
860  os << "component-node name=Woc component=Woc input=c_t\n";
861 
862  // Splitting the outputs of W*m node
863  os << "dim-range-node name=r_t input-node=W-m dim-offset=0 "
864  << "dim=" << projection_dim << std::endl;
865  os << "dim-range-node name=p_t input-node=W-m dim-offset=" << projection_dim
866  << " dim=" << projection_dim << std::endl;
867 
868  // Splitting outputs of W*x node
869  os << "dim-range-node name=W_ix-x_t input-node=W-x dim-offset=0 "
870  << "dim=" << cell_dim << std::endl;
871  os << "dim-range-node name=W_fx-x_t input-node=W-x "
872  << "dim-offset=" << cell_dim << " dim="<<cell_dim << std::endl;
873  os << "dim-range-node name=W_cx-x_t input-node=W-x "
874  << "dim-offset=" << 2 * cell_dim << " dim="<<cell_dim << std::endl;
875  os << "dim-range-node name=W_ox-x_t input-node=W-x "
876  << "dim-offset=" << 3 * cell_dim << " dim="<<cell_dim << std::endl;
877 
878  // Splitting outputs of W*r node
879  os << "dim-range-node name=W_ir-r_tminus1 input-node=W-r dim-offset=0 "
880  << "dim=" << cell_dim << std::endl;
881  os << "dim-range-node name=W_fr-r_tminus1 input-node=W-r "
882  << "dim-offset=" << cell_dim << " dim="<<cell_dim << std::endl;
883  os << "dim-range-node name=W_cr-r_tminus1 input-node=W-r "
884  << "dim-offset=" << 2 * cell_dim << " dim="<<cell_dim << std::endl;
885  os << "dim-range-node name=W_or-r_tminus1 input-node=W-r "
886  << "dim-offset=" << 3 * cell_dim << " dim="<<cell_dim << std::endl;
887 
888  // Non-linear operations
889  os << "component-node name=c_t component=c_t input=Sum(f_t-c_tminus1, i_t-g)\n";
890  os << "component-node name=h component=h input=c_t\n";
891  os << "component-node name=i_t component=i_t input=Sum(W_ix-x_t, Sum(W_ir-r_tminus1, Wic))\n";
892  os << "component-node name=f_t component=f_t input=Sum(W_fx-x_t, Sum(W_fr-r_tminus1, Wfc))\n";
893  os << "component-node name=o_t component=o_t input=Sum(W_ox-x_t, Sum(W_or-r_tminus1, Woc))\n";
894  os << "component-node name=f_t-c_tminus1 component=f_t-c_tminus1 input=Append(f_t, Offset(c_t"
895  << offset << "))\n";
896  os << "component-node name=i_t-g component=i_t-g input=Append(i_t, g)\n";
897  os << "component-node name=m_t component=m_t input=Append(o_t, h)\n";
898 
899  os << "component-node name=g component=g input=Sum(W_cx-x_t, W_cr-r_tminus1)\n";
900 
901  // Final affine transform
902  os << "component-node name=Wyr component=Wyr input=r_t\n";
903  os << "component-node name=Wyp component=Wyp input=p_t\n";
904 
905  os << "component-node name=final_affine component=final_affine input=Sum(Wyr, Wyp)\n";
906 
907  os << "component-node name=posteriors component=logsoftmax input=final_affine\n";
908  os << "output-node name=output input=posteriors\n";
909 
910  configs->push_back(os.str());
911 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateConfigSequenceLstmWithTruncation()

void kaldi::nnet3::GenerateConfigSequenceLstmWithTruncation ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 580 of file nnet-test-utils.cc.

References rnnlm::i, NnetGenerationOptions::output_dim, kaldi::Rand(), and kaldi::RandInt().

Referenced by GenerateConfigSequence().

582  {
583  std::ostringstream os;
584 
585  std::vector<int32> splice_context;
586  for (int32 i = -5; i < 4; i++)
587  if (Rand() % 3 == 0)
588  splice_context.push_back(i);
589  if (splice_context.empty())
590  splice_context.push_back(0);
591 
592  int32 input_dim = 10 + Rand() % 20,
593  spliced_dim = input_dim * splice_context.size(),
594  output_dim = (opts.output_dim > 0 ?
595  opts.output_dim :
596  100 + Rand() % 200),
597  cell_dim = 40 + Rand() % 50,
598  projection_dim = std::ceil(cell_dim / (Rand() % 10 + 1));
599  int32 clipping_threshold = RandInt(6, 50),
600  zeroing_threshold = RandInt(1, 5),
601  zeroing_interval = RandInt(1, 5) * 10;
602  BaseFloat scale = 0.8 + 0.1*RandInt(0,3);
603 
604  os << "input-node name=input dim=" << input_dim << std::endl;
605 
606  // Parameter Definitions W*(* replaced by - to have valid names)
607  // Input gate control : Wi* matrices
608  os << "component name=Wi-xr type=NaturalGradientAffineComponent"
609  << " input-dim=" << spliced_dim + projection_dim
610  << " output-dim=" << cell_dim << std::endl;
611  os << "component name=Wic type=PerElementScaleComponent "
612  << " dim=" << cell_dim << std::endl;
613 
614  // Forget gate control : Wf* matrices
615  os << "component name=Wf-xr type=NaturalGradientAffineComponent"
616  << " input-dim=" << spliced_dim + projection_dim
617  << " output-dim=" << cell_dim << std::endl;
618  os << "component name=Wfc type=PerElementScaleComponent "
619  << " dim=" << cell_dim << std::endl;
620 
621  // Output gate control : Wo* matrices
622  os << "component name=Wo-xr type=NaturalGradientAffineComponent"
623  << " input-dim=" << spliced_dim + projection_dim
624  << " output-dim=" << cell_dim << std::endl;
625  os << "component name=Woc type=PerElementScaleComponent "
626  << " dim=" << cell_dim << std::endl;
627 
628  // Cell input matrices : Wc* matrices
629  os << "component name=Wc-xr type=NaturalGradientAffineComponent"
630  << " input-dim=" << spliced_dim + projection_dim
631  << " output-dim=" << cell_dim << std::endl;
632 
633 
634 
635  // projection matrices : Wrm and Wpm
636  os << "component name=W-m type=NaturalGradientAffineComponent "
637  << " input-dim=" << cell_dim
638  << " output-dim=" << 2 * projection_dim << std::endl;
639 
640  // Output : Wyr and Wyp
641  os << "component name=Wy- type=NaturalGradientAffineComponent "
642  << " input-dim=" << 2 * projection_dim
643  << " output-dim=" << cell_dim << std::endl;
644 
645  // Defining the diagonal matrices
646  // Defining the final affine transform
647  os << "component name=final_affine type=NaturalGradientAffineComponent "
648  << "input-dim=" << cell_dim << " output-dim=" << output_dim << std::endl;
649  os << "component name=logsoftmax type=LogSoftmaxComponent dim="
650  << output_dim << std::endl;
651 
652  // Defining the non-linearities
653  // declare a no-op component so that we can use a sum descriptor's output
654  // multiple times, and to make the config more readable given the equations
655  os << "component name=i type=SigmoidComponent dim="
656  << cell_dim << std::endl;
657  os << "component name=f type=SigmoidComponent dim="
658  << cell_dim << std::endl;
659  os << "component name=o type=SigmoidComponent dim="
660  << cell_dim << std::endl;
661  os << "component name=g type=TanhComponent dim="
662  << cell_dim << std::endl;
663  os << "component name=h type=TanhComponent dim="
664  << cell_dim << std::endl;
665  os << "component name=c1 type=ElementwiseProductComponent "
666  << " input-dim=" << 2 * cell_dim
667  << " output-dim=" << cell_dim << std::endl;
668  os << "component name=c2 type=ElementwiseProductComponent "
669  << " input-dim=" << 2 * cell_dim
670  << " output-dim=" << cell_dim << std::endl;
671  os << "component name=m type=ElementwiseProductComponent "
672  << " input-dim=" << 2 * cell_dim
673  << " output-dim=" << cell_dim << std::endl;
674  os << "component name=c type=BackpropTruncationComponent dim="
675  << cell_dim
676  << " scale=" << scale
677  << " clipping-threshold=" << clipping_threshold
678  << " zeroing-threshold=" << zeroing_threshold
679  << " zeroing-interval=" << zeroing_interval
680  << " recurrence-interval=1" << std::endl;
681  os << "component name=r type=BackpropTruncationComponent dim="
682  << projection_dim
683  << " scale=" << scale
684  << " clipping-threshold=" << clipping_threshold
685  << " zeroing-threshold=" << zeroing_threshold
686  << " zeroing-interval=" << zeroing_interval
687  << " recurrence-interval=1" << std::endl;
688 
689  // Defining the computations
690  std::ostringstream temp_string_stream;
691  for (size_t i = 0; i < splice_context.size(); i++) {
692  int32 offset = splice_context[i];
693  temp_string_stream << "Offset(input, " << offset << ")";
694  if (i + 1 < splice_context.size())
695  temp_string_stream << ", ";
696  }
697  std::string spliced_input = temp_string_stream.str();
698 
699  int32 offset = RandInt(-3, 3);
700  if (offset == 0)
701  offset = -1;
702 
703 
704  std::string c_tminus1;
705  {
706  std::ostringstream os_temp;
707  os_temp << "IfDefined(Offset(c_t, " << offset << "))";
708  c_tminus1 = os_temp.str();
709  }
710  os << "component-node name=c_t component=c input=Sum(c1_t, c2_t)\n";
711 
712  // i_t
713  os << "component-node name=i1 component=Wi-xr input=Append("
714  << spliced_input << ", IfDefined(Offset(r_t, " << offset << ")))\n";
715  os << "component-node name=i2 component=Wic "
716  << " input=" << c_tminus1 << std::endl;
717  os << "component-node name=i_t component=i input=Sum(i1, i2)\n";
718 
719  // f_t
720  os << "component-node name=f1 component=Wf-xr input=Append("
721  << spliced_input << ", IfDefined(Offset(r_t, " << offset << ")))\n";
722  os << "component-node name=f2 component=Wfc "
723  << " input=" << c_tminus1 << std::endl;
724  os << "component-node name=f_t component=f input=Sum(f1, f2)\n";
725 
726  // o_t
727  os << "component-node name=o1 component=Wo-xr input=Append("
728  << spliced_input << ", IfDefined(Offset(r_t, " << offset << ")))\n";
729  os << "component-node name=o2 component=Woc input=Sum(c1_t, c2_t)\n";
730  os << "component-node name=o_t component=o input=Sum(o1, o2)\n";
731 
732  // h_t
733  os << "component-node name=h_t component=h input=Sum(c1_t, c2_t)\n";
734 
735  // g_t
736  os << "component-node name=g1 component=Wc-xr input=Append("
737  << spliced_input << ", IfDefined(Offset(r_t, " << offset << ")))\n";
738  os << "component-node name=g_t component=g input=g1\n";
739 
740  // parts of c_t
741  os << "component-node name=c1_t component=c1 "
742  << " input=Append(f_t, " << c_tminus1 << ")\n";
743  os << "component-node name=c2_t component=c2 input=Append(i_t, g_t)\n";
744 
745  // m_t
746  os << "component-node name=m_t component=m input=Append(o_t, h_t)\n";
747 
748  // r_t and p_t
749  os << "component-node name=rp_t component=W-m input=m_t\n";
750  // Splitting outputs of Wy- node
751  os << "dim-range-node name=r_t_pretrunc input-node=rp_t dim-offset=0 "
752  << "dim=" << projection_dim << std::endl;
753  os << "component-node name=r_t component=r input=r_t_pretrunc\n";
754 
755  // y_t
756  os << "component-node name=y_t component=Wy- input=rp_t\n";
757 
758  // Final affine transform
759  os << "component-node name=final_affine component=final_affine input=y_t\n";
760  os << "component-node name=posteriors component=logsoftmax input=final_affine\n";
761  os << "output-node name=output input=posteriors\n";
762  configs->push_back(os.str());
763 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateConfigSequenceRestrictedAttention()

void kaldi::nnet3::GenerateConfigSequenceRestrictedAttention ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 1130 of file nnet-test-utils.cc.

References kaldi::RandInt().

Referenced by GenerateConfigSequence().

1132  {
1133  std::ostringstream ss;
1134 
1135 
1136  int32 input_dim = RandInt(100, 150),
1137  num_heads = RandInt(1, 2),
1138  key_dim = RandInt(20, 40),
1139  value_dim = RandInt(20, 40),
1140  time_stride = RandInt(1, 3),
1141  num_left_inputs = RandInt(1, 4),
1142  num_right_inputs = RandInt(0, 2),
1143  num_left_inputs_required = RandInt(0, num_left_inputs),
1144  num_right_inputs_required = RandInt(0, num_right_inputs);
1145  bool output_context = (RandInt(0, 1) == 0);
1146  int32 context_dim = (num_left_inputs + 1 + num_right_inputs),
1147  query_dim = key_dim + context_dim;
1148  int32 attention_input_dim = num_heads * (key_dim + value_dim + query_dim);
1149 
1150  std::string cur_layer_descriptor = "input";
1151 
1152  { // input layer.
1153  ss << "input-node name=input dim=" << input_dim
1154  << std::endl;
1155  }
1156 
1157  { // affine component
1158  ss << "component name=affine type=NaturalGradientAffineComponent input-dim="
1159  << input_dim << " output-dim=" << attention_input_dim << std::endl;
1160  ss << "component-node name=affine component=affine input=input"
1161  << std::endl;
1162  }
1163 
1164  { // attention component
1165  ss << "component-node name=attention component=attention input=affine"
1166  << std::endl;
1167  ss << "component name=attention type=RestrictedAttentionComponent"
1168  << " num-heads=" << num_heads << " key-dim=" << key_dim
1169  << " value-dim=" << value_dim << " time-stride=" << time_stride
1170  << " num-left-inputs=" << num_left_inputs << " num-right-inputs="
1171  << num_right_inputs << " num-left-inputs-required="
1172  << num_left_inputs_required << " num-right-inputs-required="
1173  << num_right_inputs_required
1174  << " output-context=" << (output_context ? "true" : "false")
1175  << (RandInt(0, 1) == 0 ? " key-scale=1.0" : "")
1176  << std::endl;
1177  }
1178 
1179  { // output
1180  ss << "output-node name=output input=attention" << std::endl;
1181  }
1182  configs->push_back(ss.str());
1183 }
kaldi::int32 int32
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateConfigSequenceRnn()

void kaldi::nnet3::GenerateConfigSequenceRnn ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 263 of file nnet-test-utils.cc.

References rnnlm::i, NnetGenerationOptions::output_dim, kaldi::Rand(), and kaldi::RandInt().

Referenced by GenerateConfigSequence().

265  {
266  std::ostringstream os;
267 
268  std::vector<int32> splice_context;
269  for (int32 i = -5; i < 4; i++)
270  if (Rand() % 3 == 0)
271  splice_context.push_back(i);
272  if (splice_context.empty())
273  splice_context.push_back(0);
274 
275  int32 input_dim = 10 + Rand() % 20,
276  spliced_dim = input_dim * splice_context.size(),
277  output_dim = (opts.output_dim > 0 ?
278  opts.output_dim :
279  100 + Rand() % 200),
280  hidden_dim = 40 + Rand() % 50;
281  os << "component name=affine1 type=NaturalGradientAffineComponent input-dim="
282  << spliced_dim << " output-dim=" << hidden_dim << std::endl;
283  if (RandInt(0, 1) == 0) {
284  os << "component name=nonlin1 type=RectifiedLinearComponent dim="
285  << hidden_dim << std::endl;
286  } else {
287  os << "component name=nonlin1 type=TanhComponent dim="
288  << hidden_dim << std::endl;
289  }
290  os << "component name=recurrent_affine1 type=NaturalGradientAffineComponent input-dim="
291  << hidden_dim << " output-dim=" << hidden_dim << std::endl;
292  os << "component name=affine2 type=NaturalGradientAffineComponent input-dim="
293  << hidden_dim << " output-dim=" << output_dim << std::endl;
294  os << "component name=logsoftmax type=LogSoftmaxComponent dim="
295  << output_dim << std::endl;
296  os << "input-node name=input dim=" << input_dim << std::endl;
297 
298  os << "component-node name=affine1_node component=affine1 input=Append(";
299  for (size_t i = 0; i < splice_context.size(); i++) {
300  int32 offset = splice_context[i];
301  os << "Offset(input, " << offset << ")";
302  if (i + 1 < splice_context.size())
303  os << ", ";
304  }
305  os << ")\n";
306  os << "component-node name=recurrent_affine1 component=recurrent_affine1 "
307  "input=Offset(nonlin1, -1)\n";
308  os << "component-node name=nonlin1 component=nonlin1 "
309  "input=Sum(affine1_node, IfDefined(recurrent_affine1))\n";
310  os << "component-node name=affine2 component=affine2 input=nonlin1\n";
311  os << "component-node name=output_nonlin component=logsoftmax input=affine2\n";
312  os << "output-node name=output input=output_nonlin\n";
313  configs->push_back(os.str());
314 }
kaldi::int32 int32
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateConfigSequenceRnnClockwork()

void kaldi::nnet3::GenerateConfigSequenceRnnClockwork ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 322 of file nnet-test-utils.cc.

References rnnlm::i, NnetGenerationOptions::output_dim, and kaldi::Rand().

Referenced by GenerateConfigSequence().

324  {
325  std::ostringstream os;
326 
327  std::vector<int32> splice_context;
328  for (int32 i = -5; i < 4; i++)
329  if (Rand() % 3 == 0)
330  splice_context.push_back(i);
331  if (splice_context.empty())
332  splice_context.push_back(0);
333 
334  int32 input_dim = 10 + Rand() % 20,
335  spliced_dim = input_dim * splice_context.size(),
336  output_dim = (opts.output_dim > 0 ?
337  opts.output_dim :
338  100 + Rand() % 200),
339  hidden_dim = 40 + Rand() % 50;
340  os << "component name=affine1 type=NaturalGradientAffineComponent input-dim="
341  << spliced_dim << " output-dim=" << hidden_dim << std::endl;
342  os << "component name=nonlin1 type=RectifiedLinearComponent dim="
343  << hidden_dim << std::endl;
344  os << "component name=recurrent_affine1 type=NaturalGradientAffineComponent input-dim="
345  << hidden_dim << " output-dim=" << hidden_dim << std::endl;
346  // the suffix _0, _1, _2 equals the index of the output-frame modulo 3; there
347  // are 3 versions of the final affine layer. There was a paper by Vincent
348  // Vanhoucke about something like this.
349  os << "component name=final_affine_0 type=NaturalGradientAffineComponent input-dim="
350  << hidden_dim << " output-dim=" << output_dim << std::endl;
351  os << "component name=final_affine_1 type=NaturalGradientAffineComponent input-dim="
352  << hidden_dim << " output-dim=" << output_dim << std::endl;
353  os << "component name=final_affine_2 type=NaturalGradientAffineComponent input-dim="
354  << hidden_dim << " output-dim=" << output_dim << std::endl;
355  os << "component name=logsoftmax type=LogSoftmaxComponent dim="
356  << output_dim << std::endl;
357  os << "input-node name=input dim=" << input_dim << std::endl;
358 
359  os << "component-node name=affine1_node component=affine1 input=Append(";
360  for (size_t i = 0; i < splice_context.size(); i++) {
361  int32 offset = splice_context[i];
362  os << "Offset(input, " << offset << ")";
363  if (i + 1 < splice_context.size())
364  os << ", ";
365  }
366  os << ")\n";
367  os << "component-node name=recurrent_affine1 component=recurrent_affine1 "
368  "input=Offset(nonlin1, -1)\n";
369  os << "component-node name=nonlin1 component=nonlin1 "
370  "input=Sum(affine1_node, IfDefined(recurrent_affine1))\n";
371  os << "component-node name=final_affine_0 component=final_affine_0 input=nonlin1\n";
372  os << "component-node name=final_affine_1 component=final_affine_1 input=Offset(nonlin1, -1)\n";
373  os << "component-node name=final_affine_2 component=final_affine_2 input=Offset(nonlin1, 1)\n";
374  os << "component-node name=output_nonlin component=logsoftmax input=Switch(final_affine_0, final_affine_1, final_affine_2)\n";
375  os << "output-node name=output input=output_nonlin\n";
376  configs->push_back(os.str());
377 }
kaldi::int32 int32
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45

◆ GenerateConfigSequenceSimple()

void kaldi::nnet3::GenerateConfigSequenceSimple ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 111 of file nnet-test-utils.cc.

References NnetGenerationOptions::allow_final_nonlinearity, NnetGenerationOptions::allow_ivector, rnnlm::i, NnetGenerationOptions::output_dim, kaldi::Rand(), and kaldi::RandInt().

Referenced by GenerateConfigSequence().

113  {
114  std::ostringstream os;
115 
116  std::vector<int32> splice_context;
117  for (int32 i = -5; i < 4; i++)
118  if (Rand() % 3 == 0)
119  splice_context.push_back(i);
120  if (splice_context.empty())
121  splice_context.push_back(0);
122 
123  int32 input_dim = 10 + Rand() % 20,
124  output_dim = (opts.output_dim > 0 ?
125  opts.output_dim :
126  100 + Rand() % 200),
127  hidden_dim = 40 + Rand() % 50;
128  int32 ivector_dim = 10 + Rand() % 20;
129  if (RandInt(0, 1) == 0 || !opts.allow_ivector)
130  ivector_dim = 0;
131  int32 spliced_dim = input_dim * splice_context.size() + ivector_dim;
132 
133  bool use_final_nonlinearity = (opts.allow_final_nonlinearity &&
134  RandInt(0, 1) == 0);
135  bool use_batch_norm = (RandInt(0, 1) == 0);
136 
137  os << "component name=affine1 type=NaturalGradientAffineComponent input-dim="
138  << spliced_dim << " output-dim=" << hidden_dim << std::endl;
139  os << "component name=relu1 type=RectifiedLinearComponent dim="
140  << hidden_dim << std::endl;
141  if (use_batch_norm) {
142  int32 block_dim = (hidden_dim % 2 == 0 ? hidden_dim / 2 : hidden_dim);
143  os << "component name=batch-norm type=BatchNormComponent dim="
144  << hidden_dim << " block-dim=" << block_dim
145  << " target-rms=2.0";
146  if (RandInt(0, 1) == 0)
147  os << " epsilon=3.0";
148  os << '\n';
149  }
150  os << "component name=final_affine type=NaturalGradientAffineComponent input-dim="
151  << hidden_dim << " output-dim=" << output_dim << std::endl;
152  if (use_final_nonlinearity) {
153  if (Rand() % 2 == 0) {
154  os << "component name=logsoftmax type=SoftmaxComponent dim="
155  << output_dim << std::endl;
156  } else {
157  os << "component name=logsoftmax type=LogSoftmaxComponent dim="
158  << output_dim << std::endl;
159  }
160  }
161  os << "input-node name=input dim=" << input_dim << std::endl;
162  if (ivector_dim != 0)
163  os << "input-node name=ivector dim=" << ivector_dim << std::endl;
164 
165  os << "component-node name=affine1_node component=affine1 input=Append(";
166  if (ivector_dim != 0)
167  os << "ReplaceIndex(ivector, t, 0), ";
168  for (size_t i = 0; i < splice_context.size(); i++) {
169  int32 offset = splice_context[i];
170  if (RandInt(0, 1) == 0) {
171  os << "Offset(input, " << offset << ")";
172  } else {
173  // testing the Scale() expression.
174  os << "Scale(-1, Offset(input, " << offset << "))";
175  }
176  if (i + 1 < splice_context.size())
177  os << ", ";
178  }
179  os << ")\n";
180  if (RandInt(0, 1) == 0) {
181  os << "component-node name=nonlin1 component=relu1 input=affine1_node\n";
182  } else if (RandInt(0, 1) == 0) {
183  os << "component-node name=nonlin1 component=relu1 input=Scale(-1.0, affine1_node)\n";
184  } else {
185  os << "component-node name=nonlin1 component=relu1 input=Sum(Const(1.0, "
186  << hidden_dim << "), Scale(-1.0, affine1_node))\n";
187  }
188  if (use_batch_norm) {
189  os << "component-node name=batch-norm component=batch-norm input=nonlin1\n";
190  os << "component-node name=final_affine component=final_affine input=batch-norm\n";
191  } else {
192  os << "component-node name=final_affine component=final_affine input=nonlin1\n";
193  }
194  if (use_final_nonlinearity) {
195  os << "component-node name=output_nonlin component=logsoftmax input=final_affine\n";
196  os << "output-node name=output input=output_nonlin\n";
197  } else {
198  os << "output-node name=output input=final_affine\n";
199  }
200  configs->push_back(os.str());
201 
202  if ((Rand() % 2) == 0) {
203  std::ostringstream os2;
204  os2 << "component name=affine2 type=NaturalGradientAffineComponent input-dim="
205  << hidden_dim << " output-dim=" << hidden_dim << std::endl;
206  os2 << "component name=relu2 type=RectifiedLinearComponent dim="
207  << hidden_dim << std::endl;
208  // regenerate the final_affine component when we add the new config.
209  os2 << "component name=final_affine type=NaturalGradientAffineComponent input-dim="
210  << hidden_dim << " output-dim=" << output_dim << std::endl;
211  os2 << "component-node name=affine2 component=affine2 input=nonlin1\n";
212  os2 << "component-node name=relu2 component=relu2 input=affine2\n";
213  os2 << "component-node name=final_affine component=final_affine input=relu2\n";
214  configs->push_back(os2.str());
215  }
216 }
kaldi::int32 int32
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateConfigSequenceSimpleContext()

void kaldi::nnet3::GenerateConfigSequenceSimpleContext ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 54 of file nnet-test-utils.cc.

References rnnlm::i, NnetGenerationOptions::output_dim, kaldi::Rand(), and kaldi::RandInt().

Referenced by GenerateConfigSequence().

56  {
57  std::ostringstream os;
58 
59  std::vector<int32> splice_context;
60  for (int32 i = -5; i < 4; i++)
61  if (Rand() % 3 == 0)
62  splice_context.push_back(i);
63  if (splice_context.empty())
64  splice_context.push_back(0);
65 
66  int32 input_dim = 10 + Rand() % 20,
67  spliced_dim = input_dim * splice_context.size(),
68  output_dim = (opts.output_dim > 0 ?
69  opts.output_dim :
70  100 + Rand() % 200);
71 
72  if (RandInt(0,1) == 0) {
73  // do it the traditional way with an AffineComponent and an Append() expression.
74  os << "component name=affine1 type=AffineComponent input-dim="
75  << spliced_dim << " output-dim=" << output_dim << std::endl;
76 
77  os << "input-node name=input dim=" << input_dim << std::endl;
78 
79  os << "component-node name=affine1_node component=affine1 input=Append(";
80  for (size_t i = 0; i < splice_context.size(); i++) {
81  int32 offset = splice_context[i];
82  os << "Offset(input, " << offset << ")";
83  if (i + 1 < splice_context.size())
84  os << ", ";
85  }
86  os << ")\n";
87  os << "output-node name=output input=affine1_node\n";
88  } else {
89  os << "component name=tdnn1 type=TdnnComponent input-dim="
90  << input_dim << " output-dim=" << output_dim
91  << " time-offsets=";
92  for (size_t i = 0; i < splice_context.size(); i++) {
93  if (i>0) os << ',';
94  os << splice_context[i];
95  }
96  os << " use-bias=" << (RandInt(0,1) == 0 ? "true":"false")
97  << " use-natural-gradient=" << (RandInt(0,1) == 0 ? "true":"false")
98  << std::endl;
99  os << "input-node name=input dim=" << input_dim << std::endl;
100  os << "component-node name=tdnn1_node component=tdnn1 input=input\n";
101  os << "output-node name=output input=tdnn1_node\n";
102  }
103  configs->push_back(os.str());
104 }
kaldi::int32 int32
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateConfigSequenceSimplest()

void kaldi::nnet3::GenerateConfigSequenceSimplest ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 33 of file nnet-test-utils.cc.

References NnetGenerationOptions::output_dim, and kaldi::Rand().

Referenced by GenerateConfigSequence().

35  {
36  std::ostringstream os;
37 
38  int32 input_dim = 10 + Rand() % 20,
39  output_dim = (opts.output_dim > 0 ?
40  opts.output_dim :
41  100 + Rand() % 200);
42 
43 
44  os << "component name=affine1 type=AffineComponent input-dim="
45  << input_dim << " output-dim=" << output_dim << std::endl;
46 
47  os << "input-node name=input dim=" << input_dim << std::endl;
48  os << "component-node name=affine1_node component=affine1 input=input\n";
49  os << "output-node name=output input=affine1_node\n";
50  configs->push_back(os.str());
51 }
kaldi::int32 int32
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45

◆ GenerateConfigSequenceStatistics()

void kaldi::nnet3::GenerateConfigSequenceStatistics ( const NnetGenerationOptions opts,
std::vector< std::string > *  configs 
)

Definition at line 219 of file nnet-test-utils.cc.

References kaldi::RandInt().

Referenced by GenerateConfigSequence().

221  {
222  int32 input_dim = RandInt(10, 30),
223  input_period = RandInt(1, 3),
224  stats_period = input_period * RandInt(1, 3),
225  left_context = stats_period * RandInt(1, 10),
226  right_context = stats_period * RandInt(1, 10),
227  log_count_features = RandInt(0, 3);
228  BaseFloat variance_floor = RandInt(1, 10) * 1.0e-10;
229  bool output_stddevs = (RandInt(0, 1) == 0);
230 
231  int32 raw_stats_dim = 1 + input_dim + (output_stddevs ? input_dim : 0),
232  pooled_stats_dim = log_count_features + input_dim +
233  (output_stddevs ? input_dim : 0);
234  std::ostringstream os;
235  os << "input-node name=input dim=" << input_dim << std::endl;
236  os << "component name=statistics-extraction type=StatisticsExtractionComponent "
237  << "input-dim=" << input_dim << " input-period=" << input_period
238  << " output-period=" << stats_period << " include-variance="
239  << std::boolalpha << output_stddevs << "\n";
240 
241  os << "component name=statistics-pooling type=StatisticsPoolingComponent "
242  << "input-dim=" << raw_stats_dim << " input-period=" << stats_period
243  << " left-context=" << left_context << " right-context=" << right_context
244  << " num-log-count-features=" << log_count_features << " output-stddevs="
245  << std::boolalpha << output_stddevs << " variance-floor="
246  << variance_floor << "\n";
247 
248  os << "component name=affine type=AffineComponent "
249  << "input-dim=" << input_dim << " output-dim=" << pooled_stats_dim
250  << "\n";
251 
252  os << "component-node name=statistics-extraction component=statistics-extraction "
253  << "input=input\n";
254  os << "component-node name=statistics-pooling component=statistics-pooling "
255  << "input=statistics-extraction\n";
256  os << "component-node name=affine component=affine input=input\n";
257  os << "output-node name=output input=Sum(affine, Round(statistics-pooling, "
258  << stats_period << "))\n";
259  configs->push_back(os.str());
260 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateRandomComponentConfig()

static void kaldi::nnet3::GenerateRandomComponentConfig ( std::string *  component_type,
std::string *  config 
)
static

Definition at line 1400 of file nnet-test-utils.cc.

References rnnlm::i, KALDI_ERR, rnnlm::n, kaldi::Rand(), kaldi::RandInt(), and kaldi::RandUniform().

Referenced by GenerateRandomSimpleComponent().

1401  {
1402 
1403  int32 n = RandInt(0, 37);
1404  BaseFloat learning_rate = 0.001 * RandInt(1, 100);
1405 
1406  std::ostringstream os;
1407  switch(n) {
1408  case 0: {
1409  *component_type = "PnormComponent";
1410  int32 output_dim = RandInt(1, 50), group_size = RandInt(1, 15),
1411  input_dim = output_dim * group_size;
1412  os << "input-dim=" << input_dim << " output-dim=" << output_dim;
1413  break;
1414  }
1415  case 1: {
1416  BaseFloat target_rms = (RandInt(1, 200) / 100.0);
1417  std::string add_log_stddev = (Rand() % 2 == 0 ? "True" : "False");
1418  *component_type = "NormalizeComponent";
1419 
1420  int32 block_dim = RandInt(2, 50), num_blocks = RandInt(1, 3),
1421  dim = block_dim * num_blocks;
1422  // avoid dim=1 because the derivatives would be zero, which
1423  // makes them hard to test.
1424  os << "dim=" << dim << " block-dim=" << block_dim
1425  << " target-rms=" << target_rms
1426  << " add-log-stddev=" << add_log_stddev;
1427  break;
1428  }
1429  case 2: {
1430  *component_type = "SigmoidComponent";
1431  os << "dim=" << RandInt(1, 50);
1432  break;
1433  }
1434  case 3: {
1435  *component_type = "TanhComponent";
1436  os << "dim=" << RandInt(1, 50);
1437  break;
1438  }
1439  case 4: {
1440  *component_type = "RectifiedLinearComponent";
1441  os << "dim=" << RandInt(1, 50);
1442  break;
1443  }
1444  case 5: {
1445  *component_type = "SoftmaxComponent";
1446  os << "dim=" << RandInt(1, 50);
1447  break;
1448  }
1449  case 6: {
1450  *component_type = "LogSoftmaxComponent";
1451  os << "dim=" << RandInt(1, 50);
1452  break;
1453  }
1454  case 7: {
1455  *component_type = "NoOpComponent";
1456  os << "dim=" << RandInt(1, 50);
1457  break;
1458  }
1459  case 8: {
1460  *component_type = "FixedAffineComponent";
1461  int32 input_dim = RandInt(1, 50), output_dim = RandInt(1, 50);
1462  os << "input-dim=" << input_dim << " output-dim=" << output_dim;
1463  break;
1464  }
1465  case 9: {
1466  *component_type = "AffineComponent";
1467  int32 input_dim = RandInt(1, 50), output_dim = RandInt(1, 50);
1468  os << "input-dim=" << input_dim << " output-dim=" << output_dim
1469  << " learning-rate=" << learning_rate;
1470  break;
1471  }
1472  case 10: {
1473  *component_type = "NaturalGradientAffineComponent";
1474  int32 input_dim = RandInt(1, 50), output_dim = RandInt(1, 50);
1475  os << "input-dim=" << input_dim << " output-dim=" << output_dim
1476  << " learning-rate=" << learning_rate;
1477  break;
1478  }
1479  case 11: {
1480  *component_type = "SumGroupComponent";
1481  std::vector<int32> sizes;
1482  int32 num_groups = RandInt(1, 50);
1483  os << "sizes=";
1484  for (int32 i = 0; i < num_groups; i++) {
1485  os << RandInt(1, 5);
1486  if (i + 1 < num_groups)
1487  os << ',';
1488  }
1489  break;
1490  }
1491  case 12: {
1492  *component_type = "FixedScaleComponent";
1493  os << "dim=" << RandInt(1, 100);
1494  break;
1495  }
1496  case 13: {
1497  *component_type = "FixedBiasComponent";
1498  os << "dim=" << RandInt(1, 100);
1499  break;
1500  }
1501  case 14: {
1502  *component_type = "NaturalGradientPerElementScaleComponent";
1503  os << "dim=" << RandInt(1, 100)
1504  << " learning-rate=" << learning_rate;
1505  break;
1506  }
1507  case 15: {
1508  *component_type = "PerElementScaleComponent";
1509  os << "dim=" << RandInt(1, 100)
1510  << " learning-rate=" << learning_rate;
1511  break;
1512  }
1513  case 16: {
1514  *component_type = "ElementwiseProductComponent";
1515  int32 output_dim = RandInt(1, 100), multiple = RandInt(2, 4),
1516  input_dim = output_dim * multiple;
1517  os << "input-dim=" << input_dim << " output-dim=" << output_dim;
1518  break;
1519  }
1520  case 17: {
1521  int32 input_vectorization = Rand() % 2;
1522  std::string vectorization;
1523  if (input_vectorization == 0) {
1524  vectorization = "yzx";
1525  } else {
1526  vectorization = "zyx";
1527  }
1528  *component_type = "ConvolutionComponent";
1529  int32 input_x_dim = 10 + Rand() % 20,
1530  input_y_dim = 10 + Rand() % 20,
1531  input_z_dim = 3 + Rand() % 10,
1532  filt_x_dim = 1 + Rand() % input_x_dim,
1533  filt_y_dim = 1 + Rand() % input_y_dim,
1534  num_filters = 1 + Rand() % 10,
1535  filt_x_step = (1 + Rand() % filt_x_dim),
1536  filt_y_step = (1 + Rand() % filt_y_dim);
1537  int32 remainder = (input_x_dim - filt_x_dim) % filt_x_step;
1538  // adjusting input_x_dim to ensure divisibility
1539  input_x_dim = input_x_dim - remainder;
1540  remainder = (input_y_dim - filt_y_dim) % filt_y_step;
1541  // adjusting input_x_dim to ensure divisibility
1542  input_y_dim = input_y_dim - remainder;
1543 
1544  os << "input-x-dim=" << input_x_dim
1545  << " input-y-dim=" << input_y_dim
1546  << " input-z-dim=" << input_z_dim
1547  << " filt-x-dim=" << filt_x_dim
1548  << " filt-y-dim=" << filt_y_dim
1549  << " filt-x-step=" << filt_x_step
1550  << " filt-y-step=" << filt_y_step
1551  << " num-filters=" << num_filters
1552  << " input-vectorization-order=" << vectorization
1553  << " learning-rate=" << learning_rate;
1554  break;
1555  // TODO : add test for file based initialization. But confirm how to write
1556  // a file which is not going to be overwritten by other components
1557  }
1558  case 18: {
1559  *component_type = "PermuteComponent";
1560  int32 input_dim = 10 + Rand() % 100;
1561  std::vector<int32> column_map(input_dim);
1562  for (int32 i = 0; i < input_dim; i++)
1563  column_map[i] = i;
1564  std::random_shuffle(column_map.begin(), column_map.end());
1565  std::ostringstream buffer;
1566  for (int32 i = 0; i < input_dim-1; i++)
1567  buffer << column_map[i] << ",";
1568  buffer << column_map.back();
1569  os << "column-map=" << buffer.str();
1570  break;
1571  }
1572  case 19: {
1573  *component_type = "PerElementOffsetComponent";
1574  std::string param_config = RandInt(0, 1)?
1575  " param-mean=0.0 param-stddev=0.0":
1576  " param-mean=1.0 param-stddev=1.0";
1577  int32 block_dim = RandInt(10, 20), dim = block_dim * RandInt(1, 2);
1578  os << "dim=" << dim << " block-dim=" << block_dim
1579  << " use-natural-gradient=" << (RandInt(0, 1) == 0 ? "true" : "false")
1580  << " learning-rate=" << learning_rate << param_config;
1581  break;
1582  }
1583  case 20: case 21: {
1584  *component_type = "CompositeComponent";
1585  int32 cur_dim = RandInt(20, 30), num_components = RandInt(1, 3),
1586  max_rows_process = RandInt(1, 30);
1587  os << "num-components=" << num_components
1588  << " max-rows-process=" << max_rows_process;
1589  std::vector<std::string> sub_configs;
1590  for (int32 i = 1; i <= num_components; i++) {
1591  if (RandInt(1, 3) == 1) {
1592  os << " component" << i << "='type=RectifiedLinearComponent dim="
1593  << cur_dim << "'";
1594  } else if (RandInt(1, 2) == 1) {
1595  os << " component" << i << "='type=TanhComponent dim="
1596  << cur_dim << "'";
1597  } else {
1598  int32 next_dim = RandInt(20, 30);
1599  os << " component" << i << "='type=AffineComponent input-dim="
1600  << cur_dim << " output-dim=" << next_dim << "'";
1601  cur_dim = next_dim;
1602  }
1603  }
1604  break;
1605  }
1606  case 22: {
1607  *component_type = "SumGroupComponent";
1608  int32 num_groups = RandInt(1, 50),
1609  input_dim = num_groups * RandInt(1, 15);
1610  os << "input-dim=" << input_dim << " output-dim=" << num_groups;
1611  break;
1612  }
1613  case 23: {
1614  *component_type = "RepeatedAffineComponent";
1615  int32 num_repeats = RandInt(1, 50),
1616  input_dim = num_repeats * RandInt(1, 15),
1617  output_dim = num_repeats * RandInt(1, 15);
1618  os << "input-dim=" << input_dim << " output-dim=" << output_dim
1619  << " num-repeats=" << num_repeats;
1620  break;
1621  }
1622  case 24: {
1623  *component_type = "BlockAffineComponent";
1624  int32 num_blocks = RandInt(1, 50),
1625  input_dim = num_blocks * RandInt(1, 15),
1626  output_dim = num_blocks * RandInt(1, 15);
1627  os << "input-dim=" << input_dim << " output-dim=" << output_dim
1628  << " num-blocks=" << num_blocks;
1629  break;
1630  }
1631  case 25: {
1632  *component_type = "NaturalGradientRepeatedAffineComponent";
1633  int32 num_repeats = RandInt(1, 50),
1634  input_dim = num_repeats * RandInt(1, 15),
1635  output_dim = num_repeats * RandInt(1, 15);
1636  os << "input-dim=" << input_dim << " output-dim=" << output_dim
1637  << " num-repeats=" << num_repeats;
1638  break;
1639  }
1640  case 26: {
1641  *component_type = "MaxpoolingComponent";
1642  int32 input_x_dim = 5 + Rand() % 10,
1643  input_y_dim = 5 + Rand() % 10,
1644  input_z_dim = 5 + Rand() % 10;
1645  int32 pool_x_size = 1 + Rand() % input_x_dim,
1646  pool_y_size = 1 + Rand() % input_y_dim,
1647  pool_z_size = 1 + Rand() % input_z_dim;
1648  int32 pool_x_step = (1 + Rand() % pool_x_size),
1649  pool_y_step = (1 + Rand() % pool_y_size),
1650  pool_z_step = (1 + Rand() % pool_z_size);
1651  // adjusting input dim to ensure divisibility
1652  int32 remainder = (input_x_dim - pool_x_size) % pool_x_step;
1653  input_x_dim = input_x_dim - remainder;
1654  remainder = (input_y_dim - pool_y_size) % pool_y_step;
1655  input_y_dim = input_y_dim - remainder;
1656  remainder = (input_z_dim - pool_z_size) % pool_z_step;
1657  input_z_dim = input_z_dim - remainder;
1658  os << " input-x-dim=" << input_x_dim
1659  << " input-y-dim=" << input_y_dim
1660  << " input-z-dim=" << input_z_dim
1661  << " pool-x-size=" << pool_x_size
1662  << " pool-y-size=" << pool_y_size
1663  << " pool-z-size=" << pool_z_size
1664  << " pool-x-step=" << pool_x_step
1665  << " pool-y-step=" << pool_y_step
1666  << " pool-z-step=" << pool_z_step;
1667  break;
1668  }
1669  case 27: {
1670  *component_type = "ConstantFunctionComponent";
1671  int32 input_dim = RandInt(1, 50), output_dim = RandInt(1, 50);
1672  bool is_updatable = (RandInt(0, 1) == 0),
1673  use_natural_gradient = (RandInt(0, 1) == 0);
1674  os << "input-dim=" << input_dim << " output-dim=" << output_dim
1675  << " learning-rate=" << learning_rate
1676  << " is-updatable=" << std::boolalpha << is_updatable
1677  << " use-natural-gradient=" << std::boolalpha << use_natural_gradient;
1678  break;
1679  }
1680  case 28: {
1681  *component_type = "ClipGradientComponent";
1682  os << "dim=" << RandInt(1, 50);
1683  os << " clipping-threshold=" << RandInt(1, 50)
1684  << " norm-based-clipping=" << (RandInt(0, 1) == 0 ? "false" : "true");
1685  if (RandInt(0, 1) == 1)
1686  os << " self-repair-scale="
1687  << (RandInt(0, 1) == 0 ? 0 : RandInt(1, 50));
1688  if (RandInt(0, 1) == 1)
1689  os << " self-repair-clipped-proportion-threshold=" << RandUniform();
1690  if (RandInt(0, 1) == 1)
1691  os << " self-repair-target=" << RandUniform();
1692  break;
1693  }
1694  case 29: {
1695  *component_type = "DropoutComponent";
1696  bool test_mode = (RandInt(0, 1) == 0);
1697  os << "dim=" << RandInt(1, 200)
1698  << " dropout-proportion=" << RandUniform() << " test-mode="
1699  << (test_mode ? "true" : "false");
1700  break;
1701  }
1702  case 30: {
1703  *component_type = "LstmNonlinearityComponent";
1704  // set self-repair scale to zero so the derivative tests will pass.
1705  os << "cell-dim=" << RandInt(1, 200)
1706  << " self-repair-scale=0.0";
1707  break;
1708  }
1709  // I think we'll get in the habit of allocating a larger number of case
1710  // labels to the most recently added component, so it gets tested more
1711  case 31: {
1712  *component_type = "BatchNormComponent";
1713  int32 block_dim = RandInt(1, 20), dim = block_dim * RandInt(1, 2);
1714  bool test_mode = (RandInt(0, 1) == 0);
1715  os << " dim=" << dim
1716  << " block-dim=" << block_dim << " target-rms="
1717  << RandInt(1, 4) << " test-mode="
1718  << (test_mode ? "true" : "false")
1719  << " epsilon=" << (RandInt(0, 1) == 0 ? "0.1" : "1.0");
1720  break;
1721  }
1722  case 32: {
1723  *component_type = "SumBlockComponent";
1724  BaseFloat scale = 0.5 * RandInt(1, 3);
1725  BaseFloat output_dim = RandInt(1, 10),
1726  input_dim = output_dim * RandInt(1, 3);
1727  os << "input-dim=" << input_dim
1728  << " output-dim=" << output_dim
1729  << " scale=" << scale;
1730  break;
1731  }
1732  case 33: {
1733  *component_type = "ScaleAndOffsetComponent";
1734  int32 block_dim = RandInt(10, 20),
1735  num_blocks = RandInt(1, 3),
1736  dim = block_dim * num_blocks;
1737  os << "dim=" << dim << " block-dim=" << block_dim
1738  << " use-natural-gradient="
1739  << (RandInt(0,1) == 0 ? "true" : "false");
1740  break;
1741  }
1742  case 34: {
1743  *component_type = "LinearComponent";
1744  int32 input_dim = RandInt(1, 50), output_dim = RandInt(1, 50);
1745  os << "input-dim=" << input_dim << " output-dim=" << output_dim
1746  << " learning-rate=" << learning_rate;
1747  break;
1748  }
1749  case 35: {
1750  // This is not technically a SimpleComponent, but it behaves as one
1751  // if time-offsets=0.
1752  *component_type = "TdnnComponent";
1753  int32 input_dim = RandInt(1, 50), output_dim = RandInt(1, 50);
1754  os << "input-dim=" << input_dim << " output-dim=" << output_dim
1755  << " learning-rate=" << learning_rate << " time-offsets=0"
1756  << " use-natural-gradient=" << (RandInt(0,1) == 0 ? "true":"false")
1757  << " use-bias=" << (RandInt(0,1) == 0 ? "true":"false");
1758  break;
1759  }
1760  case 36: {
1761  *component_type = "GruNonlinearityComponent";
1762  int32 cell_dim = RandInt(10, 20);
1763  int32 recurrent_dim = (RandInt(0, 1) == 0 ?
1764  RandInt(5, cell_dim - 1) : cell_dim);
1765  os << "cell-dim=" << cell_dim
1766  << " recurrent-dim=" << recurrent_dim;
1767  break;
1768  }
1769  case 37: {
1770  *component_type = "OutputGruNonlinearityComponent";
1771  os << "cell-dim=" << RandInt(10, 20)
1772  << " learning-rate=" << learning_rate;
1773 
1774  break;
1775  }
1776  default:
1777  KALDI_ERR << "Error generating random component";
1778  }
1779  *config = os.str();
1780 }
float RandUniform(struct RandomState *state=NULL)
Returns a random number strictly between 0 and 1.
Definition: kaldi-math.h:151
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
struct rnnlm::@11::@12 n
#define KALDI_ERR
Definition: kaldi-error.h:147
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenerateRandomSimpleComponent()

Component * GenerateRandomSimpleComponent ( )

Generates random simple component for testing.

Definition at line 1783 of file nnet-test-utils.cc.

References GenerateRandomComponentConfig(), ConfigLine::HasUnusedValues(), Component::InitFromConfig(), KALDI_ERR, Component::NewComponentOfType(), ConfigLine::ParseLine(), ConfigLine::UnusedValues(), and ConfigLine::WholeLine().

Referenced by NnetGenerationOptions::NnetGenerationOptions(), and UnitTestNnetComponent().

1783  {
1784  std::string component_type, config;
1785  GenerateRandomComponentConfig(&component_type, &config);
1786  ConfigLine config_line;
1787  if (!config_line.ParseLine(config))
1788  KALDI_ERR << "Bad config line " << config;
1789 
1790  Component *c = Component::NewComponentOfType(component_type);
1791  if (c == NULL)
1792  KALDI_ERR << "Invalid component type " << component_type;
1793  c->InitFromConfig(&config_line);
1794  if (config_line.HasUnusedValues()) {
1795  KALDI_ERR << "Config line " << config_line.WholeLine()
1796  << " has unused values: "
1797  << config_line.UnusedValues();
1798  }
1799  return c;
1800 }
static void GenerateRandomComponentConfig(std::string *component_type, std::string *config)
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ GenerateSimpleNnetTrainingExample()

void GenerateSimpleNnetTrainingExample ( int32  num_supervised_frames,
int32  left_context,
int32  right_context,
int32  input_dim,
int32  output_dim,
int32  ivector_dim,
NnetExample example 
)

Low-level function that generates an nnet training example.

By "simple" we mean there is one output named "output", an input named "input", and possibly also an input named "ivector" (this will be assumed absent if ivector_dim <= 0). This function generates exactly "left_context" or "right_context" frames of context on the left and right respectively.

Definition at line 1832 of file nnet-test-utils.cc.

References GeneralMatrix::Compress(), NnetIo::features, rnnlm::i, NnetExample::io, KALDI_ASSERT, kaldi::RandInt(), kaldi::RandUniform(), and MatrixBase< Real >::SetRandn().

Referenced by NnetGenerationOptions::NnetGenerationOptions(), UnitTestNnetExample(), and UnitTestNnetMergeExamples().

1839  {
1840  KALDI_ASSERT(num_supervised_frames > 0 && left_context >= 0 &&
1841  right_context >= 0 && output_dim > 0 && input_dim > 0
1842  && example != NULL);
1843  example->io.clear();
1844 
1845  int32 feature_t_begin = RandInt(0, 2);
1846  int32 num_feat_frames = left_context + right_context + num_supervised_frames;
1847  Matrix<BaseFloat> input_mat(num_feat_frames, input_dim);
1848  input_mat.SetRandn();
1849  NnetIo input_feat("input", feature_t_begin, input_mat);
1850  if (RandInt(0, 1) == 0)
1851  input_feat.features.Compress();
1852  example->io.push_back(input_feat);
1853 
1854  if (ivector_dim > 0) {
1855  // Create a feature for the iVectors. iVectors always have t=0 in the
1856  // current framework.
1857  Matrix<BaseFloat> ivector_mat(1, ivector_dim);
1858  ivector_mat.SetRandn();
1859  NnetIo ivector_feat("ivector", 0, ivector_mat);
1860  if (RandInt(0, 1) == 0)
1861  ivector_feat.features.Compress();
1862  example->io.push_back(ivector_feat);
1863  }
1864 
1865  { // set up the output supervision.
1866  Posterior labels(num_supervised_frames);
1867  for (int32 t = 0; t < num_supervised_frames; t++) {
1868  int32 num_labels = RandInt(1, 3);
1869  BaseFloat remaining_prob_mass = 1.0;
1870  for (int32 i = 0; i < num_labels; i++) {
1871  BaseFloat this_prob = (i+1 == num_labels ? 1.0 : RandUniform()) *
1872  remaining_prob_mass;
1873  remaining_prob_mass -= this_prob;
1874  labels[t].push_back(std::pair<int32, BaseFloat>(RandInt(0, output_dim-1),
1875  this_prob));
1876  }
1877  }
1878  int32 supervision_t_begin = feature_t_begin + left_context;
1879  NnetIo output_sup("output", output_dim, supervision_t_begin,
1880  labels);
1881  example->io.push_back(output_sup);
1882  }
1883 }
float RandUniform(struct RandomState *state=NULL)
Returns a random number strictly between 0 and 1.
Definition: kaldi-math.h:151
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
std::vector< std::vector< std::pair< int32, BaseFloat > > > Posterior
Posterior is a typedef for storing acoustic-state (actually, transition-id) posteriors over an uttera...
Definition: posterior.h:42
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GenRandDescriptor()

void kaldi::nnet3::GenRandDescriptor ( int32  num_nodes,
Descriptor desc 
)

Definition at line 76 of file nnet-descriptor-test.cc.

References GenRandSumDescriptor(), and kaldi::Rand().

Referenced by UnitTestDescriptorIo(), and UnitTestGeneralDescriptor().

77  {
78  int32 num_parts = 1 + Rand() % 3;
79  std::vector<SumDescriptor*> parts;
80  for (int32 part = 0; part < num_parts; part++)
81  parts.push_back(GenRandSumDescriptor(num_nodes));
82  *desc = Descriptor(parts);
83 
84 }
kaldi::int32 int32
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
SumDescriptor * GenRandSumDescriptor(int32 num_nodes)

◆ GenRandForwardingDescriptor()

ForwardingDescriptor* kaldi::nnet3::GenRandForwardingDescriptor ( int32  num_nodes)

Definition at line 25 of file nnet-descriptor-test.cc.

References rnnlm::i, ReplaceIndexForwardingDescriptor::kT, ReplaceIndexForwardingDescriptor::kX, rnnlm::n, kaldi::Rand(), Index::t, and Index::x.

Referenced by GenRandSumDescriptor().

25  {
26  if (Rand() % 2 != 0) {
27  return new SimpleForwardingDescriptor(Rand() % num_nodes);
28  } else {
29  int32 r = Rand() % 4;
30  if (r == 0) {
31  Index offset;
32  offset.t = Rand() % 5;
33  offset.x = Rand() % 2;
34  return
36  offset);
37  } else if (r == 1) {
38  std::vector<ForwardingDescriptor*> vec;
39  int32 n = 1 + Rand() % 3;
40  for (int32 i = 0; i < n; i++)
41  vec.push_back(GenRandForwardingDescriptor(num_nodes));
42  return new SwitchingForwardingDescriptor(vec);
43  } else if (r == 2) {
45  GenRandForwardingDescriptor(num_nodes), 1 + Rand() % 4);
46  } else {
48  GenRandForwardingDescriptor(num_nodes),
49  (Rand() % 2 == 0 ? ReplaceIndexForwardingDescriptor::kT :
50  ReplaceIndexForwardingDescriptor::kX),
51  -2 + Rand() % 4);
52  }
53  }
54 }
SimpleForwardingDescriptor is the base-case of ForwardingDescriptor, consisting of a source node in t...
kaldi::int32 int32
ForwardingDescriptor * GenRandForwardingDescriptor(int32 num_nodes)
For use in clockwork RNNs and the like, this forwarding-descriptor rounds the time-index t down to th...
struct Index is intended to represent the various indexes by which we number the rows of the matrices...
Definition: nnet-common.h:44
Chooses from different inputs based on the the time index modulo (the number of ForwardingDescriptors...
struct rnnlm::@11::@12 n
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
Offsets in &#39;t&#39; and &#39;x&#39; values of other ForwardingDescriptors.
This ForwardingDescriptor modifies the indexes (n, t, x) by replacing one of them (normally t) with a...

◆ GenRandSumDescriptor()

SumDescriptor* kaldi::nnet3::GenRandSumDescriptor ( int32  num_nodes)

Definition at line 57 of file nnet-descriptor-test.cc.

References GenRandForwardingDescriptor(), BinarySumDescriptor::kFailoverOperation, BinarySumDescriptor::kSumOperation, and kaldi::Rand().

Referenced by GenRandDescriptor().

58  {
59  if (Rand() % 3 != 0) {
60  bool not_required = (Rand() % 5 == 0);
61  if (not_required)
62  return new OptionalSumDescriptor(GenRandSumDescriptor(num_nodes));
63  else
64  return new SimpleSumDescriptor(GenRandForwardingDescriptor(num_nodes));
65  } else {
66  return new BinarySumDescriptor(
67  (Rand() % 2 == 0 ? BinarySumDescriptor::kSumOperation:
68  BinarySumDescriptor::kFailoverOperation),
69  GenRandSumDescriptor(num_nodes),
70  GenRandSumDescriptor(num_nodes));
71  }
72 }
This is the case of class SumDescriptor, in which we contain just one term, and that term is optional...
BinarySumDescriptor can represent either A + B, or (A if defined, else B).
ForwardingDescriptor * GenRandForwardingDescriptor(int32 num_nodes)
This is the normal base-case of SumDescriptor which just wraps a ForwardingDescriptor.
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
SumDescriptor * GenRandSumDescriptor(int32 num_nodes)

◆ GetChainComputationRequest()

void GetChainComputationRequest ( const Nnet nnet,
const NnetChainExample eg,
bool  need_model_derivative,
bool  store_component_stats,
bool  use_xent_regularization,
bool  use_xent_derivative,
ComputationRequest computation_request 
)

This function takes a NnetChainExample and produces a ComputationRequest.

Assumes you don't want the derivatives w.r.t. the inputs; if you do, you can create the ComputationRequest manually. Assumes that if need_model_derivative is true, you will be supplying derivatives w.r.t. all outputs.

If use_xent_regularization == true, then it assumes that for each output name (e.g. "output" in the eg, there is another output with the same dimension and with the suffix "-xent" on its name, e.g. named "output-xent". The derivative w.r.t. the xent objective will only be supplied to the nnet computation if 'use_xent_derivative' is true (we propagate back the xent derivative to the model only in training, not in model-combination in nnet3-chain-combine).

Definition at line 290 of file nnet-chain-example.cc.

References Nnet::GetNodeIndex(), IoSpecification::has_deriv, rnnlm::i, NnetIo::indexes, NnetChainSupervision::indexes, IoSpecification::indexes, NnetChainExample::inputs, ComputationRequest::inputs, Nnet::IsInputNode(), Nnet::IsOutputNode(), KALDI_ERR, NnetIo::name, NnetChainSupervision::name, IoSpecification::name, ComputationRequest::need_model_derivative, ComputationRequest::outputs, NnetChainExample::outputs, and ComputationRequest::store_component_stats.

Referenced by NnetChainComputeProb::Compute(), NnetChainExampleStructureCompare::operator()(), and NnetChainTrainer::Train().

296  {
297  request->inputs.clear();
298  request->inputs.reserve(eg.inputs.size());
299  request->outputs.clear();
300  request->outputs.reserve(eg.outputs.size() * 2);
301  request->need_model_derivative = need_model_derivative;
302  request->store_component_stats = store_component_stats;
303  for (size_t i = 0; i < eg.inputs.size(); i++) {
304  const NnetIo &io = eg.inputs[i];
305  const std::string &name = io.name;
306  int32 node_index = nnet.GetNodeIndex(name);
307  if (node_index == -1 ||
308  !nnet.IsInputNode(node_index))
309  KALDI_ERR << "Nnet example has input named '" << name
310  << "', but no such input node is in the network.";
311 
312  request->inputs.resize(request->inputs.size() + 1);
313  IoSpecification &io_spec = request->inputs.back();
314  io_spec.name = name;
315  io_spec.indexes = io.indexes;
316  io_spec.has_deriv = false;
317  }
318  for (size_t i = 0; i < eg.outputs.size(); i++) {
319  // there will normally be exactly one output , named "output"
320  const NnetChainSupervision &sup = eg.outputs[i];
321  const std::string &name = sup.name;
322  int32 node_index = nnet.GetNodeIndex(name);
323  if (node_index == -1 &&
324  !nnet.IsOutputNode(node_index))
325  KALDI_ERR << "Nnet example has output named '" << name
326  << "', but no such output node is in the network.";
327  request->outputs.resize(request->outputs.size() + 1);
328  IoSpecification &io_spec = request->outputs.back();
329  io_spec.name = name;
330  io_spec.indexes = sup.indexes;
331  io_spec.has_deriv = need_model_derivative;
332 
333  if (use_xent_regularization) {
334  size_t cur_size = request->outputs.size();
335  request->outputs.resize(cur_size + 1);
336  IoSpecification &io_spec = request->outputs[cur_size - 1],
337  &io_spec_xent = request->outputs[cur_size];
338  // the IoSpecification for the -xent output is the same
339  // as for the regular output, except for its name which has
340  // the -xent suffix (and the has_deriv member may differ).
341  io_spec_xent = io_spec;
342  io_spec_xent.name = name + "-xent";
343  io_spec_xent.has_deriv = use_xent_derivative;
344  }
345  }
346  // check to see if something went wrong.
347  if (request->inputs.empty())
348  KALDI_ERR << "No inputs in computation request.";
349  if (request->outputs.empty())
350  KALDI_ERR << "No outputs in computation request.";
351 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ GetChainNnetExampleSize()

int32 kaldi::nnet3::GetChainNnetExampleSize ( const NnetChainExample a)

This function returns the 'size' of a chain example as defined for purposes of merging egs, which is defined as the largest number of Indexes in any of the inputs or outputs of the example.

◆ GetChunkSize()

int32 GetChunkSize ( const Nnet nnet,
int32  frame_subsampling_factor,
int32  advised_chunk_size 
)

Definition at line 81 of file nnet-compile-looped.cc.

References KALDI_ASSERT, and Nnet::Modulus().

Referenced by DecodableNnetSimpleLoopedInfo::Init(), and UnitTestNnetCompileLooped().

83  {
84  int32 modulus = nnet.Modulus();
85  KALDI_ASSERT(modulus > 0 && frame_subsampling_factor > 0 &&
86  advised_chunk_size > 0);
87  int32 chunk_size = advised_chunk_size;
88  while (1) {
89  if (chunk_size % modulus == 0 &&
90  chunk_size % frame_subsampling_factor == 0)
91  return chunk_size;
92  chunk_size++;
93  }
94 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ GetCommandsOfType()

void GetCommandsOfType ( const NnetComputation computation,
CommandType  t,
std::vector< int32 > *  command_indexes 
)

This utility function works out from a computation, the command-indexes of the commands of the given type.

Definition at line 1429 of file nnet-analyze.cc.

References NnetComputation::commands.

Referenced by ComputationLoopedOptimizer::FindTimeShift(), and ComputationLoopedOptimizer::Optimize().

1431  {
1432  int32 num_commands = computation.commands.size();
1433  command_indexes->clear();
1434  for (int32 c = 0; c < num_commands; c++)
1435  if (computation.commands[c].command_type == t)
1436  command_indexes->push_back(c);
1437 }
kaldi::int32 int32

◆ GetComputationRequest()

void GetComputationRequest ( const Nnet nnet,
const NnetExample eg,
bool  need_model_derivative,
bool  store_component_stats,
ComputationRequest computation_request 
)

This function takes a NnetExample (which should already have been frame-selected, if desired, and merged into a minibatch) and produces a ComputationRequest.

It assumes you don't want the derivatives w.r.t. the inputs; if you do, you can create/modify the ComputationRequest manually. Assumes that if need_model_derivative is true, you will be supplying derivatives w.r.t. all outputs.

Definition at line 202 of file nnet-example-utils.cc.

References Nnet::GetNodeIndex(), IoSpecification::has_deriv, rnnlm::i, NnetIo::indexes, IoSpecification::indexes, ComputationRequest::inputs, NnetExample::io, Nnet::IsInputNode(), Nnet::IsOutputNode(), KALDI_ERR, NnetIo::name, IoSpecification::name, ComputationRequest::need_model_derivative, ComputationRequest::outputs, and ComputationRequest::store_component_stats.

Referenced by NnetLdaStatsAccumulator::AccStats(), NnetComputerFromEg::Compute(), NnetComputeProb::Compute(), and NnetTrainer::Train().

206  {
207  request->inputs.clear();
208  request->inputs.reserve(eg.io.size());
209  request->outputs.clear();
210  request->outputs.reserve(eg.io.size());
211  request->need_model_derivative = need_model_derivative;
212  request->store_component_stats = store_component_stats;
213  for (size_t i = 0; i < eg.io.size(); i++) {
214  const NnetIo &io = eg.io[i];
215  const std::string &name = io.name;
216  int32 node_index = nnet.GetNodeIndex(name);
217  if (node_index == -1 ||
218  (!nnet.IsInputNode(node_index) && !nnet.IsOutputNode(node_index)))
219  KALDI_ERR << "Nnet example has input or output named '" << name
220  << "', but no such input or output node is in the network.";
221 
222  std::vector<IoSpecification> &dest =
223  nnet.IsInputNode(node_index) ? request->inputs : request->outputs;
224  dest.resize(dest.size() + 1);
225  IoSpecification &io_spec = dest.back();
226  io_spec.name = name;
227  io_spec.indexes = io.indexes;
228  io_spec.has_deriv = nnet.IsOutputNode(node_index) && need_model_derivative;
229  }
230  // check to see if something went wrong.
231  if (request->inputs.empty())
232  KALDI_ERR << "No inputs in computation request.";
233  if (request->outputs.empty())
234  KALDI_ERR << "No outputs in computation request.";
235 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ GetCount()

int32 kaldi::nnet3::GetCount ( double  expected_count)

Definition at line 66 of file nnet3-copy-egs.cc.

References KALDI_ASSERT, and kaldi::WithProb().

Referenced by main().

66  {
67  KALDI_ASSERT(expected_count >= 0.0);
68  int32 ans = floor(expected_count);
69  expected_count -= ans;
70  if (WithProb(expected_count))
71  ans++;
72  return ans;
73 }
bool WithProb(BaseFloat prob, struct RandomState *state)
Definition: kaldi-math.cc:72
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ GetDiscriminativeComputationRequest()

void GetDiscriminativeComputationRequest ( const Nnet nnet,
const NnetDiscriminativeExample eg,
bool  need_model_derivative,
bool  store_component_stats,
bool  use_xent_regularization,
bool  use_xent_derivative,
ComputationRequest computation_request 
)

This function takes a NnetDiscriminativeExample and produces a ComputationRequest.

Assumes you don't want the derivatives w.r.t. the inputs; if you do, you can create the ComputationRequest manually. Assumes that if need_model_derivative is true, you will be supplying derivatives w.r.t. all outputs.

Definition at line 284 of file nnet-discriminative-example.cc.

References Nnet::GetNodeIndex(), IoSpecification::has_deriv, rnnlm::i, NnetIo::indexes, NnetDiscriminativeSupervision::indexes, IoSpecification::indexes, NnetDiscriminativeExample::inputs, ComputationRequest::inputs, Nnet::IsInputNode(), Nnet::IsOutputNode(), KALDI_ERR, NnetIo::name, NnetDiscriminativeSupervision::name, IoSpecification::name, ComputationRequest::need_model_derivative, NnetDiscriminativeExample::outputs, ComputationRequest::outputs, and ComputationRequest::store_component_stats.

Referenced by NnetDiscriminativeComputeObjf::Compute(), NnetDiscriminativeExampleStructureCompare::operator()(), and NnetDiscriminativeTrainer::Train().

290  {
291  request->inputs.clear();
292  request->inputs.reserve(eg.inputs.size());
293  request->outputs.clear();
294  request->outputs.reserve(eg.outputs.size());
295  request->need_model_derivative = need_model_derivative;
296  request->store_component_stats = store_component_stats;
297  for (size_t i = 0; i < eg.inputs.size(); i++) {
298  const NnetIo &io = eg.inputs[i];
299  const std::string &name = io.name;
300  int32 node_index = nnet.GetNodeIndex(name);
301  if (node_index == -1 &&
302  !nnet.IsInputNode(node_index))
303  KALDI_ERR << "Nnet example has input named '" << name
304  << "', but no such input node is in the network.";
305 
306  request->inputs.resize(request->inputs.size() + 1);
307  IoSpecification &io_spec = request->inputs.back();
308  io_spec.name = name;
309  io_spec.indexes = io.indexes;
310  io_spec.has_deriv = false;
311  }
312  for (size_t i = 0; i < eg.outputs.size(); i++) {
313  // there will normally be exactly one output , named "output"
314  const NnetDiscriminativeSupervision &sup = eg.outputs[i];
315  const std::string &name = sup.name;
316  int32 node_index = nnet.GetNodeIndex(name);
317  if (node_index == -1 &&
318  !nnet.IsOutputNode(node_index))
319  KALDI_ERR << "Nnet example has output named '" << name
320  << "', but no such output node is in the network.";
321  request->outputs.resize(request->outputs.size() + 1);
322  IoSpecification &io_spec = request->outputs.back();
323  io_spec.name = name;
324  io_spec.indexes = sup.indexes;
325  io_spec.has_deriv = need_model_derivative;
326 
327  if (use_xent_regularization) {
328  size_t cur_size = request->outputs.size();
329  request->outputs.resize(cur_size + 1);
330  IoSpecification &io_spec = request->outputs[cur_size - 1],
331  &io_spec_xent = request->outputs[cur_size];
332  // the IoSpecification for the -xent output is the same
333  // as for the regular output, except for its name which has
334  // the -xent suffix (and the has_deriv member may differ).
335  io_spec_xent = io_spec;
336  io_spec_xent.name = name + "-xent";
337  io_spec_xent.has_deriv = use_xent_derivative;
338  }
339  }
340  // check to see if something went wrong.
341  if (request->inputs.empty())
342  KALDI_ERR << "No inputs in computation request.";
343  if (request->outputs.empty())
344  KALDI_ERR << "No outputs in computation request.";
345 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ GetDiscriminativeNnetExampleSize()

int32 kaldi::nnet3::GetDiscriminativeNnetExampleSize ( const NnetDiscriminativeExample a)

This function returns the 'size' of a discriminative example as defined for purposes of merging egs, which is defined as the largest number of Indexes in any of the inputs or outputs of the example.

◆ GetIndexesMultiStrings()

static void kaldi::nnet3::GetIndexesMultiStrings ( const Nnet nnet,
const NnetComputation computation,
std::vector< std::string > *  indexes_multi_strings 
)
static

Definition at line 462 of file nnet-computation.cc.

References NnetComputation::SubMatrixInfo::col_offset, rnnlm::i, NnetComputation::indexes_multi, rnnlm::j, KALDI_WARN, NnetComputation::matrices, NnetComputation::SubMatrixInfo::matrix_index, NnetComputation::MatrixInfo::num_cols, NnetComputation::SubMatrixInfo::num_cols, NnetComputation::MatrixInfo::num_rows, NnetComputation::SubMatrixInfo::num_rows, NnetComputation::SubMatrixInfo::row_offset, and NnetComputation::submatrices.

Referenced by NnetComputation::GetCommandStrings(), and NnetComputation::Print().

465  {
466  int32 indexes_multi_size = computation.indexes_multi.size();
467  indexes_multi_strings->resize(indexes_multi_size);
468 
469  for (int32 i = 0; i < indexes_multi_size; i++) {
470  std::ostringstream os;
471  os << "[";
472  const std::vector<std::pair<int32, int32> > &vec =
473  computation.indexes_multi[i];
474  int32 size = vec.size();
475  for (int32 j = 0; j < size; j++) {
476  int32 submat_index = vec[j].first, row_index = vec[j].second;
477  if (submat_index == -1) {
478  os << "NULL";
479  } else {
480  const NnetComputation::SubMatrixInfo &submat =
481  computation.submatrices[submat_index];
482  const NnetComputation::MatrixInfo &mat =
483  computation.matrices[submat.matrix_index];
484  int32 row = row_index + submat.row_offset;
485  int32 col_start = submat.col_offset,
486  col_end = col_start + submat.num_cols;
487  if (!(row_index < submat.num_rows &&
488  row < mat.num_rows)) {
489  KALDI_WARN << "Invalid indexes in indexes-multi[" << i
490  << ": submatrix " << submat_index << " = m"
491  << submat.matrix_index << "(" << submat.row_offset
492  << ':' << (submat.row_offset + submat.num_rows - 1)
493  << ',' << submat.col_offset << ':'
494  << (submat.col_offset + submat.num_cols - 1) << ") has "
495  << submat.num_rows << " rows, but you access row "
496  << row_index;
497  }
498  if (col_start == 0 && col_end == mat.num_cols)
499  os << 'm' << submat.matrix_index << '(' << row << ",:)";
500  else
501  os << 'm' << submat.matrix_index << '(' << row << ',' << col_start
502  << ':' << (col_end - 1) << ')';
503  }
504  if (j + 1 < size) os << ",";
505  }
506  os << "]";
507  (*indexes_multi_strings)[i] = os.str();
508  }
509 }
kaldi::int32 int32
#define KALDI_WARN
Definition: kaldi-error.h:150

◆ GetIndexesStrings()

static void kaldi::nnet3::GetIndexesStrings ( const Nnet nnet,
const NnetComputation computation,
std::vector< std::string > *  indexes_strings 
)
static

Definition at line 448 of file nnet-computation.cc.

References rnnlm::i, NnetComputation::indexes, and PrintIntegerVector().

Referenced by NnetComputation::GetCommandStrings(), and NnetComputation::Print().

450  {
451  int32 size = computation.indexes.size();
452  indexes_strings->resize(size);
453  for (int32 i = 0; i < size; i++) {
454  std::ostringstream os;
455  PrintIntegerVector(os, computation.indexes[i]);
456  (*indexes_strings)[i] = os.str();
457  }
458 }
kaldi::int32 int32
void PrintIntegerVector(std::ostream &os, const std::vector< int32 > &ints)
Definition: nnet-common.cc:525

◆ GetIoNames()

static void kaldi::nnet3::GetIoNames ( const std::vector< NnetExample > &  src,
std::vector< std::string > *  names_vec 
)
static

Definition at line 34 of file nnet-example-utils.cc.

References kaldi::CopySetToVector().

Referenced by MergeExamples().

35  {
36  std::set<std::string> names;
37  std::vector<NnetExample>::const_iterator iter = src.begin(), end = src.end();
38  for (; iter != end; ++iter) {
39  std::vector<NnetIo>::const_iterator iter2 = iter->io.begin(),
40  end2 = iter->io.end();
41  for (; iter2 != end2; ++iter2)
42  names.insert(iter2->name);
43  }
44  CopySetToVector(names, names_vec);
45 }
void CopySetToVector(const std::set< T > &s, std::vector< T > *v)
Copies the elements of a set to a vector.
Definition: stl-utils.h:86

◆ GetIoSizes()

static void kaldi::nnet3::GetIoSizes ( const std::vector< NnetExample > &  src,
const std::vector< std::string > &  names,
std::vector< int32 > *  sizes 
)
static

Definition at line 50 of file nnet-example-utils.cc.

References NnetIo::features, rnnlm::i, NnetIo::indexes, KALDI_ASSERT, KALDI_ERR, NnetIo::name, GeneralMatrix::NumCols(), and GeneralMatrix::NumRows().

Referenced by MergeExamples().

52  {
53  std::vector<int32> dims(names.size(), -1); // just for consistency checking.
54  sizes->clear();
55  sizes->resize(names.size(), 0);
56  std::vector<std::string>::const_iterator names_begin = names.begin(),
57  names_end = names.end();
58  std::vector<NnetExample>::const_iterator iter = src.begin(), end = src.end();
59  for (; iter != end; ++iter) {
60  std::vector<NnetIo>::const_iterator iter2 = iter->io.begin(),
61  end2 = iter->io.end();
62  for (; iter2 != end2; ++iter2) {
63  const NnetIo &io = *iter2;
64  std::vector<std::string>::const_iterator names_iter =
65  std::lower_bound(names_begin, names_end, io.name);
66  KALDI_ASSERT(*names_iter == io.name);
67  int32 i = names_iter - names_begin;
68  int32 this_dim = io.features.NumCols();
69  if (dims[i] == -1) {
70  dims[i] = this_dim;
71  } else if (dims[i] != this_dim) {
72  KALDI_ERR << "Merging examples with inconsistent feature dims: "
73  << dims[i] << " vs. " << this_dim << " for '"
74  << io.name << "'.";
75  }
76  KALDI_ASSERT(io.features.NumRows() == io.indexes.size());
77  int32 this_size = io.indexes.size();
78  (*sizes)[i] += this_size;
79  }
80  }
81 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ GetMaxMemoryUse()

int64 GetMaxMemoryUse ( const NnetComputation computation)

Definition at line 1439 of file nnet-analyze.cc.

References NnetComputation::Command::arg1, NnetComputation::Command::arg2, NnetComputation::Command::command_type, NnetComputation::commands, kAcceptInput, KALDI_ASSERT, kAllocMatrix, kaldi::kCompressedMatrixInt8, kaldi::kCompressedMatrixUint8, kCompressMatrix, kDeallocMatrix, kDecompressMatrix, NnetComputation::SubMatrixInfo::num_cols, NnetComputation::SubMatrixInfo::num_rows, and NnetComputation::submatrices.

Referenced by Optimize(), and OptimizeMemoryCompression().

1439  {
1440  int64 cur_memory_use = 0,
1441  max_memory_use = 0;
1442  int32 num_commands = computation.commands.size(),
1443  num_submatrices = computation.submatrices.size();
1444  // the vector 'num_compressed_bytes' is used to remember the number of bytes
1445  // in the compressed matrices for each submatrix (this will only be used for
1446  // those that correspond to a 'whole matrix). It's needed because the
1447  // decompression command doesn't tell us what compression type was used for
1448  // that matrix.
1449  std::vector<int32> num_compressed_bytes(num_submatrices, -100000000);
1450  for (int32 command_index = 0; command_index < num_commands; ++command_index) {
1451  const NnetComputation::Command &c = computation.commands[command_index];
1452  int64 this_num_bytes = -100000000,
1453  this_compressed_num_bytes = -10000000;
1454 
1455 
1456  if (c.arg1 >= 0 && c.arg1 < num_submatrices) {
1457  // if arg1 could plausibly be a sub-matrix index...
1458  const NnetComputation::SubMatrixInfo &submat_info =
1459  computation.submatrices[c.arg1];
1460  this_num_bytes = static_cast<int64>(sizeof(BaseFloat)) *
1461  submat_info.num_rows * submat_info.num_cols;
1462 
1463  if (c.command_type == kCompressMatrix) {
1464  this_compressed_num_bytes =
1465  ((c.arg2 == static_cast<int32>(kCompressedMatrixInt8) ||
1466  c.arg2 == static_cast<int32>(kCompressedMatrixUint8)) ?
1467  1 : 2) * static_cast<int64>(submat_info.num_rows) *
1468  submat_info.num_cols;
1469  num_compressed_bytes[c.arg1] = this_compressed_num_bytes;
1470  } else if (c.command_type == kDecompressMatrix) {
1471  this_compressed_num_bytes = num_compressed_bytes[c.arg1];
1472  }
1473  }
1474  switch (c.command_type) {
1475  case kAllocMatrix:
1476  case kAcceptInput:
1477  cur_memory_use += this_num_bytes;
1478  break;
1479  case kDeallocMatrix:
1480  cur_memory_use -= this_num_bytes;
1481  break;
1482  case kCompressMatrix:
1483  cur_memory_use += this_compressed_num_bytes - this_num_bytes;
1484  break;
1485  case kDecompressMatrix:
1486  cur_memory_use += this_num_bytes - this_compressed_num_bytes;
1487  break;
1488  default:
1489  break;
1490  }
1491  KALDI_ASSERT(cur_memory_use >= 0);
1492  if (cur_memory_use > max_memory_use)
1493  max_memory_use = cur_memory_use;
1494  }
1495  return max_memory_use;
1496 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ GetNnetChainExampleSize()

int32 kaldi::nnet3::GetNnetChainExampleSize ( const NnetChainExample a)

Definition at line 437 of file nnet-chain-example.cc.

References rnnlm::i, NnetChainExample::inputs, and NnetChainExample::outputs.

Referenced by ChainExampleMerger::AcceptExample(), ChainExampleMerger::Finish(), and ChainExampleMerger::WriteMinibatch().

437  {
438  int32 ans = 0;
439  for (size_t i = 0; i < a.inputs.size(); i++) {
440  int32 s = a.inputs[i].indexes.size();
441  if (s > ans)
442  ans = s;
443  }
444  for (size_t i = 0; i < a.outputs.size(); i++) {
445  int32 s = a.outputs[i].indexes.size();
446  if (s > ans)
447  ans = s;
448  }
449  return ans;
450 }
kaldi::int32 int32

◆ GetNnetDiscriminativeExampleSize()

int32 kaldi::nnet3::GetNnetDiscriminativeExampleSize ( const NnetDiscriminativeExample a)

Definition at line 430 of file nnet-discriminative-example.cc.

References rnnlm::i, NnetDiscriminativeExample::inputs, and NnetDiscriminativeExample::outputs.

Referenced by DiscriminativeExampleMerger::AcceptExample(), DiscriminativeExampleMerger::Finish(), and DiscriminativeExampleMerger::WriteMinibatch().

430  {
431  int32 ans = 0;
432  for (size_t i = 0; i < a.inputs.size(); i++) {
433  int32 s = a.inputs[i].indexes.size();
434  if (s > ans)
435  ans = s;
436  }
437  for (size_t i = 0; i < a.outputs.size(); i++) {
438  int32 s = a.outputs[i].indexes.size();
439  if (s > ans)
440  ans = s;
441  }
442  return ans;
443 }
kaldi::int32 int32

◆ GetNnetExampleSize()

int32 GetNnetExampleSize ( const NnetExample a)

This function returns the 'size' of a nnet-example as defined for purposes of merging egs, which is defined as the largest number of Indexes in any of the inputs or outputs of the example.

Definition at line 1178 of file nnet-example-utils.cc.

References rnnlm::i, and NnetExample::io.

Referenced by ExampleMerger::AcceptExample(), ExampleMerger::Finish(), and ExampleMerger::WriteMinibatch().

1178  {
1179  int32 ans = 0;
1180  for (size_t i = 0; i < a.io.size(); i++) {
1181  int32 s = a.io[i].indexes.size();
1182  if (s > ans)
1183  ans = s;
1184  }
1185  return ans;
1186 }
kaldi::int32 int32

◆ GetNumNvalues()

int32 GetNumNvalues ( const std::vector< NnetIo > &  io_vec,
bool  exhaustive 
)

This utility function can be used to obtain the number of distinct 'n' values in a training example.

This is the number of examples (e.g. sequences) that have been combined into a single example. (Actually it returns the (largest - smallest + 1) of 'n' values, and assumes they are consecutive).

Parameters
[in]vecThe vector of NnetIo objects from the training example (NnetExample or NnetChainExample) for which we need the number of 'n' values
[in]exhaustiveIf true, it will check exhaustively what largest and smallest 'n' values are. If 'false' it does it in a fast way which will return the same answer as if exhaustive == true for all the types of eg we currently create (basically: correct if the last row of the input or supervision matrices has the last-numbered 'n' value), and will occasionally (randomly) do a test to check that this is the same as if we called it with 'exhaustive=true'.

Definition at line 2198 of file nnet-utils.cc.

References rnnlm::i, NnetIo::indexes, KALDI_ASSERT, KALDI_ERR, rnnlm::n, and kaldi::RandInt().

Referenced by CollapseModelConfig::CollapseModelConfig(), NnetChainTrainer::TrainInternal(), NnetTrainer::TrainInternal(), NnetChainTrainer::TrainInternalBackstitch(), and NnetTrainer::TrainInternalBackstitch().

2199  {
2200  int32 num_n_values = -1;
2201  for (size_t i = 0; i < io_vec.size(); i++) {
2202  const NnetIo &io = io_vec[i];
2203  int32 this_num_n_values;
2204  const std::vector<Index> &index_vec = io.indexes;
2205  KALDI_ASSERT(!index_vec.empty() &&
2206  "Empty input or output in ComputationRequest?");
2207  if (exhaustive) {
2208  int32 lowest_n_value = std::numeric_limits<int32>::max(),
2209  highest_n_value = std::numeric_limits<int32>::min();
2210  std::vector<Index>::const_iterator
2211  iter = index_vec.begin(), end = index_vec.end();
2212  for (; iter != end; ++iter) {
2213  int32 n = iter->n;
2214  if (n < lowest_n_value) { lowest_n_value = n; }
2215  if (n > highest_n_value) { highest_n_value = n; }
2216  }
2217  this_num_n_values = highest_n_value + 1 - lowest_n_value;
2218  } else {
2219  // we assume that the 'n' values range from zero to N-1,
2220  // where N is the number of distinct 'n' values.
2221  this_num_n_values = index_vec.back().n + 1;
2222  }
2223  if (num_n_values == -1) {
2224  num_n_values = this_num_n_values;
2225  } else {
2226  if (num_n_values != this_num_n_values) {
2227  KALDI_ERR << "Different inputs/outputs of ComputationRequest have "
2228  "different numbers of n values: " << num_n_values
2229  << " vs. " << this_num_n_values;
2230  }
2231  }
2232  }
2233  if (!exhaustive && RandInt(0, 100) == 0) {
2234  int32 num_n_values_check = GetNumNvalues(io_vec, true);
2235  if (num_n_values != num_n_values_check) {
2236  KALDI_ERR << "Exhaustive and quick checks returned different "
2237  "answers: " << num_n_values << " vs. "
2238  << num_n_values_check;
2239  }
2240  }
2241  return num_n_values;
2242 }
kaldi::int32 int32
int32 GetNumNvalues(const std::vector< NnetIo > &io_vec, bool exhaustive)
This utility function can be used to obtain the number of distinct &#39;n&#39; values in a training example...
Definition: nnet-utils.cc:2198
struct rnnlm::@11::@12 n
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ GetNxList()

void GetNxList ( const std::vector< Index > &  indexes,
std::vector< std::pair< int32, int32 > > *  pairs 
)

This function outputs a unique, lexicographically sorted list of the pairs of (n, x) values that are encountered in the provided list of Indexes.

Definition at line 416 of file nnet-compile-utils.cc.

Referenced by kaldi::nnet3::time_height_convolution::GetComputationIo(), RestrictedAttentionComponent::GetIndexes(), and kaldi::nnet3::time_height_convolution::GetIndexesForComputation().

417  {
418  // set of (n,x) pairs
419  std::unordered_set<std::pair<int32, int32>, PairHasher<int32> > n_x_set;
420 
421  for (std::vector<Index>::const_iterator iter = indexes.begin();
422  iter != indexes.end(); ++iter)
423  n_x_set.insert(std::pair<int32, int32>(iter->n, iter->x));
424  pairs->clear();
425  pairs->reserve(n_x_set.size());
426  for (std::unordered_set<std::pair<int32, int32>, PairHasher<int32> >::iterator
427  iter = n_x_set.begin(); iter != n_x_set.end(); ++iter)
428  pairs->push_back(*iter);
429  std::sort(pairs->begin(), pairs->end());
430 }

◆ GetPrecomputedIndexes()

ComponentPrecomputedIndexes* kaldi::nnet3::GetPrecomputedIndexes ( const Component c,
int32  num_rows 
)

Definition at line 180 of file nnet-component-test.cc.

References rnnlm::i, kReordersIndexes, Component::PrecomputeIndexes(), Component::Properties(), and Component::ReorderIndexes().

Referenced by TestSimpleComponentDataDerivative(), TestSimpleComponentModelDerivative(), and TestSimpleComponentPropagateProperties().

181  {
182  std::vector<Index> input_indexes(num_rows);
183  int32 num_t_values;
184  if (num_rows % 3 == 0) { num_t_values = 3; }
185  else if (num_rows % 2 == 0) { num_t_values = 2; }
186  else { num_t_values = 1; }
187 
188  for (int32 i = 0; i < num_rows; i++) {
189  input_indexes[i].n = i % num_t_values;
190  input_indexes[i].x = 0;
191  input_indexes[i].t = i / num_t_values;
192  }
193  std::vector<Index> output_indexes(input_indexes);
194 
195  if (c.Properties()&kReordersIndexes) {
196  c.ReorderIndexes(&input_indexes, &output_indexes);
197  }
198  MiscComputationInfo misc_info;
199  bool need_backprop = true; // just in case.
201  input_indexes,
202  output_indexes,
203  need_backprop);
204  // ans will be NULL in most cases.
205  return ans;
206 }
kaldi::int32 int32
virtual ComponentPrecomputedIndexes * PrecomputeIndexes(const MiscComputationInfo &misc_info, const std::vector< Index > &input_indexes, const std::vector< Index > &output_indexes, bool need_backprop) const
This function must return NULL for simple Components.
virtual int32 Properties() const =0
Return bitmask of the component&#39;s properties.
virtual void ReorderIndexes(std::vector< Index > *input_indexes, std::vector< Index > *output_indexes) const
This function only does something interesting for non-simple Components.

◆ GetSubmatCounts()

void kaldi::nnet3::GetSubmatCounts ( const std::vector< std::vector< std::pair< int32, int32 > > > &  submat_lists,
std::unordered_map< int32, int32 > *  submat_counts,
std::vector< int32 > *  submats_with_large_counts 
)

Gets counts of submatrices (the 1st members of pairs) in submat_lists.

Also outputs, to 'submats_with_large_counts', a list of submatrix indexes that have counts over half of submat_lists.size(). (These will be separated out into their own AddRows() commands).

Definition at line 35 of file nnet-compile-utils.cc.

References KALDI_ASSERT.

Referenced by SplitLocations().

38  {
39  auto iter = submat_lists.begin(), end = submat_lists.end();
40  for (; iter != end; ++iter) {
41  std::vector<std::pair<int32, int32> >::const_iterator
42  iter2 = iter->begin(), end2 = iter->end();
43  for (; iter2 != end2; ++iter2) {
44  int32 submat_index = iter2->first;
45  KALDI_ASSERT(submat_index >= 0); // We don't expect -1's in submat_lists.
46  std::unordered_map<int32,int32>::iterator
47  iter = submat_counts->find(submat_index);
48  if (iter == submat_counts->end())
49  (*submat_counts)[submat_index] = 1;
50  else
51  iter->second++;
52  }
53  }
54  auto counts_iter = submat_counts->begin(),
55  counts_end = submat_counts->end();
56  size_t cutoff = submat_lists.size() / 2;
57  for (; counts_iter != counts_end; ++counts_iter)
58  if (counts_iter->second > cutoff)
59  submats_with_large_counts->push_back(counts_iter->first);
60 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ GetSubMatrixOfSubMatrix()

static NnetComputation::SubMatrixInfo kaldi::nnet3::GetSubMatrixOfSubMatrix ( const NnetComputation computation,
int32  submat_a,
int32  submat_b 
)
static

This static function returns a SubMatrixInfo corresponding to replacing the matrix-index in a's "matrix_index" with, essentially, sub-matrix b.

Of course the matrix_index will be b's "matrix_index", but we may have to modify the row and column offsets. The idea is that sub-matrix submat_b should have the same dimensions as the matrix underlying submat_a.

Definition at line 789 of file nnet-optimize-utils.cc.

References NnetComputation::SubMatrixInfo::col_offset, KALDI_ASSERT, NnetComputation::matrices, NnetComputation::SubMatrixInfo::matrix_index, NnetComputation::MatrixInfo::num_cols, NnetComputation::SubMatrixInfo::num_cols, NnetComputation::MatrixInfo::num_rows, NnetComputation::SubMatrixInfo::num_rows, NnetComputation::SubMatrixInfo::row_offset, and NnetComputation::submatrices.

Referenced by VariableMergingOptimizer::DoMerge().

790  {
791  KALDI_ASSERT(static_cast<size_t>(submat_a) < computation.submatrices.size());
792  KALDI_ASSERT(static_cast<size_t>(submat_b) < computation.submatrices.size());
793  const NnetComputation::SubMatrixInfo &a = computation.submatrices[submat_a],
794  &b = computation.submatrices[submat_b];
795  const NnetComputation::MatrixInfo &a_mat =
796  computation.matrices[a.matrix_index];
797  KALDI_ASSERT(a_mat.num_rows == b.num_rows && a_mat.num_cols == b.num_cols);
798  NnetComputation::SubMatrixInfo ans;
799  ans.matrix_index = b.matrix_index;
800  ans.row_offset = a.row_offset + b.row_offset;
801  ans.num_rows = a.num_rows;
802  ans.col_offset = a.col_offset + b.col_offset;
803  ans.num_cols = a.num_cols;
804  return ans;
805 }
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ GetTList()

void GetTList ( const std::vector< Index > &  indexes,
std::vector< int32 > *  t_values 
)

This function outputs a sorted, unique list of the 't' values that are encountered in the provided list of Indexes If 't' values equal to kNoTime are encountered, they are ignored and are not output.

Definition at line 434 of file nnet-compile-utils.cc.

References kNoTime.

Referenced by kaldi::nnet3::time_height_convolution::GetComputationIo().

435  {
436  // set of t values
437  std::unordered_set<int32> t_set;
438 
439  for (std::vector<Index>::const_iterator iter = indexes.begin();
440  iter != indexes.end(); ++iter)
441  if (iter->t != kNoTime)
442  t_set.insert(iter->t);
443  t_values->clear();
444  t_values->reserve(t_set.size());
445  for (std::unordered_set<int32>::iterator iter = t_set.begin();
446  iter != t_set.end(); ++iter)
447  t_values->push_back(*iter);
448  std::sort(t_values->begin(), t_values->end());
449 }
const int kNoTime
Definition: nnet-common.cc:573

◆ GraphHasCycles()

bool GraphHasCycles ( const std::vector< std::vector< int32 > > &  graph)

This function returns 'true' if the graph represented in 'graph' contains cycles (including cycles where a single node has an arc to itself).

Definition at line 300 of file nnet-graph.cc.

References FindSccs(), and rnnlm::i.

Referenced by NnetIsRecurrent().

300  {
301  std::vector<std::vector<int32> > sccs;
302  FindSccs(graph, &sccs);
303  for (size_t i = 0; i < sccs.size(); i++) {
304  if (sccs[i].size() > 1)
305  return true;
306  }
307  // the next code checks for links from a state to itself.
308  int32 num_nodes = graph.size();
309  for (size_t i = 0; i < num_nodes; i++)
310  for (std::vector<int32>::const_iterator iter = graph[i].begin(),
311  end = graph[i].end(); iter != end; ++iter)
312  if (*iter == i) return true;
313  return false;
314 }
kaldi::int32 int32
void FindSccs(const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *sccs)
Given a directed graph (where each std::vector<int32> is a list of destination-nodes of arcs coming f...
Definition: nnet-graph.cc:156

◆ HasBatchnorm()

bool HasBatchnorm ( const Nnet nnet)

Returns true if nnet has at least one component of type BatchNormComponent.

Definition at line 527 of file nnet-utils.cc.

References Nnet::GetComponent(), and Nnet::NumComponents().

Referenced by main().

527  {
528  for (int32 c = 0; c < nnet.NumComponents(); c++) {
529  const Component *comp = nnet.GetComponent(c);
530  if (dynamic_cast<const BatchNormComponent*>(comp) != NULL)
531  return true;
532  }
533  return false;
534 }
kaldi::int32 int32

◆ HasContiguousProperty()

bool HasContiguousProperty ( const std::vector< int32 > &  indexes,
std::vector< std::pair< int32, int32 > > *  reverse_indexes 
)

This function returns true if for each integer i != -1, all the indexes j at which indexes[j] == i are consecutive with no gaps (more formally: if j1 < j2 < j3 and indexes[j1] != -1 and indexes[j1] == indexes[j3], then indexes[j1] == indexes[j2]).

For example, the vector [ 1 2 1 ] lacks the contiguous property because 1 appears in two places with a different number in the middle. If the vector has the contiguous property, this function also outputs to "reverse_indexes" the begin and end of these ranges, so that indexes[j] == i for all j such that (*reverse_indexes)[i].first <= j && j < (*reverse_indexes)[i].second.

Definition at line 369 of file nnet-compile-utils.cc.

References rnnlm::i, rnnlm::j, KALDI_ASSERT, and KALDI_WARN.

Referenced by Compiler::CompileBackwardFromIndexes(), UnitTestEnsureContiguousProperty(), and UnitTestHasContiguousProperty().

371  {
372  reverse_indexes->clear();
373  int32 num_indexes = indexes.size();
374  if (num_indexes == 0)
375  return true;
376  int32 num_input_indexes =
377  *std::max_element(indexes.begin(), indexes.end()) + 1;
378  KALDI_ASSERT(num_input_indexes >= 0);
379  if (num_input_indexes == 0) {
380  // we don't really expect this input, filled with -1's.
381  KALDI_WARN << "HasContiguousProperty called on vector of -1's.";
382  return true;
383  }
384  reverse_indexes->resize(num_input_indexes,
385  std::pair<int32,int32>(-1, -1));
386  // set each pair's "first" to the min index of all elements
387  // of "indexes" with that value, and the "second" to the
388  // max plus one.
389  for (int32 i = 0; i < num_indexes; i++) {
390  int32 j = indexes[i];
391  if (j == -1) continue;
392  KALDI_ASSERT(j >= 0);
393  std::pair<int32, int32> &pair = (*reverse_indexes)[j];
394  if (pair.first == -1) {
395  pair.first = i;
396  pair.second = i + 1;
397  } else {
398  pair.first = std::min(pair.first, i);
399  pair.second = std::max(pair.second, i + 1);
400  }
401  }
402  // check that the contiguous property holds.
403  for (int32 i = 0; i < num_input_indexes; i++) {
404  std::pair<int32, int32> pair = (*reverse_indexes)[i];
405  if (pair.first != -1) {
406  for (int32 j = pair.first; j < pair.second; j++)
407  if (indexes[j] != i)
408  return false;
409  }
410  }
411  return true;
412 }
kaldi::int32 int32
#define KALDI_WARN
Definition: kaldi-error.h:150
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ HasXentOutputs()

static bool kaldi::nnet3::HasXentOutputs ( const Nnet nnet)
static

Definition at line 235 of file nnet-chain-diagnostics.cc.

References Nnet::GetNodeIndex(), Nnet::GetNodeNames(), and Nnet::IsOutputNode().

Referenced by RecomputeStats().

235  {
236  const std::vector<std::string> node_names = nnet.GetNodeNames();
237  for (std::vector<std::string>::const_iterator it = node_names.begin();
238  it != node_names.end(); ++it) {
239  int32 node_index = nnet.GetNodeIndex(*it);
240  if (nnet.IsOutputNode(node_index) &&
241  it->find("-xent") != std::string::npos) {
242  return true;
243  }
244  }
245  return false;
246 }
kaldi::int32 int32

◆ IdentifyIndexesArgs()

void IdentifyIndexesArgs ( std::vector< NnetComputation::Command > *  commands,
std::vector< int32 * > *  indexes_args 
)

Identifies in the vector of commands, arguments that correspond to indexes into the computation's 'indexes' array, and outputs a list of pointers to those arguments to 'indexes_args'.

Useful in renumbering code.

Definition at line 133 of file nnet-optimize-utils.cc.

References NnetComputation::Command::arg3, NnetComputation::Command::command_type, kAddRows, and kCopyRows.

Referenced by ComputationRenumberer::RenumberIndexes().

134  {
135  indexes_args->clear();
136  std::vector<NnetComputation::Command>::iterator iter = commands->begin(),
137  end = commands->end();
138  for (; iter != end; ++iter) {
139  NnetComputation::Command &command = *iter;
140  if (command.command_type == kCopyRows ||
141  command.command_type == kAddRows)
142  indexes_args->push_back(&(command.arg3));
143  }
144 }

◆ IdentifyIndexesMultiArgs()

void IdentifyIndexesMultiArgs ( std::vector< NnetComputation::Command > *  commands,
std::vector< int32 * > *  indexes_multi_args 
)

Identifies in the vector of commands, arguments that correspond to indexes into the computation's indexes_multi array, and outputs a list of pointers to those arguments to 'indexes_multi_args'.

Useful in renumbering code.

Definition at line 105 of file nnet-optimize-utils.cc.

References NnetComputation::Command::arg2, NnetComputation::Command::command_type, kAddRowsMulti, kAddToRowsMulti, kCopyRowsMulti, and kCopyToRowsMulti.

Referenced by ComputationRenumberer::RemoveIndexesMultiDuplicates(), and ComputationRenumberer::RemoveUnusedIndexesMulti().

106  {
107  indexes_multi_args->clear();
108  std::vector<NnetComputation::Command>::iterator iter = commands->begin(),
109  end = commands->end();
110  for (; iter != end; ++iter) {
111  NnetComputation::Command &command = *iter;
112  if (command.command_type == kAddRowsMulti ||
113  command.command_type == kAddToRowsMulti ||
114  command.command_type == kCopyRowsMulti ||
115  command.command_type == kCopyToRowsMulti)
116  indexes_multi_args->push_back(&(command.arg2));
117  }
118 }

◆ IdentifyIndexesRangesArgs()

void IdentifyIndexesRangesArgs ( std::vector< NnetComputation::Command > *  commands,
std::vector< int32 * > *  indexes_ranges_args 
)

Identifies in the vector of commands, arguments that correspond to indexes into the computation's 'indexes_ranges' array, and outputs a list of pointers to those arguments to 'indexes_ranges_args'.

Useful in renumbering code.

Definition at line 121 of file nnet-optimize-utils.cc.

References NnetComputation::Command::arg3, NnetComputation::Command::command_type, and kAddRowRanges.

Referenced by ComputationRenumberer::RenumberIndexesRanges().

122  {
123  indexes_ranges_args->clear();
124  std::vector<NnetComputation::Command>::iterator iter = commands->begin(),
125  end = commands->end();
126  for (; iter != end; ++iter) {
127  NnetComputation::Command &command = *iter;
128  if (command.command_type == kAddRowRanges)
129  indexes_ranges_args->push_back(&(command.arg3));
130  }
131 }

◆ IdentifyMatrixArgsInComputation()

void kaldi::nnet3::IdentifyMatrixArgsInComputation ( NnetComputation computation,
std::vector< int32 *> *  matrix_args 
)

Definition at line 96 of file nnet-optimize-utils.cc.

References NnetComputation::submatrices.

97  {
98  int32 num_submatrices = computation->submatrices.size();
99  matrix_args->reserve(computation->submatrices.size());
100  for (int32 s = 1; s < num_submatrices; s++)
101  matrix_args->push_back(&(computation->submatrices[s].matrix_index));
102 }
kaldi::int32 int32

◆ IdentifySubmatrixArgs() [1/2]

void IdentifySubmatrixArgs ( NnetComputation::Command command,
std::vector< int32 * > *  submatrix_args 
)

This function outputs to "submatrix_args" the addresses of a subset of arguments arg1 through arg6 in "command", that correspond to the indexes of submatrices.

This is useful in renumbering code. Note: some of the pointers may point to a zero value, for optional submatrix args.

Definition at line 28 of file nnet-optimize-utils.cc.

References NnetComputation::Command::arg1, NnetComputation::Command::arg2, NnetComputation::Command::arg3, NnetComputation::Command::arg4, NnetComputation::Command::arg5, NnetComputation::Command::arg6, NnetComputation::Command::command_type, kAcceptInput, kAddRowRanges, kAddRows, kAddRowsMulti, kAddToRowsMulti, KALDI_ERR, kAllocMatrix, kBackprop, kBackpropNoModelUpdate, kCopyRows, kCopyRowsMulti, kCopyToRowsMulti, kDeallocMatrix, kGotoLabel, kMatrixAdd, kMatrixCopy, kNoOperation, kNoOperationLabel, kNoOperationMarker, kNoOperationPermanent, kPropagate, kProvideOutput, kSetConst, and kSwapMatrix.

Referenced by IdentifySubmatrixArgs(), and IdentifySubmatrixArgsInComputation().

29  {
30  submatrix_args->clear();
31  switch (c->command_type) {
32  case kAllocMatrix:
33  case kDeallocMatrix:
34  case kSetConst:
35  submatrix_args->push_back(&c->arg1);
36  break;
37  case kSwapMatrix:
38  submatrix_args->push_back(&c->arg1);
39  submatrix_args->push_back(&c->arg2);
40  break;
41  case kPropagate:
42  submatrix_args->push_back(&c->arg3);
43  submatrix_args->push_back(&c->arg4);
44  break;
45  case kBackprop:
47  submatrix_args->push_back(&c->arg3);
48  submatrix_args->push_back(&c->arg4);
49  submatrix_args->push_back(&c->arg5);
50  submatrix_args->push_back(&c->arg6);
51  break;
52  case kMatrixCopy:
53  case kMatrixAdd:
54  case kAddRows:
55  case kCopyRows:
56  case kAddRowRanges:
57  submatrix_args->push_back(&c->arg1);
58  submatrix_args->push_back(&c->arg2);
59  break;
60  case kAddRowsMulti:
61  case kCopyRowsMulti:
62  case kAddToRowsMulti:
63  case kCopyToRowsMulti:
64  submatrix_args->push_back(&c->arg1);
65  break;
66  case kAcceptInput: case kProvideOutput:
67  submatrix_args->push_back(&c->arg1);
68  break;
69  case kNoOperation:
71  case kNoOperationMarker:
72  case kNoOperationLabel:
73  case kGotoLabel:
74  break;
75  default:
76  KALDI_ERR << "Unknown command type.";
77  }
78 }
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ IdentifySubmatrixArgs() [2/2]

void IdentifySubmatrixArgs ( std::vector< NnetComputation::Command > *  commands,
std::vector< int32 * > *  submatrix_args 
)

This function outputs to "submatrix_args" the addresses of the args (arguments arg1 through arg6) in the vector "commands", that correspond to the indexes of submatrices.

This is useful in renumbering code. Note: some of the pointers may point to a zero value, for optional submatrix args.

Definition at line 80 of file nnet-optimize-utils.cc.

References IdentifySubmatrixArgs().

81  {
82  submatrix_args->clear();
83  std::vector<NnetComputation::Command>::iterator iter = commands->begin(),
84  end = commands->end();
85  std::vector<int32*> this_submatrix_args;
86  for (; iter != end; ++iter) {
87  IdentifySubmatrixArgs(&(*iter), &this_submatrix_args);
88  submatrix_args->insert(submatrix_args->end(),
89  this_submatrix_args.begin(),
90  this_submatrix_args.end());
91  }
92 }
void IdentifySubmatrixArgs(std::vector< NnetComputation::Command > *commands, std::vector< int32 *> *submatrix_args)
This function outputs to "submatrix_args" the addresses of the args (arguments arg1 through arg6) in ...

◆ IdentifySubmatrixArgsInComputation()

void IdentifySubmatrixArgsInComputation ( NnetComputation computation,
std::vector< int32 * > *  submatrix_args 
)

This function outputs to "submatrix_args" the addresses of integers in 'computation' that correspond to submatrices.

These may be present in 'commands', and in 'indexes_multi'. This is useful in renumbering code. Note: some of the pointers may point to a zero value, for optional submatrix args in commands, but for efficiency we don't provide pointers for the -1's in 'indexes_multi'.

Definition at line 340 of file nnet-optimize-utils.cc.

References NnetComputation::commands, rnnlm::i, IdentifySubmatrixArgs(), and NnetComputation::indexes_multi.

Referenced by ComputationRenumberer::ComputeSubmatrixIsUsed(), and ComputationRenumberer::RenumberSubmatrices().

341  {
342  IdentifySubmatrixArgs(&(computation->commands), submatrix_args);
343 
344  size_t extra_size = 0;
345  for (size_t i = 0; i < computation->indexes_multi.size(); i++)
346  extra_size += computation->indexes_multi[i].size();
347  submatrix_args->reserve(submatrix_args->size() + extra_size);
348 
349  for (size_t i = 0; i < computation->indexes_multi.size(); i++) {
350  std::vector<std::pair<int32, int32> > &indexes_multi =
351  computation->indexes_multi[i];
352  std::vector<std::pair<int32, int32> >::iterator
353  iter = indexes_multi.begin(), end = indexes_multi.end();
354  for (; iter != end; ++iter)
355  if (iter->first != -1)
356  submatrix_args->push_back(&(iter->first));
357  }
358 }
void IdentifySubmatrixArgs(std::vector< NnetComputation::Command > *commands, std::vector< int32 *> *submatrix_args)
This function outputs to "submatrix_args" the addresses of the args (arguments arg1 through arg6) in ...

◆ IndexesHaveSpecialStructure()

static bool kaldi::nnet3::IndexesHaveSpecialStructure ( const std::vector< int32 > &  indexes,
int32 first_nonnegative_pos,
int32 first_nonnegative_value,
int32 num_nonnegative_indexes 
)
static

Definition at line 2252 of file nnet-optimize-utils.cc.

References KALDI_ASSERT, and rnnlm::n.

Referenced by ReplaceRowWithMatrixOps().

2255  {
2256  KALDI_ASSERT(!indexes.empty());
2257  const int32 *indexes_ptr = &(indexes[0]);
2258  size_t pos = 0, size = indexes.size();
2259 
2260  // Find the first nonnegative element of 'indexes'.
2261  for (; pos < size; ++pos)
2262  if (indexes_ptr[pos] >= 0)
2263  break;
2264  if (pos == size)
2265  return false; // all -1's... should not happen, but not our problem.
2266  *first_nonnegative_pos = static_cast<int32>(pos);
2267  int32 n = indexes_ptr[pos];
2268  *first_nonnegative_value = n;
2269  // Find the first element after '*first_nonnegative_index' that isn't
2270  // consecutive.
2271  for (; pos < size; ++pos,++n)
2272  if (indexes_ptr[pos] != n)
2273  break;
2274 
2275  *num_nonnegative_indexes = n - *first_nonnegative_value;
2276 
2277  // Check that the remaining values are all <0 (assumed equal to -1, but
2278  // checking <0 may be faster as just one instruction).
2279  for (; pos < size; ++pos)
2280  if (indexes_ptr[pos] >= 0)
2281  return false; // does not have the special structure.
2282 
2283  return true;
2284 }
kaldi::int32 int32
struct rnnlm::@11::@12 n
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ IndexesMultiToSubmatrixIndexes()

static void kaldi::nnet3::IndexesMultiToSubmatrixIndexes ( const std::vector< std::pair< int32, int32 > > &  indexes_multi,
std::vector< int32 > *  submatrix_indexes 
)
static

given a vector of pairs from computation.indexes_multi_indexes containing paris (submatrix-index, row-index), this function outputs to "submatrix_indexes" all (unique) submatrix indexes that appear; and it outputs to "contains_null_marker" true if the pair (-1, -1) appears anywhere in indexes_multi, and false otherwise.

Definition at line 264 of file nnet-analyze.cc.

References kaldi::SortAndUniq().

Referenced by ComputeCommandAttributes().

266  {
267  submatrix_indexes->clear();
268  std::vector<std::pair<int32, int32> >::const_iterator
269  iter = indexes_multi.begin(), end = indexes_multi.end();
270  int32 cur_submatrix_index = -1; // an optimization.
271  for (; iter != end; ++iter) {
272  int32 submatrix_index = iter->first;
273  if (submatrix_index != -1 && submatrix_index != cur_submatrix_index) {
274  cur_submatrix_index = submatrix_index;
275  submatrix_indexes->push_back(submatrix_index);
276  }
277  }
278  SortAndUniq(submatrix_indexes);
279 }
kaldi::int32 int32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39

◆ InsertCommands()

void InsertCommands ( std::vector< std::pair< int32, NnetComputation::Command > > *  commands,
NnetComputation computation 
)

Inserts commands into the computation at the requested places.

'commands' is a list of pairs (command-index, command) that is expected to be sorted on command-index. For each entry (c, command) in 'commands', 'command' is inserted into 'computation' just *before* the command that (at entry) is in computation->commands[c]. If there are multiple pairs with the same index c, they will remain in the same order in which they were present in 'commands'; however, 'commands' does not have to be sorted on 'c'. As a special case, if c == computation->commands.size(), the corresponding commands are inserted at the beginning of the computation. This function will appropriately renumber the argument of the kGotoLabel command of any 'looped' computation. Command indexes c in commands[*].first must be in the range [0, computation->commands.size()]. This function may modify 'commands' by sorting it.

Definition at line 4640 of file nnet-optimize-utils.cc.

References NnetComputation::commands, FixGotoLabel(), rnnlm::i, KALDI_ASSERT, and kaldi::RandInt().

Referenced by MemoryCompressionOptimizer::ModifyComputation(), and RowOpsSplitter::SplitCommands().

4642  {
4643  int32 num_new_commands = new_commands->size(),
4644  num_old_commands = computation->commands.size();
4645  if (num_new_commands == 0)
4646  return;
4647  CommandPairComparator comparison_operator;
4648  // use std::stable_sort so that for entries in 'new_commands' that
4649  // have the same .first value, they stay in the same order they were
4650  // in before sorting.
4651  std::stable_sort(new_commands->begin(), new_commands->end(),
4652  comparison_operator);
4653 
4654  if (RandInt(0, 3) == 0) { // check 'new_commands'
4655  for (int32 i = 0; i + 1 < num_new_commands; i++) {
4656  KALDI_ASSERT((*new_commands)[i].first <= (*new_commands)[i+1].first &&
4657  (*new_commands)[i].first >= 0 &&
4658  (*new_commands)[i+1].first <= num_old_commands);
4659  }
4660  }
4661  std::vector<NnetComputation::Command> merged_commands;
4662  merged_commands.reserve(num_old_commands + num_new_commands);
4663 
4664  std::vector<std::pair<int32, NnetComputation::Command> >::const_iterator
4665  new_commands_iter = new_commands->begin(),
4666  new_commands_end = new_commands->end();
4667 
4668  for (int32 old_command_index = 0; old_command_index <= num_old_commands;
4669  old_command_index++) {
4670  while (new_commands_iter != new_commands_end &&
4671  new_commands_iter->first <= old_command_index) {
4672  merged_commands.push_back(new_commands_iter->second);
4673  ++new_commands_iter;
4674  }
4675  if (old_command_index < num_old_commands)
4676  merged_commands.push_back(computation->commands[old_command_index]);
4677  }
4678  KALDI_ASSERT(merged_commands.size() == num_old_commands +
4679  num_new_commands);
4680  // copy to 'computation->commands' via shallow swap.
4681  computation->commands.swap(merged_commands);
4682  FixGotoLabel(computation);
4683 }
kaldi::int32 int32
void FixGotoLabel(NnetComputation *computation)
This function ensures that the arg1 of a final command of type kGotoLabel is the same as the command ...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ IoSpecificationIsDecomposable()

static bool kaldi::nnet3::IoSpecificationIsDecomposable ( const IoSpecification io_spec,
IoSpecification mini_io_spec,
int32 num_n_values_out 
)
static

Definition at line 3822 of file nnet-optimize-utils.cc.

References ConvertNumNValues(), FindNStride(), IoSpecification::has_deriv, IoSpecification::indexes, KALDI_ASSERT, and IoSpecification::name.

Referenced by RequestIsDecomposable().

3824  {
3825  mini_io_spec->name = io_spec.name;
3826  mini_io_spec->has_deriv = io_spec.has_deriv;
3827  const std::vector<Index> &indexes = io_spec.indexes;
3828  KALDI_ASSERT(!indexes.empty() && "Empty Indexes in computation request");
3829 
3830  bool full_check = true; // We might eventually change this to false, for
3831  // efficiency.
3832  int32 num_n_values = indexes.back().n + 1;
3833  if (num_n_values <= 2) {
3834  // Computations with 2 or fewer 'n' values are not decomposable, as there
3835  // would be no speed benefit in shortcut compilation (which relies on
3836  // compiling an otherwise similar computation with n == 2).
3837  return false;
3838  }
3839  *num_n_values_out = num_n_values;
3840 
3841  int32 n_stride = FindNStride(indexes, full_check);
3842 
3843  if (n_stride == 0)
3844  return false;
3845 
3846  ConvertNumNValues(n_stride, num_n_values, 2,
3847  indexes, &(mini_io_spec->indexes));
3848 
3849  return true;
3850 }
static int32 FindNStride(const std::vector< Cindex > &cindexes, bool full_check)
static void ConvertNumNValues(int32 n_stride, int32 old_N, int32 new_N, const std::vector< Index > &indexes_in, std::vector< Index > *indexes_out)
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ IsNoop()

static bool kaldi::nnet3::IsNoop ( const NnetComputation::Command command)
static

Definition at line 699 of file nnet-optimize-utils.cc.

References NnetComputation::Command::command_type, and kNoOperation.

Referenced by RemoveNoOps().

699  {
700  return command.command_type == kNoOperation;
701 }

◆ IsSimpleNnet()

bool IsSimpleNnet ( const Nnet nnet)

This function returns true if the nnet has the following properties: It has an output called "output" (other outputs are allowed but may be ignored).

It has an input called "input", and possibly an extra input called "ivector", but no other inputs. There are probably some other properties that we really ought to be checking, and we may add more later on.

Definition at line 52 of file nnet-utils.cc.

References Nnet::GetNodeIndex(), Nnet::IsInputNode(), Nnet::IsOutputNode(), and NumInputNodes().

Referenced by ComputeExampleComputationRequestSimple(), ComputeSimpleNnetContext(), DecodableNnetSimple::DecodableNnetSimple(), Nnet::Info(), DecodableNnetSimpleLoopedInfo::Init(), main(), NnetInfo(), and AmNnetSimple::SetContext().

52  {
53  // check that we have an output node and called "output".
54  if (nnet.GetNodeIndex("output") == -1 ||
55  !nnet.IsOutputNode(nnet.GetNodeIndex("output")))
56  return false;
57  // check that there is an input node named "input".
58  if (nnet.GetNodeIndex("input") == -1 ||
59  !nnet.IsInputNode(nnet.GetNodeIndex("input")))
60  return false;
61  // if there was just one input, then it was named
62  // "input" and everything checks out.
63  if (NumInputNodes(nnet) == 1)
64  return true;
65  // Otherwise, there should be input node with name "input" and one
66  // should be called "ivector".
67  return nnet.GetNodeIndex("ivector") != -1 &&
68  nnet.IsInputNode(nnet.GetNodeIndex("ivector"));
69 }
int32 NumInputNodes(const Nnet &nnet)
returns the number of input nodes of this nnet.
Definition: nnet-utils.cc:43

◆ KlDivergence()

BaseFloat kaldi::nnet3::KlDivergence ( const Vector< BaseFloat > &  p,
const Vector< BaseFloat > &  q 
)

Definition at line 31 of file nnet3-am-adjust-priors.cc.

References VectorBase< Real >::Dim(), rnnlm::i, KALDI_ASSERT, KALDI_WARN, kaldi::Log(), and VectorBase< Real >::Sum().

Referenced by PrintPriorDiagnostics().

32  {
33  BaseFloat sum_p = p.Sum(), sum_q = q.Sum();
34  if (fabs(sum_p - 1.0) > 0.01 || fabs(sum_q - 1.0) > 0.01) {
35  KALDI_WARN << "KlDivergence: vectors are not close to being normalized "
36  << sum_p << ", " << sum_q;
37  }
38  KALDI_ASSERT(p.Dim() == q.Dim());
39  double ans = 0.0;
40 
41  for (int32 i = 0; i < p.Dim(); i++) {
42  BaseFloat p_prob = p(i) / sum_p, q_prob = q(i) / sum_q;
43  ans += p_prob * Log(p_prob / q_prob);
44  }
45  return ans;
46 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
double Log(double x)
Definition: kaldi-math.h:100
#define KALDI_WARN
Definition: kaldi-error.h:150
MatrixIndexT Dim() const
Returns the dimension of the vector.
Definition: kaldi-vector.h:64
Real Sum() const
Returns sum of the elements.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ LimitDerivativeTimes() [1/2]

void kaldi::nnet3::LimitDerivativeTimes ( const Nnet nnet,
const ComputationRequest request,
const NnetOptimizeOptions opts,
NnetComputation computation 
)

This optimization, which has no effect unless you set –min-deriv-time or –max-deriv-time, modifies the backprop operations for efficiency based on the assumption that derivatives for any Cindex with t < min_deriv_time or t > max_deriv_time are zero.

(this is based on the fact that derivatives in recurrent setups will either decay to zero over time, or will explode and anyway become meaningless). This is only applied if you are not comoputing any input-derivatives). The assumption, for simple Components, is that backprop operations are no-ops as long as the input was zeroed, because the back-propagated derivatives would be zero and the model would not be updated.

The most important effect of this operation is to modify some operations of type kBackprop and kBackpropNoModelUpdate for simple Components, to either make them operate on row ranges of their original input (which in general will be newly created submatrices), or to remove them altogether if they do not operate on any 't' values within the correct range.

We assert as a requirement of this optimization that all allocation commands must zero their matrices (this effectively means that you cannot apply this optimization after RemoveUnnecessaryZeroing()). This means that we don't have to worry about leaving things undefined after removing backprop operations. We also assert that backprop commands that set instead of adding to their input, must not be outputting to things that were previously set to nonzero values. (this shouldn't ever be a problem, but we do check.

Note: after this optimization it will likely be beneficial to call RemoveUnnecessaryOperations to remove operations not of type kBackprop that have now become unnecessary– e.g. operations that do the backprop through Descriptors.

◆ LimitDerivativeTimes() [2/2]

void LimitDerivativeTimes ( const Nnet nnet,
int32  min_deriv_time,
int32  max_deriv_time,
NnetComputation computation 
)

Definition at line 2215 of file nnet-optimize-utils.cc.

References DerivativeTimeLimiter::LimitDerivTimes().

Referenced by Optimize().

2218  {
2219  DerivativeTimeLimiter limiter(nnet, min_deriv_time, max_deriv_time,
2220  computation);
2221  limiter.LimitDerivTimes();
2222 }

◆ MakeSccGraph()

void MakeSccGraph ( const std::vector< std::vector< int32 > > &  graph,
const std::vector< std::vector< int32 > > &  sccs,
std::vector< std::vector< int32 > > *  scc_graph 
)

Given a list of sccs of a graph (e.g.

as computed by FindSccs), compute a directed graph on the sccs. Of course this directed graph will be acyclic.

Definition at line 164 of file nnet-graph.cc.

References rnnlm::i, rnnlm::j, KALDI_ASSERT, and kaldi::SortAndUniq().

Referenced by ComputeNnetComputationEpochs(), and UnitTestMakeSccGraph().

166  {
167  KALDI_ASSERT(scc_graph != NULL);
168  scc_graph->clear();
169  scc_graph->resize(sccs.size());
170 
171  // Hash map from node to SCC index.
172  std::vector<int32> node_to_scc_index(graph.size());
173  for (int32 i = 0; i < sccs.size(); ++i) {
174  for (int32 j = 0; j < sccs[i].size(); ++j) {
175  KALDI_ASSERT(sccs[i][j] >= 0 && sccs[i][j] < graph.size());
176  node_to_scc_index[sccs[i][j]] = i;
177  }
178  }
179 
180  // Builds graph.
181  for (int32 i = 0; i < sccs.size(); ++i) {
182  for (int32 j = 0; j < sccs[i].size(); ++j) {
183  int32 node = sccs[i][j];
184  KALDI_ASSERT(node >= 0 && node < graph.size());
185  for (int32 k = 0; k < graph[node].size(); ++k) {
186  if (node_to_scc_index[graph[node][k]] != i) { // Exclucding self.
187  (*scc_graph)[i].push_back(node_to_scc_index[graph[node][k]]);
188  }
189  }
190  }
191  // If necessary, we can use a hash maps to avoid this sorting.
192  SortAndUniq(&((*scc_graph)[i]));
193  }
194 }
kaldi::int32 int32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ MatrixIsUnused()

bool MatrixIsUnused ( const Analyzer analyzer,
const NnetComputation computation,
int32  m 
)

This function returns true if matrix 1 <= m < computation->matrices.size() is unused, defined as: it is not an input or an output, and is not accessed other than via commands of type kAllocMatrix, kDeallocMatrix, and kSetConst.

Definition at line 4582 of file nnet-optimize-utils.cc.

References MatrixAccesses::accesses, NnetComputation::Command::command_type, NnetComputation::commands, rnnlm::i, MatrixAccesses::is_input, MatrixAccesses::is_output, kNoOperation, kSetConst, and Analyzer::matrix_accesses.

Referenced by DerivativeTimeLimiter::PruneMatrices().

4584  {
4585  const MatrixAccesses &accesses = analyzer.matrix_accesses[m];
4586  if (accesses.is_input || accesses.is_output)
4587  return false;
4588  for (size_t i = 0; i < accesses.accesses.size(); i++) {
4589  int32 command_index = accesses.accesses[i].command_index;
4590  const NnetComputation::Command &command =
4591  computation.commands[command_index];
4592  if (command.command_type != kNoOperation &&
4593  command.command_type != kSetConst) {
4594  return false;
4595  }
4596  }
4597  return true;
4598 }
kaldi::int32 int32

◆ MaxMemoryUsage()

int32 kaldi::nnet3::MaxMemoryUsage ( const NnetComputation computation)

Returns the total memory, in bytes, used by the computation (just the temporary memory, not counting the memory used by the nnet itself).

This is defined as the maximum amount of memory used at any one instant.

◆ MaxOutputTimeInRequest()

int32 MaxOutputTimeInRequest ( const ComputationRequest request)

Definition at line 484 of file nnet-optimize.cc.

References rnnlm::i, KALDI_ERR, and ComputationRequest::outputs.

Referenced by CompileLoopedInternal(), CachingOptimizingCompiler::CompileNoShortcut(), NnetOptimizeOptions::Register(), UnitTestNnetCompute(), and UnitTestNnetInputDerivatives().

484  {
485  int32 ans = std::numeric_limits<int32>::min();
486  for (size_t i = 0; i < request.outputs.size(); i++) {
487  const std::vector<Index> &indexes (request.outputs[i].indexes);
488  std::vector<Index>::const_iterator iter = indexes.begin(),
489  end = indexes.end();
490  for (; iter != end; ++iter)
491  if (iter->t > ans)
492  ans = iter->t;
493  }
494  if (ans == std::numeric_limits<int32>::min()) {
495  KALDI_ERR << "Failed to find any output indexes in computation request.";
496  }
497  return ans;
498 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ MergeChainExamples()

void MergeChainExamples ( bool  compress,
std::vector< NnetChainExample > *  input,
NnetChainExample output 
)

This function merges a list of NnetChainExample objects into a single one– intended to be used when forming minibatches for neural net training.

If 'compress' it compresses the output features (recommended to save disk space).

Note: the input is left as it was at the start, but it is temporarily changed inside the function; this is a trick to allow us to use the MergeExamples() routine while avoiding having to rewrite code.

Definition at line 256 of file nnet-chain-example.cc.

References rnnlm::i, NnetChainExample::inputs, NnetExample::io, rnnlm::j, KALDI_ASSERT, MergeExamples(), MergeSupervision(), and NnetChainExample::outputs.

Referenced by NnetChainExampleStructureCompare::operator()(), and ChainExampleMerger::WriteMinibatch().

258  {
259  int32 num_examples = input->size();
260  KALDI_ASSERT(num_examples > 0);
261  // we temporarily make the input-features in 'input' look like regular NnetExamples,
262  // so that we can recycle the MergeExamples() function.
263  std::vector<NnetExample> eg_inputs(num_examples);
264  for (int32 i = 0; i < num_examples; i++)
265  eg_inputs[i].io.swap((*input)[i].inputs);
266  NnetExample eg_output;
267  MergeExamples(eg_inputs, compress, &eg_output);
268  // swap the inputs back so that they are not really changed.
269  for (int32 i = 0; i < num_examples; i++)
270  eg_inputs[i].io.swap((*input)[i].inputs);
271  // write to 'output->inputs'
272  eg_output.io.swap(output->inputs);
273 
274  // Now deal with the chain-supervision 'outputs'. There will
275  // normally be just one of these, with name "output", but we
276  // handle the more general case.
277  int32 num_output_names = (*input)[0].outputs.size();
278  output->outputs.resize(num_output_names);
279  for (int32 i = 0; i < num_output_names; i++) {
280  std::vector<const NnetChainSupervision*> to_merge(num_examples);
281  for (int32 j = 0; j < num_examples; j++) {
282  KALDI_ASSERT((*input)[j].outputs.size() == num_output_names);
283  to_merge[j] = &((*input)[j].outputs[i]);
284  }
285  MergeSupervision(to_merge,
286  &(output->outputs[i]));
287  }
288 }
static void MergeSupervision(const std::vector< const NnetChainSupervision *> &inputs, NnetChainSupervision *output)
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void MergeExamples(const std::vector< NnetExample > &src, bool compress, NnetExample *merged_eg)
Merge a set of input examples into a single example (typically the size of "src" will be the minibatc...

◆ MergeDiscriminativeExamples() [1/2]

void kaldi::nnet3::MergeDiscriminativeExamples ( std::vector< NnetDiscriminativeExample > *  input,
bool  compress,
NnetDiscriminativeExample output 
)

Appends the given vector of examples (which must be non-empty) into a single output example.

Intended to be used when forming minibatches for neural net training. If 'compress' it compresses the output features (recommended to save disk space).

Note: the input is left as it was at the start, but it is temporarily changed inside the function; this is a trick to allow us to use the MergeExamples() routine while avoiding having to rewrite code.

◆ MergeDiscriminativeExamples() [2/2]

void kaldi::nnet3::MergeDiscriminativeExamples ( bool  compress,
std::vector< NnetDiscriminativeExample > *  input,
NnetDiscriminativeExample output 
)

Definition at line 247 of file nnet-discriminative-example.cc.

References rnnlm::i, NnetDiscriminativeExample::inputs, NnetExample::io, rnnlm::j, KALDI_ASSERT, MergeExamples(), MergeSupervision(), and NnetDiscriminativeExample::outputs.

Referenced by NnetDiscriminativeExampleStructureCompare::operator()(), and DiscriminativeExampleMerger::WriteMinibatch().

250  {
251  int32 num_examples = input->size();
252  KALDI_ASSERT(num_examples > 0);
253  // we temporarily make the input-features in 'input' look like regular
254  // NnetExamples, so that we can recycle the
255  // MergeExamples() function.
256  std::vector<NnetExample> eg_inputs(num_examples);
257  for (int32 i = 0; i < num_examples; i++)
258  eg_inputs[i].io.swap((*input)[i].inputs);
259  NnetExample eg_output;
260  MergeExamples(eg_inputs, compress, &eg_output);
261  // swap the inputs back so that they are not really changed.
262  for (int32 i = 0; i < num_examples; i++)
263  eg_inputs[i].io.swap((*input)[i].inputs);
264  // write to 'output->inputs'
265  eg_output.io.swap(output->inputs);
266 
267  // Now deal with the discriminative-supervision 'outputs'. There will
268  // normally be just one of these, with name "output", but we
269  // handle the more general case.
270  int32 num_output_names = (*input)[0].outputs.size();
271  output->outputs.resize(num_output_names);
272  for (int32 i = 0; i < num_output_names; i++) {
273  std::vector<const NnetDiscriminativeSupervision*> to_merge(num_examples);
274  for (int32 j = 0; j < num_examples; j++) {
275  KALDI_ASSERT((*input)[j].outputs.size() == num_output_names);
276  to_merge[j] = &((*input)[j].outputs[i]);
277  }
278  MergeSupervision(to_merge,
279  &(output->outputs[i]));
280  }
281 }
kaldi::int32 int32
void MergeSupervision(const std::vector< const NnetDiscriminativeSupervision *> &inputs, NnetDiscriminativeSupervision *output)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void MergeExamples(const std::vector< NnetExample > &src, bool compress, NnetExample *merged_eg)
Merge a set of input examples into a single example (typically the size of "src" will be the minibatc...

◆ MergeExamples()

void MergeExamples ( const std::vector< NnetExample > &  src,
bool  compress,
NnetExample dest 
)

Merge a set of input examples into a single example (typically the size of "src" will be the minibatch size).

Will crash if "src" is the empty vector. If "compress" is true, it will compress any non-sparse features in the output.

Definition at line 162 of file nnet-example-utils.cc.

References GetIoNames(), GetIoSizes(), KALDI_ASSERT, and MergeIo().

Referenced by MergeChainExamples(), MergeDiscriminativeExamples(), UnitTestNnetMergeExamples(), and ExampleMerger::WriteMinibatch().

164  {
165  KALDI_ASSERT(!src.empty());
166  std::vector<std::string> io_names;
167  GetIoNames(src, &io_names);
168  // the sizes are the total number of Indexes we have across all examples.
169  std::vector<int32> io_sizes;
170  GetIoSizes(src, io_names, &io_sizes);
171  MergeIo(src, io_names, io_sizes, compress, merged_eg);
172 }
static void GetIoNames(const std::vector< NnetExample > &src, std::vector< std::string > *names_vec)
static void GetIoSizes(const std::vector< NnetExample > &src, const std::vector< std::string > &names, std::vector< int32 > *sizes)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static void MergeIo(const std::vector< NnetExample > &src, const std::vector< std::string > &names, const std::vector< int32 > &sizes, bool compress, NnetExample *merged_eg)

◆ MergeIo()

static void kaldi::nnet3::MergeIo ( const std::vector< NnetExample > &  src,
const std::vector< std::string > &  names,
const std::vector< int32 > &  sizes,
bool  compress,
NnetExample merged_eg 
)
static

Definition at line 88 of file nnet-example-utils.cc.

References kaldi::AppendGeneralMatrixRows(), NnetIo::features, rnnlm::i, NnetIo::indexes, NnetExample::io, KALDI_ASSERT, rnnlm::n, and NnetIo::name.

Referenced by MergeExamples().

92  {
93  // The total number of Indexes we have across all examples.
94  int32 num_feats = names.size();
95 
96  std::vector<int32> cur_size(num_feats, 0);
97 
98  // The features in the different NnetIo in the Indexes across all examples
99  std::vector<std::vector<GeneralMatrix const*> > output_lists(num_feats);
100 
101  // Initialize the merged_eg
102  merged_eg->io.clear();
103  merged_eg->io.resize(num_feats);
104  for (int32 f = 0; f < num_feats; f++) {
105  NnetIo &io = merged_eg->io[f];
106  int32 size = sizes[f];
107  KALDI_ASSERT(size > 0);
108  io.name = names[f];
109  io.indexes.resize(size);
110  }
111 
112  std::vector<std::string>::const_iterator names_begin = names.begin(),
113  names_end = names.end();
114  std::vector<NnetExample>::const_iterator eg_iter = src.begin(),
115  eg_end = src.end();
116  for (int32 n = 0; eg_iter != eg_end; ++eg_iter, ++n) {
117  std::vector<NnetIo>::const_iterator io_iter = eg_iter->io.begin(),
118  io_end = eg_iter->io.end();
119  for (; io_iter != io_end; ++io_iter) {
120  const NnetIo &io = *io_iter;
121  std::vector<std::string>::const_iterator names_iter =
122  std::lower_bound(names_begin, names_end, io.name);
123  KALDI_ASSERT(*names_iter == io.name);
124 
125  int32 f = names_iter - names_begin;
126  int32 this_size = io.indexes.size();
127  int32 &this_offset = cur_size[f];
128  KALDI_ASSERT(this_size + this_offset <= sizes[f]);
129 
130  // Add f'th Io's features
131  output_lists[f].push_back(&(io.features));
132 
133  // Work on the Indexes for the f^th Io in merged_eg
134  NnetIo &output_io = merged_eg->io[f];
135  std::copy(io.indexes.begin(), io.indexes.end(),
136  output_io.indexes.begin() + this_offset);
137  std::vector<Index>::iterator output_iter = output_io.indexes.begin();
138  // Set the n index to be different for each of the original examples.
139  for (int32 i = this_offset; i < this_offset + this_size; i++) {
140  // we could easily support merging already-merged egs, but I don't see a
141  // need for it right now.
142  KALDI_ASSERT(output_iter[i].n == 0 &&
143  "Merging already-merged egs? Not currentlysupported.");
144  output_iter[i].n = n;
145  }
146  this_offset += this_size; // note: this_offset is a reference.
147  }
148  }
149  KALDI_ASSERT(cur_size == sizes);
150  for (int32 f = 0; f < num_feats; f++) {
151  AppendGeneralMatrixRows(output_lists[f],
152  &(merged_eg->io[f].features));
153  if (compress) {
154  // the following won't do anything if the features were sparse.
155  merged_eg->io[f].features.Compress();
156  }
157  }
158 }
kaldi::int32 int32
struct rnnlm::@11::@12 n
void AppendGeneralMatrixRows(const std::vector< const GeneralMatrix *> &src, GeneralMatrix *mat)
Appends all the matrix rows of a list of GeneralMatrixes, to get a single GeneralMatrix.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ MergeSupervision() [1/2]

void MergeSupervision ( const std::vector< const NnetDiscriminativeSupervision *> &  inputs,
NnetDiscriminativeSupervision output 
)

Definition at line 185 of file nnet-discriminative-example.cc.

References NnetDiscriminativeSupervision::CheckDim(), NnetDiscriminativeSupervision::deriv_weights, VectorBase< Real >::Dim(), NnetDiscriminativeSupervision::indexes, KALDI_ASSERT, kaldi::kUndefined, kaldi::discriminative::MergeSupervision(), rnnlm::n, NnetDiscriminativeSupervision::name, NnetDiscriminativeSupervision::supervision, and DiscriminativeSupervision::Swap().

187  {
188  int32 num_inputs = inputs.size(),
189  num_indexes = 0;
190  for (int32 n = 0; n < num_inputs; n++) {
191  KALDI_ASSERT(inputs[n]->name == inputs[0]->name);
192  num_indexes += inputs[n]->indexes.size();
193  }
194  output->name = inputs[0]->name;
195  std::vector<const discriminative::DiscriminativeSupervision*> input_supervision;
196  input_supervision.reserve(inputs.size());
197  for (int32 n = 0; n < num_inputs; n++)
198  input_supervision.push_back(&(inputs[n]->supervision));
199  discriminative::DiscriminativeSupervision output_supervision;
200  discriminative::MergeSupervision(input_supervision,
201  &output_supervision);
202  output->supervision.Swap(&(output_supervision));
203 
204  output->indexes.clear();
205  output->indexes.reserve(num_indexes);
206  for (int32 n = 0; n < num_inputs; n++) {
207  const std::vector<Index> &src_indexes = inputs[n]->indexes;
208  int32 cur_size = output->indexes.size();
209  output->indexes.insert(output->indexes.end(),
210  src_indexes.begin(), src_indexes.end());
211  std::vector<Index>::iterator iter = output->indexes.begin() + cur_size,
212  end = output->indexes.end();
213  // change the 'n' index to correspond to the index into 'input'.
214  // Each example gets a different 'n' value, starting from 0.
215  for (; iter != end; ++iter) {
216  KALDI_ASSERT(iter->n == 0 && "Merging already-merged discriminative egs");
217  iter->n = n;
218  }
219  }
220  KALDI_ASSERT(output->indexes.size() == num_indexes);
221  // OK, at this point the 'indexes' will be in the wrong order,
222  // because they should be first sorted by 't' and next by 'n'.
223  // 'sort' will fix this, due to the operator < on type Index.
224  // TODO: Is this required?
225  std::sort(output->indexes.begin(), output->indexes.end());
226 
227  // merge the deriv_weights.
228  if (inputs[0]->deriv_weights.Dim() != 0) {
229  int32 frames_per_sequence = inputs[0]->deriv_weights.Dim();
230  output->deriv_weights.Resize(output->indexes.size(), kUndefined);
231  KALDI_ASSERT(output->deriv_weights.Dim() ==
232  frames_per_sequence * num_inputs);
233  for (int32 n = 0; n < num_inputs; n++) {
234  const Vector<BaseFloat> &src_deriv_weights = inputs[n]->deriv_weights;
235  KALDI_ASSERT(src_deriv_weights.Dim() == frames_per_sequence);
236  // the ordering of the deriv_weights corresponds to the ordering of the
237  // Indexes, where the time dimension has the greater stride.
238  for (int32 t = 0; t < frames_per_sequence; t++) {
239  output->deriv_weights(t * num_inputs + n) = src_deriv_weights(t);
240  }
241  }
242  }
243  output->CheckDim();
244 }
kaldi::int32 int32
struct rnnlm::@11::@12 n
void MergeSupervision(const std::vector< const NnetDiscriminativeSupervision *> &inputs, NnetDiscriminativeSupervision *output)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ MergeSupervision() [2/2]

static void kaldi::nnet3::MergeSupervision ( const std::vector< const NnetChainSupervision *> &  inputs,
NnetChainSupervision output 
)
static

Definition at line 195 of file nnet-chain-example.cc.

References NnetChainSupervision::CheckDim(), NnetChainSupervision::deriv_weights, VectorBase< Real >::Dim(), NnetChainSupervision::indexes, KALDI_ASSERT, kaldi::kUndefined, rnnlm::n, NnetChainSupervision::name, and NnetChainSupervision::supervision.

Referenced by MergeChainExamples(), MergeDiscriminativeExamples(), and NnetDiscriminativeExampleStructureCompare::operator()().

197  {
198  int32 num_inputs = inputs.size(),
199  num_indexes = 0;
200  for (int32 n = 0; n < num_inputs; n++) {
201  KALDI_ASSERT(inputs[n]->name == inputs[0]->name);
202  num_indexes += inputs[n]->indexes.size();
203  }
204  output->name = inputs[0]->name;
205  std::vector<const chain::Supervision*> input_supervision;
206  input_supervision.reserve(inputs.size());
207  for (int32 n = 0; n < num_inputs; n++)
208  input_supervision.push_back(&(inputs[n]->supervision));
209  chain::Supervision output_supervision;
210  MergeSupervision(input_supervision,
211  &output_supervision);
212  output->supervision.Swap(&output_supervision);
213 
214  output->indexes.clear();
215  output->indexes.reserve(num_indexes);
216  for (int32 n = 0; n < num_inputs; n++) {
217  const std::vector<Index> &src_indexes = inputs[n]->indexes;
218  int32 cur_size = output->indexes.size();
219  output->indexes.insert(output->indexes.end(),
220  src_indexes.begin(), src_indexes.end());
221  std::vector<Index>::iterator iter = output->indexes.begin() + cur_size,
222  end = output->indexes.end();
223  // change the 'n' index to correspond to the index into 'input'.
224  // Each example gets a different 'n' value, starting from 0.
225  for (; iter != end; ++iter) {
226  KALDI_ASSERT(iter->n == 0 && "Merging already-merged chain egs");
227  iter->n = n;
228  }
229  }
230  KALDI_ASSERT(output->indexes.size() == num_indexes);
231  // OK, at this point the 'indexes' will be in the wrong order,
232  // because they should be first sorted by 't' and next by 'n'.
233  // 'sort' will fix this, due to the operator < on type Index.
234  std::sort(output->indexes.begin(), output->indexes.end());
235 
236  // merge the deriv_weights.
237  if (inputs[0]->deriv_weights.Dim() != 0) {
238  int32 frames_per_sequence = inputs[0]->deriv_weights.Dim();
239  output->deriv_weights.Resize(output->indexes.size(), kUndefined);
240  KALDI_ASSERT(output->deriv_weights.Dim() ==
241  frames_per_sequence * num_inputs);
242  for (int32 n = 0; n < num_inputs; n++) {
243  const Vector<BaseFloat> &src_deriv_weights = inputs[n]->deriv_weights;
244  KALDI_ASSERT(src_deriv_weights.Dim() == frames_per_sequence);
245  // the ordering of the deriv_weights corresponds to the ordering of the
246  // Indexes, where the time dimension has the greater stride.
247  for (int32 t = 0; t < frames_per_sequence; t++) {
248  output->deriv_weights(t * num_inputs + n) = src_deriv_weights(t);
249  }
250  }
251  }
252  output->CheckDim();
253 }
static void MergeSupervision(const std::vector< const NnetChainSupervision *> &inputs, NnetChainSupervision *output)
kaldi::int32 int32
struct rnnlm::@11::@12 n
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ MergeTaskOutput() [1/2]

void MergeTaskOutput ( const std::vector< NnetInferenceTask > &  tasks,
Matrix< BaseFloat > *  output 
)

Merges together the 'output_cpu' (if the 'output_to_cpu' members are true) or the 'output' members of 'tasks' into a single CPU matrix 'output'.

Requires that those outputs are nonempty (i.e. that those tasks must have been completed).

Parameters
[in]tasksThe vector of tasks whose outputs are to be merged. The tasks must have already been completed.
[outputoutput The spliced-together output matrix

TODO: in the future, maybe start from GPU and use pinned matrices for the transfer.

Definition at line 968 of file nnet-batch-compute.cc.

References NnetInferenceTask::first_used_output_frame_index, rnnlm::i, KALDI_ASSERT, NnetInferenceTask::num_initial_unused_output_frames, NnetInferenceTask::num_used_output_frames, MatrixBase< Real >::NumCols(), NnetInferenceTask::output, NnetInferenceTask::output_cpu, NnetInferenceTask::output_to_cpu, Matrix< Real >::Resize(), and MatrixBase< Real >::RowRange().

Referenced by NnetBatchInference::GetOutput(), and NnetBatchComputerOptions::Register().

970  {
971  int32 num_tasks = tasks.size(),
972  num_output_frames = 0,
973  output_dim = -1;
974  for (int32 i = 0; i < num_tasks; i++) {
975  const NnetInferenceTask &task = tasks[i];
976  num_output_frames += task.num_used_output_frames;
977  if (i == 0) {
978  output_dim = (task.output_to_cpu ?
979  task.output_cpu.NumCols() :
980  task.output.NumCols());
981  }
982  }
983  KALDI_ASSERT(num_output_frames != 0 && output_dim != 0);
984  int32 cur_output_frame = 0;
985  output->Resize(num_output_frames, output_dim);
986  for (int32 i = 0; i < num_tasks; i++) {
987  const NnetInferenceTask &task = tasks[i];
988  int32 skip = task.num_initial_unused_output_frames,
989  num_used = task.num_used_output_frames;
990  KALDI_ASSERT(cur_output_frame == task.first_used_output_frame_index);
991  if (task.output_to_cpu) {
992  output->RowRange(cur_output_frame, num_used).CopyFromMat(
993  task.output_cpu.RowRange(skip, num_used));
994  } else {
995  output->RowRange(cur_output_frame, num_used).CopyFromMat(
996  task.output.RowRange(skip, num_used));
997  }
998  cur_output_frame += num_used;
999  }
1000  KALDI_ASSERT(cur_output_frame == num_output_frames);
1001 }
kaldi::int32 int32
SubMatrix< Real > RowRange(const MatrixIndexT row_offset, const MatrixIndexT num_rows) const
Definition: kaldi-matrix.h:209
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void Resize(const MatrixIndexT r, const MatrixIndexT c, MatrixResizeType resize_type=kSetZero, MatrixStrideType stride_type=kDefaultStride)
Sets matrix to a specified size (zero is OK as long as both r and c are zero).

◆ MergeTaskOutput() [2/2]

void MergeTaskOutput ( const std::vector< NnetInferenceTask > &  tasks,
CuMatrix< BaseFloat > *  output 
)

Definition at line 1002 of file nnet-batch-compute.cc.

References CuMatrixBase< Real >::Data(), NnetInferenceTask::first_used_output_frame_index, rnnlm::i, KALDI_ASSERT, kaldi::kUndefined, NnetInferenceTask::num_initial_unused_output_frames, NnetInferenceTask::num_used_output_frames, MatrixBase< Real >::NumCols(), CuMatrixBase< Real >::NumCols(), CuMatrixBase< Real >::NumRows(), NnetInferenceTask::output, NnetInferenceTask::output_cpu, NnetInferenceTask::output_to_cpu, CuMatrix< Real >::Resize(), MatrixBase< Real >::RowRange(), CuMatrixBase< Real >::RowRange(), and CuMatrixBase< Real >::Stride().

1004  {
1005  int32 num_tasks = tasks.size(),
1006  num_output_frames = 0,
1007  output_dim = -1;
1008  for (int32 i = 0; i < num_tasks; i++) {
1009  const NnetInferenceTask &task = tasks[i];
1010  num_output_frames += task.num_used_output_frames;
1011  if (i == 0) {
1012  output_dim = (task.output_to_cpu ?
1013  task.output_cpu.NumCols() :
1014  task.output.NumCols());
1015  }
1016  }
1017  KALDI_ASSERT(num_output_frames != 0 && output_dim != 0);
1018  int32 cur_output_frame = 0;
1019  output->Resize(num_output_frames, output_dim, kUndefined);
1020 
1021 #if HAVE_CUDA == 1
1022  if (CuDevice::Instantiate().Enabled()) {
1023 
1024  std::vector<const BaseFloat*> inputs(num_tasks);
1025  std::vector<BaseFloat*> outputs(num_tasks);
1026  std::vector<int32_t> ldi(num_tasks), ldo(num_tasks);
1027  std::vector<int32_t> num_rows(num_tasks), num_cols(num_tasks);
1028 
1029  int b=0; // batch counter
1030  for (int32 i = 0; i < num_tasks; i++) {
1031  const NnetInferenceTask &task = tasks[i];
1032  int32 skip = task.num_initial_unused_output_frames,
1033  num_used = task.num_used_output_frames;
1034  KALDI_ASSERT(cur_output_frame == task.first_used_output_frame_index);
1035  if (task.output_to_cpu) {
1036  output->RowRange(cur_output_frame, num_used).CopyFromMat(
1037  task.output_cpu.RowRange(skip, num_used));
1038  } else {
1039  CuSubMatrix<BaseFloat> output_mat =
1040  output->RowRange(cur_output_frame, num_used);
1041  const CuSubMatrix<BaseFloat> input_mat =
1042  task.output.RowRange(skip, num_used);
1043 
1044  // create matrix batch description arrays
1045  num_rows[b] = output_mat.NumRows();
1046  num_cols[b] = output_mat.NumCols();
1047  outputs[b] = output_mat.Data();
1048  inputs[b] = input_mat.Data();
1049  ldo[b] = output_mat.Stride();
1050  ldi[b] = input_mat.Stride();
1051  b++; // increase batch count
1052  }
1053  cur_output_frame += num_used;
1054  }
1055 
1056  // execute batched copy
1057  cuda_batched_copy_mats(b, &num_rows[0], &num_cols[0], &inputs[0], &ldi[0],
1058  &outputs[0], &ldo[0]);
1059 
1060  } else
1061 #endif
1062  {
1063  for (int32 i = 0; i < num_tasks; i++) {
1064  const NnetInferenceTask &task = tasks[i];
1065  int32 skip = task.num_initial_unused_output_frames,
1066  num_used = task.num_used_output_frames;
1067  KALDI_ASSERT(cur_output_frame == task.first_used_output_frame_index);
1068  if (task.output_to_cpu) {
1069  output->RowRange(cur_output_frame, num_used).CopyFromMat(
1070  task.output_cpu.RowRange(skip, num_used));
1071  } else {
1072  output->RowRange(cur_output_frame, num_used).CopyFromMat(
1073  task.output.RowRange(skip, num_used));
1074  }
1075  cur_output_frame += num_used;
1076  }
1077  }
1078 
1079  KALDI_ASSERT(cur_output_frame == num_output_frames);
1080 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ Mod()

I kaldi::nnet3::Mod ( m,
n 
)

Mod(m, n), defined for integers m and n where n > 0, returns the modulus m % n, defined as the integer 0 <= i < n such that i and m are congruent modulo n; for instance, Mod(13, 10) = 3.

This is like the % operation in C/C++, except that it always returns a positive value even for negative m; in 99% of cases where it makes a difference, this is what you want. In the C/C++ standard, the sign of a % b for negative a is not specified (except by relation with the division '/' operator), but in practice it would be <= 0 for almost all implementations.

Definition at line 106 of file nnet-compile-looped.cc.

References rnnlm::n.

Referenced by CreateLoopedComputationRequest().

106  {
107  I ans = m % n;
108  if (ans < 0) ans += n;
109  return ans;
110 }
struct rnnlm::@11::@12 n

◆ ModifyNnetIvectorPeriod()

void ModifyNnetIvectorPeriod ( int32  ivector_period,
Nnet nnet 
)

This function modifies the descriptors in the neural network to change the periodicity with which it expects to read an iVector at its input.

We normally train neural networks that expect to see an iVector at frame zero only; this is because we train on fixed-size chunks and the iVector doesn't change that much within each chunk. However, expecting just one iVector isn't that convenient for looped recognition because it changes with time, so we modify the iVector input period in the network by replacing expressions like ReplaceIndex(ivector, t, 0) with Round(ivector, 10) [assuming ivector_period == 10]. The descriptor doesn't have to be named "ivector", it would work for ReplaceIndex(foo, t, 0). This won't work in every conceivable network, but it does do what you want in the cases of interest.

It does this in a rather simple way, by getting the config lines that correspond to descriptors, and doing a search-and-replace. It's maybe not ideal, but it was the easiest way to do it.

Definition at line 28 of file nnet-compile-looped.cc.

References ConfigLine::FirstToken(), Nnet::GetConfigLines(), rnnlm::i, KALDI_ASSERT, KALDI_ERR, ConfigLine::ParseLine(), and Nnet::ReadConfig().

Referenced by DecodableNnetSimpleLoopedInfo::Init(), and UnitTestNnetCompileLooped().

29  {
30  KALDI_ASSERT(ivector_period > 0);
31  std::vector<std::string> config_lines;
32  nnet->GetConfigLines(false, &config_lines);
33  std::ostringstream config_to_read;
34  for (size_t i = 0; i < config_lines.size(); i++) {
35  std::string s = config_lines[i];
36  ConfigLine config_line;
37  bool b = config_line.ParseLine(config_lines[i]);
38  KALDI_ASSERT(b && "Could not parse config line.");
39  if (config_line.FirstToken() == "component-node") {
40  // What we're trying to do here is: find a line like:
41  // component-node name=foo component=foo input=Append(bar, ReplaceIndex(ivector, t, 0))
42  // we want to replace it with something like:
43  // component-node name=foo component=foo input=Append(bar, ReplaceIndex(ivector, t, 0))
44  // .. and we want this to also work if instead of 'ivector' it has something like
45  // Scale(0.5, ivector). We assume that ReplaceIndex() expressions only occur in this
46  // type of context.
47  std::string whole_line = config_lines[i];
48  std::string to_search_for = "ReplaceIndex(";
49  std::string::size_type to_search_for_size = to_search_for.size();
50  std::string::size_type pos = whole_line.find(to_search_for);
51  if (pos != std::string::npos) {
52  std::string::size_type comma_pos = whole_line.find(", t, 0)", pos);
53  if (comma_pos != std::string::npos) {
54  // if the line contained ReplaceIndex(ivector, t, 0),
55  // descriptor_name would now be 'ivector'.
56  std::string descriptor_name =
57  whole_line.substr(pos + to_search_for_size,
58  comma_pos - (pos + to_search_for_size));
59  // Note: 7, below, is the size of: ", t, 0)".
60  std::string::size_type end_pos = comma_pos + 7;
61  std::string::size_type expr_size = end_pos - pos;
62  // e.g. expr_size would be strlen("ReplaceIndex(ivector, t, 0)").
63  std::ostringstream to_replace_with;
64  to_replace_with << "Round(" << descriptor_name << ", " << ivector_period << ")";
65  whole_line.replace(pos, expr_size, to_replace_with.str());
66  config_to_read << whole_line << "\n";
67  } else {
68  KALDI_ERR << "Could not process the ReplaceIndex expression in: "
69  << whole_line;
70  }
71  }
72  }
73  }
74  if (!config_to_read.str().empty()) {
75  std::istringstream is(config_to_read.str());
76  nnet->ReadConfig(is);
77  }
78 }
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ MoveSizingCommands()

void MoveSizingCommands ( const Nnet nnet,
NnetComputation computation 
)

This optimization moves commands that allocate and zero matrices to as late as possible, and moves commands that deallocate matrices to as early as possible.

Definition at line 152 of file nnet-optimize.cc.

References MatrixAccesses::accesses, MatrixAccesses::allocate_command, NnetComputation::Command::command_type, NnetComputation::commands, ComputeCommandAttributes(), ComputeMatrixAccesses(), ComputeVariableAccesses(), MatrixAccesses::deallocate_command, ComputationVariables::Init(), KALDI_ASSERT, kAllocMatrix, kDeallocMatrix, kGotoLabel, and kSetConst.

Referenced by Optimize().

152  {
153  ComputationVariables variables;
154  variables.Init(*computation);
155  std::vector<CommandAttributes> attributes;
156  ComputeCommandAttributes(nnet, *computation, variables, &attributes);
157  std::vector<std::vector<Access> > variable_accesses;
158  ComputeVariableAccesses(variables, attributes, &variable_accesses);
159  std::vector<MatrixAccesses> matrix_accesses;
160  ComputeMatrixAccesses(nnet, *computation, variables, attributes,
161  &matrix_accesses);
162 
163  // The way we will renumber the commands is, we will first set this vector up
164  // with pairs (command-index * 3, pointer-to-command), and we will then modify
165  // the command-indexes in this vector to the numbers that we want, and sort
166  // it. The reason for the * 3 is so that we can number commands "just-after"
167  // existing indexes (by adding 1) and "just-before" (by subtracting 1).
168  int32 num_commands = computation->commands.size(),
169  num_matrices = matrix_accesses.size();
170 
171  // Matrix allocation commands tend to be followed by a command that zeroes the
172  // matrix. We want to treat the two commands as a single unit for purposes of
173  // reordering. is_command_pair[c] will be true if command c is the first
174  // element of such a pair.
175  std::vector<bool> is_command_pair(num_commands, false);
176  for (int32 c = 0; c + 1 < num_commands; c++) {
177  if (computation->commands[c].command_type == kAllocMatrix &&
178  computation->commands[c+1].command_type == kSetConst &&
179  computation->commands[c].arg1 == computation->commands[c+1].arg1 &&
180  computation->commands[c+1].alpha == 0.0) {
181  is_command_pair[c] = true;
182  }
183  }
184 
185  // 'command_reordering' contains (new-number, old-number) of commands.
186  // the new-number is multiplied by 3 for reasons explained above.
187  std::vector<std::pair<int32,int32> >
188  command_reordering(num_commands);
189  // Note: for now we include the second-elements-of-pairs (i.e. the zeroing
190  // commands that follow allocation commands) here; we'll ignore them later.
191  for (int32 c = 0; c < num_commands; c++) {
192  command_reordering[c].first = c * 3;
193  command_reordering[c].second = c;
194  }
195  for (int32 m = 1; m < num_matrices; m++) {
196  const MatrixAccesses &ma = matrix_accesses[m];
197  // The following if-block relates to reordering of allocation (and,
198  // implicitly, zeroing) commands.
199  if (ma.allocate_command != -1 &&
200  computation->commands[ma.allocate_command].command_type == kAllocMatrix) {
201  // first_access_command will be index of first access, except for the
202  // zeroing command that immediately follows the initialization command.
203  int32 first_access_command = -1;
204  // this block sets 'first_access_command'.
205  if (!ma.accesses.empty()) {
206  first_access_command = ma.accesses[0].command_index;
207  if (first_access_command == ma.allocate_command + 1 &&
208  is_command_pair[ma.allocate_command]) {
209  if (ma.accesses.size() > 1)
210  first_access_command = ma.accesses[1].command_index;
211  else
212  first_access_command = -1;
213  }
214  }
215  if (first_access_command != -1) {
216  KALDI_ASSERT(first_access_command > ma.allocate_command);
217  // move the initialization command to just before the first access.
218  command_reordering[ma.allocate_command].first =
219  first_access_command * 3 - 1;
220  }
221  }
222  // The following if-block relates to reordering of deallocation
223  // commands.
224  if (ma.deallocate_command != -1 && !ma.accesses.empty() &&
225  computation->commands[ma.deallocate_command].command_type ==
226  kDeallocMatrix) {
227  int32 last_access_command = ma.accesses.back().command_index;
228  // move the deallocation command to just after the last access.
229  command_reordering[ma.deallocate_command].first =
230  last_access_command * 3 + 1;
231  }
232  }
233  std::sort(command_reordering.begin(), command_reordering.end());
234  std::vector<NnetComputation::Command> reordered_commands;
235  reordered_commands.reserve(num_commands);
236  for (int32 c = 0; c < num_commands; c++) {
237  int32 old_index = command_reordering[c].second;
238  NnetComputation::Command &old_command = computation->commands[old_index];
239  // the following assert is because this optimization is not allowed
240  // after looped optimization.
241  KALDI_ASSERT(old_command.command_type != kGotoLabel);
242  if (old_index > 0 && is_command_pair[old_index - 1]) {
243  // If the old command-index was a zeroing command that follows
244  // an allocation command, ignore it; it will be reordered to
245  // right after wherever the allocation command went, and we'll
246  // deal with it when we deal with the first element of the pair.
247  continue;
248  } else {
249  reordered_commands.push_back(computation->commands[old_index]);
250  if (is_command_pair[old_index]) {
251  // if this command is the first member of an (allocation, zeroing)
252  // pair then we need to deal with the zeroing command as well.
253  reordered_commands.push_back(computation->commands[old_index + 1]);
254  }
255  }
256  }
257  computation->commands = reordered_commands;
258 }
kaldi::int32 int32
void ComputeCommandAttributes(const Nnet &nnet, const NnetComputation &computation, const ComputationVariables &vars, std::vector< CommandAttributes > *attributes)
void ComputeVariableAccesses(const ComputationVariables &variables, const std::vector< CommandAttributes > &command_attributes, std::vector< std::vector< Access > > *variable_accesses)
After the command-level attributes have been computed, this function organizes them per variable (see...
void ComputeMatrixAccesses(const Nnet &nnet, const NnetComputation &computation, const ComputationVariables &variables, const std::vector< CommandAttributes > &command_attributes, std::vector< MatrixAccesses > *matrix_accesses)
This function organizes information in the CommandAttributes in a way that is convenient to access pe...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ NameMatchesPattern()

bool NameMatchesPattern ( const char *  name,
const char *  pattern 
)

Definition at line 235 of file nnet-parse.cc.

Referenced by SvdApplier::DecomposeComponents(), ReadEditConfig(), ReduceRankOfComponents(), and UnitTestNameMatchesPattern().

235  {
236  if (*pattern == '*') {
237  return NameMatchesPattern(name, pattern + 1) ||
238  (*name != '\0' && NameMatchesPattern(name + 1, pattern));
239  } else if (*name == *pattern) {
240  return (*name == '\0' || NameMatchesPattern(name + 1, pattern + 1));
241  } else {
242  return false;
243  }
244 }
bool NameMatchesPattern(const char *name, const char *pattern)
Definition: nnet-parse.cc:235

◆ NnetInfo()

std::string NnetInfo ( const Nnet nnet)

This function returns various info about the neural net.

If the nnet satisfied IsSimpleNnet(nnet), the info includes "left-context=5\nright-context=3\n...". The info includes the output of nnet.Info(). This is modeled after the info that AmNnetSimple returns in its Info() function (we need this in the CTC code).

Definition at line 492 of file nnet-utils.cc.

References ComputeSimpleNnetContext(), Nnet::Info(), Nnet::InputDim(), IsSimpleNnet(), and Nnet::OutputDim().

Referenced by UnitTestNnetContext().

492  {
493  std::ostringstream ostr;
494  if (IsSimpleNnet(nnet)) {
495  int32 left_context, right_context;
496  // this call will crash if the nnet is not 'simple'.
497  ComputeSimpleNnetContext(nnet, &left_context, &right_context);
498  ostr << "left-context: " << left_context << "\n";
499  ostr << "right-context: " << right_context << "\n";
500  }
501  ostr << "input-dim: " << nnet.InputDim("input") << "\n";
502  ostr << "ivector-dim: " << nnet.InputDim("ivector") << "\n";
503  ostr << "output-dim: " << nnet.OutputDim("output") << "\n";
504  ostr << "# Nnet info follows.\n";
505  ostr << nnet.Info();
506  return ostr.str();
507 }
kaldi::int32 int32
void ComputeSimpleNnetContext(const Nnet &nnet, int32 *left_context, int32 *right_context)
ComputeSimpleNnetContext computes the left-context and right-context of a nnet.
Definition: nnet-utils.cc:146
bool IsSimpleNnet(const Nnet &nnet)
This function returns true if the nnet has the following properties: It has an output called "output"...
Definition: nnet-utils.cc:52

◆ NnetIsRecurrent()

bool NnetIsRecurrent ( const Nnet nnet)

Returns true if 'nnet' has some kind of recurrency.

Definition at line 1441 of file nnet-utils.cc.

References GraphHasCycles(), and NnetToDirectedGraph().

Referenced by TestNnetDecodable(), UnitTestNnetInputDerivatives(), and UnitTestNnetModelDerivatives().

1441  {
1442  std::vector<std::vector<int32> > graph;
1443  NnetToDirectedGraph(nnet, &graph);
1444  return GraphHasCycles(graph);
1445 }
void NnetToDirectedGraph(const Nnet &nnet, std::vector< std::vector< int32 > > *graph)
This function takes an nnet and turns it to a directed graph on nodes.
Definition: nnet-graph.cc:30
bool GraphHasCycles(const std::vector< std::vector< int32 > > &graph)
This function returns &#39;true&#39; if the graph represented in &#39;graph&#39; contains cycles (including cycles wh...
Definition: nnet-graph.cc:300

◆ NnetParametersAreIdentical()

bool NnetParametersAreIdentical ( const Nnet nnet1,
const Nnet nnet2,
BaseFloat  threshold 
)

Used for testing that the updatable parameters in two networks are the same.

May crash if structure differs. Prints warning and returns false if parameters differ. E.g. set threshold to 1.0e-05 (it's a relative threshold, applied per component).

Definition at line 1802 of file nnet-test-utils.cc.

References UpdatableComponent::DotProduct(), Nnet::GetComponent(), Nnet::GetComponentName(), KALDI_ASSERT, KALDI_WARN, kUpdatableComponent, Nnet::NumComponents(), Component::Properties(), and Component::Type().

Referenced by NnetGenerationOptions::NnetGenerationOptions(), and UnitTestNnetOptimizeWithOptions().

1804  {
1805  KALDI_ASSERT(nnet1.NumComponents() == nnet2.NumComponents());
1806  int32 num_components = nnet1.NumComponents();
1807  for (int32 c = 0; c < num_components; c++) {
1808  const Component *c1 = nnet1.GetComponent(c),
1809  *c2 = nnet2.GetComponent(c);
1810  KALDI_ASSERT(c1->Type() == c2->Type());
1811  if (c1->Properties() & kUpdatableComponent) {
1812  const UpdatableComponent *u1 = dynamic_cast<const UpdatableComponent*>(c1),
1813  *u2 = dynamic_cast<const UpdatableComponent*>(c2);
1814  KALDI_ASSERT(u1 != NULL && u2 != NULL);
1815  BaseFloat prod11 = u1->DotProduct(*u1), prod12 = u1->DotProduct(*u2),
1816  prod21 = u2->DotProduct(*u1), prod22 = u2->DotProduct(*u2);
1817  BaseFloat max_prod = std::max(std::max(prod11, prod12),
1818  std::max(prod21, prod22)),
1819  min_prod = std::min(std::min(prod11, prod12),
1820  std::min(prod21, prod22));
1821  if (max_prod - min_prod > threshold * max_prod) {
1822  KALDI_WARN << "Component '" << nnet1.GetComponentName(c)
1823  << "' differs in nnet1 versus nnet2: prod(11,12,21,22) = "
1824  << prod11 << ',' << prod12 << ',' << prod21 << ',' << prod22;
1825  return false;
1826  }
1827  }
1828  }
1829  return true;
1830 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_WARN
Definition: kaldi-error.h:150
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ NnetToDirectedGraph()

void NnetToDirectedGraph ( const Nnet nnet,
std::vector< std::vector< int32 > > *  graph 
)

This function takes an nnet and turns it to a directed graph on nodes.

This is the reverse of the dependency graph. The nodes will be numbered from 0 to graph->size() - 1, where graph->size() == nnet.NumNodes(). For each node-index n, the vector in (*graph)[n] will contain a list of all the nodes that have a direct dependency on node n (in order to compute them). For instance, if n is the output node, (*graph)[n] will be the empty list because no other node will depend on it.

Definition at line 30 of file nnet-graph.cc.

References NetworkNode::descriptor, Nnet::GetNode(), Descriptor::GetNodeDependencies(), rnnlm::i, KALDI_ASSERT, KALDI_ERR, kComponent, kDescriptor, kDimRange, kInput, rnnlm::n, NetworkNode::node_index, NetworkNode::node_type, Nnet::NumNodes(), kaldi::SortAndUniq(), and NetworkNode::u.

Referenced by ComputeNnetComputationEpochs(), FindOrphanNodes(), and NnetIsRecurrent().

31  {
32  graph->clear();
33  int32 num_nodes = nnet.NumNodes();
34  graph->resize(num_nodes);
35  for (int32 n = 0; n < num_nodes; n++) {
36  const NetworkNode &node = nnet.GetNode(n);
37  // handle dependencies of this node.
38  std::vector<int32> node_dependencies;
39  switch (node.node_type) {
40  case kInput:
41  break; // no node dependencies.
42  case kDescriptor:
43  node.descriptor.GetNodeDependencies(&node_dependencies);
44  break;
45  case kComponent:
46  node_dependencies.push_back(n - 1);
47  break;
48  case kDimRange:
49  node_dependencies.push_back(node.u.node_index);
50  break;
51  default:
52  KALDI_ERR << "Invalid node type";
53  }
54  SortAndUniq(&node_dependencies);
55  for (size_t i = 0; i < node_dependencies.size(); i++) {
56  int32 dep_n = node_dependencies[i];
57  KALDI_ASSERT(dep_n >= 0 && dep_n < num_nodes);
58  (*graph)[dep_n].push_back(n);
59  }
60  }
61 }
kaldi::int32 int32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
struct rnnlm::@11::@12 n
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ NormalizeTextDescriptor()

std::string kaldi::nnet3::NormalizeTextDescriptor ( const std::vector< std::string > &  node_names,
const std::string &  desc_str 
)

Definition at line 180 of file nnet-descriptor-test.cc.

References GeneralDescriptor::ConvertToDescriptor(), DescriptorTokenize(), KALDI_ERR, KALDI_LOG, GeneralDescriptor::Parse(), and Descriptor::WriteConfig().

Referenced by UnitTestGeneralDescriptorSpecial().

181  {
182  std::vector<std::string> tokens;
183  DescriptorTokenize(desc_str, &tokens);
184  tokens.push_back("end of input");
185  const std::string *next_token = &(tokens[0]);
186  GeneralDescriptor *gen_desc = GeneralDescriptor::Parse(node_names,
187  &next_token);
188  if (*next_token != "end of input")
189  KALDI_ERR << "Parsing Descriptor, expected end of input but got "
190  << "'" << *next_token << "'";
191  Descriptor *desc = gen_desc->ConvertToDescriptor();
192  std::ostringstream ostr;
193  desc->WriteConfig(ostr, node_names);
194  delete gen_desc;
195  delete desc;
196  KALDI_LOG << "Result of normalizing " << desc_str << " is: " << ostr.str();
197  return ostr.str();
198 }
This class is only used when parsing Descriptors.
bool DescriptorTokenize(const std::string &input, std::vector< std::string > *tokens)
This function tokenizes input when parsing Descriptor configuration values.
Definition: nnet-parse.cc:30
#define KALDI_ERR
Definition: kaldi-error.h:147
void WriteConfig(std::ostream &os, const std::vector< std::string > &node_names) const
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ NumInputNodes()

int32 NumInputNodes ( const Nnet nnet)

returns the number of input nodes of this nnet.

Definition at line 43 of file nnet-utils.cc.

References Nnet::IsInputNode(), rnnlm::n, and Nnet::NumNodes().

Referenced by IsSimpleNnet().

43  {
44  int32 ans = 0;
45  for (int32 n = 0; n < nnet.NumNodes(); n++)
46  if (nnet.IsInputNode(n))
47  ans++;
48  return ans;
49 }
kaldi::int32 int32
struct rnnlm::@11::@12 n

◆ NumOutputIndexes()

int32 kaldi::nnet3::NumOutputIndexes ( const NnetExample eg)

Definition at line 32 of file nnet3-merge-egs.cc.

References rnnlm::i, and NnetExample::io.

32  {
33  for (size_t i = 0; i < eg.io.size(); i++)
34  if (eg.io[i].name.find("output") != std::string::npos)
35  return eg.io[i].indexes.size();
36  return 1; // Suppress compiler warning.
37 }
std::vector< NnetIo > io
"io" contains the input and output.
Definition: nnet-example.h:116

◆ NumOutputNodes()

int32 NumOutputNodes ( const Nnet nnet)

returns the number of output nodes of this nnet.

Definition at line 35 of file nnet-utils.cc.

References Nnet::IsOutputNode(), rnnlm::n, and Nnet::NumNodes().

35  {
36  int32 ans = 0;
37  for (int32 n = 0; n < nnet.NumNodes(); n++)
38  if (nnet.IsOutputNode(n))
39  ans++;
40  return ans;
41 }
kaldi::int32 int32
struct rnnlm::@11::@12 n

◆ NumParameters()

int32 NumParameters ( const Nnet src)

Returns the total of the number of parameters in the updatable components of the nnet.

Definition at line 359 of file nnet-utils.cc.

References Nnet::GetComponent(), KALDI_ERR, kUpdatableComponent, Nnet::NumComponents(), UpdatableComponent::NumParameters(), and Component::Properties().

Referenced by LstmNonlinearityComponent::ConsolidateMemory(), Nnet::Info(), ConstantComponent::IsComputable(), LinearComponent::LinearComponent(), main(), AffineComponent::Properties(), BlockAffineComponent::Properties(), RepeatedAffineComponent::Properties(), PerElementScaleComponent::Properties(), PerElementOffsetComponent::Properties(), ConstantFunctionComponent::Properties(), CompositeComponent::Type(), LstmNonlinearityComponent::UnVectorize(), UnVectorizeNnet(), UpdateNnetMovingAverage(), LstmNonlinearityComponent::Vectorize(), and VectorizeNnet().

359  {
360  int32 ans = 0;
361  for (int32 c = 0; c < src.NumComponents(); c++) {
362  const Component *comp = src.GetComponent(c);
363  if (comp->Properties() & kUpdatableComponent) {
364  // For now all updatable components inherit from class UpdatableComponent.
365  // If that changes in future, we will change this code.
366  const UpdatableComponent *uc =
367  dynamic_cast<const UpdatableComponent*>(comp);
368  if (uc == NULL)
369  KALDI_ERR << "Updatable component does not inherit from class "
370  "UpdatableComponent; change this code.";
371  ans += uc->NumParameters();
372  }
373  }
374  return ans;
375 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ NumUpdatableComponents()

int32 NumUpdatableComponents ( const Nnet dest)

Returns the number of updatable components in the nnet.

Definition at line 422 of file nnet-utils.cc.

References Nnet::GetComponent(), kUpdatableComponent, Nnet::NumComponents(), and Component::Properties().

Referenced by kaldi::nnet2::CombineNnets(), FastNnetCombiner::CombineNnets(), kaldi::nnet2::CombineNnetsA(), FastNnetCombiner::ComputeCurrentNnet(), kaldi::nnet2::GetUpdateDirection(), main(), PrintVectorPerUpdatableComponent(), and UpdateNnetWithMaxChange().

422  {
423  int32 ans = 0;
424  for (int32 c = 0; c < dest.NumComponents(); c++) {
425  const Component *comp = dest.GetComponent(c);
426  if (comp->Properties() & kUpdatableComponent)
427  ans++;
428  }
429  return ans;
430 }
kaldi::int32 int32

◆ operator<<() [1/3]

std::ostream & operator<< ( std::ostream &  os,
const ComputationGraphBuilder::ComputableInfo info 
)

This is to be used in logging only.

Definition at line 318 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::kComputable, ComputationGraphBuilder::kNotComputable, and ComputationGraphBuilder::kUnknown.

319  {
320  switch (info) {
321  case ComputationGraphBuilder::kUnknown: os << "kUnknown";
322  break;
323  case ComputationGraphBuilder::kComputable: os << "kComputable";
324  break;
325  case ComputationGraphBuilder::kNotComputable: os << "kNotComputable";
326  break;
327  default: os << "[invalid enum value]"; break;
328  }
329  return os;
330 }

◆ operator<<() [2/3]

std::ostream & operator<< ( std::ostream &  ostream,
const Index index 
)

Definition at line 424 of file nnet-common.cc.

References Index::n, Index::t, and Index::x.

Referenced by IndexLessNxt::operator()().

424  {
425  return ostream << '(' << index.n << ' ' << index.t << ' ' << index.x << ')';
426 }

◆ operator<<() [3/3]

std::ostream & operator<< ( std::ostream &  ostream,
const Cindex cindex 
)

Definition at line 428 of file nnet-common.cc.

428  {
429  return ostream << '(' << cindex.first << ' ' << cindex.second << ')';
430 }

◆ Optimize()

void Optimize ( const NnetOptimizeOptions config,
const Nnet nnet,
int32  max_output_time_in_request,
NnetComputation computation 
)

This is the top-level function for optimizing a computation.

Note: it should really be called OptimizeAndPostprocess(), because there is at least one thing it does (reordering I/O commands) that is necessary for a computation to be run.

Parameters
[in]configThe options that control, among other things, which optimizations to apply.
[in]nnetThe neural net for which the computation is being built
[in]max_output_time_in_requestThis value is only needed when the max-deriv-time-relative config value is set in 'config'. It should be set to the largest 't' value encountered in any of the indexes in the 'output' IoSpecifications in the ComputationRequests used to compile the computation. However if there are multiple ComputationRequests (i.e. it was an online computation) you can just set it to any value you want, because backpropagation is not supported so the max-deriv-time-relative configuration value would not have any effect.
[in,out]computationThe computation to be optimized; this function modifies it in-place.

Definition at line 501 of file nnet-optimize.cc.

References NnetOptimizeOptions::allocate_from_other, NnetOptimizeOptions::backprop_in_place, CheckComputation(), NnetOptimizeOptions::consolidate_model_update, ConsolidateIoOperations(), ConsolidateModelUpdate(), NnetOptimizeOptions::convert_addition, ConvertAdditionToAssignment(), NnetOptimizeOptions::extend_matrices, ExtendMatrices(), FixGotoLabel(), GetMaxMemoryUse(), kaldi::GetVerboseLevel(), NnetOptimizeOptions::initialize_undefined, KALDI_LOG, LimitDerivativeTimes(), NnetOptimizeOptions::max_deriv_time, NnetOptimizeOptions::max_deriv_time_relative, NnetOptimizeOptions::memory_compression_level, NnetOptimizeOptions::min_deriv_time, NnetOptimizeOptions::move_sizing_commands, MoveSizingCommands(), NnetOptimizeOptions::optimize, NnetOptimizeOptions::optimize_looped_computation, NnetOptimizeOptions::optimize_row_ops, OptimizeLoopedComputation(), OptimizeMemoryCompression(), NnetOptimizeOptions::propagate_in_place, NnetOptimizeOptions::remove_assignments, RemoveUnnecessaryAllocation(), RemoveUnnecessaryZeroing(), RenumberComputation(), ReplaceRowWithMatrixOps(), NnetOptimizeOptions::snip_row_ops, SnipRowOps(), NnetOptimizeOptions::split_row_ops, SplitRowOps(), and VariableMergingOptimization().

Referenced by CompileLoopedInternal(), CachingOptimizingCompiler::CompileNoShortcut(), ComputationLoopedOptimizer::ComputationLoopedOptimizer(), MemoryCompressionOptimizer::MemoryCompressionOptimizer(), NnetOptimizeOptions::Register(), UnitTestNnetCompute(), and UnitTestNnetInputDerivatives().

504  {
505  if (GetVerboseLevel() >= 3) {
506  CheckComputation(nnet, *computation, true);
507  KALDI_LOG << "Before optimization, max memory use (bytes) = "
508  << GetMaxMemoryUse(*computation);
509  }
510 
511  { // Call LimitDerivativeTimes(); it's important that this
512  // should come before other optimizations (search for "insist" in
513  // nnet-optimize-utils.cc for the reasons).
514  // this will do nothing unless --min-deriv-time or --max-deriv-time
515  // or --max-deriv-time-relative was set.
516  int32 max_deriv_time = config.max_deriv_time;
517  if (config.max_deriv_time_relative != std::numeric_limits<int32>::max())
518  max_deriv_time = config.max_deriv_time_relative +
519  max_output_time_in_request;
520  if (config.min_deriv_time != std::numeric_limits<int32>::min() ||
521  max_deriv_time != std::numeric_limits<int32>::max())
522  LimitDerivativeTimes(nnet, config.min_deriv_time,
523  max_deriv_time, computation);
524  }
525 
526  if (GetVerboseLevel() >= 3)
527  CheckComputation(nnet, *computation, true);
528 
529  if (config.optimize && config.consolidate_model_update) {
530  ConsolidateModelUpdate(nnet, computation);
531 
532  if (GetVerboseLevel() >= 3)
533  CheckComputation(nnet, *computation, true);
534  }
535 
536  if (config.optimize && config.convert_addition) {
537  ConvertAdditionToAssignment(nnet, computation);
538  if (GetVerboseLevel() >= 3)
539  CheckComputation(nnet, *computation, true);
540  }
541 
542 
543  if (config.optimize && (config.snip_row_ops || config.optimize_row_ops ||
544  config.split_row_ops)) {
545  bool must_renumber = false;
546  if (config.snip_row_ops && SnipRowOps(computation))
547  must_renumber = true;
548  if (config.split_row_ops && SplitRowOps(computation))
549  must_renumber = true;
550  if (config.optimize_row_ops && ReplaceRowWithMatrixOps(computation))
551  must_renumber = true;
552 
553  if (must_renumber) {
554  RenumberComputation(computation);
555  if (GetVerboseLevel() >= 3)
556  CheckComputation(nnet, *computation, false);
557  }
558  }
559 
560  if (config.optimize && config.extend_matrices &&
561  !config.optimize_looped_computation) {
562  ExtendMatrices(computation);
563  if (GetVerboseLevel() >= 3)
564  CheckComputation(nnet, *computation, false);
565  }
566 
567 
568  if (config.optimize &&
569  (config.remove_assignments || config.backprop_in_place ||
570  config.propagate_in_place)) {
571  VariableMergingOptimization(config, nnet, computation);
572  if (GetVerboseLevel() >= 3)
573  CheckComputation(nnet, *computation, false);
574  }
575 
576  if (config.optimize && config.initialize_undefined) {
577  RemoveUnnecessaryZeroing(nnet, computation);
578  if (GetVerboseLevel() >= 3)
579  CheckComputation(nnet, *computation, false);
580  }
581 
582 
583  if ((config.optimize && config.move_sizing_commands) ||
584  config.optimize_looped_computation) {
585  MoveSizingCommands(nnet, computation);
586  if (GetVerboseLevel() >= 3)
587  CheckComputation(nnet, *computation, false);
588  }
589 
590  // the looped computation optimization has to go before
591  // 'RemoveUnnecessaryAllocation()'. We don't gate this by 'config.optimize'
592  // because it's necessary for looped computation to run.
593  if (config.optimize_looped_computation) {
594  OptimizeLoopedComputation(nnet, computation);
595  if (GetVerboseLevel() >= 3)
596  CheckComputation(nnet, *computation, false);
597  }
598 
599  if (config.optimize && config.allocate_from_other &&
600  !config.optimize_looped_computation) {
601  // Don't do this if it's an looped computation because we're not sure if it
602  // would be correct in that case, as written. In any case the performance
603  // benefit is tiny.
604  RemoveUnnecessaryAllocation(nnet, computation);
605  if (GetVerboseLevel() >= 3)
606  CheckComputation(nnet, *computation, false);
607  }
608 
609  // The following is not configurable because it is necessary for
610  // the computation to run correctly (we do it after compilation too,
611  // but the operations may have been put out of order by
612  // other optimizations.)
613  ConsolidateIoOperations(nnet, computation);
614 
615  if (config.optimize_looped_computation)
616  FixGotoLabel(computation);
617 
618 
619  if (config.memory_compression_level > 0 &&
620  !config.optimize_looped_computation) {
621  OptimizeMemoryCompression(nnet, config.memory_compression_level,
622  computation);
623  if (GetVerboseLevel() >= 3)
624  CheckComputation(nnet, *computation, false);
625  }
626 
627  if (GetVerboseLevel() >= 3) {
628  CheckComputation(nnet, *computation, false);
629  KALDI_LOG << "After optimization, max memory use (bytes) = "
630  << GetMaxMemoryUse(*computation);
631  }
632 }
bool SplitRowOps(NnetComputation *computation)
This function detects cases where commands of type kAddRowsMulti, kAddToRowsMulti, kCopyRowsMulti, kCopyToRowsMulti use indexes that correspond to at most two submatrices, in two distinct ranges without gaps filled by -1&#39;s, and could be converted to at most two commands of type kMatrixAdd, kMatrixCopy, kAddRows or kCopyRows.
void OptimizeLoopedComputation(const Nnet &nnet, NnetComputation *computation)
This function tries to optimize computation &#39;computation&#39; for an &#39;looped&#39; computation.
void ConsolidateIoOperations(const Nnet &nnet, NnetComputation *computation)
This optimization puts the input operations (kAcceptInput) and output operations (kProvideOutput) at ...
void RenumberComputation(NnetComputation *computation)
This function detects submatrices and matrices that are never used (e.g.
int32 GetVerboseLevel()
Get verbosity level, usually set via command line &#39;–verbose=&#39; switch.
Definition: kaldi-error.h:60
void VariableMergingOptimization(const NnetOptimizeOptions &config, const Nnet &nnet, NnetComputation *computation)
This wraps class VariableMergingOptimizer in a simplified interface.
void ConvertAdditionToAssignment(const Nnet &nnet, NnetComputation *computation)
This converts addition operations (things with Add in their names) to copy operations (things with Co...
kaldi::int32 int32
void ExtendMatrices(NnetComputation *computation)
This is not really an optimization in itself but it can make things easier for class VariableMergingO...
void LimitDerivativeTimes(const Nnet &nnet, int32 min_deriv_time, int32 max_deriv_time, NnetComputation *computation)
void OptimizeMemoryCompression(const Nnet &nnet, int32 memory_compression_level, NnetComputation *computation)
Performs optimization to reduce memory usage where possible, making use of the kCompressMatrix and kD...
void MoveSizingCommands(const Nnet &nnet, NnetComputation *computation)
This optimization moves commands that allocate and zero matrices to as late as possible, and moves commands that deallocate matrices to as early as possible.
int64 GetMaxMemoryUse(const NnetComputation &computation)
void RemoveUnnecessaryAllocation(const Nnet &nnet, NnetComputation *computation)
This optimization detects cases where we deallocate a matrix, and then later allocate another matrix ...
void RemoveUnnecessaryZeroing(const Nnet &nnet, NnetComputation *computation)
This optimization function removes, where possible, commands of type type kSetConst.
bool ReplaceRowWithMatrixOps(NnetComputation *computation)
This function detects cases where commands of type kCopyRows, kAddRows or kAddToRows can be converted...
void FixGotoLabel(NnetComputation *computation)
This function ensures that the arg1 of a final command of type kGotoLabel is the same as the command ...
void ConsolidateModelUpdate(const Nnet &nnet, NnetComputation *computation)
This optimization consolidates the model-update part of backprop commands, for components in (e...
void CheckComputation(const Nnet &nnet, const NnetComputation &computation, bool check_rewrite)
This is a convenience interface for class ComputationChecker.
bool SnipRowOps(NnetComputation *computation)
This function detects cases where commands of type kCopyRows, kAddRows, kAddRowsMulti, kAddToRowsMulti, kCopyRowsMulti, kCopyToRowsMulti or kAddRowRanges use indexes that start or end with -1&#39;s or equivalents, and replace them with similar commands that act on a sub-matrix of the matrices they are currently acting on.
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ OptimizeLoopedComputation()

void OptimizeLoopedComputation ( const Nnet nnet,
NnetComputation computation 
)

This function tries to optimize computation 'computation' for an 'looped' computation.

It expects as input a computation with no backprop but with multiple 'segments' separated by command kNoOperationLabel, where each segment corresponds to a new chunk of input and output. It tries to locate a pair of segment boundaries, with command indexes c1 and c2, where the active matrices have the same debug-info other than a time offset and can be identified with each other, and the no-op command at c2 can be replaced with 'got c1', creating a computation that 'goes on forever'. If it can't do this, it does nothing. You can figure out that this is the case by checking whether kGotoLabel is the last command in the computation. [If this optimization fails, the whole computation may have to be regenerated with more segments.]

Definition at line 4544 of file nnet-optimize-utils.cc.

References ComputationLoopedOptimizer::Optimize().

Referenced by Optimize().

4545  {
4546  ComputationLoopedOptimizer optimizer(nnet, computation);
4547  optimizer.Optimize();
4548 }

◆ OptimizeMemoryCompression()

void OptimizeMemoryCompression ( const Nnet nnet,
int32  memory_compression_level,
NnetComputation computation 
)

Performs optimization to reduce memory usage where possible, making use of the kCompressMatrix and kDecompressMatrix commands.

Should only be done after most other optimizations, because some optimizations (such as variable-merging) would not work correctly after doing this optimization. This does nothing for looped computations. It's OK, though, to expand a shortcut computation (i.e. call ExpandComputation) after doing this.

memory_compression_level determines how aggressive the compression is. Allowed values: 0 = no compression at all 1 = compression that doesn't affect results (e.g. compress ReLU outputs to 1 byte, as just the sign is needed). 2 = compression that may affect the results slightly (e.g. 16-bit compression of the output of NormalizeComponent and the like), but this is not implemented yet, so equivalent to 1. 3 = compression that may affect the results more than just slightly. Not implemented yet, so equivalent to 1.

Definition at line 4899 of file nnet-optimize-utils.cc.

References NnetComputation::commands, GetMaxMemoryUse(), kaldi::GetVerboseLevel(), rnnlm::i, KALDI_VLOG, KALDI_WARN, kGotoLabel, kNoOperationMarker, and MemoryCompressionOptimizer::Optimize().

Referenced by Optimize().

4901  {
4902  if (memory_compression_level == 0 || computation->commands.empty())
4903  return;
4904  // don't apply this optimization to looped computations.
4905  if (computation->commands.back().command_type == kGotoLabel)
4906  return;
4907 
4908  // 'middle_command' will be the index of the command of type
4909  // 'kNoOperationMarker' that separates the forward and backward
4910  // passes. If it doesn't exist, it means this computation doesn't
4911  // include
4912  int32 middle_command = -1;
4913  for (size_t i = 0; i < computation->commands.size(); i++) {
4914  if (computation->commands[i].command_type == kNoOperationMarker) {
4915  if (middle_command < 0) {
4916  middle_command = static_cast<int32>(i);
4917  } else {
4918  KALDI_WARN << "Found more than one command of type kNoOperationMarker "
4919  "in non-looped computation.";
4920  // there are more than one command of this type... this wasn't expected.
4921  // return (i.e. do nothing).
4922  return;
4923  }
4924  }
4925  }
4926  if (middle_command == -1) {
4927  return; // This computation doesn't have a backprop pass.
4928  }
4929  if (memory_compression_level >= 1) {
4930  int64 bytes_used_initial, bytes_used_final;
4931  bool verbose_ge_2 = GetVerboseLevel() >= 2;
4932  if (verbose_ge_2)
4933  bytes_used_initial = GetMaxMemoryUse(*computation);
4934 
4935  MemoryCompressionOptimizer opt(nnet, memory_compression_level,
4936  middle_command, computation);
4937  opt.Optimize();
4938 
4939  if (verbose_ge_2) {
4940  bytes_used_final = GetMaxMemoryUse(*computation);
4941  if (bytes_used_final != bytes_used_initial) {
4942  KALDI_VLOG(2) << "Memory compression reduced memory use from "
4943  << bytes_used_initial << " to "
4944  << bytes_used_final << " bytes.";
4945  }
4946  }
4947  }
4948 }
int32 GetVerboseLevel()
Get verbosity level, usually set via command line &#39;–verbose=&#39; switch.
Definition: kaldi-error.h:60
kaldi::int32 int32
int64 GetMaxMemoryUse(const NnetComputation &computation)
#define KALDI_WARN
Definition: kaldi-error.h:150
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156

◆ ParseConfigLines()

void kaldi::nnet3::ParseConfigLines ( const std::vector< std::string > &  lines,
std::vector< ConfigLine > *  config_lines 
)

Definition at line 224 of file nnet-parse.cc.

References rnnlm::i, and KALDI_ERR.

Referenced by Nnet::ReadConfig(), and ReadEditConfig().

225  {
226  config_lines->resize(lines.size());
227  for (size_t i = 0; i < lines.size(); i++) {
228  bool ret = (*config_lines)[i].ParseLine(lines[i]);
229  if (!ret) {
230  KALDI_ERR << "Error parsing config line: " << lines[i];
231  }
232  }
233 }
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ ParsingContext()

static std::string kaldi::nnet3::ParsingContext ( const std::string *  token_ptr)
static

Definition at line 29 of file nnet-descriptor.cc.

Referenced by ExpectToken(), and ReadIntegerToken().

29  {
30  if (*token_ptr == "end of input")
31  return "";
32  std::string next_few_tokens = ", next part of line is: ";
33  // in the next line, *token_ptr should never equal "" but it's to mitigate the
34  // effect of bugs where we read past the end of the array.
35  while (*token_ptr != "end of input" && *token_ptr != "" &&
36  next_few_tokens.size() < 40) {
37  next_few_tokens = (next_few_tokens + " ") + *token_ptr;
38  token_ptr++;
39  }
40  if (*token_ptr != "end of input")
41  next_few_tokens = next_few_tokens + " ...";
42  return next_few_tokens;
43 }

◆ PerturbImage()

void kaldi::nnet3::PerturbImage ( const ImageAugmentationConfig config,
MatrixBase< BaseFloat > *  image 
)

This function randomly modifies (perturbs) the image by applying different geometric transformations according to the options in 'config'.

References: "Digital Image Processing book by Gonzalez and Woods" and "Keras: github.com/fchollet/keras/blob/master/keras/preprocessing/image.py"

Parameters
[in]configConfiguration class that says how to perturb the image.
[in,out]imageThe image matrix to be modified. image->NumRows() is the width (number of x values) in the image; image->NumCols() is the height times number of channels/colors (channel varies the fastest).

Definition at line 205 of file nnet3-egs-augment-image.cc.

References MatrixBase< Real >::AddMatMat(), MatrixBase< Real >::AddMatMatMat(), ApplyAffineTransform(), ImageAugmentationConfig::Check(), ImageAugmentationConfig::GetFillMode(), ImageAugmentationConfig::horizontal_flip_prob, ImageAugmentationConfig::horizontal_shift, MatrixBase< Real >::IsUnit(), KALDI_ERR, kaldi::kNoTrans, kaldi::kUndefined, M_PI, ImageAugmentationConfig::num_channels, MatrixBase< Real >::NumCols(), MatrixBase< Real >::NumRows(), kaldi::RandUniform(), ImageAugmentationConfig::rotation_degree, ImageAugmentationConfig::rotation_prob, MatrixBase< Real >::SetUnit(), ImageAugmentationConfig::vertical_shift, and kaldi::WithProb().

Referenced by PerturbImageInNnetExample().

206  {
207  config.Check();
208  FillMode fill_mode = config.GetFillMode();
209  int32 image_width = image->NumRows(),
210  num_channels = config.num_channels,
211  image_height = image->NumCols() / num_channels;
212  if (image->NumCols() % num_channels != 0) {
213  KALDI_ERR << "Number of columns in image must divide the number "
214  "of channels";
215  }
216  // We do an affine transform which
217  // handles flipping, translation, rotation, magnification, and shear.
218  Matrix<BaseFloat> transform_mat(3, 3, kUndefined);
219  transform_mat.SetUnit();
220 
221  Matrix<BaseFloat> shift_mat(3, 3, kUndefined);
222  shift_mat.SetUnit();
223  // translation (shift) mat:
224  // [ 1 0 x_shift
225  // 0 1 y_shift
226  // 0 0 1 ]
227  BaseFloat horizontal_shift = (2.0 * RandUniform() - 1.0) *
228  config.horizontal_shift * image_width;
229  BaseFloat vertical_shift = (2.0 * RandUniform() - 1.0) *
230  config.vertical_shift * image_height;
231  shift_mat(0, 2) = round(horizontal_shift);
232  shift_mat(1, 2) = round(vertical_shift);
233  // since we will center the image before applying the transform,
234  // horizontal flipping is simply achieved by setting [0, 0] to -1:
235  if (WithProb(config.horizontal_flip_prob))
236  shift_mat(0, 0) = -1.0;
237 
238  Matrix<BaseFloat> rotation_mat(3, 3, kUndefined);
239  rotation_mat.SetUnit();
240  // rotation mat:
241  // [ cos(theta) -sin(theta) 0
242  // sin(theta) cos(theta) 0
243  // 0 0 1 ]
244  if (RandUniform() <= config.rotation_prob) {
245  BaseFloat theta = (2 * config.rotation_degree * RandUniform() -
246  config.rotation_degree) / 180.0 * M_PI;
247  rotation_mat(0, 0) = cos(theta);
248  rotation_mat(0, 1) = -sin(theta);
249  rotation_mat(1, 0) = sin(theta);
250  rotation_mat(1, 1) = cos(theta);
251  }
252 
253  Matrix<BaseFloat> shear_mat(3, 3, kUndefined);
254  shear_mat.SetUnit();
255  // shear mat:
256  // [ 1 -sin(shear) 0
257  // 0 cos(shear) 0
258  // 0 0 1 ]
259 
260  Matrix<BaseFloat> zoom_mat(3, 3, kUndefined);
261  zoom_mat.SetUnit();
262  // zoom mat:
263  // [ x_zoom 0 0
264  // 0 y_zoom 0
265  // 0 0 1 ]
266 
267  // transform_mat = rotation_mat * shift_mat * shear_mat * zoom_mat:
268  transform_mat.AddMatMat(1.0, shift_mat, kNoTrans,
269  shear_mat, kNoTrans, 0.0);
270  transform_mat.AddMatMatMat(1.0, rotation_mat, kNoTrans,
271  transform_mat, kNoTrans,
272  zoom_mat, kNoTrans, 0.0);
273  if (transform_mat.IsUnit()) // nothing to do
274  return;
275 
276  // we should now change the origin of transform to the center of
277  // the image (necessary for flipping, zoom, shear, and rotation)
278  // we do this by using two translations: one before the main transform
279  // and one after.
280  Matrix<BaseFloat> set_origin_mat(3, 3, kUndefined);
281  set_origin_mat.SetUnit();
282  set_origin_mat(0, 2) = image_width / 2.0 - 0.5;
283  set_origin_mat(1, 2) = image_height / 2.0 - 0.5;
284  Matrix<BaseFloat> reset_origin_mat(3, 3, kUndefined);
285  reset_origin_mat.SetUnit();
286  reset_origin_mat(0, 2) = -image_width / 2.0 + 0.5;
287  reset_origin_mat(1, 2) = -image_height / 2.0 + 0.5;
288 
289  // transform_mat = set_origin_mat * transform_mat * reset_origin_mat
290  transform_mat.AddMatMatMat(1.0, set_origin_mat, kNoTrans,
291  transform_mat, kNoTrans,
292  reset_origin_mat, kNoTrans, 0.0);
293  ApplyAffineTransform(transform_mat, config.num_channels, image, fill_mode);
294 }
float RandUniform(struct RandomState *state=NULL)
Returns a random number strictly between 0 and 1.
Definition: kaldi-math.h:151
#define M_PI
Definition: kaldi-math.h:44
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Definition: kaldi-matrix.h:67
bool WithProb(BaseFloat prob, struct RandomState *state)
Definition: kaldi-math.cc:72
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_ERR
Definition: kaldi-error.h:147
void ApplyAffineTransform(MatrixBase< BaseFloat > &transform, int32 num_channels, MatrixBase< BaseFloat > *image, FillMode fill_mode)
This function applies a geometric transformation &#39;transform&#39; to the image.
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
Definition: kaldi-matrix.h:64

◆ PerturbImageInNnetExample()

void kaldi::nnet3::PerturbImageInNnetExample ( const ImageAugmentationConfig config,
NnetExample eg 
)

This function does image perturbation as directed by 'config' The example 'eg' is expected to contain a NnetIo member with the name 'input', representing an image.

Definition at line 302 of file nnet3-egs-augment-image.cc.

References NnetIo::features, GeneralMatrix::GetMatrix(), rnnlm::i, NnetExample::io, KALDI_ERR, NnetIo::name, and PerturbImage().

Referenced by main().

304  {
305  int32 io_size = eg->io.size();
306  bool found_input = false;
307  for (int32 i = 0; i < io_size; i++) {
308  NnetIo &io = eg->io[i];
309  if (io.name == "input") {
310  found_input = true;
311  Matrix<BaseFloat> image;
312  io.features.GetMatrix(&image);
313  // note: 'GetMatrix' may uncompress if it was compressed.
314  // We won't recompress, but this won't matter because this
315  // program is intended to be used as part of a pipe, we
316  // likely won't be dumping the perturbed data to disk.
317  PerturbImage(config, &image);
318 
319  // modify the 'io' object.
320  io.features = image;
321  }
322  }
323  if (!found_input)
324  KALDI_ERR << "Nnet example to perturb had no NnetIo object named 'input'";
325 }
void GetMatrix(Matrix< BaseFloat > *mat) const
Outputs the contents as a matrix.
kaldi::int32 int32
GeneralMatrix features
The features or labels.
Definition: nnet-example.h:46
#define KALDI_ERR
Definition: kaldi-error.h:147
void PerturbImage(const ImageAugmentationConfig &config, MatrixBase< BaseFloat > *image)
This function randomly modifies (perturbs) the image by applying different geometric transformations ...
std::string name
the name of the input in the neural net; in simple setups it will just be "input".
Definition: nnet-example.h:36
std::vector< NnetIo > io
"io" contains the input and output.
Definition: nnet-example.h:116

◆ PerturbParams()

void PerturbParams ( BaseFloat  stddev,
Nnet nnet 
)

◆ PrintCindex()

void PrintCindex ( std::ostream &  os,
const Cindex cindex,
const std::vector< std::string > &  node_names 
)

Definition at line 432 of file nnet-common.cc.

References KALDI_ASSERT.

Referenced by ComputationGraph::Print().

433  {
434  KALDI_ASSERT(static_cast<size_t>(cindex.first) < node_names.size());
435  os << node_names[cindex.first] << "(" << cindex.second.n << ","
436  << cindex.second.t;
437  if (cindex.second.x != 0)
438  os << "," << cindex.second.x;
439  os << ")";
440 }
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ PrintCindexes()

void PrintCindexes ( std::ostream &  ostream,
const std::vector< Cindex > &  cindexes,
const std::vector< std::string > &  node_names 
)

this will only be used for pretty-printing.

It prints a vector of Cindexes in a compact, human-readable way with compression of ranges. If the values of the node indexes are the same for the entire vector, it will just be node-name followed by the output of PrintIndexes, e.g. some_node[ (1,1,0) ]. Otherwise it will divide the vector into ranges that each have all the same node name, and will print out each range in the way we just mentioned. 'node_names' will usually come from a call like nnet.GetNodeNames().

Definition at line 498 of file nnet-common.cc.

References KALDI_ASSERT, and PrintIndexes().

Referenced by PrintComputationPreamble().

500  {
501  int32 num_cindexes = cindexes.size();
502  if (num_cindexes == 0) {
503  ostream << "[ ]";
504  return;
505  }
506  int32 cur_offset = 0;
507  std::vector<Index> indexes;
508  indexes.reserve(cindexes.size());
509  while (cur_offset < num_cindexes) {
510  int32 cur_node_index = cindexes[cur_offset].first;
511  while (cur_offset < num_cindexes &&
512  cindexes[cur_offset].first == cur_node_index) {
513  indexes.push_back(cindexes[cur_offset].second);
514  cur_offset++;
515  }
516  KALDI_ASSERT(static_cast<size_t>(cur_node_index) < node_names.size());
517  const std::string &node_name = node_names[cur_node_index];
518  ostream << node_name;
519  PrintIndexes(ostream, indexes);
520  indexes.clear();
521  }
522 }
void PrintIndexes(std::ostream &os, const std::vector< Index > &indexes)
this will only be used for pretty-printing.
Definition: nnet-common.cc:442
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ PrintCommand() [1/2]

std::string kaldi::nnet3::PrintCommand ( int32  num_commands,
int32  command 
)

Definition at line 28 of file nnet-analyze-test.cc.

Referenced by NnetComputation::GetCommandStrings(), NnetComputation::Print(), and UnitTestNnetAnalyze().

29  {
30  std::ostringstream os;
31  if (command < 0 || command >= num_commands)
32  os << command;
33  else
34  os << 'c' << command;
35  return os.str();
36 }

◆ PrintCommand() [2/2]

static void kaldi::nnet3::PrintCommand ( std::ostream &  os_out,
const Nnet nnet,
const NnetComputation computation,
int32  command_index,
const std::vector< std::string > &  submatrix_strings,
const std::vector< std::string > &  indexes_strings,
const std::vector< std::string > &  indexes_multi_strings 
)
static

Definition at line 513 of file nnet-computation.cc.

References NnetComputation::Command::alpha, NnetComputation::Command::arg1, NnetComputation::Command::arg2, NnetComputation::Command::arg3, NnetComputation::Command::arg4, NnetComputation::Command::arg5, NnetComputation::Command::arg6, NnetComputation::Command::command_type, NnetComputation::commands, Nnet::GetComponentName(), Nnet::GetNodeName(), rnnlm::i, NnetComputation::indexes_ranges, kAcceptInput, kAddRowRanges, kAddRows, kAddRowsMulti, kAddToRowsMulti, KALDI_ASSERT, KALDI_ERR, kAllocMatrix, kBackprop, kBackpropNoModelUpdate, kaldi::kCompressedMatrixInt16, kaldi::kCompressedMatrixInt8, kaldi::kCompressedMatrixUint8, kCompressMatrix, kCopyRows, kCopyRowsMulti, kCopyToRowsMulti, kDeallocMatrix, kDecompressMatrix, kGotoLabel, kMatrixAdd, kMatrixCopy, kNoOperation, kNoOperationLabel, kNoOperationMarker, kNoOperationPermanent, kPropagate, kProvideOutput, kSetConst, kSwapMatrix, NnetComputation::need_model_derivative, and NnetComputation::submatrices.

519  {
520  // If the string is longer than 'max_string_length' characters, it will
521  // be summarized with '...' in the middle.
522  size_t max_string_length = 200;
523  std::ostringstream os;
524  KALDI_ASSERT(command_index < computation.commands.size());
525  os << "c" << command_index << ": ";
526  const NnetComputation::Command &c = computation.commands[command_index];
527  switch (c.command_type) {
528  case kAllocMatrix:
529  os << submatrix_strings[c.arg1] << " = undefined("
530  << computation.submatrices[c.arg1].num_rows
531  << ',' << computation.submatrices[c.arg1].num_cols << ")\n";
532  break;
533  case kDeallocMatrix:
534  os << submatrix_strings[c.arg1] << " = []\n";
535  break;
536  case kSwapMatrix:
537  os << submatrix_strings[c.arg1] << ".swap("
538  << submatrix_strings[c.arg2] << ") [dim = "
539  << computation.submatrices[c.arg1].num_rows << " x "
540  << computation.submatrices[c.arg1].num_cols << "]\n";
541  break;
542  case kSetConst:
543  os << submatrix_strings[c.arg1] << ".set(" << c.alpha << ") [dim = "
544  << computation.submatrices[c.arg1].num_rows << " x "
545  << computation.submatrices[c.arg1].num_cols << "];\n";
546  break;
547  case kPropagate:
548  os << nnet.GetComponentName(c.arg1) << ".Propagate(";
549  if (c.arg2 == 0) os << "NULL, ";
550  else os << "precomputed_indexes[" << c.arg2 << "], ";
551  os << submatrix_strings[c.arg3] << ", &" << submatrix_strings[c.arg4]
552  << ")\n";
553  break;
554  case kBackprop:
555  case kBackpropNoModelUpdate: {
556  int32 component_index = c.arg1;
557  os << nnet.GetComponentName(component_index) << ".Backprop(";
558  if (c.arg2 == 0) os << "NULL, ";
559  else os << "precomputed_indexes[" << c.arg2 << "], ";
560  os << submatrix_strings[c.arg3] << ", "
561  << submatrix_strings[c.arg4] << ", "
562  << submatrix_strings[c.arg5] << ", "
563  << (computation.need_model_derivative &&
564  c.command_type == kBackprop ?
565  "[component-pointer], " : "NULL, ")
566  << (c.arg6 == 0 ? std::string("NULL") :
567  std::string("&") + submatrix_strings[c.arg6]) << ")\n";
568  break;
569  }
570  case kMatrixCopy:
571  if (c.alpha == 1.0) {
572  os << submatrix_strings[c.arg1] << " = "
573  << submatrix_strings[c.arg2] << "\n";
574  } else {
575  os << submatrix_strings[c.arg1] << " = "
576  << c.alpha << " * "
577  << submatrix_strings[c.arg2] << "\n";
578  }
579  break;
580  case kMatrixAdd:
581  if (c.alpha == 1.0) {
582  os << submatrix_strings[c.arg1] << " += "
583  << submatrix_strings[c.arg2] << "\n";
584  } else {
585  os << submatrix_strings[c.arg1] << " += "
586  << c.alpha << " * "
587  << submatrix_strings[c.arg2] << "\n";
588  }
589  break;
590  case kAddRows:
591  case kCopyRows:
592  os << submatrix_strings[c.arg1] << "."
593  << (c.command_type == kAddRows ? "AddRows" :
594  "CopyRows") << "(" << c.alpha << ", "
595  << submatrix_strings[c.arg2] << indexes_strings[c.arg3] << ")\n";
596  break;
597  case kAddRowsMulti:
598  case kAddToRowsMulti:
599  case kCopyRowsMulti:
600  case kCopyToRowsMulti: {
601  CommandType ct = c.command_type;
602  os << submatrix_strings[c.arg1] << "."
603  << (ct == kAddRowsMulti ? "AddRowsMulti" :
604  (ct == kAddToRowsMulti? "AddToRowsMulti" :
605  (ct == kCopyRowsMulti ? "CopyRowsMulti" :
606  "CopyToRowsMulti"))) << "("
607  << c.alpha << ", "
608  << indexes_multi_strings[c.arg2] << ")\n";
609  break;
610  }
611  case kAddRowRanges: {
612  os << submatrix_strings[c.arg1] << ".AddRowRanges("
613  << c.alpha << ", "
614  << submatrix_strings[c.arg2] << ", [";
615  const std::vector<std::pair<int32, int32> > &pairs =
616  computation.indexes_ranges[c.arg3];
617  for (size_t i = 0; i < pairs.size(); i++) {
618  if (pairs[i].first == -1) {
619  os << "null";
620  } else {
621  os << pairs[i].first << ":" << (pairs[i].second - 1);
622  }
623  if (i + 1 < pairs.size()) os << ",";
624  }
625  os << "])\n";
626  break;
627  }
628  case kCompressMatrix: {
629  BaseFloat range = c.alpha;
630  std::string truncate = (c.arg3 != 0 ? "true" : "false");
631  std::string compressed_matrix_type;
632  if (c.arg2 == kCompressedMatrixInt8) { compressed_matrix_type = "int8"; }
633  else if (c.arg2 == kCompressedMatrixUint8) { compressed_matrix_type = "uint8"; }
634  else if (c.arg2 == kCompressedMatrixInt16) { compressed_matrix_type = "int16"; }
635  else {
637  compressed_matrix_type = "uint16";
638  }
639  os << "CompressMatrix(" << submatrix_strings[c.arg1] << ", "
640  << range << ", " << compressed_matrix_type << ", "
641  << truncate << ")\n";
642  break;
643  }
644  case kDecompressMatrix:
645  os << "DecompressMatrix(" << submatrix_strings[c.arg1] << ")\n";
646  break;
647  case kAcceptInput:
648  os << submatrix_strings[c.arg1] << " = user input [for node: '"
649  << nnet.GetNodeName(c.arg2) << "']\n";
650  break;
651  case kProvideOutput:
652  os << "output " << submatrix_strings[c.arg1] << " to user"
653  << " [for node: '" << nnet.GetNodeName(c.arg2) << "']\n";
654  break;
655  case kNoOperation:
656  os << "[no-op]\n";
657  break;
659  os << "[no-op-permanent]\n";
660  break;
661  case kNoOperationMarker:
662  os << "# computation segment separator [e.g., begin backward commands]\n";
663  break;
664  case kNoOperationLabel:
665  os << "[label for goto statement]\n";
666  break;
667  case kGotoLabel:
668  os << "goto c" << c.arg1 << "\n";
669  break;
670  default:
671  KALDI_ERR << "Un-handled command type.";
672  }
673  std::string str = os.str();
674  if (str.size() <= max_string_length) {
675  os_out << str;
676  } else {
677  size_t len = str.size();
678  os_out << str.substr(0, max_string_length / 2) << " ... "
679  << str.substr(len - max_string_length / 2);
680  }
681 }
CommandType
CommandType is an enum that describes the category of the command used in the NnetComputation.
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ PrintCommandAttributes()

void PrintCommandAttributes ( std::ostream &  os,
const std::vector< CommandAttributes > &  attributes 
)

This function is to be used in debugging; it produces human-readable output.

Definition at line 1368 of file nnet-analyze.cc.

References CommandAttributes::matrices_read, CommandAttributes::matrices_written, CommandAttributes::variables_read, and CommandAttributes::variables_written.

Referenced by CommandAttributes::CommandAttributes().

1369  {
1370  int32 num_commands = attributes.size();
1371  for (int32 c = 0; c < num_commands; c++) {
1372  const CommandAttributes &this_attr = attributes[c];
1373  os << "c" << c << ": ";
1374  if (!this_attr.variables_read.empty()) {
1375  os << "r(";
1376  std::vector<int32>::const_iterator iter = this_attr.variables_read.begin(),
1377  end = this_attr.variables_read.end();
1378  for (; iter != end; ++iter) {
1379  os << "v" << *iter;
1380  if (iter+1 != end) os << ",";
1381  }
1382  os << ") ";
1383  }
1384  if (!this_attr.variables_written.empty()) {
1385  os << "w(";
1386  std::vector<int32>::const_iterator
1387  iter = this_attr.variables_written.begin(),
1388  end = this_attr.variables_written.end();
1389  for (; iter != end; ++iter) {
1390  os << "v" << *iter;
1391  if (iter+1 != end) os << ",";
1392  }
1393  os << ") ";
1394  }
1395  if (!this_attr.matrices_read.empty()) {
1396  os << "r(";
1397  std::vector<int32>::const_iterator iter = this_attr.matrices_read.begin(),
1398  end = this_attr.matrices_read.end();
1399  for (; iter != end; ++iter) {
1400  os << "m" << *iter;
1401  if (iter+1 != end) os << ",";
1402  }
1403  os << ") ";
1404  }
1405  if (!this_attr.matrices_written.empty()) {
1406  os << "w(";
1407  std::vector<int32>::const_iterator
1408  iter = this_attr.matrices_written.begin(),
1409  end = this_attr.matrices_written.end();
1410  for (; iter != end; ++iter) {
1411  os << "m" << *iter;
1412  if (iter+1 != end) os << ",";
1413  }
1414  os << ")";
1415  }
1416  os << "\n";
1417  }
1418 }
kaldi::int32 int32

◆ PrintComputationPreamble()

static void kaldi::nnet3::PrintComputationPreamble ( std::ostream &  os,
const NnetComputation c,
const Nnet nnet,
const std::vector< std::string > &  submatrix_strings,
const std::vector< std::string > &  indexes_strings,
const std::vector< std::string > &  indexes_multi_strings 
)
static

Definition at line 684 of file nnet-computation.cc.

References NnetComputation::MatrixDebugInfo::cindexes, Nnet::GetNodeNames(), rnnlm::i, NnetComputation::MatrixDebugInfo::is_deriv, KALDI_ASSERT, NnetComputation::matrices, NnetComputation::matrix_debug_info, and PrintCindexes().

Referenced by NnetComputation::GetCommandStrings(), and NnetComputation::Print().

690  {
691 
692  // First print info about the matrices.
693  os << "matrix ";
694  for (int32 i = 1; i < c.matrices.size(); i++) {
695  os << "m" << i << "(" << c.matrices[i].num_rows
696  << ", " << c.matrices[i].num_cols << ")";
697  if (i + 1 < c.matrices.size())
698  os << ", ";
699  }
700  os << "\n";
701  if (!c.matrix_debug_info.empty()) {
702  os << "# The following show how matrices correspond to network-nodes and\n"
703  << "# cindex-ids. Format is: matrix = <node-id>.[value|deriv][ <list-of-cindex-ids> ]\n"
704  << "# where a cindex-id is written as (n,t[,x]) but ranges of t values are compressed\n"
705  << "# so we write (n, tfirst:tlast).\n";
706  KALDI_ASSERT(c.matrix_debug_info.size() == c.matrices.size());
707  for (int32 i = 1; i < c.matrices.size(); i++) {
708  const NnetComputation::MatrixDebugInfo &debug_info =
709  c.matrix_debug_info[i];
710  os << "m" << i << " == " << (debug_info.is_deriv ? "deriv: " : "value: ");
711  PrintCindexes(os, debug_info.cindexes, nnet.GetNodeNames());
712  os << "\n";
713  }
714  }
715 }
kaldi::int32 int32
void PrintCindexes(std::ostream &ostream, const std::vector< Cindex > &cindexes, const std::vector< std::string > &node_names)
this will only be used for pretty-printing.
Definition: nnet-common.cc:498
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ PrintFloatSuccinctly()

static void kaldi::nnet3::PrintFloatSuccinctly ( std::ostream &  os,
BaseFloat  f 
)
static

Definition at line 94 of file nnet-parse.cc.

Referenced by SummarizeVector().

94  {
95  if (fabs(f) < 10000.0 && fabs(f) >= 10.0) {
96  os << std::fixed << std::setprecision(0) << f;
97  } else if (fabs(f) >= 0.995) {
98  os << std::fixed << std::setprecision(1) << f;
99  } else if (fabs(f) >= 0.01) {
100  os << std::fixed << std::setprecision(2) << f;
101  } else {
102  os << std::setprecision(1) << f;
103  }
104  os.unsetf(std::ios_base::floatfield);
105  os << std::setprecision(6); // Restore the default.
106 }

◆ PrintGraphToString()

std::string PrintGraphToString ( const std::vector< std::vector< int32 > > &  graph)

Prints a graph to a string in a pretty way for human readability, e.g.

as 0 -> 1,2; 1 -> 2; 2 -> 3,4,5; etc.

Definition at line 248 of file nnet-graph.cc.

References rnnlm::i, and rnnlm::j.

Referenced by ComputeNnetComputationEpochs().

248  {
249  std::ostringstream os;
250  int32 num_nodes = graph.size();
251  for (int32 i = 0; i < num_nodes; i++) {
252  os << i << " -> (";
253  const std::vector<int32> &vec = graph[i];
254  int32 size = vec.size();
255  for (int32 j = 0; j < size; j++) {
256  os << vec[j];
257  if (j + 1 < size) os << ",";
258  }
259  os << ")";
260  if (i + 1 < num_nodes) os << "; ";
261  }
262  return os.str();
263 }
kaldi::int32 int32

◆ PrintIndexes()

void PrintIndexes ( std::ostream &  ostream,
const std::vector< Index > &  indexes 
)

this will only be used for pretty-printing.

It prints a vector of Indexes in a compact, human-readable way with compression of ranges (it also doesn't print the x index if it's 1.0. Example output: "[ (1,1:20), (2, 1:20) ]" which would correspond to the indexes [ (1,1,0), (1,2,0) ... (1,20,0) (2,1,0) ... (2,20,0) ].

Definition at line 442 of file nnet-common.cc.

References rnnlm::i, KALDI_ASSERT, Index::n, Index::t, and Index::x.

Referenced by IoSpecification::Print(), and PrintCindexes().

443  {
444  if (indexes.empty()) {
445  os << "[ ]";
446  return;
447  }
448  // If the string is longer than 'max_string_length' characters, it will
449  // be summarized with '...' in the middle.
450  size_t max_string_length = 200;
451  std::ostringstream os_temp;
452 
453  // range_starts will be the starts of ranges (with consecutive t values and
454  // the same n value and zero x values) that we compactly print. we'll append
455  // "end" to range_starts for convenience.n
456  std::vector<int32> range_starts;
457  int32 cur_start = 0, end = indexes.size();
458  for (int32 i = cur_start; i < end; i++) {
459  const Index &index = indexes[i];
460  if (i > cur_start &&
461  (index.t != indexes[i-1].t + 1 ||
462  index.n != indexes[i-1].n ||
463  index.x != indexes[i-1].x)) {
464  range_starts.push_back(cur_start);
465  cur_start = i;
466  }
467  }
468  range_starts.push_back(cur_start);
469  range_starts.push_back(end);
470  os_temp << "[";
471  int32 num_ranges = range_starts.size() - 1;
472  for (int32 r = 0; r < num_ranges; r++) {
473  int32 range_start = range_starts[r], range_end = range_starts[r+1];
474  KALDI_ASSERT(range_end > range_start);
475  os_temp << "(" << indexes[range_start].n << ",";
476  if (range_end == range_start + 1)
477  os_temp << indexes[range_start].t;
478  else
479  os_temp << indexes[range_start].t << ":" << indexes[range_end - 1].t;
480  if (indexes[range_start].x != 0)
481  os_temp << "," << indexes[range_start].x;
482  os_temp << ")";
483  if (r + 1 < num_ranges)
484  os_temp << ", ";
485  }
486  os_temp << "]";
487 
488  std::string str = os_temp.str();
489  if (str.size() <= max_string_length) {
490  os << str;
491  } else {
492  size_t len = str.size();
493  os << str.substr(0, max_string_length / 2) << " ... "
494  << str.substr(len - max_string_length / 2);
495  }
496 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ PrintIntegerVector()

void PrintIntegerVector ( std::ostream &  os,
const std::vector< int32 > &  ints 
)

Definition at line 525 of file nnet-common.cc.

References rnnlm::i, and KALDI_ASSERT.

Referenced by kaldi::nnet3::computation_graph::ComputeEpochInfo(), and GetIndexesStrings().

526  {
527  if (ints.empty()) {
528  os << "[ ]";
529  return;
530  }
531  // range_starts will be the starts of ranges (with consecutive or identical
532  // values) that we compactly print. we'll append "end" to range_starts for
533  // convenience.
534  std::vector<int32> range_starts;
535  int32 cur_start = 0, end = ints.size();
536  for (int32 i = cur_start; i < end; i++) {
537  if (i > cur_start) {
538  int32 range_start_val = ints[cur_start],
539  range_start_plus_one_val = ints[cur_start+1],
540  cur_val = ints[i];
541  // if we have reached the end of a range...
542  if (!((range_start_plus_one_val == range_start_val &&
543  cur_val == range_start_val) ||
544  (range_start_plus_one_val == range_start_val + 1 &&
545  cur_val == range_start_val + i - cur_start))) {
546  range_starts.push_back(cur_start);
547  cur_start = i;
548  }
549  }
550  }
551  range_starts.push_back(cur_start);
552  range_starts.push_back(end);
553  os << "[";
554  int32 num_ranges = range_starts.size() - 1;
555  for (int32 r = 0; r < num_ranges; r++) {
556  int32 range_start = range_starts[r], range_end = range_starts[r+1];
557  KALDI_ASSERT(range_end > range_start);
558  if (range_end == range_start + 1)
559  os << ints[range_start];
560  else if (range_end == range_start + 2) // don't print ranges of 2.
561  os << ints[range_start] << ", " << ints[range_start+1];
562  else if (ints[range_start] == ints[range_start+1])
563  os << ints[range_start] << "x" << (range_end - range_start);
564  else
565  os << ints[range_start] << ":" << ints[range_end - 1];
566  if (r + 1 < num_ranges)
567  os << ", ";
568  }
569  os << "]";
570 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ PrintMatrixAccesses()

void PrintMatrixAccesses ( std::ostream &  os,
const std::vector< MatrixAccesses > &  matrix_accesses 
)

This function is to be used in debugging; it produces human-readable output.

Definition at line 1350 of file nnet-analyze.cc.

References MatrixAccesses::accesses, MatrixAccesses::allocate_command, MatrixAccesses::deallocate_command, kReadAccess, and kWriteAccess.

Referenced by MatrixAccesses::MatrixAccesses().

1351  {
1352  int32 num_matrices = matrix_accesses.size();
1353  for (int32 m = 1; m < num_matrices; m++) {
1354  const MatrixAccesses &a = matrix_accesses[m];
1355  os << "m" << m << ": init-command=" << a.allocate_command
1356  << ", destroy-command=" << a.deallocate_command
1357  << ", accesses=";
1358  std::vector<Access>::const_iterator iter = a.accesses.begin(),
1359  end = a.accesses.end();
1360  for (; iter != end; ++iter)
1361  os << 'c' << iter->command_index << "("
1362  << (iter->access_type == kReadAccess ? "r" :
1363  (iter->access_type == kWriteAccess ? "w" : "rw")) << ") ";
1364  os << "\n";
1365  }
1366 }
kaldi::int32 int32

◆ PrintParameterStats() [1/2]

void PrintParameterStats ( std::ostringstream &  os,
const std::string &  name,
const CuVectorBase< BaseFloat > &  params,
bool  include_mean = false 
)

Print to 'os' some information about the mean and standard deviation of some parameters, used in Info() functions in nnet-simple-component.cc.

For example: PrintParameterStats(os, "bias", bias_params_, true); would print to 'os' something like the string ", bias-{mean,stddev}=-0.013,0.196". If 'include_mean = false', it will print something like ", bias-rms=0.2416", and this represents and uncentered standard deviation.

Definition at line 157 of file nnet-parse.cc.

References CuVectorBase< Real >::Dim(), CuVectorBase< Real >::Sum(), and kaldi::VecVec().

Referenced by LstmNonlinearityComponent::ConsolidateMemory(), ConvolutionComponent::Info(), TimeHeightConvolutionComponent::Info(), LstmNonlinearityComponent::Info(), AffineComponent::Info(), TdnnComponent::Info(), BlockAffineComponent::Info(), RepeatedAffineComponent::Info(), ConstantComponent::Info(), LinearComponent::Info(), FixedAffineComponent::Info(), FixedScaleComponent::Info(), FixedBiasComponent::Info(), PerElementScaleComponent::Info(), PerElementOffsetComponent::Info(), ConstantFunctionComponent::Info(), and ScaleAndOffsetComponent::Info().

160  {
161  os << std::setprecision(4);
162  os << ", " << name << '-';
163  if (include_mean) {
164  BaseFloat mean = params.Sum() / params.Dim(),
165  stddev = std::sqrt(VecVec(params, params) / params.Dim() - mean * mean);
166  os << "{mean,stddev}=" << mean << ',' << stddev;
167  } else {
168  BaseFloat rms = std::sqrt(VecVec(params, params) / params.Dim());
169  os << "rms=" << rms;
170  }
171  os << std::setprecision(6); // restore the default precision.
172 }
float BaseFloat
Definition: kaldi-types.h:29
Real VecVec(const VectorBase< Real > &a, const VectorBase< Real > &b)
Returns dot product between v1 and v2.
Definition: kaldi-vector.cc:37

◆ PrintParameterStats() [2/2]

void PrintParameterStats ( std::ostringstream &  os,
const std::string &  name,
const CuMatrix< BaseFloat > &  params,
bool  include_mean = false,
bool  include_row_norms = false,
bool  include_column_norms = false,
bool  include_singular_values = false 
)

Print to 'os' some information about the mean and standard deviation of some parameters, used in Info() functions in nnet-simple-component.cc.

For example: PrintParameterStats(os, "linear-params", linear_params_; would print to 'os' something like the string ", linear-params-rms=0.239". If you set 'include_mean' to true, it will print something like ", linear-params-{mean-stddev}=0.103,0.183". If you set 'include_row_norms' to true, it will print something like ", linear-params-row-norms=[percentiles(0,1........, stddev=0.0508]" If you set 'include_column_norms' to true, it will print something like ", linear-params-col-norms=[percentiles(0,1........, stddev=0.0508]" If you set 'include_singular_values' to true, it will print something like ", linear-params-singular-values=[percentiles(0,1........, stddev=0.0508]"

Definition at line 174 of file nnet-parse.cc.

References CuVectorBase< Real >::AddDiagMat2(), kaldi::kNoTrans, kaldi::kTrans, CuMatrixBase< Real >::NumCols(), CuMatrixBase< Real >::NumRows(), CuMatrixBase< Real >::Sum(), SummarizeVector(), MatrixBase< Real >::Svd(), Vector< Real >::Swap(), and kaldi::TraceMatMat().

180  {
181  os << std::setprecision(4);
182  os << ", " << name << '-';
183  int32 dim = params.NumRows() * params.NumCols();
184  if (include_mean) {
185  BaseFloat mean = params.Sum() / dim,
186  stddev = std::sqrt(TraceMatMat(params, params, kTrans) / dim -
187  mean * mean);
188  os << "{mean,stddev}=" << mean << ',' << stddev;
189  } else {
190  BaseFloat rms = std::sqrt(TraceMatMat(params, params, kTrans) / dim);
191  os << "rms=" << rms;
192  }
193  os << std::setprecision(6); // restore the default precision.
194 
195  if (include_row_norms) {
196  CuVector<BaseFloat> row_norms(params.NumRows());
197  row_norms.AddDiagMat2(1.0, params, kNoTrans, 0.0);
198  row_norms.ApplyPow(0.5);
199  Vector<BaseFloat> row_norms_cpu;
200  row_norms.Swap(&row_norms_cpu);
201  os << ", " << name << "-row-norms="
202  << SummarizeVector(row_norms_cpu);
203  }
204  if (include_column_norms) {
205  CuVector<BaseFloat> col_norms(params.NumCols());
206  col_norms.AddDiagMat2(1.0, params, kTrans, 0.0);
207  col_norms.ApplyPow(0.5);
208  Vector<BaseFloat> col_norms_cpu;
209  col_norms.Swap(&col_norms_cpu);
210  os << ", " << name << "-col-norms="
211  << SummarizeVector(col_norms_cpu);
212  }
213  if (include_singular_values) {
214  Matrix<BaseFloat> params_cpu(params);
215  Vector<BaseFloat> s(std::min(params.NumRows(), params.NumCols()));
216  params_cpu.Svd(&s);
217  std::string singular_values_str = SummarizeVector(s);
218  os << ", " << name << "-singular-values=" << singular_values_str;
219  std::ostringstream name_os;
220  }
221 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
std::string SummarizeVector(const CuVectorBase< BaseFloat > &cu_vec)
Definition: nnet-parse.cc:152
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.

◆ PrintPriorDiagnostics()

void kaldi::nnet3::PrintPriorDiagnostics ( const Vector< BaseFloat > &  old_priors,
const Vector< BaseFloat > &  new_priors 
)

Definition at line 48 of file nnet3-am-adjust-priors.cc.

References VectorBase< Real >::AddVec(), VectorBase< Real >::ApplyAbs(), VectorBase< Real >::Dim(), KALDI_LOG, KlDivergence(), and VectorBase< Real >::Max().

Referenced by main().

49  {
50  if (old_priors.Dim() == 0) {
51  KALDI_LOG << "Model did not previously have priors attached.";
52  } else {
53  Vector<BaseFloat> diff_prior(new_priors);
54  diff_prior.AddVec(-1.0, old_priors);
55  diff_prior.ApplyAbs();
56  int32 max_index;
57  diff_prior.Max(&max_index);
58  KALDI_LOG << "Adjusting priors: largest absolute difference was for "
59  << "pdf " << max_index << ", " << old_priors(max_index)
60  << " -> " << new_priors(max_index);
61  KALDI_LOG << "Adjusting priors: K-L divergence from old to new is "
62  << KlDivergence(old_priors, new_priors);
63  }
64 }
kaldi::int32 int32
MatrixIndexT Dim() const
Returns the dimension of the vector.
Definition: kaldi-vector.h:64
BaseFloat KlDivergence(const Vector< BaseFloat > &p, const Vector< BaseFloat > &q)
A class representing a vector.
Definition: kaldi-vector.h:406
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ PrintVectorPerUpdatableComponent()

std::string PrintVectorPerUpdatableComponent ( const Nnet nnet,
const VectorBase< BaseFloat > &  vec 
)

This function is for printing, to a string, a vector with one element per updatable component of the nnet (e.g.

the output of ComponentDotProducts), in a human readable way, as [ component-name1:number1 component-name2:number2 ... ].

Definition at line 231 of file nnet-utils.cc.

References VectorBase< Real >::Dim(), Nnet::GetComponent(), Nnet::GetComponentName(), KALDI_ASSERT, kUpdatableComponent, Nnet::NumComponents(), NumUpdatableComponents(), and Component::Properties().

Referenced by main().

232  {
233  std::ostringstream os;
234  os << "[ ";
235  KALDI_ASSERT(NumUpdatableComponents(nnet) == vec.Dim());
236  int32 updatable_c = 0;
237  for (int32 c = 0; c < nnet.NumComponents(); c++) {
238  const Component *comp = nnet.GetComponent(c);
239  if (comp->Properties() & kUpdatableComponent) {
240  const std::string &component_name = nnet.GetComponentName(c);
241  os << component_name << ':' << vec(updatable_c) << ' ';
242  updatable_c++;
243  }
244  }
245  KALDI_ASSERT(updatable_c == vec.Dim());
246  os << ']';
247  return os.str();
248 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
int32 NumUpdatableComponents(const Nnet &dest)
Returns the number of updatable components in the nnet.
Definition: nnet-utils.cc:422

◆ PrintVectorVectorPair()

void kaldi::nnet3::PrintVectorVectorPair ( std::vector< std::vector< std::pair< int32, int32 > > >  vec_vec_pair)

Definition at line 50 of file nnet-compile-utils-test.cc.

References rnnlm::i, rnnlm::j, and KALDI_LOG.

Referenced by UnitTestSplitLocations(), and UnitTestSplitLocationsBackward().

51  {
52  std::ostringstream ostream;
53  for (int32 i = 0; i < vec_vec_pair.size(); i++) {
54  for (int32 j = 0; j < vec_vec_pair[i].size(); j++) {
55  ostream << "(" << vec_vec_pair[i][j].first << ","
56  << vec_vec_pair[i][j].second << ") ";
57  }
58  ostream << std::endl;
59  }
60  KALDI_LOG << ostream.str();
61 }
kaldi::int32 int32
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ ProcessFile() [1/3]

static bool kaldi::nnet3::ProcessFile ( const GeneralMatrix feats,
const MatrixBase< BaseFloat > *  ivector_feats,
int32  ivector_period,
const Posterior pdf_post,
const std::string &  utt_id,
bool  compress,
int32  num_pdfs,
int32  length_tolerance,
UtteranceSplitter utt_splitter,
NnetExampleWriter example_writer 
)
static

Definition at line 33 of file nnet3-get-egs.cc.

References NnetExample::Compress(), UtteranceSplitter::Config(), kaldi::ExtractRowRangeWithPadding(), ChunkTimeInfo::first_frame, ExampleGenerationConfig::frame_subsampling_factor, UtteranceSplitter::GetChunksForUtterance(), rnnlm::i, NnetExample::io, KALDI_WARN, ChunkTimeInfo::left_context, UtteranceSplitter::LengthsMatch(), ChunkTimeInfo::num_frames, MatrixBase< Real >::NumCols(), MatrixBase< Real >::NumRows(), GeneralMatrix::NumRows(), ChunkTimeInfo::output_weights, kaldi::RandInt(), ChunkTimeInfo::right_context, MatrixBase< Real >::Row(), and TableWriter< Holder >::Write().

42  {
43  int32 num_input_frames = feats.NumRows();
44  if (!utt_splitter->LengthsMatch(utt_id, num_input_frames,
45  static_cast<int32>(pdf_post.size()),
46  length_tolerance))
47  return false; // LengthsMatch() will have printed a warning.
48 
49  std::vector<ChunkTimeInfo> chunks;
50 
51  utt_splitter->GetChunksForUtterance(num_input_frames, &chunks);
52 
53  if (chunks.empty()) {
54  KALDI_WARN << "Not producing egs for utterance " << utt_id
55  << " because it is too short: "
56  << num_input_frames << " frames.";
57  }
58 
59  // 'frame_subsampling_factor' is not used in any recipes at the time of
60  // writing, this is being supported to unify the code with the 'chain' recipes
61  // and in case we need it for some reason in future.
62  int32 frame_subsampling_factor =
63  utt_splitter->Config().frame_subsampling_factor;
64 
65  for (size_t c = 0; c < chunks.size(); c++) {
66  const ChunkTimeInfo &chunk = chunks[c];
67 
68  int32 tot_input_frames = chunk.left_context + chunk.num_frames +
69  chunk.right_context;
70 
71  int32 start_frame = chunk.first_frame - chunk.left_context;
72 
73  GeneralMatrix input_frames;
74  ExtractRowRangeWithPadding(feats, start_frame, tot_input_frames,
75  &input_frames);
76 
77  // 'input_frames' now stores the relevant rows (maybe with padding) from the
78  // original Matrix or (more likely) CompressedMatrix. If a CompressedMatrix,
79  // it does this without un-compressing and re-compressing, so there is no loss
80  // of accuracy.
81 
82  NnetExample eg;
83  // call the regular input "input".
84  eg.io.push_back(NnetIo("input", -chunk.left_context, input_frames));
85 
86  if (ivector_feats != NULL) {
87  // if applicable, add the iVector feature.
88  // choose iVector from a random frame in the chunk
89  int32 ivector_frame = RandInt(start_frame,
90  start_frame + num_input_frames - 1),
91  ivector_frame_subsampled = ivector_frame / ivector_period;
92  if (ivector_frame_subsampled < 0)
93  ivector_frame_subsampled = 0;
94  if (ivector_frame_subsampled >= ivector_feats->NumRows())
95  ivector_frame_subsampled = ivector_feats->NumRows() - 1;
96  Matrix<BaseFloat> ivector(1, ivector_feats->NumCols());
97  ivector.Row(0).CopyFromVec(ivector_feats->Row(ivector_frame_subsampled));
98  eg.io.push_back(NnetIo("ivector", 0, ivector));
99  }
100 
101  // Note: chunk.first_frame and chunk.num_frames will both be
102  // multiples of frame_subsampling_factor.
103  int32 start_frame_subsampled = chunk.first_frame / frame_subsampling_factor,
104  num_frames_subsampled = chunk.num_frames / frame_subsampling_factor;
105 
106  Posterior labels(num_frames_subsampled);
107 
108  // TODO: it may be that using these weights is not actually helpful (with
109  // chain training, it was not), and that setting them all to 1 is better.
110  // We could add a boolean option to this program to control that; but I
111  // don't want to add such an option if experiments show that it is not
112  // helpful.
113  for (int32 i = 0; i < num_frames_subsampled; i++) {
114  int32 t = i + start_frame_subsampled;
115  if (t < pdf_post.size())
116  labels[i] = pdf_post[t];
117  for (std::vector<std::pair<int32, BaseFloat> >::iterator
118  iter = labels[i].begin(); iter != labels[i].end(); ++iter)
119  iter->second *= chunk.output_weights[i];
120  }
121 
122  eg.io.push_back(NnetIo("output", num_pdfs, 0, labels, frame_subsampling_factor));
123 
124  if (compress)
125  eg.Compress();
126 
127  std::ostringstream os;
128  os << utt_id << "-" << chunk.first_frame;
129 
130  std::string key = os.str(); // key is <utt_id>-<frame_id>
131 
132  example_writer->Write(key, eg);
133  }
134  return true;
135 }
NnetExample is the input data and corresponding label (or labels) for one or more frames of input...
Definition: nnet-example.h:111
This class is a wrapper that enables you to store a matrix in one of three forms: either as a Matrix<...
bool LengthsMatch(const std::string &utt, int32 utterance_length, int32 supervision_length, int32 length_tolerance=0) const
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Definition: kaldi-matrix.h:67
kaldi::int32 int32
void Write(const std::string &key, const T &value) const
std::vector< std::vector< std::pair< int32, BaseFloat > > > Posterior
Posterior is a typedef for storing acoustic-state (actually, transition-id) posteriors over an uttera...
Definition: posterior.h:42
const SubVector< Real > Row(MatrixIndexT i) const
Return specific row of matrix [const].
Definition: kaldi-matrix.h:188
void ExtractRowRangeWithPadding(const GeneralMatrix &in, int32 row_offset, int32 num_rows, GeneralMatrix *out)
This function extracts a row-range of a GeneralMatrix and writes as a GeneralMatrix containing the sa...
void Compress()
Compresses any (input) features that are not sparse.
#define KALDI_WARN
Definition: kaldi-error.h:150
const ExampleGenerationConfig & Config() const
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
Definition: kaldi-matrix.h:64
MatrixIndexT NumRows() const
void GetChunksForUtterance(int32 utterance_length, std::vector< ChunkTimeInfo > *chunk_info)
struct ChunkTimeInfo is used by class UtteranceSplitter to output information about how we split an u...
std::vector< NnetIo > io
"io" contains the input and output.
Definition: nnet-example.h:116
std::vector< BaseFloat > output_weights
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ ProcessFile() [2/3]

static bool kaldi::nnet3::ProcessFile ( const GeneralMatrix feats,
const MatrixBase< BaseFloat > *  ivector_feats,
int32  ivector_period,
const MatrixBase< BaseFloat > &  targets,
const std::string &  utt_id,
bool  compress,
int32  num_targets,
int32  length_tolerance,
UtteranceSplitter utt_splitter,
NnetExampleWriter example_writer 
)
static

Definition at line 34 of file nnet3-get-egs-dense-targets.cc.

References NnetExample::Compress(), UtteranceSplitter::Config(), VectorBase< Real >::CopyFromVec(), kaldi::ExtractRowRangeWithPadding(), ChunkTimeInfo::first_frame, ExampleGenerationConfig::frame_subsampling_factor, UtteranceSplitter::GetChunksForUtterance(), rnnlm::i, NnetExample::io, KALDI_ASSERT, KALDI_WARN, ChunkTimeInfo::left_context, UtteranceSplitter::LengthsMatch(), ChunkTimeInfo::num_frames, MatrixBase< Real >::NumCols(), MatrixBase< Real >::NumRows(), GeneralMatrix::NumRows(), kaldi::RandInt(), ChunkTimeInfo::right_context, MatrixBase< Real >::Row(), and TableWriter< Holder >::Write().

43  {
44  int32 num_input_frames = feats.NumRows();
45  if (!utt_splitter->LengthsMatch(utt_id, num_input_frames,
46  targets.NumRows(),
47  length_tolerance)) {
48  return false;
49  }
50  if (targets.NumRows() == 0)
51  return false;
52  KALDI_ASSERT(num_targets < 0 || targets.NumCols() == num_targets);
53 
54  std::vector<ChunkTimeInfo> chunks;
55 
56  utt_splitter->GetChunksForUtterance(num_input_frames, &chunks);
57 
58  if (chunks.empty()) {
59  KALDI_WARN << "Not producing egs for utterance " << utt_id
60  << " because it is too short: "
61  << num_input_frames << " frames.";
62  return false;
63  }
64 
65  // 'frame_subsampling_factor' is not used in any recipes at the time of
66  // writing, this is being supported to unify the code with the 'chain' recipes
67  // and in case we need it for some reason in future.
68  int32 frame_subsampling_factor =
69  utt_splitter->Config().frame_subsampling_factor;
70 
71  for (size_t c = 0; c < chunks.size(); c++) {
72  const ChunkTimeInfo &chunk = chunks[c];
73 
74  int32 tot_input_frames = chunk.left_context + chunk.num_frames +
75  chunk.right_context;
76 
77  int32 start_frame = chunk.first_frame - chunk.left_context;
78 
79  GeneralMatrix input_frames;
80  ExtractRowRangeWithPadding(feats, start_frame, tot_input_frames,
81  &input_frames);
82 
83  // 'input_frames' now stores the relevant rows (maybe with padding) from the
84  // original Matrix or (more likely) CompressedMatrix. If a CompressedMatrix,
85  // it does this without un-compressing and re-compressing, so there is no loss
86  // of accuracy.
87 
88  NnetExample eg;
89  // call the regular input "input".
90  eg.io.push_back(NnetIo("input", -chunk.left_context, input_frames));
91 
92  if (ivector_feats != NULL) {
93  // if applicable, add the iVector feature.
94  // choose iVector from a random frame in the chunk
95  int32 ivector_frame = RandInt(start_frame,
96  start_frame + num_input_frames - 1),
97  ivector_frame_subsampled = ivector_frame / ivector_period;
98  if (ivector_frame_subsampled < 0)
99  ivector_frame_subsampled = 0;
100  if (ivector_frame_subsampled >= ivector_feats->NumRows())
101  ivector_frame_subsampled = ivector_feats->NumRows() - 1;
102  Matrix<BaseFloat> ivector(1, ivector_feats->NumCols());
103  ivector.Row(0).CopyFromVec(ivector_feats->Row(ivector_frame_subsampled));
104  eg.io.push_back(NnetIo("ivector", 0, ivector));
105  }
106 
107  // Note: chunk.first_frame and chunk.num_frames will both be
108  // multiples of frame_subsampling_factor.
109  int32 start_frame_subsampled = chunk.first_frame / frame_subsampling_factor,
110  num_frames_subsampled = chunk.num_frames / frame_subsampling_factor;
111 
112  KALDI_ASSERT(start_frame_subsampled + num_frames_subsampled - 1 <
113  targets.NumRows());
114 
115 
116  // add the labels.
117  Matrix<BaseFloat> targets_part(num_frames_subsampled, targets.NumCols());
118  for (int32 i = 0; i < num_frames_subsampled; i++) {
119  // Copy the i^th row of the target matrix from the (t+i)^th row of the
120  // input targets matrix
121  int32 t = i + start_frame_subsampled;
122  if (t >= targets.NumRows())
123  t = targets.NumRows() - 1;
124  SubVector<BaseFloat> this_target_dest(targets_part, i);
125  SubVector<BaseFloat> this_target_src(targets, t);
126  this_target_dest.CopyFromVec(this_target_src);
127  }
128 
129  // push this created targets matrix into the eg
130  eg.io.push_back(NnetIo("output", 0, targets_part, frame_subsampling_factor));
131 
132  if (compress)
133  eg.Compress();
134 
135  std::ostringstream os;
136  os << utt_id << "-" << chunk.first_frame;
137 
138  std::string key = os.str(); // key is <utt_id>-<frame_id>
139 
140  example_writer->Write(key, eg);
141  }
142  return true;
143 }
NnetExample is the input data and corresponding label (or labels) for one or more frames of input...
Definition: nnet-example.h:111
This class is a wrapper that enables you to store a matrix in one of three forms: either as a Matrix<...
bool LengthsMatch(const std::string &utt, int32 utterance_length, int32 supervision_length, int32 length_tolerance=0) const
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Definition: kaldi-matrix.h:67
kaldi::int32 int32
void Write(const std::string &key, const T &value) const
const SubVector< Real > Row(MatrixIndexT i) const
Return specific row of matrix [const].
Definition: kaldi-matrix.h:188
void ExtractRowRangeWithPadding(const GeneralMatrix &in, int32 row_offset, int32 num_rows, GeneralMatrix *out)
This function extracts a row-range of a GeneralMatrix and writes as a GeneralMatrix containing the sa...
void Compress()
Compresses any (input) features that are not sparse.
#define KALDI_WARN
Definition: kaldi-error.h:150
const ExampleGenerationConfig & Config() const
#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
MatrixIndexT NumRows() const
void GetChunksForUtterance(int32 utterance_length, std::vector< ChunkTimeInfo > *chunk_info)
struct ChunkTimeInfo is used by class UtteranceSplitter to output information about how we split an u...
std::vector< NnetIo > io
"io" contains the input and output.
Definition: nnet-example.h:116
Represents a non-allocating general vector which can be defined as a sub-vector of higher-level vecto...
Definition: kaldi-vector.h:501
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ ProcessFile() [3/3]

static bool kaldi::nnet3::ProcessFile ( const discriminative::SplitDiscriminativeSupervisionOptions config,
const TransitionModel tmodel,
const MatrixBase< BaseFloat > &  feats,
const MatrixBase< BaseFloat > *  ivector_feats,
int32  ivector_period,
const discriminative::DiscriminativeSupervision supervision,
const std::string &  utt_id,
bool  compress,
UtteranceSplitter utt_splitter,
NnetDiscriminativeExampleWriter example_writer 
)
static

Definition at line 39 of file nnet3-discriminative-get-egs.cc.

References NnetDiscriminativeExample::Compress(), UtteranceSplitter::Config(), VectorBase< Real >::CopyFromVec(), ChunkTimeInfo::first_frame, ExampleGenerationConfig::frame_subsampling_factor, DiscriminativeSupervision::frames_per_sequence, UtteranceSplitter::GetChunksForUtterance(), DiscriminativeSupervisionSplitter::GetFrameRange(), NnetDiscriminativeExample::inputs, rnnlm::j, KALDI_ASSERT, KALDI_WARN, kaldi::kUndefined, ChunkTimeInfo::left_context, UtteranceSplitter::LengthsMatch(), ChunkTimeInfo::num_frames, DiscriminativeSupervision::num_sequences, MatrixBase< Real >::NumCols(), MatrixBase< Real >::NumRows(), ChunkTimeInfo::output_weights, NnetDiscriminativeExample::outputs, kaldi::RandInt(), ChunkTimeInfo::right_context, MatrixBase< Real >::Row(), and TableWriter< Holder >::Write().

Referenced by main().

48  {
49  KALDI_ASSERT(supervision.num_sequences == 1);
50  int32 num_input_frames = feats.NumRows(),
51  num_output_frames = supervision.frames_per_sequence;
52 
53  if (!utt_splitter->LengthsMatch(utt_id, num_input_frames, num_output_frames))
54  return false; // LengthsMatch() will have printed a warning.
55 
56  std::vector<ChunkTimeInfo> chunks;
57 
58  utt_splitter->GetChunksForUtterance(num_input_frames, &chunks);
59 
60  if (chunks.empty()) {
61  KALDI_WARN << "Not producing egs for utterance " << utt_id
62  << " because it is too short: "
63  << num_input_frames << " frames.";
64  }
65 
66  int32 frame_subsampling_factor = utt_splitter->Config().frame_subsampling_factor;
67 
69  supervision);
70 
71  for (size_t c = 0; c < chunks.size(); c++) {
72  ChunkTimeInfo &chunk = chunks[c];
73 
74  NnetDiscriminativeExample nnet_discriminative_eg;
75  nnet_discriminative_eg.outputs.resize(1);
76 
77  int32 start_frame_subsampled = chunk.first_frame / frame_subsampling_factor,
78  num_frames_subsampled = chunk.num_frames / frame_subsampling_factor;
79 
81 
82  splitter.GetFrameRange(start_frame_subsampled,
83  num_frames_subsampled,
84  (c == 0 ? false : true),
85  &supervision_part);
86 
87  SubVector<BaseFloat> output_weights(
88  &(chunk.output_weights[0]),
89  static_cast<int32>(chunk.output_weights.size()));
90 
91  int32 first_frame = 0; // we shift the time-indexes of all these parts so
92  // that the supervised part starts from frame 0.
93  NnetDiscriminativeSupervision nnet_supervision("output", supervision_part,
94  output_weights,
95  first_frame,
96  frame_subsampling_factor);
97  nnet_discriminative_eg.outputs[0].Swap(&nnet_supervision);
98 
99  nnet_discriminative_eg.inputs.resize(ivector_feats != NULL ? 2 : 1);
100 
101 
102  int32 tot_input_frames = chunk.left_context + chunk.num_frames +
103  chunk.right_context;
104 
105  Matrix<BaseFloat> input_frames(tot_input_frames, feats.NumCols(),
106  kUndefined);
107 
108  int32 start_frame = chunk.first_frame - chunk.left_context;
109  for (int32 t = start_frame; t < start_frame + tot_input_frames; t++) {
110  int32 t2 = t;
111  if (t2 < 0) t2 = 0;
112  if (t2 >= num_input_frames) t2 = num_input_frames - 1;
113  int32 j = t - start_frame;
114  SubVector<BaseFloat> src(feats, t2),
115  dest(input_frames, j);
116  dest.CopyFromVec(src);
117  }
118 
119  NnetIo input_io("input", -chunk.left_context, input_frames);
120  nnet_discriminative_eg.inputs[0].Swap(&input_io);
121 
122  if (ivector_feats != NULL) {
123  // if applicable, add the iVector feature.
124  // choose iVector from a random frame in the chunk
125  int32 ivector_frame = RandInt(start_frame,
126  start_frame + num_input_frames - 1),
127  ivector_frame_subsampled = ivector_frame / ivector_period;
128  if (ivector_frame_subsampled < 0)
129  ivector_frame_subsampled = 0;
130  if (ivector_frame_subsampled >= ivector_feats->NumRows())
131  ivector_frame_subsampled = ivector_feats->NumRows() - 1;
132  Matrix<BaseFloat> ivector(1, ivector_feats->NumCols());
133  ivector.Row(0).CopyFromVec(ivector_feats->Row(ivector_frame_subsampled));
134  NnetIo ivector_io("ivector", 0, ivector);
135  nnet_discriminative_eg.inputs[1].Swap(&ivector_io);
136  }
137 
138  if (compress)
139  nnet_discriminative_eg.Compress();
140 
141  std::ostringstream os;
142  os << utt_id << "-" << chunk.first_frame;
143 
144  std::string key = os.str(); // key is <utt_id>-<frame_id>
145 
146  example_writer->Write(key, nnet_discriminative_eg);
147  }
148  return true;
149 }
bool LengthsMatch(const std::string &utt, int32 utterance_length, int32 supervision_length, int32 length_tolerance=0) const
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Definition: kaldi-matrix.h:67
kaldi::int32 int32
void Write(const std::string &key, const T &value) const
const SubVector< Real > Row(MatrixIndexT i) const
Return specific row of matrix [const].
Definition: kaldi-matrix.h:188
#define KALDI_WARN
Definition: kaldi-error.h:150
const ExampleGenerationConfig & Config() const
#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
std::vector< NnetIo > inputs
&#39;inputs&#39; contains the input to the network– normally just it has just one element called "input"...
std::vector< NnetDiscriminativeSupervision > outputs
&#39;outputs&#39; contains the sequence output supervision.
void GetChunksForUtterance(int32 utterance_length, std::vector< ChunkTimeInfo > *chunk_info)
struct ChunkTimeInfo is used by class UtteranceSplitter to output information about how we split an u...
std::vector< BaseFloat > output_weights
Represents a non-allocating general vector which can be defined as a sub-vector of higher-level vecto...
Definition: kaldi-vector.h:501
NnetDiscriminativeExample is like NnetExample, but specialized for sequence training.
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ ProcessRangeFile()

static void kaldi::nnet3::ProcessRangeFile ( const std::string &  range_rxfilename,
unordered_map< std::string, std::vector< ChunkInfo *> > *  utt_to_chunks 
)
static

Definition at line 41 of file nnet3-xvector-get-egs.cc.

References kaldi::ConvertStringToInteger(), KALDI_ERR, ChunkInfo::label, ChunkInfo::name, ChunkInfo::num_frames, ChunkInfo::output_archive_id, kaldi::SplitStringToVector(), ChunkInfo::start_frame, and Input::Stream().

Referenced by main().

42  {
43  Input range_input(range_rxfilename);
44  if (!range_rxfilename.empty()) {
45  std::string line;
46  while (std::getline(range_input.Stream(), line)) {
47  ChunkInfo *chunk_info = new ChunkInfo();
48  std::vector<std::string> fields;
49  SplitStringToVector(line, " \t\n\r", true, &fields);
50  if (fields.size() != 6)
51  KALDI_ERR << "Expected 6 fields in line of range file, got "
52  << fields.size() << " instead.";
53 
54  std::string utt = fields[0],
55  start_frame_str = fields[3],
56  num_frames_str = fields[4],
57  label_str = fields[5];
58 
59  if (!ConvertStringToInteger(fields[1], &(chunk_info->output_archive_id))
60  || !ConvertStringToInteger(start_frame_str, &(chunk_info->start_frame))
61  || !ConvertStringToInteger(num_frames_str, &(chunk_info->num_frames))
62  || !ConvertStringToInteger(label_str, &(chunk_info->label)))
63  KALDI_ERR << "Expected integer for output archive in range file.";
64 
65  chunk_info->name = utt + "-" + start_frame_str + "-" + num_frames_str
66  + "-" + label_str;
67  unordered_map<std::string, std::vector<ChunkInfo*> >::iterator
68  got = utt_to_chunks->find(utt);
69 
70  if (got == utt_to_chunks->end()) {
71  std::vector<ChunkInfo* > chunk_infos;
72  chunk_infos.push_back(chunk_info);
73  utt_to_chunks->insert(std::pair<std::string,
74  std::vector<ChunkInfo* > > (utt, chunk_infos));
75  } else {
76  got->second.push_back(chunk_info);
77  }
78  }
79  }
80 }
bool ConvertStringToInteger(const std::string &str, Int *out)
Converts a string into an integer via strtoll and returns false if there was any kind of problem (i...
Definition: text-utils.h:118
void SplitStringToVector(const std::string &full, const char *delim, bool omit_empty_strings, std::vector< std::string > *out)
Split a string using any of the single character delimiters.
Definition: text-utils.cc:63
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ ReadCindexVector()

void ReadCindexVector ( std::istream &  is,
bool  binary,
std::vector< Cindex > *  vec 
)

Definition at line 309 of file nnet-common.cc.

References ExpectToken(), rnnlm::i, KALDI_ERR, kaldi::ReadBasicType(), and ReadCindexVectorElementBinary().

Referenced by NnetComputation::MatrixDebugInfo::Read(), and UnitTestCindexIo().

310  {
311  ExpectToken(is, binary, "<I1V>");
312  int32 size;
313  ReadBasicType(is, binary, &size);
314  if (size < 0) {
315  KALDI_ERR << "Error reading Index vector: size = "
316  << size;
317  }
318  vec->resize(size);
319  if (!binary) {
320  for (int32 i = 0; i < size; i++) {
321  is >> std::ws;
322  if (is.peek() == static_cast<int>(']') || i == 0) {
323  if (i != 0)
324  is.get();
325  is >> std::ws;
326  if (is.peek() == static_cast<int>('[')) {
327  is.get();
328  } else {
329  KALDI_ERR << "ReadCintegerVector: expected to see [, saw "
330  << is.peek() << ", at file position " << is.tellg();
331  }
332  ReadBasicType(is, binary, &((*vec)[i].first));
333  is >> std::ws;
334  if (is.peek() == static_cast<int>(':')) {
335  is.get();
336  } else {
337  KALDI_ERR << "ReadCintegerVector: expected to see :, saw "
338  << is.peek() << ", at file position " << is.tellg();
339  }
340  } else {
341  (*vec)[i].first = (*vec)[i-1].first;
342  }
343  (*vec)[i].second.Read(is, binary);
344  if (i == size - 1) {
345  is >> std::ws;
346  if (is.peek() == static_cast<int>(']')) {
347  is.get();
348  } else {
349  KALDI_ERR << "ReadCintegerVector: expected to see ], saw "
350  << is.peek() << ", at file position " << is.tellg();
351  }
352  }
353  }
354  } else {
355  for (int32 i = 0; i < size; i++)
357  }
358 }
void ReadBasicType(std::istream &is, bool binary, T *t)
ReadBasicType is the name of the read function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:55
kaldi::int32 int32
void ExpectToken(std::istream &is, bool binary, const char *token)
ExpectToken tries to read in the given token, and throws an exception on failure. ...
Definition: io-funcs.cc:191
static void ReadCindexVectorElementBinary(std::istream &is, int32 i, std::vector< Cindex > *vec)
Definition: nnet-common.cc:224
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ ReadCindexVectorElementBinary()

static void kaldi::nnet3::ReadCindexVectorElementBinary ( std::istream &  is,
int32  i,
std::vector< Cindex > *  vec 
)
static

Definition at line 224 of file nnet-common.cc.

References rnnlm::i, KALDI_ASSERT, KALDI_ERR, Index::n, kaldi::ReadBasicType(), Index::t, and Index::x.

Referenced by ReadCindexVector().

227  {
228  bool binary = true;
229  Index &index = (*vec)[i].second;
230  if (!is.good())
231  KALDI_ERR << "End of file while reading vector of Cindex.";
232  if (is.peek() == static_cast<int>('|')) {
233  is.get();
234  ReadBasicType(is, binary, &((*vec)[i].first));
235  } else {
236  KALDI_ASSERT(i != 0);
237  (*vec)[i].first = (*vec)[i-1].first;
238  }
239  signed char c = is.get();
240  if (i == 0) {
241  if (std::abs(int(c)) < 125) {
242  index.n = 0;
243  index.t = c;
244  index.x = 0;
245  } else if (c == 125 || c == 126) {
246  index.n = c - 125;
247  index.t = 0;
248  index.x = 0;
249  } else {
250  if (c != 127)
251  KALDI_ERR << "Unexpected character " << c
252  << " encountered while reading Cindex vector.";
253  ReadBasicType(is, binary, &(index.n));
254  ReadBasicType(is, binary, &(index.t));
255  ReadBasicType(is, binary, &(index.x));
256  }
257  } else {
258  Index &last_index = (*vec)[i-1].second;
259  if (std::abs(int(c)) < 124) {
260  index.n = last_index.n;
261  index.t = last_index.t + c;
262  index.x = last_index.x;
263  } else if (c == 125 || c == 126) {
264  index.n = last_index.n + c - 125;
265  index.t = last_index.t;
266  index.x = last_index.x;
267  } else {
268  if (c != 127)
269  KALDI_ERR << "Unexpected character " << c
270  << " encountered while reading Cindex vector.";
271  ReadBasicType(is, binary, &(index.n));
272  ReadBasicType(is, binary, &(index.t));
273  ReadBasicType(is, binary, &(index.x));
274  }
275  }
276 }
void ReadBasicType(std::istream &is, bool binary, T *t)
ReadBasicType is the name of the read function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:55
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ReadEditConfig()

void ReadEditConfig ( std::istream &  config_file,
Nnet nnet 
)

ReadEditConfig() reads a file with a similar-looking format to the config file read by Nnet::ReadConfig(), but this consists of a sequence of operations to perform on an existing network, mostly modifying components.

It's one "directive" (i.e. command) per line, but if supplying the options via the –edits option to programs like nnet3-am-copy, you can use a semicolon in place of the newline to separate commands.

The following describes the allowed commands. Note: all patterns are like UNIX globbing patterns where the only metacharacter is '*', representing zero or more characters.

  convert-to-fixed-affine [name=<name-pattern>]
    Converts the given affine components to FixedAffineComponent which is not updatable.

  remove-orphan-nodes [remove-orphan-inputs=(true|false)]
    Removes orphan nodes (that are never used to compute anything).  Note:
    remove-orphan-inputs defaults to false.

  remove-orphan-components
    Removes orphan components (those that are never used by any node).

  remove-orphans [remove-orphan-inputs=(true|false)]
    The same as calling remove-orphan-nodes and then remove-orphan-components.

  set-learning-rate [name=<name-pattern>] learning-rate=<learning-rate>
     Sets the learning rate for any updatable components matching the name pattern.
     Note: this sets the 'underlying' learning rate, i.e. it will get
     multiplied by any 'learning-rate-factor' set in the components.

  set-learning-rate-factor [name=<name-pattern>] learning-rate-factor=<learning-rate-factor>
     Sets the learning rate factor for any updatable components matching the name pattern.

  rename-node old-name=<old-name> new-name=<new-name>
     Renames a node; this is a surface renaming that does not affect the structure
     (for structural changes, use the regular config file format, not the
     edits-config).  This is mostly useful for outputs, e.g. when doing
     multilingual experiments.

  remove-output-nodes name=<name-pattern>
     Removes a subset of output nodes, those matching the pattern.  You cannot
     remove internal nodes directly; instead you should use the command
     'remove-orphans'.

  set-dropout-proportion [name=<name-pattern>] proportion=<dropout-proportion>
     Sets the dropout rates for any components of type DropoutComponent,
     DropoutMaskComponent or GeneralDropoutComponent whose
     names match the given <name-pattern> (e.g. lstm*).  <name-pattern> defaults to "*".

  apply-svd name=<name-pattern> bottleneck-dim=<dim> energy-threshold=<threshold> shrinkage-threshold=<s>
     Locates all components with names matching <name-pattern>, which are
     type AffineComponent or child classes thereof.  If <dim> is
     less than the minimum of the (input or output) dimension of the component,
     it does SVD on the components' parameters, retaining only the largest
     <dim> singular values, replacing these components with sequences of two
     components, of types LinearComponent and NaturalGradientAffineComponent.
     Instead we can set the filtering criterion for the Singular values as energy-threshold,
     and retain those values which contribute to energy-threshold times the total energy of
     the original singular values. A particular SVD factored component is left unshrinked,
     if the shrinkage ratio of the total no. of its parameters,
     after the SVD based refactoring, is greater than shrinkage threshold.
     See also 'reduce-rank'.

  reduce-rank name=<name-pattern> rank=<dim>
     Locates all components with names matching <name-pattern>, which are
     type AffineComponent or child classes thereof.  Does SVD on the
     components' parameters, retaining only the largest <dim> singular values,
     and writes the reconstructed matrix back to the component.  See also
     'apply-svd', which structurally breaks the component into two pieces.

Definition at line 1234 of file nnet-utils.cc.

References SvdApplier::ApplySvd(), ConfigLine::FirstToken(), Nnet::GetComponent(), Nnet::GetComponentName(), Nnet::GetNodeIndex(), Nnet::GetNodeName(), ConfigLine::GetValue(), ConfigLine::HasUnusedValues(), rnnlm::i, Nnet::IsOutputNode(), KALDI_ERR, KALDI_LOG, rnnlm::n, NameMatchesPattern(), Nnet::NumComponents(), Nnet::NumNodes(), ParseConfigLines(), kaldi::ReadConfigLines(), ReduceRankOfComponents(), Nnet::RemoveOrphanComponents(), Nnet::RemoveOrphanNodes(), Nnet::RemoveSomeNodes(), Nnet::SetComponent(), DropoutComponent::SetDropoutProportion(), DropoutMaskComponent::SetDropoutProportion(), GeneralDropoutComponent::SetDropoutProportion(), UpdatableComponent::SetLearningRateFactor(), Nnet::SetNodeName(), UpdatableComponent::SetUnderlyingLearningRate(), ConfigLine::UnusedValues(), and ConfigLine::WholeLine().

Referenced by CollapseModelConfig::CollapseModelConfig(), and main().

1234  {
1235  std::vector<std::string> lines;
1236  ReadConfigLines(edit_config_is, &lines);
1237  // we process this as a sequence of lines.
1238  std::vector<ConfigLine> config_lines;
1239  ParseConfigLines(lines, &config_lines);
1240  for (size_t i = 0; i < config_lines.size(); i++) {
1241  ConfigLine &config_line = config_lines[i];
1242  const std::string &directive = config_lines[i].FirstToken();
1243  if (directive == "convert-to-fixed-affine") {
1244  std::string name_pattern = "*";
1245  // name_pattern defaults to '*' if none is given. Note: this pattern
1246  // matches names of components, not nodes.
1247  config_line.GetValue("name", &name_pattern);
1248  int32 num_components_changed = 0;
1249  for (int32 c = 0; c < nnet->NumComponents(); c++) {
1250  Component *component = nnet->GetComponent(c);
1251  AffineComponent *affine = NULL;
1252  if (NameMatchesPattern(nnet->GetComponentName(c).c_str(),
1253  name_pattern.c_str()) &&
1254  (affine = dynamic_cast<AffineComponent*>(component))) {
1255  nnet->SetComponent(c, new FixedAffineComponent(*affine));
1256  num_components_changed++;
1257  }
1258  }
1259  KALDI_LOG << "Converted " << num_components_changed
1260  << " components to FixedAffineComponent.";
1261  } else if (directive == "remove-orphan-nodes") {
1262  bool remove_orphan_inputs = false;
1263  config_line.GetValue("remove-orphan-inputs", &remove_orphan_inputs);
1264  nnet->RemoveOrphanNodes(remove_orphan_inputs);
1265  } else if (directive == "remove-orphan-components") {
1266  nnet->RemoveOrphanComponents();
1267  } else if (directive == "remove-orphans") {
1268  bool remove_orphan_inputs = false;
1269  config_line.GetValue("remove-orphan-inputs", &remove_orphan_inputs);
1270  nnet->RemoveOrphanNodes(remove_orphan_inputs);
1271  nnet->RemoveOrphanComponents();
1272  } else if (directive == "set-learning-rate") {
1273  std::string name_pattern = "*";
1274  // name_pattern defaults to '*' if none is given. This pattern
1275  // matches names of components, not nodes.
1276  config_line.GetValue("name", &name_pattern);
1277  BaseFloat learning_rate = -1;
1278  if (!config_line.GetValue("learning-rate", &learning_rate)) {
1279  KALDI_ERR << "In edits-config, expected learning-rate to be set in line: "
1280  << config_line.WholeLine();
1281  }
1282  // Note: the learning rate you provide will be multiplied by any
1283  // 'learning-rate-factor' that is defined in the component,
1284  // so if you call SetUnderlyingLearningRate(), the actual learning
1285  // rate (learning_rate_) is set to the value you provide times
1286  // learning_rate_factor_.
1287  UpdatableComponent *component = NULL;
1288  int32 num_learning_rates_set = 0;
1289  for (int32 c = 0; c < nnet->NumComponents(); c++) {
1290  if (NameMatchesPattern(nnet->GetComponentName(c).c_str(),
1291  name_pattern.c_str()) &&
1292  (component =
1293  dynamic_cast<UpdatableComponent*>(nnet->GetComponent(c)))) {
1294  component->SetUnderlyingLearningRate(learning_rate);
1295  num_learning_rates_set++;
1296  }
1297  }
1298  KALDI_LOG << "Set learning rates for " << num_learning_rates_set << " components.";
1299  } else if (directive == "set-learning-rate-factor") {
1300  std::string name_pattern = "*";
1301  // name_pattern defaults to '*' if none is given.
1302  config_line.GetValue("name", &name_pattern);
1303  BaseFloat learning_rate_factor = -1;
1304  if (!config_line.GetValue("learning-rate-factor", &learning_rate_factor)) {
1305  KALDI_ERR << "In edits-config, expected learning-rate-factor to be set in line: "
1306  << config_line.WholeLine();
1307  }
1308  // Note: the learning_rate_factor_ defined in the component
1309  // sets to the value you provided, so if you call SetUnderlyingLearningRate(),
1310  // the actual learning rate (learning_rate_) is set to the value you provided
1311  // times learning_rate.
1312  UpdatableComponent *component = NULL;
1313  int32 num_learning_rate_factors_set = 0;
1314  for (int32 c = 0; c < nnet->NumComponents(); c++) {
1315  if (NameMatchesPattern(nnet->GetComponentName(c).c_str(),
1316  name_pattern.c_str()) &&
1317  (component =
1318  dynamic_cast<UpdatableComponent*>(nnet->GetComponent(c)))) {
1319  component->SetLearningRateFactor(learning_rate_factor);
1320  num_learning_rate_factors_set++;
1321  }
1322  }
1323  KALDI_LOG << "Set learning rate factors for " << num_learning_rate_factors_set
1324  << " components.";
1325  } else if (directive == "rename-node") {
1326  // this is a shallow renaming of a node, and it requires that the name used is
1327  // not the name of another node.
1328  std::string old_name, new_name;
1329  if (!config_line.GetValue("old-name", &old_name) ||
1330  !config_line.GetValue("new-name", &new_name) ||
1331  config_line.HasUnusedValues()) {
1332  KALDI_ERR << "In edits-config, could not make sense of this rename-node "
1333  << "directive (expect old-name=xxx new-name=xxx) "
1334  << config_line.WholeLine();
1335  }
1336  if (nnet->GetNodeIndex(old_name) < 0)
1337  KALDI_ERR << "Could not rename node from " << old_name << " to "
1338  << new_name << " because there is no node called "
1339  << old_name;
1340  // further checks will happen inside SetNodeName().
1341  nnet->SetNodeName(nnet->GetNodeIndex(old_name), new_name);
1342  } else if (directive == "remove-output-nodes") {
1343  // note: after remove-output-nodes you probably want to do 'remove-orphans'.
1344  std::string name_pattern;
1345  if (!config_line.GetValue("name", &name_pattern) ||
1346  config_line.HasUnusedValues())
1347  KALDI_ERR << "In edits-config, could not make sense of "
1348  << "remove-output-nodes directive: "
1349  << config_line.WholeLine();
1350  std::vector<int32> nodes_to_remove;
1351  int32 outputs_remaining = 0;
1352  for (int32 n = 0; n < nnet->NumNodes(); n++) {
1353  if (nnet->IsOutputNode(n)) {
1354  if (NameMatchesPattern(nnet->GetNodeName(n).c_str(),
1355  name_pattern.c_str()))
1356  nodes_to_remove.push_back(n);
1357  else
1358  outputs_remaining++;
1359  }
1360  }
1361  KALDI_LOG << "Removing " << nodes_to_remove.size() << " output nodes.";
1362  if (outputs_remaining == 0)
1363  KALDI_ERR << "All outputs were removed.";
1364  nnet->RemoveSomeNodes(nodes_to_remove);
1365  } else if (directive == "set-dropout-proportion") {
1366  std::string name_pattern = "*";
1367  // name_pattern defaults to '*' if none is given. This pattern
1368  // matches names of components, not nodes.
1369  config_line.GetValue("name", &name_pattern);
1370  BaseFloat proportion = -1;
1371  if (!config_line.GetValue("proportion", &proportion)) {
1372  KALDI_ERR << "In edits-config, expected proportion to be set in line: "
1373  << config_line.WholeLine();
1374  }
1375  int32 num_dropout_proportions_set = 0;
1376  for (int32 c = 0; c < nnet->NumComponents(); c++) {
1377  if (NameMatchesPattern(nnet->GetComponentName(c).c_str(),
1378  name_pattern.c_str())) {
1379  DropoutComponent *dropout_component =
1380  dynamic_cast<DropoutComponent*>(nnet->GetComponent(c));
1381  DropoutMaskComponent *mask_component =
1382  dynamic_cast<DropoutMaskComponent*>(nnet->GetComponent(c));
1383  GeneralDropoutComponent *general_dropout_component =
1384  dynamic_cast<GeneralDropoutComponent*>(nnet->GetComponent(c));
1385  if (dropout_component != NULL) {
1386  dropout_component->SetDropoutProportion(proportion);
1387  num_dropout_proportions_set++;
1388  } else if (mask_component != NULL){
1389  mask_component->SetDropoutProportion(proportion);
1390  num_dropout_proportions_set++;
1391  } else if (general_dropout_component != NULL){
1392  general_dropout_component->SetDropoutProportion(proportion);
1393  num_dropout_proportions_set++;
1394  }
1395  }
1396  }
1397  KALDI_LOG << "Set dropout proportions for "
1398  << num_dropout_proportions_set << " components.";
1399  } else if (directive == "apply-svd") {
1400  std::string name_pattern;
1401  int32 bottleneck_dim = -1;
1402  BaseFloat energy_threshold = -1;
1403  BaseFloat shrinkage_threshold = 1.0;
1404  config_line.GetValue("bottleneck-dim", &bottleneck_dim);
1405  config_line.GetValue("energy-threshold", &energy_threshold);
1406  config_line.GetValue("shrinkage-threshold", &shrinkage_threshold);
1407  if (!config_line.GetValue("name", &name_pattern))
1408  KALDI_ERR << "Edit directive apply-svd requires 'name' to be specified.";
1409  if (bottleneck_dim <= 0 && energy_threshold <=0)
1410  KALDI_ERR << "Either Bottleneck-dim or energy-threshold "
1411  "must be set in apply-svd command. "
1412  "Range of possible values is (0 1]";
1413  SvdApplier applier(name_pattern, bottleneck_dim,
1414  energy_threshold,
1415  shrinkage_threshold,
1416  nnet);
1417  applier.ApplySvd();
1418  } else if (directive == "reduce-rank") {
1419  std::string name_pattern;
1420  int32 rank = -1;
1421  if (!config_line.GetValue("name", &name_pattern) ||
1422  !config_line.GetValue("rank", &rank))
1423  KALDI_ERR << "Edit directive reduce-rank requires 'name' and "
1424  "'rank' to be specified.";
1425  if (rank <= 0)
1426  KALDI_ERR << "Rank must be positive in reduce-rank command.";
1427  ReduceRankOfComponents(name_pattern, rank, nnet);
1428  } else {
1429  KALDI_ERR << "Directive '" << directive << "' is not currently "
1430  "supported (reading edit-config).";
1431  }
1432  if (config_line.HasUnusedValues()) {
1433  KALDI_ERR << "Could not interpret '" << config_line.UnusedValues()
1434  << "' in edit config line " << config_line.WholeLine();
1435  }
1436  }
1437 }
void ReduceRankOfComponents(const std::string component_name_pattern, int32 rank, Nnet *nnet)
Definition: nnet-utils.cc:1172
kaldi::int32 int32
bool NameMatchesPattern(const char *name, const char *pattern)
Definition: nnet-parse.cc:235
float BaseFloat
Definition: kaldi-types.h:29
struct rnnlm::@11::@12 n
#define KALDI_ERR
Definition: kaldi-error.h:147
void ReadConfigLines(std::istream &is, std::vector< std::string > *lines)
This function reads in a config file and *appends* its contents to a vector of lines; it is responsib...
Definition: text-utils.cc:564
void ParseConfigLines(const std::vector< std::string > &lines, std::vector< ConfigLine > *config_lines)
This function converts config-lines from a simple sequence of strings as output by ReadConfigLines()...
Definition: text-utils.cc:579
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ ReadIndexVector()

void ReadIndexVector ( std::istream &  is,
bool  binary,
std::vector< Index > *  vec 
)

Definition at line 143 of file nnet-common.cc.

References ExpectToken(), rnnlm::i, KALDI_ERR, kaldi::ReadBasicType(), and ReadIndexVectorElementBinary().

Referenced by IndexLessNxt::operator()(), NnetIo::Read(), NnetDiscriminativeSupervision::Read(), IoSpecification::Read(), NnetChainSupervision::Read(), NnetComputation::Read(), and UnitTestIndexIo().

144  {
145  ExpectToken(is, binary, "<I1V>");
146  int32 size;
147  ReadBasicType(is, binary, &size);
148  if (size < 0) {
149  KALDI_ERR << "Error reading Index vector: size = "
150  << size;
151  }
152  vec->resize(size);
153  if (!binary) {
154  for (int32 i = 0; i < size; i++)
155  (*vec)[i].Read(is, binary);
156  } else {
157  for (int32 i = 0; i < size; i++)
159  }
160 }
void ReadBasicType(std::istream &is, bool binary, T *t)
ReadBasicType is the name of the read function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:55
kaldi::int32 int32
static void ReadIndexVectorElementBinary(std::istream &is, int32 i, std::vector< Index > *vec)
Definition: nnet-common.cc:87
void ExpectToken(std::istream &is, bool binary, const char *token)
ExpectToken tries to read in the given token, and throws an exception on failure. ...
Definition: io-funcs.cc:191
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ ReadIndexVectorElementBinary()

static void kaldi::nnet3::ReadIndexVectorElementBinary ( std::istream &  is,
int32  i,
std::vector< Index > *  vec 
)
static

Definition at line 87 of file nnet-common.cc.

References rnnlm::i, KALDI_ERR, Index::n, kaldi::ReadBasicType(), Index::t, and Index::x.

Referenced by ReadIndexVector().

90  {
91  bool binary = true;
92  Index &index = (*vec)[i];
93  if (!is.good())
94  KALDI_ERR << "End of file while reading vector of Index.";
95  signed char c = is.get();
96  if (i == 0) {
97  if (std::abs(int(c)) < 125) {
98  index.n = 0;
99  index.t = c;
100  index.x = 0;
101  } else {
102  if (c != 127)
103  KALDI_ERR << "Unexpected character " << c
104  << " encountered while reading Index vector.";
105  ReadBasicType(is, binary, &(index.n));
106  ReadBasicType(is, binary, &(index.t));
107  ReadBasicType(is, binary, &(index.x));
108  }
109  } else {
110  Index &last_index = (*vec)[i-1];
111  if (std::abs(int(c)) < 125) {
112  index.n = last_index.n;
113  index.t = last_index.t + c;
114  index.x = last_index.x;
115  } else {
116  if (c != 127)
117  KALDI_ERR << "Unexpected character " << c
118  << " encountered while reading Index vector.";
119  ReadBasicType(is, binary, &(index.n));
120  ReadBasicType(is, binary, &(index.t));
121  ReadBasicType(is, binary, &(index.x));
122  }
123  }
124 }
void ReadBasicType(std::istream &is, bool binary, T *t)
ReadBasicType is the name of the read function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:55
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ ReadIntegerToken()

static int32 kaldi::nnet3::ReadIntegerToken ( const std::string &  what_we_are_parsing,
const std::string **  next_token 
)
static

Definition at line 56 of file nnet-descriptor.cc.

References kaldi::ConvertStringToInteger(), KALDI_ERR, and ParsingContext().

Referenced by GeneralDescriptor::ParseOffset(), GeneralDescriptor::ParseReplaceIndex(), and GeneralDescriptor::ParseRound().

57  {
58  int32 ans;
59  if (!ConvertStringToInteger(**next_token, &ans))
60  KALDI_ERR << "Expected integer while parsing "
61  << what_we_are_parsing << ", got '"
62  << **next_token << "'" << ParsingContext(*next_token);
63  (*next_token)++; // advance token pointer.
64  return ans;
65 }
bool ConvertStringToInteger(const std::string &str, Int *out)
Converts a string into an integer via strtoll and returns false if there was any kind of problem (i...
Definition: text-utils.h:118
kaldi::int32 int32
static std::string ParsingContext(const std::string *token_ptr)
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ ReadVectorAsChar()

void ReadVectorAsChar ( std::istream &  is,
bool  binary,
Vector< BaseFloat > *  vec 
)

Definition at line 258 of file nnet-example-utils.cc.

References VectorBase< Real >::Data(), rnnlm::i, kaldi::kUndefined, Vector< Real >::Read(), kaldi::ReadIntegerVector(), and Vector< Real >::Resize().

Referenced by NnetDiscriminativeSupervision::Read(), and NnetChainSupervision::Read().

260  {
261  if (binary) {
262  BaseFloat scale = 1.0 / 255.0;
263  std::vector<unsigned char> char_vec;
264  ReadIntegerVector(is, binary, &char_vec);
265  int32 dim = char_vec.size();
266  vec->Resize(dim, kUndefined);
267  BaseFloat *data = vec->Data();
268  for (int32 i = 0; i < dim; i++)
269  data[i] = scale * char_vec[i];
270  } else {
271  vec->Read(is, binary);
272  }
273 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
void ReadIntegerVector(std::istream &is, bool binary, std::vector< T > *v)
Function for reading STL vector of integer types.
Definition: io-funcs-inl.h:232

◆ RearrangeIndexes()

void kaldi::nnet3::RearrangeIndexes ( const std::vector< std::vector< int32 > > &  in,
std::vector< std::vector< int32 > > *  out 
)

Definition at line 367 of file nnet-combined-component.cc.

References rnnlm::i, and rnnlm::j.

Referenced by ConvolutionComponent::InderivPatchesToInderiv(), and MaxpoolingComponent::InderivPatchesToInderiv().

368  {
369  int32 D = in.size();
370  int32 L = 0;
371  for (int32 i = 0; i < D; i++)
372  if (in[i].size() > L)
373  L = in[i].size();
374  out->resize(L);
375  for (int32 i = 0; i < L; i++)
376  (*out)[i].resize(D, -1);
377  for (int32 i = 0; i < D; i++) {
378  for (int32 j = 0; j < in[i].size(); j++) {
379  (*out)[j][i] = in[i][j];
380  }
381  }
382 }
kaldi::int32 int32

◆ RecomputeStats() [1/2]

void RecomputeStats ( const std::vector< NnetChainExample > &  egs,
const chain::ChainTrainingOptions &  chain_config,
const fst::StdVectorFst den_fst,
Nnet nnet 
)

This function zeros the stored component-level stats in the nnet using ZeroComponentStats(), then recomputes them with the supplied egs.

It affects batch-norm, for instance. See also the version of RecomputeStats declared in nnet-utils.h.

Definition at line 248 of file nnet-chain-diagnostics.cc.

References NnetChainComputeProb::Compute(), HasXentOutputs(), rnnlm::i, KALDI_LOG, NnetChainComputeProb::PrintTotalStats(), NnetComputeProbOptions::store_component_stats, and ZeroComponentStats().

Referenced by main().

251  {
252  KALDI_LOG << "Recomputing stats on nnet (affects batch-norm)";
253  chain::ChainTrainingOptions chain_config(chain_config_in);
254  if (HasXentOutputs(*nnet) &&
255  chain_config.xent_regularize == 0) {
256  // this forces it to compute the output for xent outputs,
257  // usually 'output-xent', which
258  // means that we'll be computing batch-norm stats for any
259  // components in that branch that have batch-norm.
260  chain_config.xent_regularize = 0.1;
261  }
262 
263  ZeroComponentStats(nnet);
264  NnetComputeProbOptions nnet_config;
265  nnet_config.store_component_stats = true;
266  NnetChainComputeProb prob_computer(nnet_config, chain_config, den_fst, nnet);
267  for (size_t i = 0; i < egs.size(); i++)
268  prob_computer.Compute(egs[i]);
269  prob_computer.PrintTotalStats();
270  KALDI_LOG << "Done recomputing stats.";
271 }
static bool HasXentOutputs(const Nnet &nnet)
void ZeroComponentStats(Nnet *nnet)
Zeroes the component stats in all nonlinear components in the nnet.
Definition: nnet-utils.cc:269
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ RecomputeStats() [2/2]

void RecomputeStats ( const std::vector< NnetExample > &  egs,
Nnet nnet 
)

This function zeros the stored component-level stats in the nnet using ZeroComponentStats(), then recomputes them with the supplied egs.

It affects batch-norm, for instance. See also the version of RecomputeStats declared in nnet-chain-diagnostics.h.

Definition at line 550 of file nnet-utils.cc.

References NnetComputeProb::Compute(), rnnlm::i, KALDI_LOG, NnetComputeProb::PrintTotalStats(), NnetComputeProbOptions::store_component_stats, and ZeroComponentStats().

550  {
551  KALDI_LOG << "Recomputing stats on nnet (affects batch-norm)";
552  ZeroComponentStats(nnet);
553  NnetComputeProbOptions opts;
554  opts.store_component_stats = true;
555  NnetComputeProb prob_computer(opts, nnet);
556  for (size_t i = 0; i < egs.size(); i++)
557  prob_computer.Compute(egs[i]);
558  prob_computer.PrintTotalStats();
559  KALDI_LOG << "Done recomputing stats.";
560 }
void ZeroComponentStats(Nnet *nnet)
Zeroes the component stats in all nonlinear components in the nnet.
Definition: nnet-utils.cc:269
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ ReduceRankOfComponents()

void kaldi::nnet3::ReduceRankOfComponents ( const std::string  component_name_pattern,
int32  rank,
Nnet nnet 
)

Definition at line 1172 of file nnet-utils.cc.

References MatrixBase< Real >::AddMatMat(), AffineComponent::BiasParams(), SvdApplier::ModifiedComponentInfo::component_name, Nnet::GetComponent(), Nnet::GetComponentName(), AffineComponent::InputDim(), KALDI_LOG, KALDI_WARN, kaldi::kCopyData, kaldi::kNoTrans, AffineComponent::LinearParams(), NameMatchesPattern(), Nnet::NumComponents(), AffineComponent::OutputDim(), Matrix< Real >::Resize(), AffineComponent::SetParams(), kaldi::SortSvd(), CuVector< Real >::Swap(), and CuMatrix< Real >::Swap().

Referenced by ReadEditConfig().

1174  {
1175  int32 num_components_changed = 0;
1176  for (int32 c = 0; c < nnet->NumComponents(); c++) {
1177  Component *component = nnet->GetComponent(c);
1178  std::string component_name = nnet->GetComponentName(c);
1179  if (NameMatchesPattern(component_name.c_str(),
1180  component_name_pattern.c_str())) {
1181  AffineComponent *affine = dynamic_cast<AffineComponent*>(component);
1182  if (affine == NULL) {
1183  KALDI_WARN << "Not reducing rank of component " << component_name
1184  << " as it is not an AffineComponent.";
1185  continue;
1186  }
1187  int32 input_dim = affine->InputDim(),
1188  output_dim = affine->OutputDim();
1189  if (input_dim <= rank || output_dim <= rank) {
1190  KALDI_WARN << "Not reducing rank of component " << component_name
1191  << " with SVD to rank " << rank
1192  << " because its dimension is " << input_dim
1193  << " -> " << output_dim;
1194  continue;
1195  }
1196  Matrix<BaseFloat> linear_params(affine->LinearParams());
1197  Vector<BaseFloat> bias_params(affine->BiasParams());
1198 
1199  // note: 'linear_params' is of dimension output_dim by input_dim.
1200  int32 middle_dim = std::min<int32>(input_dim, output_dim);
1201  Vector<BaseFloat> s(middle_dim);
1202  Matrix<BaseFloat> U(output_dim, middle_dim),
1203  Vt(middle_dim, input_dim);
1204  linear_params.Svd(&s, &U, &Vt);
1205  // make sure the singular values are sorted from greatest to least value.
1206  SortSvd(&s, &U, &Vt);
1207  BaseFloat s_sum_orig = s.Sum();
1208  s.Resize(rank, kCopyData);
1209  U.Resize(output_dim, rank, kCopyData);
1210  Vt.Resize(rank, input_dim, kCopyData);
1211  BaseFloat s_sum_reduced = s.Sum();
1212  KALDI_LOG << "For component " << component_name
1213  << " singular value sum changed by reduce-rank command "
1214  << (s_sum_orig - s_sum_reduced)
1215  << " (from " << s_sum_orig << " to " << s_sum_reduced << ")";
1216  U.MulColsVec(s);
1217  Matrix<BaseFloat> linear_params_reduced_rank(output_dim, input_dim);
1218  linear_params_reduced_rank.AddMatMat(1.0, U, kNoTrans, Vt, kNoTrans, 0.0);
1219  CuMatrix<BaseFloat> linear_params_reduced_rank_cuda;
1220  linear_params_reduced_rank_cuda.Swap(&linear_params_reduced_rank);
1221  CuVector<BaseFloat> bias_params_cuda;
1222  bias_params_cuda.Swap(&bias_params);
1223  affine->SetParams(bias_params_cuda, linear_params_reduced_rank_cuda);
1224  num_components_changed++;
1225  }
1226  }
1227  KALDI_LOG << "Reduced rank of parameters of " << num_components_changed
1228  << " components.";
1229 }
kaldi::int32 int32
bool NameMatchesPattern(const char *name, const char *pattern)
Definition: nnet-parse.cc:235
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_WARN
Definition: kaldi-error.h:150
#define KALDI_LOG
Definition: kaldi-error.h:153
void SortSvd(VectorBase< Real > *s, MatrixBase< Real > *U, MatrixBase< Real > *Vt, bool sort_on_absolute_value)
Function to ensure that SVD is sorted.

◆ RemoveCommandsForUnusedMatrix()

void RemoveCommandsForUnusedMatrix ( const Analyzer analyzer,
int32  m,
NnetComputation computation 
)

This function removes from 'computation' the commands accessing matrix 'm', which is assumed to be unused according to the MatrixIsUnused() command above.

Specifically, it changes the types of the relevant commands in 'computation' to kNoOperation. (The commands changed in this way will be of type kAllocMatrix, kDeallocMatrix and kSetConst). The index for the matrix may later be removed entirely by RenumberComputation().

Definition at line 4600 of file nnet-optimize-utils.cc.

References MatrixAccesses::accesses, MatrixAccesses::allocate_command, NnetComputation::Command::command_type, NnetComputation::commands, MatrixAccesses::deallocate_command, rnnlm::i, KALDI_ASSERT, kAllocMatrix, kDeallocMatrix, kNoOperation, kSetConst, and Analyzer::matrix_accesses.

Referenced by DerivativeTimeLimiter::PruneMatrices().

4602  {
4603  const MatrixAccesses &accesses = analyzer.matrix_accesses[m];
4604  if (accesses.allocate_command >= 0) {
4605  NnetComputation::Command &command = computation->commands[
4606  accesses.allocate_command];
4607  KALDI_ASSERT(command.command_type == kNoOperation ||
4608  command.command_type == kAllocMatrix);
4609  command.command_type = kNoOperation;
4610  }
4611  if (accesses.deallocate_command >= 0) {
4612  NnetComputation::Command &command = computation->commands[
4613  accesses.deallocate_command];
4614  KALDI_ASSERT(command.command_type == kNoOperation ||
4615  command.command_type == kDeallocMatrix);
4616  command.command_type = kNoOperation;
4617  }
4618  for (size_t i = 0; i < accesses.accesses.size(); i++) {
4619  int32 command_index = accesses.accesses[i].command_index;
4620  NnetComputation::Command &command = computation->commands[command_index];
4621  KALDI_ASSERT(command.command_type == kNoOperation ||
4622  command.command_type == kSetConst);
4623  command.command_type = kNoOperation;
4624  }
4625 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ RemoveNoOps()

void RemoveNoOps ( NnetComputation computation)

Removes commands of type kNoOperation in the computation.

Definition at line 703 of file nnet-optimize-utils.cc.

References NnetComputation::commands, and IsNoop().

Referenced by DerivativeTimeLimiter::LimitDerivTimes(), VariableMergingOptimizer::MergeVariables(), and RemoveUnnecessaryAllocation().

703  {
704  computation->commands.erase(
705  std::remove_if(computation->commands.begin(),
706  computation->commands.end(),
707  IsNoop), computation->commands.end());
708 }
static bool IsNoop(const NnetComputation::Command &command)

◆ RemoveUnnecessaryAllocation()

void RemoveUnnecessaryAllocation ( const Nnet nnet,
NnetComputation computation 
)

This optimization detects cases where we deallocate a matrix, and then later allocate another matrix of the same size; and replaces them with commands of type kAllocFromOther or kAllocFromOtherZeroed.

Definition at line 355 of file nnet-optimize.cc.

References NnetComputation::Command::arg1, NnetComputation::Command::command_type, NnetComputation::commands, ComputeCommandPairs(), FixGotoLabel(), rnnlm::i, KALDI_ASSERT, kAllocMatrix, kDeallocMatrix, kaldi::kDefaultStride, kNoOperation, kSwapMatrix, NnetComputation::matrices, RemoveNoOps(), and NnetComputation::submatrices.

Referenced by Optimize().

356  {
357  // For each size of matrix and stride-type, represented as a pair<int32,int32>
358  // (the num-rows, and the num-cols * (stride-type == kDefaultStride ? 1 : -1), we
359  // accumulate a list of indexes of deallocation commands that
360  // are for that size, and a list of indexes of allocation commands
361  // for that size.
362  // For each distinct matrix size, we then call ComputeCommandPairs on those
363  // two lists, to get pairs of (deallocation, allocation) command-indexes that
364  // we can optimize out to a single command.
365 
366  // The map is from a (num-rows,num-columns) to two lists, of
367  // (deallocation-commands, allocation-commands). The order may seem
368  // backwards, but that's the order of the pairs we are looking for.
369  typedef unordered_map<std::pair<int32,int32>,
370  std::pair<std::vector<int32>,std::vector<int32> >,
371  PairHasher<int32> > MapType;
372  MapType pair_map;
373  int32 num_commands = computation->commands.size();
374  for (int32 command_index = 0; command_index < num_commands; command_index++) {
375  NnetComputation::Command &command = computation->commands[command_index];
376  if (command.command_type == kAllocMatrix ||
377  command.command_type == kDeallocMatrix) {
378  int32 s = command.arg1, m = computation->submatrices[s].matrix_index,
379  num_rows = computation->matrices[m].num_rows,
380  num_cols = computation->matrices[m].num_cols,
381  num_cols_mod = num_cols * (
382  computation->matrices[m].stride_type == kDefaultStride ? 1 : -1);
383  std::pair<int32,int32> p(num_rows, num_cols_mod);
384  std::pair<std::vector<int32>,std::vector<int32> > &lists = pair_map[p];
385  if (command.command_type == kDeallocMatrix)
386  lists.first.push_back(command_index);
387  else
388  lists.second.push_back(command_index);
389  }
390  }
391 
392  MapType::const_iterator iter = pair_map.begin(), end = pair_map.end();
393  std::vector<std::pair<int32,int32> > command_pairs;
394  for (; iter != end; ++iter)
395  ComputeCommandPairs(iter->second, &command_pairs);
396 
397  for (size_t i = 0; i < command_pairs.size(); i++) {
398  int32 dealloc_index = command_pairs[i].first,
399  alloc_index = command_pairs[i].second;
400  NnetComputation::Command
401  &dealloc_command = computation->commands[dealloc_index],
402  &alloc_command = computation->commands[alloc_index];
403  KALDI_ASSERT(dealloc_command.command_type ==
405  KALDI_ASSERT(alloc_command.command_type ==
406  kAllocMatrix);
407  // remove the deallocation command.
408  dealloc_command.command_type = kNoOperation;
409  alloc_command.arg2 = dealloc_command.arg1;
410  alloc_command.command_type = kSwapMatrix;
411  }
412  RemoveNoOps(computation);
413  FixGotoLabel(computation);
414 }
static void ComputeCommandPairs(const std::pair< std::vector< int32 >, std::vector< int32 > > &lists, std::vector< std::pair< int32, int32 > > *pairs)
kaldi::int32 int32
void FixGotoLabel(NnetComputation *computation)
This function ensures that the arg1 of a final command of type kGotoLabel is the same as the command ...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void RemoveNoOps(NnetComputation *computation)
Removes commands of type kNoOperation in the computation.

◆ RemoveUnnecessaryZeroing()

void RemoveUnnecessaryZeroing ( const Nnet nnet,
NnetComputation computation 
)

This optimization function removes, where possible, commands of type type kSetConst.

(It can remove them where subsequent commands are going to set the matrix without reading its previous value).

Definition at line 262 of file nnet-optimize.cc.

References MatrixAccesses::accesses, NnetComputation::Command::alpha, ComputationVariables::AppendVariablesForMatrix(), NnetComputation::Command::command_type, NnetComputation::commands, rnnlm::i, Analyzer::Init(), MatrixAccesses::is_output, kNoOperation, kSetConst, kWriteAccess, Analyzer::matrix_accesses, Analyzer::variable_accesses, and Analyzer::variables.

Referenced by Optimize().

263  {
264  Analyzer a;
265  a.Init(nnet, *computation);
266 
267  // OK, now we'll work out which matrices have all their pieces (i.e. all the
268  // variables belonging to that matrix) written to as the first instruction
269  // apart from the initial zeroing. These matrices can have the initial
270  // zeroing replaced by a sizing operation that leaves the data undefined.
271  int32 num_matrices = a.matrix_accesses.size();
272  for (int32 matrix_index = 0; matrix_index < num_matrices; matrix_index++) {
273  const MatrixAccesses &accesses = a.matrix_accesses[matrix_index];
274  if (accesses.accesses.empty())
275  continue;
276  int32 zeroing_command_index = accesses.accesses[0].command_index;
277  NnetComputation::Command *command =
278  &(computation->commands[zeroing_command_index]);
279  if (!(command->command_type == kSetConst &&
280  command->alpha == 0.0)) {
281  continue; // First command is not a zeroing command
282  }
283  // OK, the first command that accesses this matrix is a zeroing command;
284  // we're going to figure out whether it was necessary.
285  std::vector<int32> variables_for_matrix;
286  a.variables.AppendVariablesForMatrix(matrix_index, &variables_for_matrix);
287  bool all_variables_ok = true; // if this stays true, it means we don't need
288  // the initial zeroing.
289  for (size_t i = 0; i < variables_for_matrix.size(); i++) {
290  int32 variable_index = variables_for_matrix[i];
291  const std::vector<Access> &v_accesses =
292  a.variable_accesses[variable_index];
293  if (v_accesses.size() > 1 &&
294  v_accesses[1].access_type != kWriteAccess) {
295  all_variables_ok = false; // first access after zeroing was not a write
296  break;
297  }
298  if (v_accesses.size() == 1 &&
299  accesses.is_output) {
300  // the only command that touches this variable is the allocation, and it
301  // is an output variable. (this is unusual, but can happen e.g. if it's
302  // a derivative, but due to min_deriv_time and max_deriv_time it ends up
303  // always being zero.
304  all_variables_ok = false;
305  break;
306  }
307  }
308  if (all_variables_ok) {
309  // Here is where the change actually happens.
310  // Remove the zeroing command.
311  command->command_type = kNoOperation;
312  }
313  }
314 }
kaldi::int32 int32

◆ RenameOutputs()

void kaldi::nnet3::RenameOutputs ( const std::string &  new_name,
NnetExample eg 
)

Definition at line 31 of file nnet3-copy-egs.cc.

References NnetExample::io, and KALDI_ERR.

Referenced by main().

31  {
32  bool found_output = false;
33  for (std::vector<NnetIo>::iterator it = eg->io.begin();
34  it != eg->io.end(); ++it) {
35  if (it->name == "output") {
36  it->name = new_name;
37  found_output = true;
38  }
39  }
40 
41  if (!found_output)
42  KALDI_ERR << "No io-node with name 'output'"
43  << "exists in eg.";
44 }
#define KALDI_ERR
Definition: kaldi-error.h:147
std::vector< NnetIo > io
"io" contains the input and output.
Definition: nnet-example.h:116

◆ RenumberComputation()

void RenumberComputation ( NnetComputation computation)

This function detects submatrices and matrices that are never used (e.g.

due to changes made in other optimization code), and members of indexes, indexes_multi and indexes_ranges that are unused or are duplicates, and memo indexes that are unused; and it removes them from the computation by way of suitable renumbering. It does not remove no-ops from computation->commands_; to do that, call RemoveNoOps(computation).

Definition at line 693 of file nnet-optimize-utils.cc.

References ComputationRenumberer::Renumber().

Referenced by MatrixExtender::FixComputation(), DerivativeTimeLimiter::LimitDerivTimes(), VariableMergingOptimizer::MergeVariables(), Optimize(), and ComputationLoopedOptimizer::Optimize().

693  {
694  ComputationRenumberer renumberer(computation);
695  renumberer.Renumber();
696 }

◆ ReplaceRowWithMatrixOps()

bool ReplaceRowWithMatrixOps ( NnetComputation computation)

This function detects cases where commands of type kCopyRows, kAddRows or kAddToRows can be converted to commands of type kMatrixCopy or kMatrixAdd, and converts them (this may involve adding submatrices).

This function returns true if it made any changes to the computation; if it returns true, then after doing this you should at some point do RenumberComputation(), which will remove any now-unused members of computation->indexes.

Definition at line 2288 of file nnet-optimize-utils.cc.

References NnetComputation::Command::arg1, NnetComputation::Command::arg2, NnetComputation::Command::arg3, NnetComputation::Command::command_type, NnetComputation::commands, NnetComputation::indexes, IndexesHaveSpecialStructure(), kAddRows, KALDI_ASSERT, kCopyRows, kMatrixAdd, kMatrixCopy, and NnetComputation::NewSubMatrix().

Referenced by Optimize().

2288  {
2289  bool ans = false;
2290  int32 num_commands = computation->commands.size(),
2291  num_indexes = computation->indexes.size();
2292  for (int32 command_index = 0; command_index < num_commands;
2293  command_index++) {
2294  // non-const because we'll be changing it.
2295  NnetComputation::Command &c = computation->commands[command_index];
2296 
2297  int32 first_nonnegative_pos,
2298  first_nonnegative_value,
2299  num_nonnegative_indexes;
2300  switch (c.command_type) {
2301  case kCopyRows: case kAddRows: {
2302  int32 indexes_index = c.arg3;
2303  KALDI_ASSERT(indexes_index < num_indexes);
2304  const std::vector<int32> &indexes = computation->indexes[indexes_index];
2305  if (IndexesHaveSpecialStructure(indexes,
2306  &first_nonnegative_pos,
2307  &first_nonnegative_value,
2308  &num_nonnegative_indexes)) {
2309  ans = true;
2310  c.arg1 = computation->NewSubMatrix(c.arg1, first_nonnegative_pos,
2311  num_nonnegative_indexes,
2312  0, -1);
2313  c.arg2 = computation->NewSubMatrix(c.arg2, first_nonnegative_value,
2314  num_nonnegative_indexes,
2315  0, -1);
2316  c.command_type = (c.command_type == kCopyRows ? kMatrixCopy :
2317  kMatrixAdd);
2318  }
2319  break;
2320  }
2321  default:
2322  break;
2323  }
2324  }
2325  return ans;
2326 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static bool IndexesHaveSpecialStructure(const std::vector< int32 > &indexes, int32 *first_nonnegative_pos, int32 *first_nonnegative_value, int32 *num_nonnegative_indexes)

◆ RequestIsDecomposable()

bool RequestIsDecomposable ( const ComputationRequest request,
ComputationRequest mini_request,
int32 num_n_values 
)

This function, used in 'shortcut' compilation where we first compile a smaller computation with the same structure but only 2 distinct 'n' values, works out whether a computation is 'decomposable'; if so, it returns true and outputs the 'mini_request' with the same structure, and the number of 'n' values.

A computation is decomposable if the following conditions hold:

  • All of its inputs and outputs contain 'n' values for all 0 <= n < N, for some N > 2. [we output this 'N' as 'num_n_values'].
  • All of its inputs and outputs have 'regular' structure: chiefly, that within vectors of Indexes, each (t, x) pair should be present for the same set of 'n' values (0, 1, ... N-1), and that we should be able to identify the stride of the 'n' index. For more precise details on this regular structure, look at the comment for the function FindNStride(), in nnet-optimize-utils.cc.

Definition at line 3852 of file nnet-optimize-utils.cc.

References rnnlm::i, ComputationRequest::inputs, IoSpecificationIsDecomposable(), KALDI_ASSERT, ComputationRequest::misc_info, ComputationRequest::need_model_derivative, ComputationRequest::outputs, and ComputationRequest::store_component_stats.

Referenced by CachingOptimizingCompiler::CompileViaShortcut().

3854  {
3855  size_t num_inputs = request.inputs.size(),
3856  num_outputs = request.outputs.size();
3857  mini_request->inputs.resize(num_inputs);
3858  mini_request->outputs.resize(num_outputs);
3859  mini_request->need_model_derivative = request.need_model_derivative;
3860  mini_request->store_component_stats = request.store_component_stats;
3861  mini_request->misc_info = request.misc_info;
3862 
3863  KALDI_ASSERT(num_inputs != 0 && num_outputs != 0);
3864  for (size_t i = 0; i < num_inputs; i++) {
3865  int32 this_num_n_values = 0;
3866  if (!IoSpecificationIsDecomposable(request.inputs[i],
3867  &(mini_request->inputs[i]),
3868  &this_num_n_values))
3869  return false;
3870  if (i == 0) {
3871  *num_n_values = this_num_n_values;
3872  } else {
3873  if (this_num_n_values != *num_n_values)
3874  return false; // .. which would be odd.
3875  }
3876  }
3877  for (size_t i = 0; i < num_outputs; i++) {
3878  int32 this_num_n_values = 0;
3879  if (!IoSpecificationIsDecomposable(request.outputs[i],
3880  &(mini_request->outputs[i]),
3881  &this_num_n_values))
3882  return false;
3883  if (this_num_n_values != *num_n_values)
3884  return false; // .. which would be odd.
3885  }
3886  return true;
3887 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static bool IoSpecificationIsDecomposable(const IoSpecification &io_spec, IoSpecification *mini_io_spec, int32 *num_n_values_out)

◆ ResetGenerators()

void ResetGenerators ( Nnet nnet)

This function calls 'ResetGenerator()' on all components in 'nnet' that inherit from class RandomComponent.

It's used when you need to ensure consistency in things like dropout masks, across subsequent neural net evaluations. You will likely want to call srand() before calling this.

Definition at line 582 of file nnet-utils.cc.

References Nnet::GetComponent(), Nnet::NumComponents(), and RandomComponent::ResetGenerator().

Referenced by Nnet::Copy(), NnetChainTrainer::Train(), NnetTrainer::Train(), and UnitTestNnetOptimizeWithOptions().

582  {
583  for (int32 c = 0; c < nnet->NumComponents(); c++) {
584  Component *comp = nnet->GetComponent(c);
585  RandomComponent *rc = dynamic_cast<RandomComponent*>(comp);
586  if (rc != NULL)
587  rc->ResetGenerator();
588  }
589 }
kaldi::int32 int32

◆ ResetSeed()

static void kaldi::nnet3::ResetSeed ( int32  rand_seed,
const Component c 
)
static

Definition at line 27 of file nnet-component-test.cc.

References RandomComponent::ResetGenerator().

Referenced by TestSimpleComponentDataDerivative(), and TestSimpleComponentPropagateProperties().

27  {
28  RandomComponent *rand_component =
29  const_cast<RandomComponent*>(dynamic_cast<const RandomComponent*>(&c));
30 
31  if (rand_component != NULL) {
32  srand(rand_seed);
33  rand_component->ResetGenerator();
34  }
35 }

◆ RoundUpNumFrames()

void kaldi::nnet3::RoundUpNumFrames ( int32  frame_subsampling_factor,
int32 num_frames,
int32 num_frames_overlap 
)

Definition at line 275 of file nnet-example-utils.cc.

References KALDI_ERR, and KALDI_LOG.

277  {
278  if (*num_frames % frame_subsampling_factor != 0) {
279  int32 new_num_frames = frame_subsampling_factor *
280  (*num_frames / frame_subsampling_factor + 1);
281  KALDI_LOG << "Rounding up --num-frames=" << (*num_frames)
282  << " to a multiple of --frame-subsampling-factor="
283  << frame_subsampling_factor
284  << ", now --num-frames=" << new_num_frames;
285  *num_frames = new_num_frames;
286  }
287  if (*num_frames_overlap % frame_subsampling_factor != 0) {
288  int32 new_num_frames_overlap = frame_subsampling_factor *
289  (*num_frames_overlap / frame_subsampling_factor + 1);
290  KALDI_LOG << "Rounding up --num-frames-overlap=" << (*num_frames_overlap)
291  << " to a multiple of --frame-subsampling-factor="
292  << frame_subsampling_factor
293  << ", now --num-frames-overlap=" << new_num_frames_overlap;
294  *num_frames_overlap = new_num_frames_overlap;
295  }
296  if (*num_frames_overlap < 0 || *num_frames_overlap >= *num_frames) {
297  KALDI_ERR << "--num-frames-overlap=" << (*num_frames_overlap) << " < "
298  << "--num-frames=" << (*num_frames);
299  }
300 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ RunNnetComputation()

static void kaldi::nnet3::RunNnetComputation ( const MatrixBase< BaseFloat > &  features,
const Nnet nnet,
CachingOptimizingCompiler compiler,
Vector< BaseFloat > *  xvector 
)
static

Definition at line 33 of file nnet3-xvector-compute.cc.

References NnetComputer::AcceptInput(), CachingOptimizingCompiler::Compile(), VectorBase< Real >::CopyFromVec(), NnetComputer::GetOutputDestructive(), IoSpecification::has_deriv, IoSpecification::indexes, ComputationRequest::inputs, IoSpecification::name, ComputationRequest::need_model_derivative, CuMatrixBase< Real >::NumCols(), MatrixBase< Real >::NumRows(), ComputationRequest::outputs, Vector< Real >::Resize(), CuMatrixBase< Real >::Row(), NnetComputer::Run(), and ComputationRequest::store_component_stats.

Referenced by main().

35  {
36  ComputationRequest request;
37  request.need_model_derivative = false;
38  request.store_component_stats = false;
39  request.inputs.push_back(
40  IoSpecification("input", 0, features.NumRows()));
41  IoSpecification output_spec;
42  output_spec.name = "output";
43  output_spec.has_deriv = false;
44  output_spec.indexes.resize(1);
45  request.outputs.resize(1);
46  request.outputs[0].Swap(&output_spec);
47  std::shared_ptr<const NnetComputation> computation(compiler->Compile(request));
48  Nnet *nnet_to_update = NULL; // we're not doing any update.
49  NnetComputer computer(NnetComputeOptions(), *computation,
50  nnet, nnet_to_update);
51  CuMatrix<BaseFloat> input_feats_cu(features);
52  computer.AcceptInput("input", &input_feats_cu);
53  computer.Run();
54  CuMatrix<BaseFloat> cu_output;
55  computer.GetOutputDestructive("output", &cu_output);
56  xvector->Resize(cu_output.NumCols());
57  xvector->CopyFromVec(cu_output.Row(0));
58 }
bool store_component_stats
you should set need_component_stats to true if you need the average-activation and average-derivative...
const CuSubVector< Real > Row(MatrixIndexT i) const
Definition: cu-matrix.h:670
bool need_model_derivative
if need_model_derivative is true, then we&#39;ll be doing either model training or model-derivative compu...
std::vector< IoSpecification > inputs
This class represents a matrix that&#39;s stored on the GPU if we have one, and in memory if not...
Definition: matrix-common.h:71
void Resize(MatrixIndexT length, MatrixResizeType resize_type=kSetZero)
Set vector to a specified size (can be zero).
void CopyFromVec(const VectorBase< Real > &v)
Copy data from another vector (must match own size).
std::shared_ptr< const NnetComputation > Compile(const ComputationRequest &request)
Does the compilation and returns a const pointer to the result, which is owned by this class...
std::vector< Index > indexes
MatrixIndexT NumCols() const
Definition: cu-matrix.h:216
class NnetComputer is responsible for executing the computation described in the "computation" object...
Definition: nnet-compute.h:59
std::vector< IoSpecification > outputs
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
Definition: kaldi-matrix.h:64

◆ ScaleBatchnormStats()

void ScaleBatchnormStats ( BaseFloat  batchnorm_stats_scale,
Nnet nnet 
)

This function scales the batchorm stats of any batchnorm components (components of type BatchNormComponent) in 'nnet' by the scale 'batchnorm_stats_scale'.

Definition at line 536 of file nnet-utils.cc.

References Nnet::GetComponent(), KALDI_ASSERT, Nnet::NumComponents(), and BatchNormComponent::Scale().

Referenced by CollapseModelConfig::CollapseModelConfig(), NnetChainTrainer::TrainInternal(), NnetTrainer::TrainInternal(), NnetChainTrainer::TrainInternalBackstitch(), and NnetTrainer::TrainInternalBackstitch().

537  {
538  KALDI_ASSERT(batchnorm_stats_scale >= 0.0 && batchnorm_stats_scale <= 1.0);
539  if (batchnorm_stats_scale == 1.0)
540  return;
541  for (int32 c = 0; c < nnet->NumComponents(); c++) {
542  Component *comp = nnet->GetComponent(c);
543  BatchNormComponent *bc = dynamic_cast<BatchNormComponent*>(comp);
544  if (bc != NULL)
545  bc->Scale(batchnorm_stats_scale);
546  }
547 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ScaleNnet()

◆ ScaleSupervisionWeight()

void kaldi::nnet3::ScaleSupervisionWeight ( BaseFloat  weight,
NnetExample eg 
)

Definition at line 47 of file nnet3-copy-egs.cc.

References NnetExample::io, and KALDI_ERR.

Referenced by main().

47  {
48  if (weight == 1.0) return;
49 
50  bool found_output = false;
51  for (std::vector<NnetIo>::iterator it = eg->io.begin();
52  it != eg->io.end(); ++it) {
53  if (it->name == "output") {
54  it->features.Scale(weight);
55  found_output = true;
56  }
57  }
58 
59  if (!found_output)
60  KALDI_ERR << "No supervision with name 'output'"
61  << "exists in eg.";
62 }
#define KALDI_ERR
Definition: kaldi-error.h:147
std::vector< NnetIo > io
"io" contains the input and output.
Definition: nnet-example.h:116

◆ SelectFromExample()

bool kaldi::nnet3::SelectFromExample ( const NnetExample eg,
std::string  frame_str,
int32  left_context,
int32  right_context,
int32  frame_shift,
NnetExample eg_out 
)

This function is responsible for possibly selecting one frame from multiple supervised frames, and reducing the left and right context as specified.

If frame == "" it does not reduce the supervised frames; if frame == "random" it selects one random frame; otherwise it expects frame to be an integer, and will select only the output with that frame index (or return false if there was no such output).

If left_context != -1 it removes any inputs with t < (smallest output - left_context). If left_context != -1 it removes any inputs with t < (smallest output - left_context).

It returns true if it was able to select a frame. We only anticipate it ever returning false in situations where frame is an integer, and the eg came from the end of a file and has a smaller than normal number of supervised frames.

Definition at line 222 of file nnet3-copy-egs.cc.

References ContainsSingleExample(), kaldi::ConvertStringToInteger(), FilterExample(), KALDI_ERR, KALDI_WARN, kaldi::RandInt(), and ShiftExampleTimes().

Referenced by main().

227  {
228  static bool warned_left = false, warned_right = false;
229  int32 min_input_t, max_input_t,
230  min_output_t, max_output_t;
231  if (!ContainsSingleExample(eg, &min_input_t, &max_input_t,
232  &min_output_t, &max_output_t))
233  KALDI_ERR << "Too late to perform frame selection/context reduction on "
234  << "these examples (already merged?)";
235  if (frame_str != "") {
236  // select one frame.
237  if (frame_str == "random") {
238  min_output_t = max_output_t = RandInt(min_output_t,
239  max_output_t);
240  } else {
241  int32 frame;
242  if (!ConvertStringToInteger(frame_str, &frame))
243  KALDI_ERR << "Invalid option --frame='" << frame_str << "'";
244  if (frame < min_output_t || frame > max_output_t) {
245  // Frame is out of range. Should happen only rarely. Calling code
246  // makes sure of this.
247  return false;
248  }
249  min_output_t = max_output_t = frame;
250  }
251  }
252  if (left_context != -1) {
253  if (!warned_left && min_input_t > min_output_t - left_context) {
254  warned_left = true;
255  KALDI_WARN << "You requested --left-context=" << left_context
256  << ", but example only has left-context of "
257  << (min_output_t - min_input_t)
258  << " (will warn only once; this may be harmless if "
259  "using any --*left-context-initial options)";
260  }
261  min_input_t = std::max(min_input_t, min_output_t - left_context);
262  }
263  if (right_context != -1) {
264  if (!warned_right && max_input_t < max_output_t + right_context) {
265  warned_right = true;
266  KALDI_WARN << "You requested --right-context=" << right_context
267  << ", but example only has right-context of "
268  << (max_input_t - max_output_t)
269  << " (will warn only once; this may be harmless if "
270  "using any --*right-context-final options.";
271  }
272  max_input_t = std::min(max_input_t, max_output_t + right_context);
273  }
274  FilterExample(eg,
275  min_input_t, max_input_t,
276  min_output_t, max_output_t,
277  eg_out);
278  if (frame_shift != 0) {
279  std::vector<std::string> exclude_names; // we can later make this
280  exclude_names.push_back(std::string("ivector")); // configurable.
281  ShiftExampleTimes(frame_shift, exclude_names, eg_out);
282  }
283  return true;
284 }
bool ConvertStringToInteger(const std::string &str, Int *out)
Converts a string into an integer via strtoll and returns false if there was any kind of problem (i...
Definition: text-utils.h:118
kaldi::int32 int32
void ShiftExampleTimes(int32 t_offset, const std::vector< std::string > &exclude_names, NnetExample *eg)
Shifts the time-index t of everything in the "eg" by adding "t_offset" to all "t" values...
bool ContainsSingleExample(const NnetExample &eg, int32 *min_input_t, int32 *max_input_t, int32 *min_output_t, int32 *max_output_t)
Returns true if the "eg" contains just a single example, meaning that all the "n" values in the index...
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_WARN
Definition: kaldi-error.h:150
void FilterExample(const NnetExample &eg, int32 min_input_t, int32 max_input_t, int32 min_output_t, int32 max_output_t, NnetExample *eg_out)
This function filters the indexes (and associated feature rows) in a NnetExample, removing any index/...
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ SeparateSubmatsWithLargeCounts()

void kaldi::nnet3::SeparateSubmatsWithLargeCounts ( const std::vector< int32 > &  submats_to_separate,
const std::vector< std::vector< std::pair< int32, int32 > > > &  submat_lists,
std::vector< std::vector< std::pair< int32, int32 > > > *  reduced_submat_lists,
std::vector< std::vector< std::pair< int32, int32 > > > *  split_lists 
)

This function, used in SplitLocations(), is used to make separate 'split lists' for certain high-count submatrix indexes, specified by the user in 'submats_to_separate'.

These split lists will be lists of pairs that are all either (-1, 1) or (submatrix_index, x) for a particular submatrix index (constant within the split list). These high-count lists will be written to 'split_lists'; they will eventually compile to AddRows() commands. We write the remaining members of the lists in 'submat_lists' (the ones that did not make it into 'split_lists') to 'reduced_submat_lists'.

Definition at line 73 of file nnet-compile-utils.cc.

References rnnlm::i, and KALDI_ASSERT.

Referenced by SplitLocations().

77  {
78  KALDI_ASSERT(split_lists->empty() && !submats_to_separate.empty());
79  size_t num_to_separate = submats_to_separate.size(),
80  num_rows = submat_lists.size();
81  std::unordered_map<int32, size_t> submat_to_index;
82  reduced_submat_lists->clear();
83  reduced_submat_lists->resize(num_rows);
84  split_lists->resize(num_to_separate);
85  for (size_t i = 0; i < num_to_separate; i++) {
86  (*split_lists)[i].resize(num_rows, std::pair<int32, int32>(-1, -1));
87  int32 submat = submats_to_separate[i];
88  submat_to_index[submat] = i;
89  }
90  for (size_t row = 0; row < submat_lists.size(); row++) {
91  std::vector<std::pair<int32, int32> >::const_iterator
92  iter = submat_lists[row].begin(), end = submat_lists[row].end();
93  std::vector<std::pair<int32, int32> >
94  &reduced_list = (*reduced_submat_lists)[row];
95  // 'reduced_lists' will contain the pairs that don't make it into
96  // 'split_lists'.
97  for (; iter != end; ++iter) {
98  int32 submat_index = iter->first;
99  std::unordered_map<int32, size_t>::const_iterator map_iter =
100  submat_to_index.find(submat_index);
101  if (map_iter == submat_to_index.end()) { // not a large-count submatrix.
102  reduced_list.push_back(*iter);
103  continue;
104  }
105  size_t index = map_iter->second;
106  std::pair<int32,int32> &p = (*split_lists)[index][row];
107  if (p.first >= 0) {
108  // we'd only reach here if the same submat index repeated in the same
109  // row, which is possible but rare.
110  reduced_list.push_back(*iter);
111  continue;
112  }
113  p.first = submat_index;
114  int32 src_row_index = iter->second;
115  p.second = src_row_index;
116  }
117  }
118 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ SetBatchnormTestMode()

void SetBatchnormTestMode ( bool  test_mode,
Nnet nnet 
)

This function affects only components of type BatchNormComponent.

It sets "test mode" on such components (if you call it with test_mode = true, otherwise it would set normal mode, but this wouldn't be needed often). "test mode" means that instead of using statistics from the batch, it does a deterministic normalization based on statistics stored at training time.

Definition at line 564 of file nnet-utils.cc.

References Nnet::GetComponent(), Nnet::NumComponents(), and BatchNormComponent::SetTestMode().

Referenced by ComputeObjf(), main(), TestNnetDecodable(), and UnitTestNnetCompute().

564  {
565  for (int32 c = 0; c < nnet->NumComponents(); c++) {
566  Component *comp = nnet->GetComponent(c);
567  BatchNormComponent *bc = dynamic_cast<BatchNormComponent*>(comp);
568  if (bc != NULL)
569  bc->SetTestMode(test_mode);
570  }
571 }
kaldi::int32 int32

◆ SetDerivTimesOptions()

void kaldi::nnet3::SetDerivTimesOptions ( const ComputationRequest request,
NnetOptimizeOptions opt_config 
)

Definition at line 46 of file nnet-derivative-test.cc.

References ComputeMinAndMaxTimes(), ComputationRequest::inputs, KALDI_ASSERT, KALDI_LOG, NnetOptimizeOptions::max_deriv_time, NnetOptimizeOptions::min_deriv_time, ComputationRequest::outputs, and kaldi::RandInt().

Referenced by UnitTestNnetModelDerivatives().

47  {
48  int32 min_t, max_t;
49  KALDI_ASSERT(request.inputs[0].name == "input");
50  const std::vector<Index> &input_indexes = request.inputs[0].indexes;
51  ComputeMinAndMaxTimes(input_indexes, &min_t, &max_t);
52 
53  int32 orig_min_t = min_t, orig_max_t = max_t;
54  int t_length = max_t + 1 - min_t;
55  KALDI_ASSERT(t_length > 0);
56  if (t_length == 1)
57  return;
58  if (RandInt(0, 2) == 0) {
59  // remove as much as 4 frames from the left (but don't remove everything).
60  min_t += std::min(4, RandInt(0, t_length - 1));
61  opt_config->min_deriv_time = min_t;
62  t_length = max_t + 1 - min_t;
63  KALDI_ASSERT(t_length > 0);
64  }
65  if (RandInt(0, 2) == 0) {
66  max_t -= std::min(4, RandInt(0, t_length - 1));
67  opt_config->max_deriv_time = max_t;
68  t_length = max_t + 1 - min_t;
69  KALDI_ASSERT(t_length > 0);
70  }
71  if (RandInt(0, 4) == 0) {
72  // ensure that all derivs will be pruned away;
73  // this tests more code.
74  min_t = orig_min_t - 10;
75  max_t = min_t + 1;
76  }
77 
78  int32 output_min_t, output_max_t;
79  KALDI_ASSERT(request.outputs[0].name == "output");
80  ComputeMinAndMaxTimes(request.outputs[0].indexes,
81  &output_min_t, &output_max_t);
82 
83  KALDI_LOG << "ComputationRequest has output (min,max) = (" << output_min_t
84  << ',' << output_max_t << "), input (min,max) = (" << orig_min_t
85  << ',' << orig_max_t << "), limiting deriv times to ("
86  << opt_config->min_deriv_time << ','
87  << opt_config->max_deriv_time << ')';
88 }
kaldi::int32 int32
std::vector< IoSpecification > inputs
void ComputeMinAndMaxTimes(const std::vector< Index > &indexes, int32 *min_t, int32 *max_t)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
std::vector< IoSpecification > outputs
#define KALDI_LOG
Definition: kaldi-error.h:153
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ SetDropoutProportion()

void SetDropoutProportion ( BaseFloat  dropout_proportion,
Nnet nnet 
)

This function sets the dropout proportion in all dropout components to dropout_proportion value.

Definition at line 509 of file nnet-utils.cc.

References Nnet::GetComponent(), Nnet::NumComponents(), DropoutComponent::SetDropoutProportion(), DropoutMaskComponent::SetDropoutProportion(), and GeneralDropoutComponent::SetDropoutProportion().

510  {
511  for (int32 c = 0; c < nnet->NumComponents(); c++) {
512  Component *comp = nnet->GetComponent(c);
513  DropoutComponent *dc = dynamic_cast<DropoutComponent*>(comp);
514  if (dc != NULL)
515  dc->SetDropoutProportion(dropout_proportion);
516  DropoutMaskComponent *mc =
517  dynamic_cast<DropoutMaskComponent*>(nnet->GetComponent(c));
518  if (mc != NULL)
519  mc->SetDropoutProportion(dropout_proportion);
520  GeneralDropoutComponent *gdc =
521  dynamic_cast<GeneralDropoutComponent*>(nnet->GetComponent(c));
522  if (gdc != NULL)
523  gdc->SetDropoutProportion(dropout_proportion);
524  }
525 }
kaldi::int32 int32

◆ SetDropoutTestMode()

void SetDropoutTestMode ( bool  test_mode,
Nnet nnet 
)

This function affects components of child-classes of RandomComponent.

It sets "test mode" on such components (if you call it with test_mode = true, otherwise it would set normal mode, but this wouldn't be needed often). "test mode" means that having a mask containing (1-dropout_prob) in all elements.

Definition at line 573 of file nnet-utils.cc.

References Nnet::GetComponent(), Nnet::NumComponents(), and RandomComponent::SetTestMode().

Referenced by ComputeObjf(), main(), TestNnetDecodable(), and UnitTestNnetCompute().

573  {
574  for (int32 c = 0; c < nnet->NumComponents(); c++) {
575  Component *comp = nnet->GetComponent(c);
576  RandomComponent *rc = dynamic_cast<RandomComponent*>(comp);
577  if (rc != NULL)
578  rc->SetTestMode(test_mode);
579  }
580 }
kaldi::int32 int32

◆ SetLearningRate()

void SetLearningRate ( BaseFloat  learning_rate,
Nnet nnet 
)

Sets the underlying learning rate for all the components in the nnet to this value.

this will get multiplied by the individual learning-rate-factors to produce the actual learning rates.

Definition at line 276 of file nnet-utils.cc.

References Nnet::GetComponent(), KALDI_ERR, kUpdatableComponent, Nnet::NumComponents(), Component::Properties(), and UpdatableComponent::SetUnderlyingLearningRate().

Referenced by main().

277  {
278  for (int32 c = 0; c < nnet->NumComponents(); c++) {
279  Component *comp = nnet->GetComponent(c);
280  if (comp->Properties() & kUpdatableComponent) {
281  // For now all updatable components inherit from class UpdatableComponent.
282  // If that changes in future, we will change this code.
283  UpdatableComponent *uc = dynamic_cast<UpdatableComponent*>(comp);
284  if (uc == NULL)
285  KALDI_ERR << "Updatable component does not inherit from class "
286  "UpdatableComponent; change this code.";
287  uc->SetUnderlyingLearningRate(learning_rate);
288  }
289  }
290 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147

◆ SetNnetAsGradient()

void SetNnetAsGradient ( Nnet nnet)

Sets nnet as gradient by Setting is_gradient_ to true and learning_rate_ to 1 for each UpdatableComponent in nnet.

Definition at line 292 of file nnet-utils.cc.

References Nnet::GetComponent(), KALDI_ASSERT, kUpdatableComponent, Nnet::NumComponents(), Component::Properties(), and UpdatableComponent::SetAsGradient().

Referenced by NnetChainComputeProb::NnetChainComputeProb(), NnetComputeProb::NnetComputeProb(), NnetDiscriminativeComputeObjf::NnetDiscriminativeComputeObjf(), NnetDiscriminativeComputeObjf::Reset(), NnetChainComputeProb::Reset(), NnetComputeProb::Reset(), UnitTestNnetModelDerivatives(), and UnitTestNnetOptimizeWithOptions().

292  {
293  for (int32 c = 0; c < nnet->NumComponents(); c++) {
294  Component *comp = nnet->GetComponent(c);
295  if (comp->Properties() & kUpdatableComponent) {
296  UpdatableComponent *u_comp = dynamic_cast<UpdatableComponent*>(comp);
297  KALDI_ASSERT(u_comp != NULL);
298  u_comp->SetAsGradient();
299  }
300  }
301 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ SetPriors()

void kaldi::nnet3::SetPriors ( const TransitionModel tmodel,
const Vector< double > &  transition_accs,
double  prior_floor,
AmNnetSimple am_nnet 
)

Definition at line 28 of file nnet3-am-train-transitions.cc.

References VectorBase< Real >::Dim(), KALDI_ASSERT, AmNnetSimple::NumPdfs(), TransitionModel::NumPdfs(), AmNnetSimple::SetPriors(), and TransitionModel::TransitionIdToPdf().

Referenced by main().

31  {
32  KALDI_ASSERT(tmodel.NumPdfs() == am_nnet->NumPdfs());
33  Vector<BaseFloat> pdf_counts(tmodel.NumPdfs());
34  KALDI_ASSERT(transition_accs(0) == 0.0); // There is
35  // no zero transition-id.
36  for (int32 tid = 1; tid < transition_accs.Dim(); tid++) {
37  int32 pdf = tmodel.TransitionIdToPdf(tid);
38  pdf_counts(pdf) += transition_accs(tid);
39  }
40  BaseFloat sum = pdf_counts.Sum();
41  KALDI_ASSERT(sum != 0.0);
42  KALDI_ASSERT(prior_floor > 0.0 && prior_floor < 1.0);
43  pdf_counts.Scale(1.0 / sum);
44  pdf_counts.ApplyFloor(prior_floor);
45  pdf_counts.Scale(1.0 / pdf_counts.Sum()); // normalize again.
46  am_nnet->SetPriors(pdf_counts);
47 }
kaldi::int32 int32
int32 TransitionIdToPdf(int32 trans_id) const
void SetPriors(const VectorBase< BaseFloat > &priors)
float BaseFloat
Definition: kaldi-types.h:29
MatrixIndexT Dim() const
Returns the dimension of the vector.
Definition: kaldi-vector.h:64
A class representing a vector.
Definition: kaldi-vector.h:406
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ SetRequireDirectInput()

void SetRequireDirectInput ( bool  b,
Nnet nnet 
)

Calls the corresponding function in any component of type StatisticsPoolingComponent; used as a way to compute the 'real' left-right context of networks including SatisticsPoolingComponent, which will give you the minimum chunk size they can consume.

Definition at line 303 of file nnet-utils.cc.

References Nnet::GetComponent(), and Nnet::NumComponents().

Referenced by main().

303  {
304  for (int32 c = 0; c < nnet->NumComponents(); c++) {
305  Component *comp = nnet->GetComponent(c);
306  if (dynamic_cast<StatisticsPoolingComponent*>(comp) != NULL)
307  dynamic_cast<StatisticsPoolingComponent*>(comp)->SetRequireDirectInput(b);
308  }
309 }
kaldi::int32 int32
void SetRequireDirectInput(bool b, Nnet *nnet)
Calls the corresponding function in any component of type StatisticsPoolingComponent; used as a way t...
Definition: nnet-utils.cc:303

◆ ShiftChainExampleTimes()

void ShiftChainExampleTimes ( int32  frame_shift,
const std::vector< std::string > &  exclude_names,
NnetChainExample eg 
)

Shifts the time-index t of everything in the input of "eg" by adding "t_offset" to all "t" values– but excluding those with names listed in "exclude_names", e.g.

"ivector". This might be useful if you are doing subsampling of frames at the output, because shifted examples won't be quite equivalent to their non-shifted counterparts. "exclude_names" is a vector of names of nnet inputs that we avoid shifting the "t" values of– normally it will contain just the single string "ivector" because we always leave t=0 for any ivector.

Note: input features will be shifted by 'frame_shift', and indexes in the supervision in (eg->output) will be shifted by 'frame_shift' rounded to the closest multiple of the frame subsampling factor (e.g. 3). The frame subsampling factor is worked out from the time spacing between the indexes in the output.

Definition at line 353 of file nnet-chain-example.cc.

References NnetChainExample::inputs, KALDI_ASSERT, and NnetChainExample::outputs.

Referenced by NnetChainExampleStructureCompare::operator()().

355  {
356  std::vector<NnetIo>::iterator input_iter = eg->inputs.begin(),
357  input_end = eg->inputs.end();
358  for (; input_iter != input_end; ++input_iter) {
359  bool must_exclude = false;
360  std::vector<std::string>::const_iterator exclude_iter = exclude_names.begin(),
361  exclude_end = exclude_names.end();
362  for (; exclude_iter != exclude_end; ++exclude_iter)
363  if (input_iter->name == *exclude_iter)
364  must_exclude = true;
365  if (!must_exclude) {
366  std::vector<Index>::iterator indexes_iter = input_iter->indexes.begin(),
367  indexes_end = input_iter->indexes.end();
368  for (; indexes_iter != indexes_end; ++indexes_iter)
369  indexes_iter->t += frame_shift;
370  }
371  }
372  // note: we'll normally choose a small enough shift that the output-data
373  // shift will be zero after dividing by frame_subsampling_factor
374  // (e.g. frame_subsampling_factor == 3 and shift = 0 or 1.
375  std::vector<NnetChainSupervision>::iterator
376  sup_iter = eg->outputs.begin(),
377  sup_end = eg->outputs.end();
378  for (; sup_iter != sup_end; ++sup_iter) {
379  std::vector<Index> &indexes = sup_iter->indexes;
380  KALDI_ASSERT(indexes.size() >= 2 && indexes[0].n == indexes[1].n &&
381  indexes[0].x == indexes[1].x);
382  int32 frame_subsampling_factor = indexes[1].t - indexes[0].t;
383  KALDI_ASSERT(frame_subsampling_factor > 0);
384 
385  // We need to shift by a multiple of frame_subsampling_factor.
386  // Round to the closest multiple.
387  int32 supervision_frame_shift =
388  frame_subsampling_factor *
389  std::floor(0.5 + (frame_shift * 1.0 / frame_subsampling_factor));
390  if (supervision_frame_shift == 0)
391  continue;
392  std::vector<Index>::iterator indexes_iter = indexes.begin(),
393  indexes_end = indexes.end();
394  for (; indexes_iter != indexes_end; ++indexes_iter)
395  indexes_iter->t += supervision_frame_shift;
396  }
397 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ShiftDiscriminativeExampleTimes()

void ShiftDiscriminativeExampleTimes ( int32  frame_shift,
const std::vector< std::string > &  exclude_names,
NnetDiscriminativeExample eg 
)

Shifts the time-index t of everything in the input of "eg" by adding "t_offset" to all "t" values– but excluding those with names listed in "exclude_names", e.g.

"ivector". This might be useful if you are doing subsampling of frames at the output, because shifted examples won't be quite equivalent to their non-shifted counterparts. "exclude_names" is a vector of names of nnet inputs that we avoid shifting the "t" values of– normally it will contain just the single string "ivector" because we always leave t=0 for any ivector.

Note: input features will be shifted by 'frame_shift', and indexes in the supervision in (eg->output) will be shifted by 'frame_shift' rounded to the closest multiple of the frame subsampling factor (e.g. 3). The frame subsampling factor is worked out from the time spacing between the indexes in the output.

Definition at line 347 of file nnet-discriminative-example.cc.

References NnetDiscriminativeExample::inputs, KALDI_ASSERT, and NnetDiscriminativeExample::outputs.

Referenced by main(), and NnetDiscriminativeExampleStructureCompare::operator()().

349  {
350  std::vector<NnetIo>::iterator input_iter = eg->inputs.begin(),
351  input_end = eg->inputs.end();
352  for (; input_iter != input_end; ++input_iter) {
353  bool must_exclude = false;
354  std::vector<string>::const_iterator exclude_iter = exclude_names.begin(),
355  exclude_end = exclude_names.end();
356  for (; exclude_iter != exclude_end; ++exclude_iter)
357  if (input_iter->name == *exclude_iter)
358  must_exclude = true;
359  if (!must_exclude) {
360  std::vector<Index>::iterator indexes_iter = input_iter->indexes.begin(),
361  indexes_end = input_iter->indexes.end();
362  for (; indexes_iter != indexes_end; ++indexes_iter)
363  indexes_iter->t += frame_shift;
364  }
365  }
366  // note: we'll normally choose a small enough shift that the output-data
367  // shift will be zero after dividing by frame_subsampling_factor
368  // (e.g. frame_subsampling_factor == 3 and shift = 0 or 1.
369  std::vector<NnetDiscriminativeSupervision>::iterator
370  sup_iter = eg->outputs.begin(),
371  sup_end = eg->outputs.end();
372  for (; sup_iter != sup_end; ++sup_iter) {
373  std::vector<Index> &indexes = sup_iter->indexes;
374  KALDI_ASSERT(indexes.size() >= 2 && indexes[0].n == indexes[1].n &&
375  indexes[0].x == indexes[1].x);
376  int32 frame_subsampling_factor = indexes[1].t - indexes[0].t;
377  KALDI_ASSERT(frame_subsampling_factor > 0);
378 
379  // We need to shift by a multiple of frame_subsampling_factor.
380  // Round to the closest multiple.
381  int32 supervision_frame_shift =
382  frame_subsampling_factor *
383  std::floor(0.5 + (frame_shift * 1.0 / frame_subsampling_factor));
384  if (supervision_frame_shift == 0)
385  continue;
386  std::vector<Index>::iterator indexes_iter = indexes.begin(),
387  indexes_end = indexes.end();
388  for (; indexes_iter != indexes_end; ++indexes_iter)
389  indexes_iter->t += supervision_frame_shift;
390  }
391 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ ShiftExampleTimes()

void ShiftExampleTimes ( int32  t_offset,
const std::vector< std::string > &  exclude_names,
NnetExample eg 
)

Shifts the time-index t of everything in the "eg" by adding "t_offset" to all "t" values.

This might be useful in things like clockwork RNNs that are not invariant to time-shifts, to ensure that we see different shifts of each example during training. "exclude_names" is a vector (not necessarily sorted) of names of nnet inputs that we avoid shifting the "t" values of– normally it will contain just the single string "ivector" because we always leave t=0 for any ivector.

Definition at line 174 of file nnet-example-utils.cc.

References NnetExample::io.

Referenced by SelectFromExample().

176  {
177  if (t_offset == 0)
178  return;
179  std::vector<NnetIo>::iterator iter = eg->io.begin(),
180  end = eg->io.end();
181  for (; iter != end; iter++) {
182  bool name_is_excluded = false;
183  std::vector<std::string>::const_iterator
184  exclude_iter = exclude_names.begin(),
185  exclude_end = exclude_names.end();
186  for (; exclude_iter != exclude_end; ++exclude_iter) {
187  if (iter->name == *exclude_iter) {
188  name_is_excluded = true;
189  break;
190  }
191  }
192  if (!name_is_excluded) {
193  // name is not something like "ivector" that we exclude from shifting.
194  std::vector<Index>::iterator index_iter = iter->indexes.begin(),
195  index_end = iter->indexes.end();
196  for (; index_iter != index_end; ++index_iter)
197  index_iter->t += t_offset;
198  }
199  }
200 }

◆ SnipMultiRowOp()

static bool kaldi::nnet3::SnipMultiRowOp ( NnetComputation computation,
int32  command_index 
)
static

Definition at line 2434 of file nnet-optimize-utils.cc.

References NnetComputation::Command::arg1, NnetComputation::Command::arg2, NnetComputation::commands, FindNumLeadingAndTrailingNegatives(), NnetComputation::indexes_multi, KALDI_ASSERT, and NnetComputation::NewSubMatrix().

Referenced by SnipRowOps().

2435  {
2436  NnetComputation::Command &c = computation->commands[command_index];
2437  KALDI_ASSERT(static_cast<size_t>(c.arg2) < computation->indexes_multi.size());
2438  const std::vector<std::pair<int32, int32> > &indexes_multi =
2439  computation->indexes_multi[c.arg2];
2440  int32 num_leading_negatives, num_trailing_negatives;
2441  FindNumLeadingAndTrailingNegatives(indexes_multi,
2442  &num_leading_negatives,
2443  &num_trailing_negatives);
2444  if (num_leading_negatives == 0 && num_trailing_negatives == 0)
2445  return false;
2446 
2447  int32 new_num_rows = static_cast<int32>(indexes_multi.size()) -
2448  num_leading_negatives - num_trailing_negatives;
2449  KALDI_ASSERT(new_num_rows > 0);
2450  std::vector<std::pair<int32, int32> > new_indexes_multi(
2451  indexes_multi.begin() + num_leading_negatives,
2452  indexes_multi.begin() + num_leading_negatives + new_num_rows);
2453  c.arg2 = computation->indexes_multi.size();
2454  computation->indexes_multi.push_back(std::vector<std::pair<int32, int32> >());
2455  computation->indexes_multi.back().swap(new_indexes_multi);
2456  c.arg1 = computation->NewSubMatrix(c.arg1,
2457  num_leading_negatives, new_num_rows,
2458  0, -1);
2459  return true; // made a change.
2460 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static void FindNumLeadingAndTrailingNegatives(const std::vector< std::pair< int32, int32 > > &vec, int32 *num_leading_negatives, int32 *num_trailing_negatives)

◆ SnipRangesRowOp()

static bool kaldi::nnet3::SnipRangesRowOp ( NnetComputation computation,
int32  command_index 
)
static

Definition at line 2507 of file nnet-optimize-utils.cc.

References NnetComputation::Command::arg1, NnetComputation::Command::arg3, NnetComputation::commands, FindNumLeadingAndTrailingIdenticals(), NnetComputation::indexes_ranges, KALDI_ASSERT, and NnetComputation::NewSubMatrix().

Referenced by SnipRowOps().

2508  {
2509  NnetComputation::Command &c = computation->commands[command_index];
2510  KALDI_ASSERT(static_cast<size_t>(c.arg3) < computation->indexes_ranges.size());
2511  const std::vector<std::pair<int32, int32> > &indexes_ranges =
2512  computation->indexes_ranges[c.arg3];
2513  int32 num_leading_identicals, num_trailing_identicals;
2514  FindNumLeadingAndTrailingIdenticals(indexes_ranges,
2515  &num_leading_identicals,
2516  &num_trailing_identicals);
2517  if (num_leading_identicals == 0 && num_trailing_identicals == 0)
2518  return false;
2519 
2520  int32 new_num_rows = static_cast<int32>(indexes_ranges.size()) -
2521  num_leading_identicals - num_trailing_identicals;
2522  KALDI_ASSERT(new_num_rows > 0);
2523  std::vector<std::pair<int32, int32> > new_indexes_ranges(
2524  indexes_ranges.begin() + num_leading_identicals,
2525  indexes_ranges.begin() + num_leading_identicals + new_num_rows);
2526  c.arg3 = computation->indexes_ranges.size();
2527  computation->indexes_ranges.push_back(std::vector<std::pair<int32, int32> >());
2528  computation->indexes_ranges.back().swap(new_indexes_ranges);
2529  c.arg1 = computation->NewSubMatrix(c.arg1,
2530  num_leading_identicals, new_num_rows,
2531  0, -1);
2532  return true; // made a change.
2533 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static void FindNumLeadingAndTrailingIdenticals(const std::vector< std::pair< int32, int32 > > &vec, int32 *num_leading_identicals, int32 *num_trailing_identicals)

◆ SnipRowOps()

bool SnipRowOps ( NnetComputation computation)

This function detects cases where commands of type kCopyRows, kAddRows, kAddRowsMulti, kAddToRowsMulti, kCopyRowsMulti, kCopyToRowsMulti or kAddRowRanges use indexes that start or end with -1's or equivalents, and replace them with similar commands that act on a sub-matrix of the matrices they are currently acting on.

This will help efficiency by avoiding launching unnecessary copies of the kernel (that don't really have to do anything).

This function returns true if it made any changes to the computation; if it returns true, then after doing this you should at some point do RenumberComputation(), which will remove any now-unused members of computation->indexes.

Definition at line 2537 of file nnet-optimize-utils.cc.

References NnetComputation::Command::command_type, NnetComputation::commands, kAddRowRanges, kAddRows, kAddRowsMulti, kAddToRowsMulti, kCopyToRowsMulti, SnipMultiRowOp(), SnipRangesRowOp(), and SnipSingleRowOp().

Referenced by Optimize().

2537  {
2538  bool ans = false;
2539  int32 num_commands = computation->commands.size();
2540  for (int32 command_index = 0; command_index < num_commands;
2541  command_index++) {
2542  // non-const because we'll be changing it.
2543  NnetComputation::Command &c = computation->commands[command_index];
2544 
2545  // note: we can't do the snipping for commands of type case kCopyRows and case
2546  // kCopyRowsMulti, because the -1's aren't a pure no-op; they have the
2547  // meaning of setting the destination value to zero, so we can't prune
2548  // them away.
2549 
2550  switch (c.command_type) {
2551  case kAddRows: {
2552  if (SnipSingleRowOp(computation, command_index))
2553  ans = true;
2554  break;
2555  }
2556  case kAddRowsMulti: case kAddToRowsMulti:
2557  case kCopyToRowsMulti: {
2558  if (SnipMultiRowOp(computation, command_index))
2559  ans = true;
2560  break;
2561  }
2562  case kAddRowRanges: {
2563  if (SnipRangesRowOp(computation, command_index))
2564  ans = true;
2565  break;
2566  }
2567  default:
2568  break;
2569  }
2570  }
2571  return ans;
2572 }
kaldi::int32 int32
static bool SnipRangesRowOp(NnetComputation *computation, int32 command_index)
static bool SnipSingleRowOp(NnetComputation *computation, int32 command_index)
static bool SnipMultiRowOp(NnetComputation *computation, int32 command_index)

◆ SnipSingleRowOp()

static bool kaldi::nnet3::SnipSingleRowOp ( NnetComputation computation,
int32  command_index 
)
static

Definition at line 2364 of file nnet-optimize-utils.cc.

References NnetComputation::Command::arg1, NnetComputation::Command::arg3, NnetComputation::commands, FindNumLeadingAndTrailingNegatives(), NnetComputation::indexes, KALDI_ASSERT, and NnetComputation::NewSubMatrix().

Referenced by SnipRowOps().

2365  {
2366  NnetComputation::Command &c = computation->commands[command_index];
2367  KALDI_ASSERT(static_cast<size_t>(c.arg3) < computation->indexes.size());
2368  const std::vector<int32> &indexes = computation->indexes[c.arg3];
2369  int32 num_leading_negatives, num_trailing_negatives;
2371  &num_leading_negatives,
2372  &num_trailing_negatives);
2373  if (num_leading_negatives == 0 && num_trailing_negatives == 0)
2374  return false;
2375 
2376  int32 new_num_rows = static_cast<int32>(indexes.size()) -
2377  num_leading_negatives - num_trailing_negatives;
2378  KALDI_ASSERT(new_num_rows > 0);
2379  std::vector<int32> new_indexes(indexes.begin() + num_leading_negatives,
2380  indexes.begin() + num_leading_negatives +
2381  new_num_rows);
2382  c.arg3 = computation->indexes.size();
2383  computation->indexes.push_back(std::vector<int32>());
2384  computation->indexes.back().swap(new_indexes);
2385  c.arg1 = computation->NewSubMatrix(c.arg1,
2386  num_leading_negatives, new_num_rows,
2387  0, -1);
2388  return true; // made a change.
2389 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static void FindNumLeadingAndTrailingNegatives(const std::vector< std::pair< int32, int32 > > &vec, int32 *num_leading_negatives, int32 *num_trailing_negatives)

◆ SplitComputationIntoSegments()

static void kaldi::nnet3::SplitComputationIntoSegments ( const NnetComputation computation,
std::vector< std::pair< int32, int32 > > *  segments 
)
static

Split the computation up into segments bounded by kNoOperationMarker.

For each segment, a pair of command-indexes (start, end) is output to the vector 'segments', so the commands in the segment (not including kNoOperationMarker) are numbered from start ... end - 1.

Definition at line 852 of file nnet-optimize.cc.

References NnetComputation::commands, and kNoOperationMarker.

Referenced by ConsolidateIoOperations().

854  {
855 
856  int32 num_commands = computation.commands.size();
857  segments->clear();
858  int32 cur_start = 0;
859  for (int32 c = 0; c < num_commands; c++) {
860  if (computation.commands[c].command_type == kNoOperationMarker) {
861  segments->push_back(std::pair<int32, int32>(cur_start, c));
862  cur_start = c + 1;
863  }
864  }
865  segments->push_back(std::pair<int32, int32>(cur_start, num_commands));
866 }
kaldi::int32 int32

◆ SplitLocations()

void SplitLocations ( const std::vector< std::vector< std::pair< int32, int32 > > > &  submat_lists,
std::vector< std::vector< std::pair< int32, int32 > > > *  split_lists 
)

The input to this function is a vector (indexed by matrix-row-index) of lists of pairs (submat_index, row_index), and this function splits it up into a list of vectors of pairs, where those vectors are indexed by matrix-row-index.

In order to make the lists all the same length it may have to insert "dummy" pairs with value (-1, -1). In addition, this function implement certain heuristics to break up the list into pairs in a particular desirable way, which we will describe below.

Let the input be `submat_lists`, and let `num_rows = submat_lists.size()`. The value -1 is not expected to appear as either the .first or .second element of pairs in `submat_lists`.

Heuristics aside, what this function guarantees is as follows. Each pair p that is in an element of list `submat_lists[i]` (say `p = submat_lists[i][k]`), will be present as `(*split_lists)[j][i] == p`. Because we don't ban submat_lists[i] from containing duplicates, the technical definition is a little more complicated: that the count of any given pair p != (-1, -1) in `submat_lists[i][*]` is equal to the count of that same pair in `(*split_lists)[*][i]`.

Each pair present in split_lists is either (-1, -1), or will correspond to an element of submat_lists; thus the total number of pairs, excluding (-1, -1), in split_lists will be the same as the total number of pairs in submat_lists.

Note on expected input: submat_lists.dim() may be large e.g. 1024 (it usually represents a minibatch size), but the maximum size of the lists will usually be fairly small e.g. no more than 4 or so, as it represents the number of terms in a hand-coded summation expression.

The use of this function is in interpreting a command to set each row of a matrix to a sum of terms. Each pair represents an input term, interpreted as (index-of-matrix, row-index), which represents a vector that will form part of the sum.

It would be possible to simply pad at the end with (-1, -1), but this function also makes an attempt to pad more carefully so that for the most part, each output vector of pairs has inputs from only one matrix, i.e. the pair.first values are all the same. This will allow us to use a potentially more efficient command in the compiled code. It doesn't have to be 100% optimal. Note: in the most common case, all the lists will have the same length and padding will not be necessary at all.

See documentation here: Forward computation for Descriptors (SplitLocations)

Definition at line 120 of file nnet-compile-utils.cc.

References GetSubmatCounts(), rnnlm::i, and SeparateSubmatsWithLargeCounts().

Referenced by Compiler::CompileForwardFromSubmatLocationsList(), SplitLocationsBackward(), and UnitTestSplitLocations().

122  {
123  size_t num_rows = submat_lists.size(),
124  num_output_lists = 0;
125  auto iter = submat_lists.begin(), end = submat_lists.end();
126  for (; iter != end; ++iter)
127  if (iter->size() > num_output_lists)
128  num_output_lists = iter->size();
129  split_lists->clear();
130  if (num_output_lists == 0) // Odd, but could happen, maybe
131  return;
132  else if (num_output_lists == 1) {
133  split_lists->resize(1);
134  std::vector<std::pair<int32, int32> > &list = (*split_lists)[0];
135  list.resize(num_rows, std::pair<int32, int32>(-1, -1));
136  for (size_t i = 0; i < num_rows; i++) {
137  if (!submat_lists[i].empty())
138  list[i] = submat_lists[i][0];
139  }
140  return;
141  }
142 
143  // counts for each submatrix index, of how many times it occurs.
144  std::unordered_map<int32,int32> submat_counts;
145  std::vector<int32> submats_with_large_counts;
146  GetSubmatCounts(submat_lists, &submat_counts, &submats_with_large_counts);
147  if (!submats_with_large_counts.empty()) {
148  // There are submatrices with counts over half the num-rows. We assign these
149  // their own output lists.
150 
151  std::vector<std::vector<std::pair<int32, int32> > > reduced_submat_lists;
152  SeparateSubmatsWithLargeCounts(submats_with_large_counts,
153  submat_lists,
154  &reduced_submat_lists,
155  split_lists);
156  // 'reduced_split_lists' is the result of recursing with input 'reduced_submat_lists';
157  // we'll append its result to 'split_lists'.
158  std::vector<std::vector<std::pair<int32, int32> > > reduced_split_lists;
159  SplitLocations(reduced_submat_lists, &reduced_split_lists);
160  size_t cur_num_lists = split_lists->size(),
161  num_extra_lists = reduced_split_lists.size(),
162  new_num_lists = cur_num_lists + num_extra_lists;
163  split_lists->resize(new_num_lists);
164  for (size_t i = 0; i < num_extra_lists; i++)
165  (*split_lists)[cur_num_lists + i].swap(reduced_split_lists[i]);
166  return;
167  // and we're done.
168  } else {
169  // All the counts of submatrix indexes seem to be small so we are resigned to
170  // only using AddRowsMulti commands.
171  split_lists->resize(num_output_lists);
172  for (size_t i = 0; i < num_output_lists; i++)
173  (*split_lists)[i].resize(num_rows, std::pair<int32, int32>(-1, -1));
174  for (size_t row = 0; row < num_rows; row++) {
175  const std::vector<std::pair<int32, int32> > &this_list =
176  submat_lists[row];
177  size_t this_list_size = submat_lists[row].size();
178  for (size_t i = 0; i < this_list_size; i++) {
179  (*split_lists)[i][row] = this_list[i];
180  }
181  }
182  }
183 }
void SeparateSubmatsWithLargeCounts(const std::vector< int32 > &submats_to_separate, const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *reduced_submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
This function, used in SplitLocations(), is used to make separate &#39;split lists&#39; for certain high-coun...
void GetSubmatCounts(const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::unordered_map< int32, int32 > *submat_counts, std::vector< int32 > *submats_with_large_counts)
Gets counts of submatrices (the 1st members of pairs) in submat_lists.
void SplitLocations(const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
The input to this function is a vector (indexed by matrix-row-index) of lists of pairs (submat_index...

◆ SplitLocationsBackward()

void SplitLocationsBackward ( const std::vector< std::vector< std::pair< int32, int32 > > > &  submat_lists,
std::vector< std::vector< std::pair< int32, int32 > > > *  split_lists 
)

This function has the same interface as SplitLocations(); however, it ensures certain additional properties of the output "split_lists", which are necessary because of the way it is used in backprop code.

For each sub-list sublist = (*split_lists)[i], the properties it ensures are: Either:

  • all pairs in the list "sublist" are unique (except that the special pair (-1, -1) may be repeated), Or:
  • the .first values in the list "sublist" are all the same, and the .second have a special property [see the function HasContiguousProperty in nnet-compile.cc]- basically that if we list the .second elements, each unique number that appears there appears only in one contiguous range, e.g. the list [ 6 6 6 1 5 5 5 ] has this property, but [ 1 2 1 ] does not. (however, -1's are not subject to this limitation, so [ -1 4 -1 ] satisfies the property). This function ensures this property by first calling SplitLocations, and then doing further splitting as necessary to ensure the property. However, if as a result it needs to split any given initially-split list into more than 2 sub-lists, it will print a warning (once per process). If we have to split into too many lists it will generate inefficient computations, and we will need to extend the backprop code to support more general types of operation. If all elements of submat_lists are empty, the output split_lists will be the empty vector.

Definition at line 311 of file nnet-compile-utils.cc.

References ConvertToIndexes(), EnsureContiguousProperty(), rnnlm::i, rnnlm::j, SplitLocations(), and SplitPairList().

Referenced by Compiler::CompileBackwardFromSubmatLocationsList(), and UnitTestSplitLocationsBackward().

313  {
314  std::vector<std::vector<std::pair<int32, int32> > > split_lists_intermediate;
315  // Split the submat_lists
316  SplitLocations(submat_lists, &split_lists_intermediate);
317  for (size_t i = 0; i < split_lists_intermediate.size(); i++) {
318  int32 first_value;
319  std::vector<int32> second_values;
320  if (ConvertToIndexes(split_lists_intermediate[i],
321  &first_value, &second_values)) {
322  // the .first values in split_lists_intermediate[i] are all the same (or
323  // equal to -1).
324  if (first_value == -1) {
325  // all the .first values were equal to -1. this is like a NULL marker.
326  continue;
327  }
328  std::vector<std::vector<int32> > second_values_split;
329  EnsureContiguousProperty(second_values, &second_values_split);
330  if (second_values_split.size() == 1) {
331  // this branch is an optimization for speed.
332  split_lists->push_back(split_lists_intermediate[i]);
333  } else {
334  for (size_t j = 0; j < second_values_split.size(); j++) {
335  split_lists->resize(split_lists->size() + 1);
336  const std::vector<int32> &input_list = second_values_split[j];
337  std::vector<std::pair<int32, int32> > &output_list =
338  split_lists->back();
339  output_list.resize(input_list.size());
340  int32 size = input_list.size();
341  for (int32 k = 0; k < size; k++) {
342  int32 row = input_list[k];
343  if (row == -1) output_list[k].first = -1;
344  else output_list[k].first = first_value;
345  output_list[k].second = row;
346  }
347  }
348  }
349  } else {
350  // the .first values are not the same
351  // splitting the list of pairs to ensure unique pairs, unless it is
352  // (-1,-1)
353  std::vector<std::vector<std::pair<int32, int32> > > new_split_lists;
354  SplitPairList(split_lists_intermediate[i],
355  &new_split_lists);
356  for (int32 j = 0; j < new_split_lists.size(); j++) {
357  split_lists->push_back(new_split_lists[j]);
358  }
359  }
360  }
361 }
bool ConvertToIndexes(const std::vector< std::pair< int32, int32 > > &location_vector, int32 *first_value, std::vector< int32 > *second_values)
If it is the case for some i >= 0 that all the .first elements of "location_vector" are either i or -...
kaldi::int32 int32
void SplitLocations(const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
The input to this function is a vector (indexed by matrix-row-index) of lists of pairs (submat_index...
void SplitPairList(std::vector< std::pair< int32, int32 > > &list, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
This function splits a vector of pairs into a list of vectors of pairs.
void EnsureContiguousProperty(const std::vector< int32 > &indexes, std::vector< std::vector< int32 > > *indexes_out)
This function takes a vector of indexes and splits it up into as separate vectors of the same size...

◆ SplitPairList()

void kaldi::nnet3::SplitPairList ( std::vector< std::pair< int32, int32 > > &  list,
std::vector< std::vector< std::pair< int32, int32 > > > *  split_lists 
)

This function splits a vector of pairs into a list of vectors of pairs.

[note: by 'vector' we mean something that has a meaningful index that we care about; by 'list' we mean a collection of elements to be iterated over, without (in this case) meaningful indexes or even order.

Parameters
[in]listA vector of pairs; these pairs should be either (-1,-1) or (a,b) for a >= 0, b >= 0. At least one element of 'list' must be different from (-1,-1).
[out]split_listsA list, in arbitrary order, of vectors of pairs. It has the following relationship with 'list':
  • Size: for each j, split_lists[j].size() == list.size().
  • Contents must match input: For each i:
    • If list[i] == (-1, -1), then split_lists[j][i] == (-1, -1) for all j.
    • If list[i] != (-1, -1), then split_lists[j][i] == (-1, -1) for *all but one* j, and for the remaining j, split_lists[j][i] == list[i].
  • Uniqueness: for no j should split_lists[j] contain any duplicate elements (except the pair (-1,-1), which is allowed to exist in duplicate form). To satisfy the above conditions, this function will create as many lists in split_lists (i.e. as many j values) as the number of times that the most frequent pair in 'list' repeats other than the pair (-1,-1), e.g. if the pair (10,11) appears 4 times in 'list' and that is the most, split_lists->size() == 4.

Definition at line 280 of file nnet-compile-utils.cc.

References rnnlm::i, KALDI_ASSERT, and KALDI_ERR.

Referenced by SplitLocationsBackward().

281  {
282  split_lists->clear();
283  typedef unordered_map<std::pair<int32, int32>,
284  int32, PairHasher<int32> > MapType;
285  // this maps a pair not equal to -1,-1, to the number of times we've already seen it.
286  MapType pair_to_count;
287  int32 cur_num_lists = 0;
288 
289  for (int32 i = 0; i < list.size(); i++) {
290  if (list[i].first == -1)
291  continue;
292  MapType::iterator iter = pair_to_count.find(list[i]);
293  int32 this_count;
294  if (iter == pair_to_count.end())
295  pair_to_count[list[i]] = this_count = 1;
296  else
297  this_count = (++iter->second);
298  if (this_count > cur_num_lists) {
299  KALDI_ASSERT(this_count == cur_num_lists + 1);
300  split_lists->resize(this_count);
301  split_lists->back().resize(list.size(),
302  std::pair<int32, int32>(-1, -1));
303  cur_num_lists++;
304  }
305  (*split_lists)[this_count-1][i] = list[i];
306  }
307  if (split_lists->size() == 0)
308  KALDI_ERR << "Input list has just dummy pairs";
309 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ SplitRowOps()

bool SplitRowOps ( NnetComputation computation)

This function detects cases where commands of type kAddRowsMulti, kAddToRowsMulti, kCopyRowsMulti, kCopyToRowsMulti use indexes that correspond to at most two submatrices, in two distinct ranges without gaps filled by -1's, and could be converted to at most two commands of type kMatrixAdd, kMatrixCopy, kAddRows or kCopyRows.

(Note: it's important that this optimization takes place after SnipRowOps, because it doesn't remove the -1's from the edges of the indexes, it relies on that operation doing so). The "without-gaps" stipulation is just for convenience of implementation, to have fewer cases to worry about.

This function returns true if it made any changes to the computation; if it returns true, then after calling this you should at some point do RenumberComputation(), which will remove any now-unused members of computation->indexes.

Definition at line 2894 of file nnet-optimize-utils.cc.

References RowOpsSplitter::Split().

Referenced by Optimize().

2894  {
2895  RowOpsSplitter splitter(computation);
2896  return splitter.Split();
2897 }

◆ SummarizeVector() [1/3]

std::string SummarizeVector ( const VectorBase< float > &  vec)

Returns a string that summarizes a vector fairly succintly, for printing stats in info lines.

For example: "[percentiles(0,1,2,5 10,20,50,80,90 95,98,99,100)=(0.001,0.003,0.003,0.004 \ 0.005,0.01,0.07,0.11,0.14 0.18,0.24,0.29,0.39), mean=0.0745, stddev=0.0611]"

Definition at line 111 of file nnet-parse.cc.

References VectorBase< Real >::Data(), VectorBase< Real >::Dim(), rnnlm::i, KALDI_ASSERT, rnnlm::n, PrintFloatSuccinctly(), kaldi::SplitStringToIntegers(), VectorBase< Real >::Sum(), and kaldi::VecVec().

Referenced by LstmNonlinearityComponent::ConsolidateMemory(), BatchNormComponent::Info(), LstmNonlinearityComponent::Info(), NonlinearComponent::Info(), PrintParameterStats(), SummarizeVector(), and UnitTestSummarizeVector().

111  {
112  std::ostringstream os;
113  if (vec.Dim() < 10) {
114  os << "[ ";
115  for (int32 i = 0; i < vec.Dim(); i++) {
116  PrintFloatSuccinctly(os, vec(i));
117  os << ' ';
118  }
119  os << "]";
120  } else {
121  // print out mean and standard deviation, and some selected values.
122  BaseFloat mean = vec.Sum() / vec.Dim(),
123  stddev = sqrt(VecVec(vec, vec) / vec.Dim() - mean * mean);
124 
125  std::string percentiles_str = "0,1,2,5 10,20,50,80,90 95,98,99,100";
126  std::vector<int32> percentiles;
127  bool ans = SplitStringToIntegers(percentiles_str, ", ", false,
128  &percentiles);
129  KALDI_ASSERT(ans);
130  os << "[percentiles(" << percentiles_str << ")=(";
131  Vector<BaseFloat> vec_sorted(vec);
132  std::sort(vec_sorted.Data(), vec_sorted.Data() + vec_sorted.Dim());
133  int32 n = vec.Dim() - 1;
134  for (size_t i = 0; i < percentiles.size(); i++) {
135  int32 percentile = percentiles[i];
136  BaseFloat value = vec_sorted((n * percentile) / 100);
137  PrintFloatSuccinctly(os, value);
138  if (i + 1 < percentiles.size())
139  os << (i == 3 || i == 8 ? ' ' : ',');
140  }
141  os << std::setprecision(3);
142  os << "), mean=" << mean << ", stddev=" << stddev << "]";
143  }
144  return os.str();
145 }
bool SplitStringToIntegers(const std::string &full, const char *delim, bool omit_empty_strings, std::vector< I > *out)
Split a string (e.g.
Definition: text-utils.h:68
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
struct rnnlm::@11::@12 n
MatrixIndexT Dim() const
Returns the dimension of the vector.
Definition: kaldi-vector.h:64
Real Sum() const
Returns sum of the elements.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static void PrintFloatSuccinctly(std::ostream &os, BaseFloat f)
Definition: nnet-parse.cc:94
Real VecVec(const VectorBase< Real > &a, const VectorBase< Real > &b)
Returns dot product between v1 and v2.
Definition: kaldi-vector.cc:37

◆ SummarizeVector() [2/3]

std::string SummarizeVector ( const VectorBase< double > &  vec)

Definition at line 147 of file nnet-parse.cc.

References SummarizeVector().

147  {
148  Vector<float> vec_copy(vec);
149  return SummarizeVector(vec_copy);
150 }
std::string SummarizeVector(const CuVectorBase< BaseFloat > &cu_vec)
Definition: nnet-parse.cc:152

◆ SummarizeVector() [3/3]

std::string SummarizeVector ( const CuVectorBase< BaseFloat > &  cu_vec)

Definition at line 152 of file nnet-parse.cc.

References SummarizeVector().

152  {
153  Vector<float> vec(cu_vec);
154  return SummarizeVector(vec);
155 }
std::string SummarizeVector(const CuVectorBase< BaseFloat > &cu_vec)
Definition: nnet-parse.cc:152

◆ SumVectorSizes() [1/2]

static int32 kaldi::nnet3::SumVectorSizes ( const std::vector< std::vector< int32 > > &  vec)
static

Definition at line 1238 of file nnet-computation-graph.cc.

Referenced by ComputeComputationPhases(), and SumVectorSizes().

1238  {
1239  int32 ans = 0;
1240  std::vector<std::vector<int32> >::const_iterator iter = vec.begin(),
1241  end = vec.end();
1242  for (; iter != end; ++iter)
1243  ans += iter->size();
1244  return ans;
1245 }
kaldi::int32 int32

◆ SumVectorSizes() [2/2]

static int32 kaldi::nnet3::SumVectorSizes ( const std::vector< std::vector< std::vector< int32 > > > &  vec)
static

Definition at line 1247 of file nnet-computation-graph.cc.

References rnnlm::i, and SumVectorSizes().

1247  {
1248  int32 ans = 0;
1249  for (size_t i = 0; i < vec.size(); i++)
1250  ans += SumVectorSizes(vec[i]);
1251  return ans;
1252 }
static int32 SumVectorSizes(const std::vector< std::vector< std::vector< int32 > > > &vec)
kaldi::int32 int32

◆ TarjanSccRecursive()

void kaldi::nnet3::TarjanSccRecursive ( int32  node,
const std::vector< std::vector< int32 > > &  graph,
int32 global_index,
std::vector< TarjanNode > *  tarjan_nodes,
std::vector< int32 > *  tarjan_stack,
std::vector< std::vector< int32 > > *  sccs 
)

Definition at line 85 of file nnet-graph.cc.

References rnnlm::i, TarjanNode::index, KALDI_ASSERT, TarjanNode::lowlink, and TarjanNode::on_stack.

Referenced by FindSccsTarjan().

90  {
91  KALDI_ASSERT(sccs != NULL);
92  KALDI_ASSERT(tarjan_nodes != NULL);
93  KALDI_ASSERT(tarjan_stack != NULL);
94  KALDI_ASSERT(global_index != NULL);
95  KALDI_ASSERT(node >= 0 && node < graph.size());
96 
97  // Initializes the current Tarjan node.
98  (*tarjan_nodes)[node].index = *global_index;
99  (*tarjan_nodes)[node].lowlink = *global_index;
100  *global_index += 1;
101  (*tarjan_nodes)[node].on_stack = true;
102  tarjan_stack->push_back(node);
103 
104  // DFS from the current node.
105  for (int32 i = 0; i < graph[node].size(); ++i) {
106  int32 next = graph[node][i];
107 
108  if ((*tarjan_nodes)[next].index == -1) {
109  // First time we see this node.
110  TarjanSccRecursive(next, graph,
111  global_index, tarjan_nodes, tarjan_stack, sccs);
112  (*tarjan_nodes)[node].lowlink = std::min((*tarjan_nodes)[node].lowlink,
113  (*tarjan_nodes)[next].lowlink);
114  } else if ((*tarjan_nodes)[next].on_stack) {
115  // Next node is on the stack -- back edge. We can't use the lowlink of
116  // next node, because that may point to the index of the root, while the
117  // current node can't be the root.
118  (*tarjan_nodes)[node].lowlink = std::min((*tarjan_nodes)[node].lowlink,
119  (*tarjan_nodes)[next].index);
120  }
121  }
122 
123  // Output SCC.
124  if ((*tarjan_nodes)[node].index == (*tarjan_nodes)[node].lowlink) {
125  std::vector<int32> scc;
126  int32 pop_node;
127  do {
128  pop_node = tarjan_stack->back();
129  tarjan_stack->pop_back();
130  (*tarjan_nodes)[pop_node].on_stack = false;
131  scc.push_back(pop_node);
132  } while (pop_node != node);
133  KALDI_ASSERT(pop_node == node);
134  sccs->push_back(scc);
135  }
136 }
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void TarjanSccRecursive(int32 node, const std::vector< std::vector< int32 > > &graph, int32 *global_index, std::vector< TarjanNode > *tarjan_nodes, std::vector< int32 > *tarjan_stack, std::vector< std::vector< int32 > > *sccs)
Definition: nnet-graph.cc:85

◆ TestNnetComponentAddScale()

void kaldi::nnet3::TestNnetComponentAddScale ( Component c)

Definition at line 76 of file nnet-component-test.cc.

References Component::Add(), CheckStringsApproxEqual(), Component::Copy(), Component::Info(), KALDI_ASSERT, and Component::Scale().

Referenced by UnitTestNnetComponent().

76  {
77  Component *c2 = c->Copy();
78  Component *c3 = c2->Copy();
79  c3->Add(0.5, *c2);
80  c2->Scale(1.5);
82  delete c2;
83  delete c3;
84 }
Abstract base-class for neural-net components.
virtual Component * Copy() const =0
Copies component (deep copy).
virtual void Scale(BaseFloat scale)
This virtual function when called on – an UpdatableComponent scales the parameters by "scale" when c...
bool CheckStringsApproxEqual(const std::string &a, const std::string &b, int32 tolerance=3)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
virtual std::string Info() const
Returns some text-form information about this component, for diagnostics.
virtual void Add(BaseFloat alpha, const Component &other)
This virtual function when called by – an UpdatableComponent adds the parameters of another updatabl...

◆ TestNnetComponentCopy()

void kaldi::nnet3::TestNnetComponentCopy ( Component c)

Definition at line 67 of file nnet-component-test.cc.

References Component::Copy(), Component::Info(), KALDI_ERR, and kaldi::StringsApproxEqual().

Referenced by UnitTestNnetComponent().

67  {
68  Component *c2 = c->Copy();
69  if (!StringsApproxEqual(c->Info(), c2->Info())) {
70  KALDI_ERR << "Expected info strings to be equal: '"
71  << c->Info() << "' vs. '" << c2->Info() << "'";
72  }
73  delete c2;
74 }
Abstract base-class for neural-net components.
virtual Component * Copy() const =0
Copies component (deep copy).
bool StringsApproxEqual(const std::string &a, const std::string &b, int32 decimal_places_tolerance)
This function returns true when two text strings are approximately equal, and false when they are not...
Definition: text-utils.cc:335
#define KALDI_ERR
Definition: kaldi-error.h:147
virtual std::string Info() const
Returns some text-form information about this component, for diagnostics.

◆ TestNnetComponentIo()

void kaldi::nnet3::TestNnetComponentIo ( Component c)

Definition at line 52 of file nnet-component-test.cc.

References CheckStringsApproxEqual(), KALDI_ASSERT, kaldi::Rand(), Component::ReadNew(), and Component::Write().

Referenced by UnitTestNnetComponent().

52  {
53  bool binary = (Rand() % 2 == 0);
54  std::ostringstream os1;
55  c->Write(os1, binary);
56  std::istringstream is(os1.str());
57  Component *c2 = Component::ReadNew(is, binary);
58  std::ostringstream os2;
59  c2->Write(os2, binary);
60  if (!binary) {
61  std::string s1 = os1.str(), s2 = os2.str();
63  }
64  delete c2;
65 }
virtual void Write(std::ostream &os, bool binary) const =0
Write component to stream.
Abstract base-class for neural-net components.
bool CheckStringsApproxEqual(const std::string &a, const std::string &b, int32 tolerance=3)
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ TestNnetComponentUpdatable()

void kaldi::nnet3::TestNnetComponentUpdatable ( Component c)

Definition at line 109 of file nnet-component-test.cc.

References CheckStringsApproxEqual(), Component::Copy(), UpdatableComponent::DotProduct(), UpdatableComponent::Info(), KALDI_ASSERT, KALDI_ERR, kUpdatableComponent, UpdatableComponent::NumParameters(), Component::Properties(), VectorBase< Real >::Scale(), Component::Scale(), kaldi::StringsApproxEqual(), and kaldi::VecVec().

Referenced by UnitTestNnetComponent().

109  {
110  if (!(c->Properties() & kUpdatableComponent))
111  return;
112  UpdatableComponent *uc = dynamic_cast<UpdatableComponent*>(c);
113  if (uc == NULL) {
115  "Component returns updatable flag but does not inherit "
116  "from UpdatableComponent");
117  return;
118  }
119  if(!(uc->Properties() & kUpdatableComponent)){
120  // testing that if it declares itself as non-updatable,
121  // Scale() and Add() have no effect.
122  KALDI_ASSERT(uc->NumParameters() == 0);
123  KALDI_ASSERT(uc->DotProduct(*uc) == 0);
124  UpdatableComponent *uc2 = dynamic_cast<UpdatableComponent*>(uc->Copy());
125  uc2->Scale(7.0);
126  uc2->Add(3.0, *uc);
127  KALDI_ASSERT(CheckStringsApproxEqual(uc2->Info(), uc->Info()));
128  uc->Scale(0.0);
129  KALDI_ASSERT(CheckStringsApproxEqual(uc2->Info(), uc->Info()));
130  delete uc2;
131  } else {
132  KALDI_ASSERT(uc->NumParameters() != 0);
133  UpdatableComponent *uc2 = dynamic_cast<UpdatableComponent*>(uc->Copy()),
134  *uc3 = dynamic_cast<UpdatableComponent*>(uc->Copy());
135 
136  // testing some expected invariances of scale and add.
137  uc2->Scale(5.0);
138  uc2->Add(3.0, *uc3);
139  uc3->Scale(8.0);
140  // now they should both be scaled to 8 times the original component.
141  if (!StringsApproxEqual(uc2->Info(), uc3->Info())) {
142  KALDI_ERR << "Expected info strings to be equal: '"
143  << uc2->Info() << "' vs. '" << uc3->Info() << "'";
144  }
145  // testing that scaling by 0.5 works the same whether
146  // done on the vectorized paramters or via Scale().
147  Vector<BaseFloat> vec2(uc->NumParameters());
148  uc2->Vectorize(&vec2);
149  vec2.Scale(0.5);
150  uc2->UnVectorize(vec2);
151  uc3->Scale(0.5);
152  KALDI_ASSERT(CheckStringsApproxEqual(uc2->Info(), uc3->Info()));
153 
154  // testing that Scale(0.0) works the same whether done on the vectorized
155  // paramters or via SetZero(), and that unvectorizing something that's been
156  // zeroed gives us zero parameters.
157  uc2->Vectorize(&vec2);
158  vec2.SetZero();
159  uc2->UnVectorize(vec2);
160  uc3->Scale(0.0);
161  uc3->Vectorize(&vec2);
162  KALDI_ASSERT(uc2->Info() == uc3->Info() && VecVec(vec2, vec2) == 0.0);
163 
164  delete uc2;
165  delete uc3;
166  }
167 }
virtual Component * Copy() const =0
Copies component (deep copy).
virtual int32 NumParameters() const
The following new virtual function returns the total dimension of the parameters in this class...
bool StringsApproxEqual(const std::string &a, const std::string &b, int32 decimal_places_tolerance)
This function returns true when two text strings are approximately equal, and false when they are not...
Definition: text-utils.cc:335
virtual void Scale(BaseFloat scale)
This virtual function when called on – an UpdatableComponent scales the parameters by "scale" when c...
virtual BaseFloat DotProduct(const UpdatableComponent &other) const =0
Computes dot-product between parameters of two instances of a Component.
virtual int32 Properties() const =0
Return bitmask of the component&#39;s properties.
bool CheckStringsApproxEqual(const std::string &a, const std::string &b, int32 tolerance=3)
#define KALDI_ERR
Definition: kaldi-error.h:147
void Scale(Real alpha)
Multiplies all elements by this constant.
Class UpdatableComponent is a Component which has trainable parameters; it extends the interface of C...
A class representing a vector.
Definition: kaldi-vector.h:406
virtual std::string Info() const
Returns some text-form information about this component, for diagnostics.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
Real VecVec(const VectorBase< Real > &a, const VectorBase< Real > &b)
Returns dot product between v1 and v2.
Definition: kaldi-vector.cc:37

◆ TestNnetComponentVectorizeUnVectorize()

void kaldi::nnet3::TestNnetComponentVectorizeUnVectorize ( Component c)

Definition at line 86 of file nnet-component-test.cc.

References kaldi::ApproxEqual(), CheckStringsApproxEqual(), Component::Copy(), UpdatableComponent::DotProduct(), rnnlm::i, UpdatableComponent::Info(), KALDI_ASSERT, kUpdatableComponent, UpdatableComponent::NumParameters(), Component::Properties(), Component::Scale(), UpdatableComponent::UnVectorize(), and UpdatableComponent::Vectorize().

Referenced by UnitTestNnetComponent().

86  {
87  if (!(c->Properties() & kUpdatableComponent))
88  return;
89  UpdatableComponent *uc = dynamic_cast<UpdatableComponent*>(c);
90  KALDI_ASSERT(uc != NULL);
91  UpdatableComponent *uc2 = dynamic_cast<UpdatableComponent*>(uc->Copy());
92  uc2->Scale(0.0);
93  Vector<BaseFloat> params(uc2->NumParameters());
94  uc2->Vectorize(&params);
95  KALDI_ASSERT(params.Min()==0.0 && params.Sum()==0.0);
96  uc->Vectorize(&params);
97  uc2->UnVectorize(params);
99  BaseFloat x = uc2->DotProduct(*uc2), y = uc->DotProduct(*uc),
100  z = uc2->DotProduct(*uc);
101  KALDI_ASSERT(ApproxEqual(x, y) && ApproxEqual(y, z));
102  Vector<BaseFloat> params2(uc2->NumParameters());
103  uc2->Vectorize(&params2);
104  for(int i = 0; i < params.Dim(); i++)
105  KALDI_ASSERT(params(i) == params2(i));
106  delete uc2;
107 }
virtual Component * Copy() const =0
Copies component (deep copy).
virtual int32 NumParameters() const
The following new virtual function returns the total dimension of the parameters in this class...
virtual void Vectorize(VectorBase< BaseFloat > *params) const
Turns the parameters into vector form.
virtual void Scale(BaseFloat scale)
This virtual function when called on – an UpdatableComponent scales the parameters by "scale" when c...
float BaseFloat
Definition: kaldi-types.h:29
virtual BaseFloat DotProduct(const UpdatableComponent &other) const =0
Computes dot-product between parameters of two instances of a Component.
virtual int32 Properties() const =0
Return bitmask of the component&#39;s properties.
bool CheckStringsApproxEqual(const std::string &a, const std::string &b, int32 tolerance=3)
Class UpdatableComponent is a Component which has trainable parameters; it extends the interface of C...
virtual void UnVectorize(const VectorBase< BaseFloat > &params)
Converts the parameters from vector form.
A class representing a vector.
Definition: kaldi-vector.h:406
virtual std::string Info() const
Returns some text-form information about this component, for diagnostics.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
Definition: kaldi-math.h:265

◆ TestNnetDecodable()

void kaldi::nnet3::TestNnetDecodable ( Nnet nnet)

Definition at line 80 of file nnet-compute-test.cc.

References VectorBase< Real >::ApplyExp(), VectorBase< Real >::Dim(), NnetSimpleComputationOptions::frames_per_chunk, DecodableNnetSimple::GetOutputForFrame(), DecodableNnetSimpleLooped::GetOutputForFrame(), Nnet::Info(), Nnet::InputDim(), KALDI_ASSERT, NnetIsRecurrent(), Nnet::OutputDim(), kaldi::RandInt(), SetBatchnormTestMode(), SetDropoutTestMode(), and VectorBase< Real >::SetRandn().

Referenced by UnitTestNnetCompute().

80  {
81  int32 num_frames = 5 + RandInt(1, 100),
82  input_dim = nnet->InputDim("input"),
83  output_dim = nnet->OutputDim("output"),
84  ivector_dim = std::max<int32>(0, nnet->InputDim("ivector"));
85  Matrix<BaseFloat> input(num_frames, input_dim);
86 
87  SetBatchnormTestMode(true, nnet);
88  SetDropoutTestMode(true, nnet);
89 
90  input.SetRandn();
91  Vector<BaseFloat> ivector(ivector_dim);
92  ivector.SetRandn();
93 
94  Vector<BaseFloat> priors(RandInt(0, 1) == 0 ? output_dim : 0);
95  if (priors.Dim() != 0) {
96  priors.SetRandn();
97  priors.ApplyExp();
98  }
99 
100  Matrix<BaseFloat> output1(num_frames, output_dim),
101  output2(num_frames, output_dim);
102 
103  {
105  opts.frames_per_chunk = RandInt(5, 25);
106  CachingOptimizingCompiler compiler(*nnet);
107  DecodableNnetSimple decodable(opts, *nnet, priors, input, &compiler,
108  (ivector_dim != 0 ? &ivector : NULL));
109  for (int32 t = 0; t < num_frames; t++) {
110  SubVector<BaseFloat> row(output1, t);
111  decodable.GetOutputForFrame(t, &row);
112  }
113  }
114 
115  {
117  // caution: this may modify nnet, by changing how it consumes iVectors.
118  DecodableNnetSimpleLoopedInfo info(opts, priors, nnet);
119  DecodableNnetSimpleLooped decodable(info, input,
120  (ivector_dim != 0 ? &ivector : NULL));
121  for (int32 t = 0; t < num_frames; t++) {
122  SubVector<BaseFloat> row(output2, t);
123  decodable.GetOutputForFrame(t, &row);
124  }
125  }
126 
127 
128  // the components that we exclude from this test, are excluded because they
129  // all take "optional" right context, and this destroys the equivalence that
130  // we are testing.
131  if (!NnetIsRecurrent(*nnet) &&
132  nnet->Info().find("statistics-extraction") == std::string::npos &&
133  nnet->Info().find("TimeHeightConvolutionComponent") == std::string::npos &&
134  nnet->Info().find("RestrictedAttentionComponent") == std::string::npos) {
135  // this equivalence will not hold for recurrent nnets, or those that
136  // have the statistics-extraction/statistics-pooling layers,
137  // or in general for nnets with convolution components (because these
138  // might have 'optional' context if required-time-offsets != time-offsets.
139  for (int32 t = 0; t < num_frames; t++) {
140  SubVector<BaseFloat> row1(output1, t),
141  row2(output2, t);
142  KALDI_ASSERT(row1.ApproxEqual(row2));
143  }
144  }
145 }
int32 InputDim(const std::string &input_name) const
Definition: nnet-nnet.cc:669
This class enables you to do the compilation and optimization in one call, and also ensures that if t...
void SetBatchnormTestMode(bool test_mode, Nnet *nnet)
This function affects only components of type BatchNormComponent.
Definition: nnet-utils.cc:564
kaldi::int32 int32
int32 OutputDim(const std::string &output_name) const
Definition: nnet-nnet.cc:677
std::string Info() const
returns some human-readable information about the network, mostly for debugging purposes.
Definition: nnet-nnet.cc:821
void SetDropoutTestMode(bool test_mode, Nnet *nnet)
This function affects components of child-classes of RandomComponent.
Definition: nnet-utils.cc:573
A class representing a vector.
Definition: kaldi-vector.h:406
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
bool NnetIsRecurrent(const Nnet &nnet)
Returns true if &#39;nnet&#39; has some kind of recurrency.
Definition: nnet-utils.cc:1441
When you instantiate class DecodableNnetSimpleLooped, you should give it a const reference to this cl...
Represents a non-allocating general vector which can be defined as a sub-vector of higher-level vecto...
Definition: kaldi-vector.h:501
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ TestSimpleComponentDataDerivative()

bool kaldi::nnet3::TestSimpleComponentDataDerivative ( const Component c,
BaseFloat  perturb_delta 
)

Definition at line 309 of file nnet-component-test.cc.

References kaldi::ApproxEqual(), Component::Backprop(), Component::DeleteMemo(), GetPrecomputedIndexes(), rnnlm::i, Component::InputDim(), KALDI_LOG, KALDI_WARN, kBackpropNeedsInput, kBackpropNeedsOutput, kaldi::kDefaultStride, kInputContiguous, kOutputContiguous, kaldi::kSetZero, kaldi::kStrideEqualNumCols, kaldi::kTrans, Component::OutputDim(), Component::Propagate(), Component::Properties(), kaldi::Rand(), kaldi::RandInt(), ResetSeed(), CuMatrixBase< Real >::SetRandn(), kaldi::TraceMatMat(), and Component::Type().

Referenced by UnitTestNnetComponent().

310  {
311  MatrixStrideType input_stride_type = (c.Properties()&kInputContiguous) ?
313  MatrixStrideType output_stride_type = (c.Properties()&kOutputContiguous) ?
315 
316  int32 input_dim = c.InputDim(),
317  output_dim = c.OutputDim(),
318  num_rows = RandInt(1, 100),
319  rand_seed = Rand();
320  int32 properties = c.Properties();
321  CuMatrix<BaseFloat> input_data(num_rows, input_dim, kSetZero, input_stride_type),
322  output_data(num_rows, output_dim, kSetZero, output_stride_type),
323  output_deriv(num_rows, output_dim, kSetZero, output_stride_type);
324  input_data.SetRandn();
325  output_deriv.SetRandn();
326 
327  ResetSeed(rand_seed, c);
328  ComponentPrecomputedIndexes *indexes = GetPrecomputedIndexes(c, num_rows);
329  void *memo = c.Propagate(indexes, input_data, &output_data);
330 
331  CuMatrix<BaseFloat> input_deriv(num_rows, input_dim, kSetZero, input_stride_type),
332  empty_mat;
333  c.Backprop("foobar", indexes,
334  ((properties & kBackpropNeedsInput) ? input_data : empty_mat),
335  ((properties & kBackpropNeedsOutput) ? output_data : empty_mat),
336  output_deriv, memo, NULL, &input_deriv);
337  c.DeleteMemo(memo);
338 
339  int32 test_dim = 3;
340  BaseFloat original_objf = TraceMatMat(output_deriv, output_data, kTrans);
341  Vector<BaseFloat> measured_objf_change(test_dim),
342  predicted_objf_change(test_dim);
343  for (int32 i = 0; i < test_dim; i++) {
344  CuMatrix<BaseFloat> perturbed_input_data(num_rows, input_dim,
345  kSetZero, input_stride_type),
346  perturbed_output_data(num_rows, output_dim,
347  kSetZero, output_stride_type);
348  perturbed_input_data.SetRandn();
349  perturbed_input_data.Scale(perturb_delta);
350  // at this point, perturbed_input_data contains the offset at the input data.
351  predicted_objf_change(i) = TraceMatMat(perturbed_input_data, input_deriv,
352  kTrans);
353  perturbed_input_data.AddMat(1.0, input_data);
354 
355  ResetSeed(rand_seed, c);
356  c.DeleteMemo(c.Propagate(indexes, perturbed_input_data, &perturbed_output_data));
357  measured_objf_change(i) = TraceMatMat(output_deriv, perturbed_output_data,
358  kTrans) - original_objf;
359  }
360  KALDI_LOG << "Predicted objf-change = " << predicted_objf_change;
361  KALDI_LOG << "Measured objf-change = " << measured_objf_change;
362  BaseFloat threshold = 0.1;
363  bool ans = ApproxEqual(predicted_objf_change, measured_objf_change, threshold);
364  if (!ans)
365  KALDI_WARN << "Data-derivative test failed, component-type="
366  << c.Type() << ", input-dim=" << input_dim
367  << ", output-dim=" << output_dim;
368  if (c.Type() == "NormalizeComponent" && input_dim == 1) {
369  // derivatives are mathematically zero, but the measured and predicted
370  // objf have different roundoff and the relative differences are large.
371  // this is not unexpected.
372  KALDI_LOG << "Accepting deriv differences since it is NormalizeComponent "
373  << "with dim=1.";
374  return true;
375  }
376  else if (c.Type() == "ClipGradientComponent") {
377  KALDI_LOG << "Accepting deriv differences since "
378  << "it is ClipGradientComponent.";
379  return true;
380  }
381  delete indexes;
382  return ans;
383 }
virtual void * Propagate(const ComponentPrecomputedIndexes *indexes, const CuMatrixBase< BaseFloat > &in, CuMatrixBase< BaseFloat > *out) const =0
Propagate function.
kaldi::int32 int32
virtual int32 OutputDim() const =0
Returns output-dimension of this component.
This class represents a matrix that&#39;s stored on the GPU if we have one, and in memory if not...
Definition: matrix-common.h:71
virtual void DeleteMemo(void *memo) const
This virtual function only needs to be overwritten by Components that return a non-NULL memo from the...
virtual void Backprop(const std::string &debug_info, const ComponentPrecomputedIndexes *indexes, const CuMatrixBase< BaseFloat > &in_value, const CuMatrixBase< BaseFloat > &out_value, const CuMatrixBase< BaseFloat > &out_deriv, void *memo, Component *to_update, CuMatrixBase< BaseFloat > *in_deriv) const =0
Backprop function; depending on which of the arguments &#39;to_update&#39; and &#39;in_deriv&#39; are non-NULL...
static void ResetSeed(int32 rand_seed, const Component &c)
float BaseFloat
Definition: kaldi-types.h:29
virtual int32 Properties() const =0
Return bitmask of the component&#39;s properties.
MatrixStrideType
Definition: matrix-common.h:44
#define KALDI_WARN
Definition: kaldi-error.h:150
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.
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
ComponentPrecomputedIndexes * GetPrecomputedIndexes(const Component &c, int32 num_rows)
virtual std::string Type() const =0
Returns a string such as "SigmoidComponent", describing the type of the object.
A class representing a vector.
Definition: kaldi-vector.h:406
virtual int32 InputDim() const =0
Returns input-dimension of this component.
#define KALDI_LOG
Definition: kaldi-error.h:153
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
Definition: kaldi-math.h:265
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ TestSimpleComponentModelDerivative()

bool kaldi::nnet3::TestSimpleComponentModelDerivative ( const Component c,
BaseFloat  perturb_delta,
bool  test_derivative 
)

Definition at line 390 of file nnet-component-test.cc.

References kaldi::ApproxEqual(), Component::Backprop(), Component::Copy(), Component::DeleteMemo(), UpdatableComponent::DotProduct(), GetPrecomputedIndexes(), rnnlm::i, Component::InputDim(), KALDI_ASSERT, KALDI_LOG, KALDI_WARN, kBackpropNeedsInput, kBackpropNeedsOutput, kaldi::kDefaultStride, kInputContiguous, kOutputContiguous, kaldi::kSetZero, kaldi::kStrideEqualNumCols, kaldi::kTrans, kUpdatableComponent, Component::OutputDim(), UpdatableComponent::PerturbParams(), Component::Propagate(), Component::Properties(), kaldi::RandInt(), Component::Scale(), UpdatableComponent::SetAsGradient(), CuMatrixBase< Real >::SetRandn(), kaldi::TraceMatMat(), and Component::Type().

Referenced by UnitTestNnetComponent().

392  {
393  int32 input_dim = c.InputDim(),
394  output_dim = c.OutputDim(),
395  num_rows = RandInt(1, 100);
396  int32 properties = c.Properties();
397  if ((properties & kUpdatableComponent) == 0) {
398  // nothing to test.
399  return true;
400  }
401  MatrixStrideType input_stride_type = (c.Properties()&kInputContiguous) ?
403  MatrixStrideType output_stride_type = (c.Properties()&kOutputContiguous) ?
405 
406  CuMatrix<BaseFloat> input_data(num_rows, input_dim, kSetZero, input_stride_type),
407  output_data(num_rows, output_dim, kSetZero, output_stride_type),
408  output_deriv(num_rows, output_dim, kSetZero, output_stride_type);
409  input_data.SetRandn();
410  output_deriv.SetRandn();
411 
412  ComponentPrecomputedIndexes *indexes = GetPrecomputedIndexes(c, num_rows);
413  void *memo = c.Propagate(indexes, input_data, &output_data);
414 
415  BaseFloat original_objf = TraceMatMat(output_deriv, output_data, kTrans);
416 
417  Component *c_copy = c.Copy();
418 
419  const UpdatableComponent *uc = dynamic_cast<const UpdatableComponent*>(&c);
420  UpdatableComponent *uc_copy = dynamic_cast<UpdatableComponent*>(c_copy);
421  KALDI_ASSERT(uc != NULL && uc_copy != NULL);
422  if (test_derivative) {
423  uc_copy->Scale(0.0);
424  uc_copy->SetAsGradient();
425  }
426 
427  CuMatrix<BaseFloat> input_deriv(num_rows, input_dim,
428  kSetZero, input_stride_type),
429  empty_mat;
430  c.Backprop("foobar", indexes,
431  ((properties & kBackpropNeedsInput) ? input_data : empty_mat),
432  ((properties & kBackpropNeedsOutput) ? output_data : empty_mat),
433  output_deriv, memo, c_copy,
434  (RandInt(0, 1) == 0 ? &input_deriv : NULL));
435  c.DeleteMemo(memo);
436 
437  if (!test_derivative) { // Just testing that the model update is downhill.
438  CuMatrix<BaseFloat> new_output_data(num_rows, output_dim,
439  kSetZero, output_stride_type);
440  c.DeleteMemo(c_copy->Propagate(indexes, input_data, &new_output_data));
441 
442  BaseFloat new_objf = TraceMatMat(output_deriv, new_output_data, kTrans);
443  bool ans = (new_objf > original_objf);
444  if (!ans) {
445  KALDI_WARN << "After update, new objf is not better than the original objf: "
446  << new_objf << " <= " << original_objf;
447  }
448  delete c_copy;
449  delete indexes;
450  return ans;
451  } else {
452  // check that the model derivative is accurate.
453  int32 test_dim = 3;
454 
455  Vector<BaseFloat> measured_objf_change(test_dim),
456  predicted_objf_change(test_dim);
457  for (int32 i = 0; i < test_dim; i++) {
458  CuMatrix<BaseFloat> perturbed_output_data(num_rows, output_dim,
459  kSetZero, output_stride_type);
460  Component *c_perturbed = c.Copy();
461  UpdatableComponent *uc_perturbed =
462  dynamic_cast<UpdatableComponent*>(c_perturbed);
463  KALDI_ASSERT(uc_perturbed != NULL);
464  uc_perturbed->PerturbParams(perturb_delta);
465 
466  predicted_objf_change(i) = uc_copy->DotProduct(*uc_perturbed) -
467  uc_copy->DotProduct(*uc);
468  c_perturbed->Propagate(indexes, input_data, &perturbed_output_data);
469  measured_objf_change(i) = TraceMatMat(output_deriv, perturbed_output_data,
470  kTrans) - original_objf;
471  delete c_perturbed;
472  }
473  KALDI_LOG << "Predicted objf-change = " << predicted_objf_change;
474  KALDI_LOG << "Measured objf-change = " << measured_objf_change;
475  BaseFloat threshold = 0.1;
476 
477  bool ans = ApproxEqual(predicted_objf_change, measured_objf_change,
478  threshold);
479  if (!ans)
480  KALDI_WARN << "Model-derivative test failed, component-type="
481  << c.Type() << ", input-dim=" << input_dim
482  << ", output-dim=" << output_dim;
483  delete c_copy;
484  delete indexes;
485  return ans;
486  }
487 }
virtual void * Propagate(const ComponentPrecomputedIndexes *indexes, const CuMatrixBase< BaseFloat > &in, CuMatrixBase< BaseFloat > *out) const =0
Propagate function.
Abstract base-class for neural-net components.
virtual Component * Copy() const =0
Copies component (deep copy).
kaldi::int32 int32
virtual int32 OutputDim() const =0
Returns output-dimension of this component.
This class represents a matrix that&#39;s stored on the GPU if we have one, and in memory if not...
Definition: matrix-common.h:71
virtual void DeleteMemo(void *memo) const
This virtual function only needs to be overwritten by Components that return a non-NULL memo from the...
virtual void Backprop(const std::string &debug_info, const ComponentPrecomputedIndexes *indexes, const CuMatrixBase< BaseFloat > &in_value, const CuMatrixBase< BaseFloat > &out_value, const CuMatrixBase< BaseFloat > &out_deriv, void *memo, Component *to_update, CuMatrixBase< BaseFloat > *in_deriv) const =0
Backprop function; depending on which of the arguments &#39;to_update&#39; and &#39;in_deriv&#39; are non-NULL...
virtual void Scale(BaseFloat scale)
This virtual function when called on – an UpdatableComponent scales the parameters by "scale" when c...
float BaseFloat
Definition: kaldi-types.h:29
virtual BaseFloat DotProduct(const UpdatableComponent &other) const =0
Computes dot-product between parameters of two instances of a Component.
virtual int32 Properties() const =0
Return bitmask of the component&#39;s properties.
MatrixStrideType
Definition: matrix-common.h:44
#define KALDI_WARN
Definition: kaldi-error.h:150
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.
virtual void SetAsGradient()
Sets is_gradient_ to true and sets learning_rate_ to 1, ignoring learning_rate_factor_.
ComponentPrecomputedIndexes * GetPrecomputedIndexes(const Component &c, int32 num_rows)
Class UpdatableComponent is a Component which has trainable parameters; it extends the interface of C...
virtual std::string Type() const =0
Returns a string such as "SigmoidComponent", describing the type of the object.
virtual void PerturbParams(BaseFloat stddev)=0
This function is to be used in testing.
A class representing a vector.
Definition: kaldi-vector.h:406
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
virtual int32 InputDim() const =0
Returns input-dimension of this component.
#define KALDI_LOG
Definition: kaldi-error.h:153
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
Definition: kaldi-math.h:265
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ TestSimpleComponentPropagateProperties()

void kaldi::nnet3::TestSimpleComponentPropagateProperties ( const Component c)

Definition at line 210 of file nnet-component-test.cc.

References CuMatrixBase< Real >::Add(), kaldi::AssertEqual(), Component::Backprop(), Component::Copy(), CuMatrixBase< Real >::CopyFromMat(), Component::DeleteMemo(), GetPrecomputedIndexes(), Component::InputDim(), KALDI_ERR, kBackpropAdds, kBackpropInPlace, kBackpropNeedsInput, kBackpropNeedsOutput, kaldi::kDefaultStride, kInputContiguous, kOutputContiguous, kPropagateAdds, kPropagateInPlace, kaldi::kSetZero, kaldi::kStrideEqualNumCols, kaldi::kUndefined, Component::OutputDim(), Component::Propagate(), Component::Properties(), kaldi::Rand(), kaldi::RandInt(), ResetSeed(), CuMatrixBase< Real >::SetRandn(), and Component::Type().

Referenced by UnitTestNnetComponent().

210  {
211  int32 properties = c.Properties();
212  Component *c_copy = NULL;
213  int32 rand_seed = Rand();
214 
215  if (RandInt(0, 1) == 0)
216  c_copy = c.Copy(); // This will test backprop with an updatable component.
217  MatrixStrideType input_stride_type = (c.Properties()&kInputContiguous) ?
219  MatrixStrideType output_stride_type = (c.Properties()&kOutputContiguous) ?
221  MatrixStrideType both_stride_type =
224 
225  int32 input_dim = c.InputDim(),
226  output_dim = c.OutputDim(),
227  num_rows = RandInt(1, 100);
228  CuMatrix<BaseFloat> input_data(num_rows, input_dim, kUndefined,
229  input_stride_type);
230  input_data.SetRandn();
231  CuMatrix<BaseFloat> output_data3(num_rows, input_dim, kSetZero,
232  output_stride_type);
233  output_data3.CopyFromMat(input_data);
235  output_data1(num_rows, output_dim, kSetZero, output_stride_type),
236  output_data2(num_rows, output_dim, kSetZero, output_stride_type);
237  output_data2.Add(1.0);
238 
239  if ((properties & kPropagateAdds) && (properties & kPropagateInPlace)) {
240  KALDI_ERR << "kPropagateAdds and kPropagateInPlace flags are incompatible.";
241  }
242 
243  ResetSeed(rand_seed, c);
244  ComponentPrecomputedIndexes *indexes = GetPrecomputedIndexes(c, num_rows);
245  void *memo = c.Propagate(indexes, input_data, &output_data1);
246 
247  ResetSeed(rand_seed, c);
248  c.DeleteMemo(c.Propagate(indexes, input_data, &output_data2));
249  if (properties & kPropagateInPlace) {
250  ResetSeed(rand_seed, c);
251  c.DeleteMemo(c.Propagate(indexes, output_data3, &output_data3));
252  if (!output_data1.ApproxEqual(output_data3)) {
253  KALDI_ERR << "Test of kPropagateInPlace flag for component of type "
254  << c.Type() << " failed.";
255  }
256  }
257  if (properties & kPropagateAdds)
258  output_data2.Add(-1.0); // remove the offset
259  AssertEqual(output_data1, output_data2);
260 
261 
262  CuMatrix<BaseFloat> output_deriv(num_rows, output_dim, kSetZero, output_stride_type);
263  output_deriv.SetRandn();
264  CuMatrix<BaseFloat> input_deriv1(num_rows, input_dim, kSetZero, input_stride_type),
265  input_deriv2(num_rows, input_dim, kSetZero, input_stride_type);
266  CuMatrix<BaseFloat> input_deriv3(num_rows, output_dim, kSetZero, both_stride_type);
267  input_deriv3.CopyFromMat(output_deriv);
268 
269  input_deriv2.Add(1.0);
270  CuMatrix<BaseFloat> empty_mat;
271 
272  // test with input_deriv1 that's zero
273  c.Backprop("foobar", indexes,
274  ((properties & kBackpropNeedsInput) ? input_data : empty_mat),
275  ((properties & kBackpropNeedsOutput) ? output_data1 : empty_mat),
276  output_deriv,
277  memo,
278  c_copy,
279  &input_deriv1);
280  // test with input_deriv2 that's all ones.
281  c.Backprop("foobar", indexes,
282  ((properties & kBackpropNeedsInput) ? input_data : empty_mat),
283  ((properties & kBackpropNeedsOutput) ? output_data1 : empty_mat),
284  output_deriv,
285  memo,
286  c_copy,
287  &input_deriv2);
288  // test backprop in place, if supported.
289  if (properties & kBackpropInPlace) {
290  c.Backprop("foobar", indexes,
291  ((properties & kBackpropNeedsInput) ? input_data : empty_mat),
292  ((properties & kBackpropNeedsOutput) ? output_data1 : empty_mat),
293  input_deriv3,
294  memo,
295  c_copy,
296  &input_deriv3);
297  }
298  c.DeleteMemo(memo);
299 
300  if (properties & kBackpropAdds)
301  input_deriv2.Add(-1.0); // subtract the offset.
302  AssertEqual(input_deriv1, input_deriv2);
303  if (properties & kBackpropInPlace)
304  AssertEqual(input_deriv1, input_deriv3);
305  delete c_copy;
306  delete indexes;
307 }
virtual void * Propagate(const ComponentPrecomputedIndexes *indexes, const CuMatrixBase< BaseFloat > &in, CuMatrixBase< BaseFloat > *out) const =0
Propagate function.
Abstract base-class for neural-net components.
virtual Component * Copy() const =0
Copies component (deep copy).
kaldi::int32 int32
virtual int32 OutputDim() const =0
Returns output-dimension of this component.
This class represents a matrix that&#39;s stored on the GPU if we have one, and in memory if not...
Definition: matrix-common.h:71
virtual void DeleteMemo(void *memo) const
This virtual function only needs to be overwritten by Components that return a non-NULL memo from the...
virtual void Backprop(const std::string &debug_info, const ComponentPrecomputedIndexes *indexes, const CuMatrixBase< BaseFloat > &in_value, const CuMatrixBase< BaseFloat > &out_value, const CuMatrixBase< BaseFloat > &out_deriv, void *memo, Component *to_update, CuMatrixBase< BaseFloat > *in_deriv) const =0
Backprop function; depending on which of the arguments &#39;to_update&#39; and &#39;in_deriv&#39; are non-NULL...
static void ResetSeed(int32 rand_seed, const Component &c)
virtual int32 Properties() const =0
Return bitmask of the component&#39;s properties.
MatrixStrideType
Definition: matrix-common.h:44
#define KALDI_ERR
Definition: kaldi-error.h:147
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
ComponentPrecomputedIndexes * GetPrecomputedIndexes(const Component &c, int32 num_rows)
virtual std::string Type() const =0
Returns a string such as "SigmoidComponent", describing the type of the object.
static void AssertEqual(float a, float b, float relative_tolerance=0.001)
assert abs(a - b) <= relative_tolerance * (abs(a)+abs(b))
Definition: kaldi-math.h:276
virtual int32 InputDim() const =0
Returns input-dimension of this component.
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestCindexIo()

void kaldi::nnet3::UnitTestCindexIo ( )

Definition at line 62 of file nnet-common-test.cc.

References rnnlm::i, KALDI_ERR, Index::n, kaldi::RandInt(), ReadCindexVector(), Index::t, WriteCindexVector(), and Index::x.

Referenced by main().

62  {
63  std::vector<Cindex> cindexes(RandInt(0, 15));
64 
65  for (int32 i = 0; i < cindexes.size(); i++) {
66  if (i == 0 || RandInt(0, 4) == 0) {
67  cindexes[i].first = RandInt(-256, 256);
68  } else {
69  cindexes[i].first = cindexes[i-1].first;
70  }
71  Index &index = cindexes[i].second;
72  if (i == 0) {
73  if (RandInt(0, 3) == 0) {
74  index.n = 0;
75  index.x = 0;
76  if (RandInt(0, 1) == 0)
77  index.t = RandInt(-5, 5);
78  else if (RandInt(0, 1) == 0) {
79  index.t = 124;
80  } else if (RandInt(0, 1) == 0) {
81  index.t = -124;
82  } else if (RandInt(0, 1) == 0) {
83  index.t = std::numeric_limits<int32>::min();
84  } else {
85  index.t = 0;
86  }
87  } else if (RandInt(0, 1) == 0) {
88  index.t = 0;
89  index.x = 0;
90  index.n = RandInt(0, 1);
91  } else {
92  index.t = RandInt(-3, 3);
93  if (RandInt(0, 1) == 0)
94  index.t = std::numeric_limits<int32>::min();
95  index.x = RandInt(-1,1);
96  index.n = RandInt(-1,1);
97  }
98  } else {
99  if (RandInt(0, 3) == 0) {
100  cindexes[i].second.n = cindexes[i-1].second.n;
101  cindexes[i].second.x = cindexes[i-1].second.x;
102  if (RandInt(0, 1) == 0) {
103  cindexes[i].second.t = cindexes[i-1].second.t + RandInt(-127, 127);
104  } else if (RandInt(0, 1) == 0) {
105  cindexes[i].second.t = cindexes[i-1].second.t + 124;
106  } else if (RandInt(0, 1) == 0) {
107  cindexes[i].second.t = cindexes[i-1].second.t + -124;
108  } else if (RandInt(0, 1) == 0) {
109  cindexes[i].second.t = std::numeric_limits<int32>::min();
110  } else {
111  cindexes[i].second.t = RandInt(-2, 2);
112  }
113  } else if (RandInt(0, 1) == 0) {
114  cindexes[i].second.t = cindexes[i-1].second.t;
115  cindexes[i].second.x = cindexes[i-1].second.x;
116  cindexes[i].second.n = cindexes[i-1].second.n + RandInt(-2,2);
117  } else if (RandInt(0, 1) == 0) {
118  cindexes[i].second.t = cindexes[i-1].second.t + RandInt(-2, 2);
119  cindexes[i].second.x = cindexes[i-1].second.x + RandInt(-2, 2);
120  cindexes[i].second.n = cindexes[i-1].second.n + RandInt(-2,2);
121  if (RandInt(0, 3) == 0)
122  cindexes[i].second.t = std::numeric_limits<int32>::min();
123 
124  } else {
125  cindexes[i].second.t = RandInt(-128, 128);
126  cindexes[i].second.x = RandInt(-128, 128);
127  cindexes[i].second.n = RandInt(-128, 128);
128  if (RandInt(0, 3) == 0)
129  cindexes[i].second.t = std::numeric_limits<int32>::min();
130  }
131  }
132  }
133 
134  if (RandInt(0, 10) == 0) {
135  // trying to reproduce a failure
136  Cindex temp(0, Index(0, 0, 0));
137  cindexes.clear();
138  cindexes.resize(4, temp);
139  cindexes[RandInt(0, 3)].second.t = std::numeric_limits<int32>::min();
140  }
141 
142  std::ostringstream os;
143  bool binary = (RandInt(0, 1) == 0);
144  WriteCindexVector(os, binary, cindexes);
145  std::vector<Cindex> cindexes2;
146  if (RandInt(0, 1) == 0)
147  cindexes2 = cindexes;
148  std::istringstream is(os.str());
149  ReadCindexVector(is, binary, &cindexes2);
150 
151  std::ostringstream os2;
152  WriteCindexVector(os2, binary, cindexes2);
153 
154  if (cindexes != cindexes2 || os.str() != os2.str()) {
155  WriteCindexVector(std::cerr, false, cindexes);
156  std::cerr << " vs. \n";
157  WriteCindexVector(std::cerr, false, cindexes2);
158  std::cerr << "\n";
159  KALDI_ERR << "Indexes differ.";
160  }
161 }
void ReadCindexVector(std::istream &is, bool binary, std::vector< Cindex > *vec)
Definition: nnet-common.cc:309
kaldi::int32 int32
struct Index is intended to represent the various indexes by which we number the rows of the matrices...
Definition: nnet-common.h:44
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115
void WriteCindexVector(std::ostream &os, bool binary, const std::vector< Cindex > &vec)
Definition: nnet-common.cc:282
#define KALDI_ERR
Definition: kaldi-error.h:147
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestComputationRequestIo()

void kaldi::nnet3::UnitTestComputationRequestIo ( ComputationRequest request)

Definition at line 56 of file nnet-compute-test.cc.

References KALDI_ASSERT, kaldi::Rand(), ComputationRequest::Read(), and ComputationRequest::Write().

Referenced by UnitTestNnetCompute().

56  {
57  bool binary = (Rand() % 2 == 0);
58  std::ostringstream os;
59  request->Write(os, binary);
60  const std::string &original_output = os.str();
61  std::istringstream request_is(original_output);
62  request->Read(request_is, binary);
63  std::istringstream request_is2(original_output);
64  ComputationRequest request2;
65  request2.Read(request_is2, binary);
66 
67  std::ostringstream os2, os3;
68  request->Write(os2, binary);
69  request2.Write(os3, binary);
70  KALDI_ASSERT(*request == request2);
71 
72  if (binary) {
73  KALDI_ASSERT(os2.str() == original_output);
74  KALDI_ASSERT(os3.str() == original_output);
75  }
76 }
void Read(std::istream &istream, bool binary)
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void Write(std::ostream &ostream, bool binary) const

◆ UnitTestComputeGraphTranspose()

void kaldi::nnet3::UnitTestComputeGraphTranspose ( )

Definition at line 148 of file nnet-graph-test.cc.

References AssertGraphEqual(), BuildTestGraph(), BuildTestGraphTranspose(), ComputeGraphTranspose(), and KALDI_ASSERT.

Referenced by main().

148  {
149  std::vector<std::vector<int32> > graph;
150  BuildTestGraph(&graph);
151 
152  std::vector<std::vector<int32> > graph_transpose;
153  ComputeGraphTranspose(graph, &graph_transpose);
154 
155  std::vector<std::vector<int32> > ref_graph_transpose;
156  BuildTestGraphTranspose(&ref_graph_transpose);
157  KALDI_ASSERT(AssertGraphEqual(graph_transpose, ref_graph_transpose));
158 }
void BuildTestGraph(std::vector< std::vector< int32 > > *graph)
void ComputeGraphTranspose(const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *graph_transpose)
Outputs a graph in which the order of arcs is reversed.
Definition: nnet-graph.cc:63
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void BuildTestGraphTranspose(std::vector< std::vector< int32 > > *graph)
bool AssertGraphEqual(const std::vector< std::vector< int32 > > &graph1, const std::vector< std::vector< int32 > > &graph2)

◆ UnitTestComputeTopSortOrder()

void kaldi::nnet3::UnitTestComputeTopSortOrder ( )

Definition at line 187 of file nnet-graph-test.cc.

References AssertVectorEqual(), BuildTestSccGraph(), BuildTestTopSortOrder(), ComputeTopSortOrder(), and KALDI_ASSERT.

Referenced by main().

187  {
188  std::vector<std::vector<int32> > scc_graph;
189  BuildTestSccGraph(&scc_graph);
190 
191  std::vector<int32> node_to_order;
192  ComputeTopSortOrder(scc_graph, &node_to_order);
193 
194  std::vector<int32> ref_node_to_order;
195  BuildTestTopSortOrder(&ref_node_to_order);
196  KALDI_ASSERT(AssertVectorEqual(node_to_order, ref_node_to_order));
197 }
bool AssertVectorEqual(const std::vector< int32 > &vec1, const std::vector< int32 > &vec2)
void ComputeTopSortOrder(const std::vector< std::vector< int32 > > &graph, std::vector< int32 > *node_to_order)
Given an acyclic graph (where each std::vector<int32> is a list of destination-nodes of arcs coming f...
Definition: nnet-graph.cc:223
void BuildTestSccGraph(std::vector< std::vector< int32 > > *scc_graph)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void BuildTestTopSortOrder(std::vector< int32 > *node_to_order)

◆ UnitTestComputeTopSortOrder2()

void kaldi::nnet3::UnitTestComputeTopSortOrder2 ( )

Definition at line 199 of file nnet-graph-test.cc.

References AssertVectorEqual(), ComputeTopSortOrder(), and KALDI_ASSERT.

Referenced by main().

199  {
200  // The outer vector is indexed by node ID, and each nested vector contains
201  // the node IDs for its successors in the graph. For example, if there are
202  // arcs from node 0 to nodes 1 and 2, then the vector at graph[0] will be (1, 2)
203  std::vector<std::vector<int32> > graph;
204 
205  // Build a test graph:
206  // 0 ---> 1 ---> 2 ---> 4
207  // `--> 3 -----^
208  graph.resize(5);
209  graph[0].push_back(1); graph[0].push_back(3);
210  graph[1].push_back(2);
211  graph[2].push_back(4);
212  graph[3].push_back(2);
213  // graph[4] is empty(has no successors)
214 
215  // fill in the desired(topological) mapping node->order
216  std::vector<int32> ref_node_to_order;
217  ref_node_to_order.push_back(0); // node 0 comes first
218  ref_node_to_order.push_back(2); // node 1 comes third
219  ref_node_to_order.push_back(3); // node 2 comes fourth
220  ref_node_to_order.push_back(1); // node 3 comes second
221  ref_node_to_order.push_back(4); // node 4 comes last
222 
223  std::vector<int32> computed_node_to_order;
224  ComputeTopSortOrder(graph, &computed_node_to_order);
225  KALDI_ASSERT(AssertVectorEqual(ref_node_to_order, computed_node_to_order));
226 }
bool AssertVectorEqual(const std::vector< int32 > &vec1, const std::vector< int32 > &vec2)
void ComputeTopSortOrder(const std::vector< std::vector< int32 > > &graph, std::vector< int32 > *node_to_order)
Given an acyclic graph (where each std::vector<int32> is a list of destination-nodes of arcs coming f...
Definition: nnet-graph.cc:223
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ UnitTestConvertRepeatedToBlockAffine()

void kaldi::nnet3::UnitTestConvertRepeatedToBlockAffine ( )

Definition at line 50 of file nnet-utils-test.cc.

References ConvertRepeatedToBlockAffine(), Nnet::GetComponent(), rnnlm::i, KALDI_ASSERT, Nnet::NumComponents(), Nnet::ReadConfig(), and Component::Type().

Referenced by main().

50  {
51  // a test without a composite component.
52  std::string config =
53  "component name=repeated-affine1 type=RepeatedAffineComponent "
54  "input-dim=100 output-dim=200 num-repeats=20\n"
55  "component name=relu1 type=RectifiedLinearComponent dim=200\n"
56  "component name=block-affine1 type=BlockAffineComponent "
57  "input-dim=200 output-dim=100 num-blocks=10\n"
58  "component name=relu2 type=RectifiedLinearComponent dim=100\n"
59  "component name=repeated-affine2 type=NaturalGradientRepeatedAffineComponent "
60  "input-dim=100 output-dim=200 num-repeats=10\n"
61  "\n"
62  "input-node name=input dim=100\n"
63  "component-node name=repeated-affine1 component=repeated-affine1 input=input\n"
64  "component-node name=relu1 component=relu1 input=repeated-affine1\n"
65  "component-node name=block-affine1 component=block-affine1 input=relu1\n"
66  "component-node name=relu2 component=relu2 component=relu2 input=block-affine1\n"
67  "component-node name=repeated-affine2 component=repeated-affine2 input=relu2\n"
68  "output-node name=output input=repeated-affine2\n";
69 
70  Nnet nnet;
71  std::istringstream is(config);
72  nnet.ReadConfig(is);
74 
75  for(int i = 0; i < nnet.NumComponents(); i++) {
76  Component *c = nnet.GetComponent(i);
77  KALDI_ASSERT(c->Type() != "RepeatedAffineComponent"
78  && c->Type() != "NaturalGradientRepeatedAffineComponent");
79  }
80 }
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
Abstract base-class for neural-net components.
void ConvertRepeatedToBlockAffine(CompositeComponent *c_component)
Definition: nnet-utils.cc:447
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
virtual std::string Type() const =0
Returns a string such as "SigmoidComponent", describing the type of the object.
int32 NumComponents() const
Definition: nnet-nnet.h:124
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ UnitTestConvertRepeatedToBlockAffineComposite()

void kaldi::nnet3::UnitTestConvertRepeatedToBlockAffineComposite ( )

Definition at line 82 of file nnet-utils-test.cc.

References ConvertRepeatedToBlockAffine(), GenerateConfigSequenceCompositeBlock(), Nnet::GetComponent(), CompositeComponent::GetComponent(), rnnlm::i, KALDI_ASSERT, Nnet::NumComponents(), CompositeComponent::NumComponents(), NnetGenerationOptions::output_dim, Nnet::ReadConfig(), and Component::Type().

Referenced by main().

82  {
83  // test that repeated affine components nested within a CompositeComponent
84  // are converted.
85  struct NnetGenerationOptions gen_config;
86  gen_config.output_dim = 0;
87  std::vector<std::string> configs;
88  // this function generates a neural net with one component:
89  // a composite component.
90  GenerateConfigSequenceCompositeBlock(gen_config, &configs);
91  Nnet nnet;
92  std::istringstream is(configs[0]);
93  nnet.ReadConfig(is);
94  KALDI_ASSERT(nnet.NumComponents() == 1);
96  CompositeComponent *cc = dynamic_cast<CompositeComponent*>(nnet.GetComponent(0));
97  for(int i = 0; i < cc->NumComponents(); i++) {
98  const Component *c = cc->GetComponent(i);
99  KALDI_ASSERT(c->Type() == "BlockAffineComponent");
100  }
101 }
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
Abstract base-class for neural-net components.
CompositeComponent is a component representing a sequence of [simple] components. ...
void ConvertRepeatedToBlockAffine(CompositeComponent *c_component)
Definition: nnet-utils.cc:447
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
const Component * GetComponent(int32 i) const
Gets the ith component in this component.
virtual std::string Type() const =0
Returns a string such as "SigmoidComponent", describing the type of the object.
int32 NumComponents() const
Definition: nnet-nnet.h:124
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void GenerateConfigSequenceCompositeBlock(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generate a config string with a composite component composed only of block affine, repeated affine, and natural gradient repeated affine components.

◆ UnitTestDescriptorIo()

void kaldi::nnet3::UnitTestDescriptorIo ( )

Definition at line 89 of file nnet-descriptor-test.cc.

References DescriptorTokenize(), GenRandDescriptor(), rnnlm::i, KALDI_ASSERT, KALDI_LOG, KALDI_WARN, Descriptor::Parse(), kaldi::Rand(), and Descriptor::WriteConfig().

Referenced by main().

89  {
90  for (int32 i = 0; i < 100; i++) {
91  int32 num_nodes = 1 + Rand() % 5;
92  std::vector<std::string> node_names(num_nodes);
93  for (int32 i = 0; i < node_names.size(); i++) {
94  std::ostringstream ostr;
95  ostr << "a" << (i+1);
96  node_names[i] = ostr.str();
97  }
98  Descriptor desc;
99  std::ostringstream ostr;
100  GenRandDescriptor(num_nodes, &desc);
101  desc.WriteConfig(ostr, node_names);
102 
103  Descriptor desc2(desc), desc3, desc4;
104  desc3 = desc;
105  std::vector<std::string> tokens;
106  DescriptorTokenize(ostr.str(), &tokens);
107  tokens.push_back("end of input");
108  std::istringstream istr(ostr.str());
109  const std::string *next_token = &(tokens[0]);
110  bool ans = desc4.Parse(node_names, &next_token);
111  KALDI_ASSERT(ans);
112 
113  std::ostringstream ostr2;
114  desc2.WriteConfig(ostr2, node_names);
115  std::ostringstream ostr3;
116  desc3.WriteConfig(ostr3, node_names);
117  std::ostringstream ostr4;
118  desc4.WriteConfig(ostr4, node_names);
119 
120  KALDI_ASSERT(ostr.str() == ostr2.str());
121  KALDI_ASSERT(ostr.str() == ostr3.str());
122  KALDI_LOG << "x = " << ostr.str();
123  KALDI_LOG << "y = " << ostr4.str();
124  if (ostr.str() != ostr4.str()) {
125  KALDI_WARN << "x and y differ: checking that it's due to Offset normalization.";
126  KALDI_ASSERT(ostr.str().find("Offset(Offset") != std::string::npos ||
127  (ostr.str().find("Offset(") != std::string::npos &&
128  ostr.str().find(", 0)") != std::string::npos));
129  }
130  }
131 }
bool Parse(const std::vector< std::string > &node_names, const std::string **next_token)
bool DescriptorTokenize(const std::string &input, std::vector< std::string > *tokens)
This function tokenizes input when parsing Descriptor configuration values.
Definition: nnet-parse.cc:30
kaldi::int32 int32
#define KALDI_WARN
Definition: kaldi-error.h:150
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
void GenRandDescriptor(int32 num_nodes, Descriptor *desc)
void WriteConfig(std::ostream &os, const std::vector< std::string > &node_names) const
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ UnitTestDescriptorTokenize()

void kaldi::nnet3::UnitTestDescriptorTokenize ( )

Definition at line 27 of file nnet-parse-test.cc.

References DescriptorTokenize(), and KALDI_ASSERT.

Referenced by main().

27  {
28  std::vector<std::string> lines;
29 
30  std::string str = "(,test )";
31  KALDI_ASSERT(DescriptorTokenize(str, &lines));
32  KALDI_ASSERT(lines[0] == "(" && lines[1] == "," && lines[2] == "test" && lines[3] == ")");
33 
34  str = "(,1test )";
35  KALDI_ASSERT(!DescriptorTokenize(str, &lines));
36 
37  str = "t (,-1 )";
38  KALDI_ASSERT(DescriptorTokenize(str, &lines));
39  KALDI_ASSERT(lines.size() == 5 && lines[0] == "t" && lines[3] == "-1");
40 
41  str = " sd , -112 )";
42  KALDI_ASSERT(DescriptorTokenize(str, &lines));
43  KALDI_ASSERT(lines.size() == 4 && lines[0] == "sd" && lines[2] == "-112");
44 
45  str = " sd , +112 )";
46  KALDI_ASSERT(DescriptorTokenize(str, &lines));
47  KALDI_ASSERT(lines.size() == 4 && lines[0] == "sd" && lines[2] == "+112");
48 
49  str = "foo";
50  KALDI_ASSERT(DescriptorTokenize(str, &lines));
51  KALDI_ASSERT(lines.size() == 1 && lines[0] == "foo");
52 
53 }
bool DescriptorTokenize(const std::string &input, std::vector< std::string > *tokens)
This function tokenizes input when parsing Descriptor configuration values.
Definition: nnet-parse.cc:30
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ UnitTestEnsureContiguousProperty()

void kaldi::nnet3::UnitTestEnsureContiguousProperty ( )

Definition at line 222 of file nnet-compile-utils-test.cc.

References EnsureContiguousProperty(), HasContiguousProperty(), rnnlm::i, rnnlm::j, KALDI_ASSERT, and kaldi::RandInt().

Referenced by main().

222  {
223  for (int32 k = 0; k < 10; k++) {
224  int32 size = RandInt(0, 5);
225  std::vector<int32> indexes(size);
226  for (int32 i = 0; i < size; i++)
227  indexes[i] = RandInt(-1, 4);
228  std::vector<std::pair<int32, int32> > reverse_indexes;
229  bool ans = HasContiguousProperty(indexes, &reverse_indexes);
230  if (ans) { // has contiguous property -> EnsureContiguousProperty should do
231  // nothing.
232  std::vector<std::vector<int32> > indexes_split;
233  EnsureContiguousProperty(indexes, &indexes_split);
234  if (indexes.size() == 0 ||
235  *std::max_element(indexes.begin(), indexes.end()) == -1) {
236  KALDI_ASSERT(indexes_split.size() == 0);
237  } else {
238  KALDI_ASSERT(indexes_split.size() == 1 &&
239  indexes_split[0] == indexes);
240  }
241  } else {
242  std::vector<std::vector<int32> > indexes_split;
243  EnsureContiguousProperty(indexes, &indexes_split);
244  KALDI_ASSERT(indexes_split.size() > 1);
245  for (int32 i = 0; i < indexes.size(); i++) {
246  int32 this_val = indexes[i];
247  bool found = (this_val == -1); // not looking for anything if
248  // this_val is -1.
249  for (int32 j = 0; j < indexes_split.size(); j++) {
250  if (found) {
251  KALDI_ASSERT(indexes_split[j][i] == -1);
252  } else {
253  if (indexes_split[j][i] == this_val) {
254  found = true;
255  } else {
256  KALDI_ASSERT(indexes_split[j][i] == -1);
257  }
258  }
259  }
260  KALDI_ASSERT(found);
261  for (int32 j = 0; j < indexes_split.size(); j++) {
262  KALDI_ASSERT(indexes_split[j].size() == indexes.size() &&
263  HasContiguousProperty(indexes_split[j], &reverse_indexes));
264  }
265  }
266  }
267  }
268 }
bool HasContiguousProperty(const std::vector< int32 > &indexes, std::vector< std::pair< int32, int32 > > *reverse_indexes)
This function returns true if for each integer i != -1, all the indexes j at which indexes[j] == i ar...
kaldi::int32 int32
void EnsureContiguousProperty(const std::vector< int32 > &indexes, std::vector< std::vector< int32 > > *indexes_out)
This function takes a vector of indexes and splits it up into as separate vectors of the same size...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestFindSccs()

void kaldi::nnet3::UnitTestFindSccs ( )

Definition at line 160 of file nnet-graph-test.cc.

References AssertGraphEqual(), BuildTestGraph(), BuildTestSccs(), FindSccs(), and KALDI_ASSERT.

Referenced by main().

160  {
161  std::vector<std::vector<int32> > graph;
162  BuildTestGraph(&graph);
163 
164  std::vector<std::vector<int32> > sccs;
165  FindSccs(graph, &sccs);
166 
167  std::vector<std::vector<int32> > ref_sccs;
168  BuildTestSccs(&ref_sccs);
169  KALDI_ASSERT(AssertGraphEqual(sccs, ref_sccs));
170 }
void BuildTestGraph(std::vector< std::vector< int32 > > *graph)
void FindSccs(const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *sccs)
Given a directed graph (where each std::vector<int32> is a list of destination-nodes of arcs coming f...
Definition: nnet-graph.cc:156
void BuildTestSccs(std::vector< std::vector< int32 > > *sccs)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
bool AssertGraphEqual(const std::vector< std::vector< int32 > > &graph1, const std::vector< std::vector< int32 > > &graph2)

◆ UnitTestGeneralDescriptor()

void kaldi::nnet3::UnitTestGeneralDescriptor ( )

Definition at line 135 of file nnet-descriptor-test.cc.

References GeneralDescriptor::ConvertToDescriptor(), DescriptorTokenize(), GenRandDescriptor(), rnnlm::i, KALDI_ERR, KALDI_LOG, KALDI_WARN, GeneralDescriptor::Parse(), kaldi::Rand(), and Descriptor::WriteConfig().

Referenced by main().

135  {
136  for (int32 i = 0; i < 100; i++) {
137  int32 num_nodes = 1 + Rand() % 5;
138  std::vector<std::string> node_names(num_nodes);
139  for (int32 i = 0; i < node_names.size(); i++) {
140  std::ostringstream ostr;
141  ostr << "a" << (i+1);
142  node_names[i] = ostr.str();
143  }
144  Descriptor desc;
145  std::ostringstream ostr;
146  GenRandDescriptor(num_nodes, &desc);
147  desc.WriteConfig(ostr, node_names);
148 
149  Descriptor desc2(desc), desc3;
150  desc3 = desc;
151  std::vector<std::string> tokens;
152  DescriptorTokenize(ostr.str(), &tokens);
153  tokens.push_back("end of input");
154  std::istringstream istr(ostr.str());
155  const std::string *next_token = &(tokens[0]);
156 
157 
158  GeneralDescriptor *gen_desc = GeneralDescriptor::Parse(node_names,
159  &next_token);
160 
161  if (*next_token != "end of input")
162  KALDI_ERR << "Parsing Descriptor, expected end of input but got "
163  << "'" << *next_token << "'";
164 
165  Descriptor *desc4 = gen_desc->ConvertToDescriptor();
166  std::ostringstream ostr2;
167  desc4->WriteConfig(ostr2, node_names);
168  KALDI_LOG << "Original descriptor was: " << ostr.str();
169  KALDI_LOG << "Parsed descriptor was: " << ostr2.str();
170  if (ostr2.str() != ostr.str())
171  KALDI_WARN << "Strings differed. Check manually.";
172 
173  delete gen_desc;
174  delete desc4;
175  }
176 }
This class is only used when parsing Descriptors.
bool DescriptorTokenize(const std::string &input, std::vector< std::string > *tokens)
This function tokenizes input when parsing Descriptor configuration values.
Definition: nnet-parse.cc:30
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_WARN
Definition: kaldi-error.h:150
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
void GenRandDescriptor(int32 num_nodes, Descriptor *desc)
void WriteConfig(std::ostream &os, const std::vector< std::string > &node_names) const
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ UnitTestGeneralDescriptorSpecial()

void kaldi::nnet3::UnitTestGeneralDescriptorSpecial ( )

Definition at line 200 of file nnet-descriptor-test.cc.

References KALDI_ASSERT, and NormalizeTextDescriptor().

Referenced by main().

200  {
201  std::vector<std::string> names;
202  names.push_back("a");
203  names.push_back("b");
204  names.push_back("c");
205  names.push_back("d");
206  KALDI_ASSERT(NormalizeTextDescriptor(names, "a") == "a");
207  KALDI_ASSERT(NormalizeTextDescriptor(names, "Scale(-1.0, a)") == "Scale(-1, a)");
208  KALDI_ASSERT(NormalizeTextDescriptor(names, "Scale(-1.0, Scale(-2.0, a))") == "Scale(2, a)");
209  KALDI_ASSERT(NormalizeTextDescriptor(names, "Scale(2.0, Sum(Scale(2.0, a), b, c))") ==
210  "Sum(Scale(4, a), Sum(Scale(2, b), Scale(2, c)))");
211  KALDI_ASSERT(NormalizeTextDescriptor(names, "Const(1.0, 512)") == "Const(1, 512)");
212  KALDI_ASSERT(NormalizeTextDescriptor(names, "Sum(Const(1.0, 512), Scale(-1.0, a))") ==
213  "Sum(Const(1, 512), Scale(-1, a))");
214  KALDI_ASSERT(NormalizeTextDescriptor(names, "Offset(Offset(a, 3, 5), 2, 1)")
215  == "Offset(a, 5, 6)");
216 
217  KALDI_ASSERT(NormalizeTextDescriptor(names, "Offset(Sum(a, b), 2, 1)") ==
218  "Sum(Offset(a, 2, 1), Offset(b, 2, 1))");
219  KALDI_ASSERT(NormalizeTextDescriptor(names, "Sum(Append(a, b), Append(c, d))") ==
220  "Append(Sum(a, c), Sum(b, d))");
221  KALDI_ASSERT(NormalizeTextDescriptor(names, "Append(Append(a, b), Append(c, d))") ==
222  "Append(a, b, c, d)");
223  KALDI_ASSERT(NormalizeTextDescriptor(names, "Sum(a, b, c, d)") ==
224  "Sum(a, Sum(b, Sum(c, d)))");
225  KALDI_ASSERT(NormalizeTextDescriptor(names, "Sum(a)") == "a");
226  KALDI_ASSERT(NormalizeTextDescriptor(names, "Offset(a, 0)") == "a");
227 }
std::string NormalizeTextDescriptor(const std::vector< std::string > &node_names, const std::string &desc_str)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ UnitTestHasContiguousProperty()

void kaldi::nnet3::UnitTestHasContiguousProperty ( )

Definition at line 185 of file nnet-compile-utils-test.cc.

References HasContiguousProperty(), rnnlm::i, rnnlm::j, KALDI_ASSERT, KALDI_LOG, and kaldi::RandInt().

Referenced by main().

185  {
186  for (int32 k = 0; k < 10; k++) {
187  int32 size = RandInt(0, 5);
188  std::vector<int32> indexes(size);
189  for (int32 i = 0; i < size; i++)
190  indexes[i] = RandInt(-1, 4);
191  std::vector<std::pair<int32, int32> > reverse_indexes;
192  bool ans = HasContiguousProperty(indexes, &reverse_indexes);
193  if (!ans) { // doesn't have contiguous propety.
194  KALDI_LOG << "no.";
195  bool found_example = false;
196  for (int32 i = 0; i < size; i++) {
197  if (indexes[i] != -1) {
198  bool found_not_same = false;
199  for (int32 j = i + 1; j < size; j++) {
200  if (indexes[j] != indexes[i]) found_not_same = true;
201  else if (found_not_same) found_example = true; // found something like x y x.
202  }
203  }
204  }
205  KALDI_ASSERT(found_example);
206  } else {
207  KALDI_LOG << "yes.";
208  for (int32 i = 0; i < reverse_indexes.size(); i++) {
209  for (int32 j = reverse_indexes[i].first;
210  j < reverse_indexes[i].second; j++) {
211  KALDI_ASSERT(indexes[j] == i);
212  indexes[j] = -1;
213  }
214  }
215  for (int32 i = 0; i < size; i++) // make sure all indexes covered.
216  KALDI_ASSERT(indexes[i] == -1);
217  }
218  }
219 }
bool HasContiguousProperty(const std::vector< int32 > &indexes, std::vector< std::pair< int32, int32 > > *reverse_indexes)
This function returns true if for each integer i != -1, all the indexes j at which indexes[j] == i ar...
kaldi::int32 int32
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_LOG
Definition: kaldi-error.h:153
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestIndexIo()

void kaldi::nnet3::UnitTestIndexIo ( )

Definition at line 28 of file nnet-common-test.cc.

References rnnlm::i, KALDI_ERR, kaldi::RandInt(), ReadIndexVector(), and WriteIndexVector().

Referenced by main().

28  {
29  std::vector<Index> indexes(RandInt(0, 10));
30 
31  for (int32 i = 0; i < indexes.size(); i++) {
32  if (i == 0 || RandInt(0, 1) == 0) {
33  indexes[i].n = RandInt(-1, 2);
34  indexes[i].t = RandInt(-150, 150);
35  indexes[i].x = RandInt(-1, 1);
36  } else {
37  // this case gets optimized while writing. (if abs(diff-in-t) < 125).
38  indexes[i].n = indexes[i-1].n;
39  indexes[i].t = indexes[i-1].t + RandInt(-127, 127);
40  indexes[i].x = indexes[i-1].x;
41  }
42  }
43 
44  std::ostringstream os;
45  bool binary = (RandInt(0, 1) == 0);
46  WriteIndexVector(os, binary, indexes);
47 
48  std::vector<Index> indexes2;
49  if (RandInt(0, 1) == 0)
50  indexes2 = indexes;
51  std::istringstream is(os.str());
52  ReadIndexVector(is, binary, &indexes2);
53  if (indexes != indexes2) {
54  WriteIndexVector(std::cerr, false, indexes);
55  std::cerr << " vs. \n";
56  WriteIndexVector(std::cerr, false, indexes2);
57  std::cerr << "\n";
58  KALDI_ERR << "Indexes differ.";
59  }
60 }
void WriteIndexVector(std::ostream &os, bool binary, const std::vector< Index > &vec)
Definition: nnet-common.cc:126
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
void ReadIndexVector(std::istream &is, bool binary, std::vector< Index > *vec)
Definition: nnet-common.cc:143
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestMakeSccGraph()

void kaldi::nnet3::UnitTestMakeSccGraph ( )

Definition at line 172 of file nnet-graph-test.cc.

References AssertGraphEqual(), BuildTestGraph(), BuildTestSccGraph(), BuildTestSccs(), KALDI_ASSERT, and MakeSccGraph().

Referenced by main().

172  {
173  std::vector<std::vector<int32> > graph;
174  BuildTestGraph(&graph);
175 
176  std::vector<std::vector<int32> > sccs;
177  BuildTestSccs(&sccs);
178 
179  std::vector<std::vector<int32> > scc_graph;
180  MakeSccGraph(graph, sccs, &scc_graph);
181 
182  std::vector<std::vector<int32> > ref_scc_graph;
183  BuildTestSccGraph(&ref_scc_graph);
184  KALDI_ASSERT(AssertGraphEqual(scc_graph, ref_scc_graph));
185 }
void BuildTestGraph(std::vector< std::vector< int32 > > *graph)
void BuildTestSccGraph(std::vector< std::vector< int32 > > *scc_graph)
void BuildTestSccs(std::vector< std::vector< int32 > > *sccs)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void MakeSccGraph(const std::vector< std::vector< int32 > > &graph, const std::vector< std::vector< int32 > > &sccs, std::vector< std::vector< int32 > > *scc_graph)
Given a list of sccs of a graph (e.g.
Definition: nnet-graph.cc:164
bool AssertGraphEqual(const std::vector< std::vector< int32 > > &graph1, const std::vector< std::vector< int32 > > &graph2)

◆ UnitTestNameMatchesPattern()

void kaldi::nnet3::UnitTestNameMatchesPattern ( )

Definition at line 76 of file nnet-parse-test.cc.

References KALDI_ASSERT, and NameMatchesPattern().

Referenced by main().

76  {
77  KALDI_ASSERT(NameMatchesPattern("hello", "hello"));
78  KALDI_ASSERT(!NameMatchesPattern("hello", "hellox"));
79  KALDI_ASSERT(!NameMatchesPattern("hellox", "hello"));
80  KALDI_ASSERT(NameMatchesPattern("hellox", "hello*"));
81  KALDI_ASSERT(NameMatchesPattern("hello", "hello*"));
84  KALDI_ASSERT(NameMatchesPattern("foo12bar", "foo*bar"));
85  KALDI_ASSERT(NameMatchesPattern("foo12bar", "foo*"));
86  KALDI_ASSERT(NameMatchesPattern("foo12bar", "*bar"));
87 }
bool NameMatchesPattern(const char *name, const char *pattern)
Definition: nnet-parse.cc:235
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ UnitTestNnetAnalyze()

void kaldi::nnet3::UnitTestNnetAnalyze ( )

Definition at line 39 of file nnet-analyze-test.cc.

References ComputationChecker::Check(), CheckComputationOptions::check_rewrite, NnetComputation::commands, ComputeExampleComputationRequestSimple(), Compiler::CreateComputation(), ComputationAnalysis::DataInvalidatedCommand(), ComputationAnalysis::FirstNontrivialAccess(), GenerateConfigSequence(), NnetComputation::GetSubmatrixStrings(), Analyzer::Init(), rnnlm::j, KALDI_LOG, ComputationAnalysis::LastAccess(), ComputationAnalysis::LastWriteAccess(), rnnlm::n, NnetComputation::Print(), PrintCommand(), kaldi::RandInt(), Nnet::ReadConfig(), and NnetComputation::submatrices.

Referenced by main().

39  {
40  for (int32 n = 0; n < 20; n++) {
41  struct NnetGenerationOptions gen_config;
42 
43  std::vector<std::string> configs;
44  GenerateConfigSequence(gen_config, &configs);
45  Nnet nnet;
46  for (size_t j = 0; j < configs.size(); j++) {
47  KALDI_LOG << "Input config[" << j << "] is: " << configs[j];
48  std::istringstream is(configs[j]);
49  nnet.ReadConfig(is);
50  }
51 
52  ComputationRequest request;
53  std::vector<Matrix<BaseFloat> > inputs;
54  ComputeExampleComputationRequestSimple(nnet, &request, &inputs);
55 
56  NnetComputation computation;
57  Compiler compiler(request, nnet);
58 
59  CompilerOptions opts;
60  compiler.CreateComputation(opts, &computation);
61 
62  std::ostringstream os;
63  computation.Print(os, nnet);
64  KALDI_LOG << "Generated computation is: " << os.str();
65 
66  CheckComputationOptions check_config;
67  // we can do the rewrite check since it's before optimization.
68  check_config.check_rewrite = true;
69  ComputationChecker checker(check_config, nnet, computation);
70  checker.Check();
71 
72  Analyzer analyzer;
73  analyzer.Init(nnet, computation);
74  ComputationAnalysis analysis(computation, analyzer);
75  // The following output is to be eyeballed by a person.
76  std::vector<std::string> submatrix_strings;
77  computation.GetSubmatrixStrings(nnet, &submatrix_strings);
78  int32 nc = computation.commands.size();
79  for (int32 n = 0; n < 30; n++) {
80  int32 s = RandInt(1, computation.submatrices.size() - 1);
81  int32 c = RandInt(0, nc - 1);
82  KALDI_LOG << "First nontrivial access of submatrix " << submatrix_strings[s]
83  << " is command "
84  << PrintCommand(nc, analysis.FirstNontrivialAccess(s));
85  KALDI_LOG << "Last access of submatrix " << submatrix_strings[s]
86  << " is command " << PrintCommand(nc, analysis.LastAccess(s));
87  KALDI_LOG << "Last write access of submatrix " << submatrix_strings[s]
88  << " is command " << PrintCommand(nc, analysis.LastWriteAccess(s));
89  KALDI_LOG << "Data present in " << submatrix_strings[s]
90  << " at command " << c << " is invalidated at command "
91  << PrintCommand(nc, analysis.DataInvalidatedCommand(c, s));
92  }
93  }
94 }
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
void Print(std::ostream &os, const Nnet &nnet) const
kaldi::int32 int32
std::vector< Command > commands
void ComputeExampleComputationRequestSimple(const Nnet &nnet, ComputationRequest *request, std::vector< Matrix< BaseFloat > > *inputs)
This function computes an example computation request, for testing purposes.
void Init(const Nnet &nnet, const NnetComputation &computation)
std::vector< SubMatrixInfo > submatrices
struct rnnlm::@11::@12 n
std::string PrintCommand(int32 num_commands, int32 command)
This class creates an initial version of the NnetComputation, without any optimization or sharing of ...
Definition: nnet-compile.h:44
void GenerateConfigSequence(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generates a sequence of at least one config files, output as strings, where the first in the sequence...
#define KALDI_LOG
Definition: kaldi-error.h:153
This struct exists to set up various pieces of analysis; it helps avoid the repetition of code where ...
Definition: nnet-analyze.h:294
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95
void GetSubmatrixStrings(const Nnet &nnet, std::vector< std::string > *submat_strings) const
This class performs various kinds of specific analysis on top of what class Analyzer gives you immedi...
Definition: nnet-analyze.h:308

◆ UnitTestNnetCompile()

void kaldi::nnet3::UnitTestNnetCompile ( )

Definition at line 29 of file nnet-compile-test.cc.

References ComputeExampleComputationRequestSimple(), Compiler::CreateComputation(), GenerateConfigSequence(), rnnlm::j, KALDI_LOG, rnnlm::n, ComputationRequest::Print(), NnetComputation::Print(), and Nnet::ReadConfig().

Referenced by main().

29  {
30  for (int32 n = 0; n < 20; n++) {
31  struct NnetGenerationOptions gen_config;
32  std::vector<std::string> configs;
33  GenerateConfigSequence(gen_config, &configs);
34  Nnet nnet;
35  for (size_t j = 0; j < configs.size(); j++) {
36  KALDI_LOG << "Input config[" << j << "] is: " << configs[j];
37  std::istringstream is(configs[j]);
38  nnet.ReadConfig(is);
39  }
40 
41  ComputationRequest request;
42  std::vector<Matrix<BaseFloat> > inputs;
43  ComputeExampleComputationRequestSimple(nnet, &request, &inputs);
44  KALDI_LOG << "Computation request is:";
45  request.Print(std::cerr);
46 
47  NnetComputation computation;
48  Compiler compiler(request, nnet);
49 
50  CompilerOptions opts;
51  compiler.CreateComputation(opts, &computation);
52 
53  std::ostringstream os;
54  computation.Print(os, nnet);
55  KALDI_LOG << "Generated computation is: " << os.str();
56  }
57 }
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
void Print(std::ostream &os, const Nnet &nnet) const
kaldi::int32 int32
void ComputeExampleComputationRequestSimple(const Nnet &nnet, ComputationRequest *request, std::vector< Matrix< BaseFloat > > *inputs)
This function computes an example computation request, for testing purposes.
struct rnnlm::@11::@12 n
This class creates an initial version of the NnetComputation, without any optimization or sharing of ...
Definition: nnet-compile.h:44
void GenerateConfigSequence(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generates a sequence of at least one config files, output as strings, where the first in the sequence...
void Print(std::ostream &os) const
This function is for printing info about the computation request in a human-readable way...
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ UnitTestNnetCompileLooped()

void kaldi::nnet3::UnitTestNnetCompileLooped ( )

Definition at line 120 of file nnet-compile-test.cc.

References NnetGenerationOptions::allow_ivector, CompileLooped(), CreateLoopedComputationRequestSimple(), GenerateConfigSequence(), GetChunkSize(), Nnet::Info(), rnnlm::j, KALDI_LOG, ModifyNnetIvectorPeriod(), rnnlm::n, ComputationRequest::Print(), NnetComputation::Print(), kaldi::RandInt(), and Nnet::ReadConfig().

Referenced by main().

120  {
121  for (int32 n = 0; n < 20; n++) {
122  struct NnetGenerationOptions gen_config;
123  gen_config.allow_ivector = true;
124 
125  std::vector<std::string> configs;
126  GenerateConfigSequence(gen_config, &configs);
127  Nnet nnet;
128  for (size_t j = 0; j < configs.size(); j++) {
129  KALDI_LOG << "Input config[" << j << "] is: " << configs[j];
130  std::istringstream is(configs[j]);
131  nnet.ReadConfig(is);
132  }
133 
134  ComputationRequest request1, request2, request3;
135  int32 chunk_size_min = RandInt(5, 15);
136  int32 frame_subsampling_factor = RandInt(1, 3),
137  extra_left_context_begin = RandInt(0, 10),
138  extra_right_context = RandInt(0, 10),
139  num_sequences = RandInt(1, 2);
140  int32 chunk_size = GetChunkSize(nnet, frame_subsampling_factor,
141  chunk_size_min),
142  ivector_period = chunk_size;
143 
144 
145 
146  ModifyNnetIvectorPeriod(ivector_period, &nnet);
147  KALDI_LOG << "Nnet info after modifying ivector period is: "
148  << nnet.Info();
150  nnet, chunk_size, frame_subsampling_factor,
151  ivector_period, extra_left_context_begin, extra_right_context,
152  num_sequences, &request1, &request2, &request3);
153 
154  KALDI_LOG << "Computation request 1 is:";
155  request1.Print(std::cerr);
156  KALDI_LOG << "Computation request 2 is:";
157  request2.Print(std::cerr);
158  KALDI_LOG << "Computation request 3 is:";
159  request3.Print(std::cerr);
160 
161  NnetOptimizeOptions optimize_opts;
162  // todo: set optimize-looped=true.
163  NnetComputation computation;
164  CompileLooped(nnet, optimize_opts,
165  request1, request2, request3,
166  &computation);
167  KALDI_LOG << "Compiled looped computation is ";
168  computation.Print(std::cerr, nnet);
169  }
170 }
void ModifyNnetIvectorPeriod(int32 ivector_period, Nnet *nnet)
This function modifies the descriptors in the neural network to change the periodicity with which it ...
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
int32 GetChunkSize(const Nnet &nnet, int32 frame_subsampling_factor, int32 advised_chunk_size)
void Print(std::ostream &os, const Nnet &nnet) const
kaldi::int32 int32
std::string Info() const
returns some human-readable information about the network, mostly for debugging purposes.
Definition: nnet-nnet.cc:821
void CompileLooped(const Nnet &nnet, const NnetOptimizeOptions &optimize_opts, const ComputationRequest &request1, const ComputationRequest &request2, const ComputationRequest &request3, NnetComputation *computation)
CompileLooped() provides an internal interface for &#39;looped&#39; computation.
struct rnnlm::@11::@12 n
void CreateLoopedComputationRequestSimple(const Nnet &nnet, int32 chunk_size, int32 frame_subsampling_factor, int32 ivector_period, int32 extra_left_context_begin, int32 extra_right_context, int32 num_sequences, ComputationRequest *request1, ComputationRequest *request2, ComputationRequest *request3)
This function is deprecated.
void GenerateConfigSequence(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generates a sequence of at least one config files, output as strings, where the first in the sequence...
void Print(std::ostream &os) const
This function is for printing info about the computation request in a human-readable way...
#define KALDI_LOG
Definition: kaldi-error.h:153
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestNnetCompileMulti()

void kaldi::nnet3::UnitTestNnetCompileMulti ( )

Definition at line 63 of file nnet-compile-test.cc.

References NnetGenerationOptions::allow_use_of_x_dim, ComputeExampleComputationRequestSimple(), GenerateConfigSequence(), rnnlm::i, ComputationRequest::inputs, rnnlm::j, KALDI_LOG, rnnlm::n, ComputationRequest::need_model_derivative, ComputationRequest::outputs, ComputationRequest::Print(), Nnet::ReadConfig(), and ComputationRequest::store_component_stats.

Referenced by main().

63  {
64  for (int32 n = 0; n < 20; n++) {
65  struct NnetGenerationOptions gen_config;
66  gen_config.allow_use_of_x_dim = false;
67 
68  std::vector<std::string> configs;
69  GenerateConfigSequence(gen_config, &configs);
70  Nnet nnet;
71  for (size_t j = 0; j < configs.size(); j++) {
72  KALDI_LOG << "Input config[" << j << "] is: " << configs[j];
73  std::istringstream is(configs[j]);
74  nnet.ReadConfig(is);
75  }
76 
77  ComputationRequest request1, request2;
78  std::vector<Matrix<BaseFloat> > inputs1, inputs2;
79  ComputeExampleComputationRequestSimple(nnet, &request1, &inputs1);
80  ComputeExampleComputationRequestSimple(nnet, &request2, &inputs2);
81 
82 
83  KALDI_LOG << "Computation request 1 is:";
84  request1.Print(std::cerr);
85  KALDI_LOG << "Computation request 2 is:";
86  request2.Print(std::cerr);
87 
88  std::vector<const ComputationRequest*> requests;
89  request2.store_component_stats = request1.store_component_stats;
90  request1.need_model_derivative = false;
91  request2.need_model_derivative = false;
92  requests.push_back(&request1);
93  requests.push_back(&request2);
94 
95  // set all the x indexes to 1 for request 2 (they would otherwise
96  // be zero). This ensures that there is no overlap
97  // between the inputs and outputs on the two requests.
98  for (int32 i = 0; i < request2.inputs.size(); i++)
99  for (int32 j = 0; j < request2.inputs[i].indexes.size(); j++)
100  request2.inputs[i].indexes[j].x = 1;
101  for (int32 i = 0; i < request2.outputs.size(); i++)
102  for (int32 j = 0; j < request2.outputs[i].indexes.size(); j++)
103  request2.outputs[i].indexes[j].x = 1;
104 
105 
106  NnetComputation computation;
107  Compiler compiler(requests, nnet);
108 
109  CompilerOptions opts;
110  compiler.CreateComputation(opts, &computation);
111 
112  std::ostringstream os;
113  computation.Print(os, nnet);
114  KALDI_LOG << "Generated computation is: " << os.str();
115  }
116 }
bool store_component_stats
you should set need_component_stats to true if you need the average-activation and average-derivative...
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
bool need_model_derivative
if need_model_derivative is true, then we&#39;ll be doing either model training or model-derivative compu...
kaldi::int32 int32
std::vector< IoSpecification > inputs
void ComputeExampleComputationRequestSimple(const Nnet &nnet, ComputationRequest *request, std::vector< Matrix< BaseFloat > > *inputs)
This function computes an example computation request, for testing purposes.
struct rnnlm::@11::@12 n
std::vector< IoSpecification > outputs
This class creates an initial version of the NnetComputation, without any optimization or sharing of ...
Definition: nnet-compile.h:44
void GenerateConfigSequence(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generates a sequence of at least one config files, output as strings, where the first in the sequence...
void Print(std::ostream &os) const
This function is for printing info about the computation request in a human-readable way...
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ UnitTestNnetComponent()

void kaldi::nnet3::UnitTestNnetComponent ( )

Definition at line 490 of file nnet-component-test.cc.

References GenerateRandomSimpleComponent(), Component::Info(), KALDI_ERR, KALDI_LOG, rnnlm::n, TestNnetComponentAddScale(), TestNnetComponentCopy(), TestNnetComponentIo(), TestNnetComponentUpdatable(), TestNnetComponentVectorizeUnVectorize(), TestSimpleComponentDataDerivative(), TestSimpleComponentModelDerivative(), and TestSimpleComponentPropagateProperties().

Referenced by main().

490  {
491  for (int32 n = 0; n < 200; n++) {
493  KALDI_LOG << c->Info();
500  if (!TestSimpleComponentDataDerivative(*c, 1.0e-04) &&
501  !TestSimpleComponentDataDerivative(*c, 1.0e-03) &&
502  !TestSimpleComponentDataDerivative(*c, 1.0e-05) &&
503  !TestSimpleComponentDataDerivative(*c, 1.0e-06))
504  KALDI_ERR << "Component data-derivative test failed";
505 
506  if (!TestSimpleComponentModelDerivative(*c, 1.0e-04, false) &&
507  !TestSimpleComponentModelDerivative(*c, 1.0e-03, false) &&
508  !TestSimpleComponentModelDerivative(*c, 1.0e-06, false))
509  KALDI_ERR << "Component downhill-update test failed";
510 
511  if (!TestSimpleComponentModelDerivative(*c, 1.0e-04, true) &&
512  !TestSimpleComponentModelDerivative(*c, 1.0e-03, true) &&
513  !TestSimpleComponentModelDerivative(*c, 1.0e-05, true) &&
514  !TestSimpleComponentModelDerivative(*c, 1.0e-06, true))
515  KALDI_ERR << "Component model-derivative test failed";
516 
517  delete c;
518  }
519 }
void TestSimpleComponentPropagateProperties(const Component &c)
Abstract base-class for neural-net components.
kaldi::int32 int32
void TestNnetComponentAddScale(Component *c)
bool TestSimpleComponentModelDerivative(const Component &c, BaseFloat perturb_delta, bool test_derivative)
void TestNnetComponentVectorizeUnVectorize(Component *c)
struct rnnlm::@11::@12 n
#define KALDI_ERR
Definition: kaldi-error.h:147
bool TestSimpleComponentDataDerivative(const Component &c, BaseFloat perturb_delta)
void TestNnetComponentCopy(Component *c)
virtual std::string Info() const
Returns some text-form information about this component, for diagnostics.
void TestNnetComponentUpdatable(Component *c)
#define KALDI_LOG
Definition: kaldi-error.h:153
void TestNnetComponentIo(Component *c)
Component * GenerateRandomSimpleComponent()
Generates random simple component for testing.

◆ UnitTestNnetComputationIo()

void kaldi::nnet3::UnitTestNnetComputationIo ( NnetComputation computation)

Definition at line 34 of file nnet-compute-test.cc.

References KALDI_ERR, kaldi::Rand(), NnetComputation::Read(), and NnetComputation::Write().

Referenced by UnitTestNnetCompute().

34  {
35  bool binary = (Rand() % 2 == 0);
36  std::ostringstream os;
37  computation->Write(os, binary);
38  const std::string &original_output = os.str();
39  std::istringstream computation_is(original_output);
40  computation->Read(computation_is, binary);
41  std::istringstream computation_is2(original_output);
42  NnetComputation computation2;
43  computation2.Read(computation_is2, binary);
44 
45  std::ostringstream os2, os3;
46  computation->Write(os2, binary);
47  computation2.Write(os3, binary);
48 
49  if (binary) {
50  if (!(os2.str() == original_output)) {
51  KALDI_ERR << "Outputs differ for computation";
52  }
53  }
54 }
void Read(std::istream &istream, bool binary)
#define KALDI_ERR
Definition: kaldi-error.h:147
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
void Write(std::ostream &ostream, bool binary) const

◆ UnitTestNnetCompute()

void kaldi::nnet3::UnitTestNnetCompute ( )

Definition at line 147 of file nnet-compute-test.cc.

References NnetComputer::AcceptInput(), kaldi::ApproxEqual(), ComputationChecker::Check(), CheckComputationOptions::check_rewrite, CollapseModel(), NnetComputation::ComputeCudaIndexes(), ComputeExampleComputationRequestSimple(), Compiler::CreateComputation(), NnetComputeOptions::debug, GenerateConfigSequence(), NnetComputer::GetOutput(), rnnlm::i, ComputationRequest::inputs, rnnlm::j, KALDI_ERR, KALDI_LOG, MaxOutputTimeInRequest(), rnnlm::n, Optimize(), ComputationRequest::outputs, NnetComputation::Print(), kaldi::RandInt(), Nnet::ReadConfig(), NnetComputer::Run(), SetBatchnormTestMode(), SetDropoutTestMode(), CuMatrixBase< Real >::SetRandn(), CuMatrixBase< Real >::Sum(), TestNnetDecodable(), UnitTestComputationRequestIo(), and UnitTestNnetComputationIo().

Referenced by main().

147  {
148  for (int32 n = 0; n < 20; n++) {
149  struct NnetGenerationOptions gen_config;
150  bool test_collapse_model = (RandInt(0, 1) == 0);
151 
152  std::vector<std::string> configs;
153  GenerateConfigSequence(gen_config, &configs);
154  Nnet nnet;
155  for (size_t j = 0; j < configs.size(); j++) {
156  KALDI_LOG << "Input config[" << j << "] is: " << configs[j];
157  std::istringstream is(configs[j]);
158  nnet.ReadConfig(is);
159  }
160 
161  ComputationRequest request;
162  std::vector<Matrix<BaseFloat> > inputs;
163  ComputeExampleComputationRequestSimple(nnet, &request, &inputs);
164 
165  // Test CollapseModel(). Note: lines with 'collapse' in some part of them
166  // are not necessary for the rest of the test to run; they only test
167  // CollapseModel().
168  if (test_collapse_model) {
169  // this model collapsing code requires that test mode is set for batchnorm
170  // and dropout components.
171  SetBatchnormTestMode(true, &nnet);
172  SetDropoutTestMode(true, &nnet);
173  }
174 
175  NnetComputation computation;
176  Compiler compiler(request, nnet);
177  CompilerOptions opts;
178  compiler.CreateComputation(opts, &computation);
179 
180  Nnet nnet_collapsed(nnet);
181  CollapseModelConfig collapse_config;
182  NnetComputation computation_collapsed;
183 
184  if (test_collapse_model) {
185  CollapseModel(collapse_config, &nnet_collapsed);
186  Compiler compiler_collapsed(request, nnet_collapsed);
187  compiler_collapsed.CreateComputation(opts, &computation_collapsed);
188  computation_collapsed.ComputeCudaIndexes();
189  }
190 
191 
192  {
193  std::ostringstream os;
194  computation.Print(os, nnet);
195  KALDI_LOG << "Generated computation is: " << os.str();
196  UnitTestNnetComputationIo(&computation);
198  }
199  CheckComputationOptions check_config;
200  // we can do the rewrite check since it's before optimization.
201  check_config.check_rewrite = true;
202  ComputationChecker checker(check_config, nnet, computation);
203  checker.Check();
204 
205  if (RandInt(0, 1) == 0) {
206  NnetOptimizeOptions opt_config;
207 
208  Optimize(opt_config, nnet,
209  MaxOutputTimeInRequest(request),
210  &computation);
211  {
212  std::ostringstream os;
213  computation.Print(os, nnet);
214  KALDI_LOG << "Optimized computation is: " << os.str();
215  }
216  }
217 
218  NnetComputeOptions compute_opts;
219  if (RandInt(0, 1) == 0)
220  compute_opts.debug = true;
221 
222  computation.ComputeCudaIndexes();
223  NnetComputer computer(compute_opts,
224  computation,
225  nnet,
226  &nnet);
227  // provide the input to the computation.
228  for (size_t i = 0; i < request.inputs.size(); i++) {
229  CuMatrix<BaseFloat> temp(inputs[i]);
230  KALDI_LOG << "Input sum is " << temp.Sum();
231  computer.AcceptInput(request.inputs[i].name, &temp);
232 
233  }
234  computer.Run();
235 
236 
237  const CuMatrixBase<BaseFloat> &output(computer.GetOutput("output"));
238 
239  KALDI_LOG << "Output sum is " << output.Sum();
240 
241  if (test_collapse_model) {
242  NnetComputer computer_collapsed(compute_opts,
243  computation_collapsed,
244  nnet_collapsed,
245  &nnet_collapsed);
246  for (size_t i = 0; i < request.inputs.size(); i++) {
247  CuMatrix<BaseFloat> temp(inputs[i]);
248  KALDI_LOG << "Input sum is " << temp.Sum();
249  computer_collapsed.AcceptInput(request.inputs[i].name, &temp);
250  }
251  computer_collapsed.Run();
252  const CuMatrixBase<BaseFloat> &output_collapsed(
253  computer_collapsed.GetOutput("output"));
254  KALDI_LOG << "Output sum [collapsed] is " << output_collapsed.Sum();
255  if (!ApproxEqual(output, output_collapsed)) {
256  KALDI_ERR << "Regular and collapsed computations' outputs differ";
257  }
258  }
259 
260  CuMatrix<BaseFloat> output_deriv(output.NumRows(), output.NumCols());
261  output_deriv.SetRandn();
262  // output_deriv sum won't be informative so don't print it.
263  if (request.outputs[0].has_deriv) {
264  computer.AcceptInput("output", &output_deriv);
265  computer.Run();
266  for (size_t i = 0; i < request.inputs.size(); i++) {
267  if (request.inputs[i].has_deriv) {
268  const CuMatrixBase<BaseFloat> &in_deriv =
269  computer.GetOutput(request.inputs[i].name);
270  KALDI_LOG << "Input-deriv sum for input '"
271  << request.inputs[i].name << "' is " << in_deriv.Sum();
272  }
273  }
274  }
275  TestNnetDecodable(&nnet);
276  }
277 }
void CollapseModel(const CollapseModelConfig &config, Nnet *nnet)
This function modifies the neural net for efficiency, in a way that suitable to be done in test time...
Definition: nnet-utils.cc:2100
void TestNnetDecodable(Nnet *nnet)
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
Real Sum() const
Definition: cu-matrix.cc:3012
void Print(std::ostream &os, const Nnet &nnet) const
void SetBatchnormTestMode(bool test_mode, Nnet *nnet)
This function affects only components of type BatchNormComponent.
Definition: nnet-utils.cc:564
kaldi::int32 int32
std::vector< IoSpecification > inputs
This class represents a matrix that&#39;s stored on the GPU if we have one, and in memory if not...
Definition: matrix-common.h:71
void SetDropoutTestMode(bool test_mode, Nnet *nnet)
This function affects components of child-classes of RandomComponent.
Definition: nnet-utils.cc:573
void ComputeExampleComputationRequestSimple(const Nnet &nnet, ComputationRequest *request, std::vector< Matrix< BaseFloat > > *inputs)
This function computes an example computation request, for testing purposes.
int32 MaxOutputTimeInRequest(const ComputationRequest &request)
struct rnnlm::@11::@12 n
#define KALDI_ERR
Definition: kaldi-error.h:147
void Optimize(const NnetOptimizeOptions &config, const Nnet &nnet, int32 max_output_time_in_request, NnetComputation *computation)
This is the top-level function for optimizing a computation.
void UnitTestComputationRequestIo(ComputationRequest *request)
Matrix for CUDA computing.
Definition: matrix-common.h:69
class NnetComputer is responsible for executing the computation described in the "computation" object...
Definition: nnet-compute.h:59
std::vector< IoSpecification > outputs
This class creates an initial version of the NnetComputation, without any optimization or sharing of ...
Definition: nnet-compile.h:44
void UnitTestNnetComputationIo(NnetComputation *computation)
void GenerateConfigSequence(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generates a sequence of at least one config files, output as strings, where the first in the sequence...
#define KALDI_LOG
Definition: kaldi-error.h:153
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
Definition: kaldi-math.h:265
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95
Config class for the CollapseModel function.
Definition: nnet-utils.h:240

◆ UnitTestNnetContext()

void kaldi::nnet3::UnitTestNnetContext ( )

Definition at line 29 of file nnet-utils-test.cc.

References ComputeSimpleNnetContext(), GenerateConfigSequence(), KALDI_LOG, rnnlm::n, NnetInfo(), and Nnet::ReadConfig().

Referenced by main().

29  {
30  for (int32 n = 0; n < 20; n++) {
31  struct NnetGenerationOptions gen_config;
32 
33  std::vector<std::string> configs;
34  GenerateConfigSequence(gen_config, &configs);
35  Nnet nnet;
36  std::istringstream is(configs[0]);
37  nnet.ReadConfig(is);
38 
39  // this test doesn't really test anything except that it runs;
40  // we manually inspect the output.
41  int32 left_context, right_context;
42  ComputeSimpleNnetContext(nnet, &left_context, &right_context);
43  KALDI_LOG << "Left,right-context= " << left_context << ","
44  << right_context << " for config: " << configs[0];
45 
46  KALDI_LOG << "Info for nnet is: " << NnetInfo(nnet);
47  }
48 }
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
kaldi::int32 int32
void ComputeSimpleNnetContext(const Nnet &nnet, int32 *left_context, int32 *right_context)
ComputeSimpleNnetContext computes the left-context and right-context of a nnet.
Definition: nnet-utils.cc:146
struct rnnlm::@11::@12 n
std::string NnetInfo(const Nnet &nnet)
This function returns various info about the neural net.
Definition: nnet-utils.cc:492
void GenerateConfigSequence(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generates a sequence of at least one config files, output as strings, where the first in the sequence...
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ UnitTestNnetExample()

void kaldi::nnet3::UnitTestNnetExample ( )

Definition at line 35 of file nnet-example-test.cc.

References ExampleApproxEqual(), GenerateSimpleNnetTrainingExample(), KALDI_ASSERT, rnnlm::n, kaldi::RandInt(), NnetExample::Read(), and NnetExample::Write().

Referenced by main().

35  {
36  for (int32 n = 0; n < 50; n++) {
37 
38  NnetExample eg;
39  int32 num_supervised_frames = RandInt(1, 10),
40  left_context = RandInt(0, 5),
41  right_context = RandInt(0, 5),
42  input_dim = RandInt(1, 10),
43  output_dim = RandInt(5, 10),
44  ivector_dim = RandInt(-1, 2);
45  GenerateSimpleNnetTrainingExample(num_supervised_frames, left_context,
46  right_context, input_dim, output_dim,
47  ivector_dim, &eg);
48  bool binary = (RandInt(0, 1) == 0);
49  std::ostringstream os;
50  eg.Write(os, binary);
51  NnetExample eg_copy;
52  if (RandInt(0, 1) == 0)
53  eg_copy = eg;
54  std::istringstream is(os.str());
55  eg_copy.Read(is, binary);
56  std::ostringstream os2;
57  eg_copy.Write(os2, binary);
58  if (binary) {
59  KALDI_ASSERT(os.str() == os2.str());
60  KALDI_ASSERT(eg_copy == eg);
61  }
62  KALDI_ASSERT(ExampleApproxEqual(eg, eg_copy, 0.1));
63  }
64 }
NnetExample is the input data and corresponding label (or labels) for one or more frames of input...
Definition: nnet-example.h:111
void GenerateSimpleNnetTrainingExample(int32 num_supervised_frames, int32 left_context, int32 right_context, int32 output_dim, int32 input_dim, int32 ivector_dim, NnetExample *example)
Low-level function that generates an nnet training example.
kaldi::int32 int32
void Write(std::ostream &os, bool binary) const
struct rnnlm::@11::@12 n
bool ExampleApproxEqual(const NnetExample &eg1, const NnetExample &eg2, BaseFloat delta)
Returns true if the examples are approximately equal (only intended to be used in testing)...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void Read(std::istream &is, bool binary)
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestNnetInputDerivatives()

void kaldi::nnet3::UnitTestNnetInputDerivatives ( )

Definition at line 246 of file nnet-derivative-test.cc.

References NnetComputer::AcceptInput(), CuMatrixBase< Real >::AddMat(), kaldi::ApproxEqual(), ComputationChecker::Check(), CheckComputationOptions::check_rewrite, ComputeExampleComputationRequestSimple(), rnnlm::d, NnetComputeOptions::debug, GenerateConfigSequence(), NnetComputer::GetOutput(), rnnlm::i, ComputationRequest::inputs, rnnlm::j, KALDI_ASSERT, KALDI_ERR, KALDI_LOG, KALDI_WARN, kaldi::kTrans, MaxOutputTimeInRequest(), rnnlm::n, ComputationRequest::need_model_derivative, NnetIsRecurrent(), Optimize(), Nnet::OutputDim(), ComputationRequest::outputs, kaldi::RandInt(), Nnet::ReadConfig(), CuMatrix< Real >::Resize(), NnetComputer::Run(), CuMatrixBase< Real >::SetRandn(), and kaldi::TraceMatMat().

Referenced by main().

246  {
247  int32 N = 20;
248  for (int32 n = 0; n < N; n++) {
249  struct NnetGenerationOptions gen_config;
250  //gen_config.allow_nonlinearity = false;
251  //gen_config.allow_recursion = false;
252  //gen_config.allow_final_nonlinearity = true;
253  bool allow_optimization = true;
254 
255  std::vector<std::string> configs;
256  GenerateConfigSequence(gen_config, &configs);
257  Nnet nnet;
258  for (size_t j = 0; j < configs.size(); j++) {
259  KALDI_LOG << "Input config[" << j << "] is: " << configs[j];
260  std::istringstream is(configs[j]);
261  nnet.ReadConfig(is);
262  }
263 
264  ComputationRequest request;
265  std::vector<Matrix<BaseFloat> > inputs;
266  ComputeExampleComputationRequestSimple(nnet, &request, &inputs);
267 
268  // make sure that all inputs and outputs have derivatives requested/provided,
269  // and that the model-update (need_model_derivative) is not requested.
270  request.need_model_derivative = false;
271  for (int32 i = 0; i < request.inputs.size(); i++)
272  request.inputs[i].has_deriv = true;
273  request.outputs[0].has_deriv = true;
274 
275  NnetComputation computation;
276  Compiler compiler(request, nnet);
277 
278  CompilerOptions opts;
279  compiler.CreateComputation(opts, &computation);
280  {
281  std::ostringstream os;
282  computation.Print(os, nnet);
283  KALDI_LOG << "Generated computation is: " << os.str();
284  }
285  CheckComputationOptions check_config;
286  // we can do the rewrite check since it's before optimization.
287  check_config.check_rewrite = true;
288  ComputationChecker checker(check_config, nnet, computation);
289  checker.Check();
290 
291  if (RandInt(0, 3) != 0 && allow_optimization) {
292  NnetOptimizeOptions opt_config;
293  // opt_config.initialize_undefined = false; // temp
294  Optimize(opt_config, nnet,
295  MaxOutputTimeInRequest(request),
296  &computation);
297  std::ostringstream os;
298  computation.Print(os, nnet);
299  KALDI_LOG << "Optimized computation is: " << os.str();
300  }
301 
302  NnetComputeOptions compute_opts;
303  if (RandInt(0, 1) == 0)
304  compute_opts.debug = true;
305  computation.ComputeCudaIndexes();
306 
307 
308  int32 num_directions = 3; // must be >= 1. Best if it's >1, will reduce
309  // the probability of random failures.
310 
311  // the order of these vectors is:
312  // [ un-perturbed, perturbed-1, perturbed-2, perturbed-3, un-perturbed ].
313  // we compute un-perturbed twice to double-check the model did not change.
314  std::vector<BaseFloat> measured_objf(num_directions + 2, 0.0),
315  predicted_objf_change(num_directions + 2, 0.0);
316  BaseFloat delta = 1.0e-03;
317 
318  // output_deriv is the derivative of the objective function w.r.t. the
319  // (single) output. We make the objf a linear function of the output and
320  // just set the output_deriv to be a random matrix, which defines the
321  // objective function.
322  CuMatrix<BaseFloat> output_deriv;
323  output_deriv.Resize(request.outputs[0].indexes.size(),
324  nnet.OutputDim("output"));
325  output_deriv.SetRandn();
326 
327  std::vector<CuMatrix<BaseFloat> > delta_inputs(inputs.size());
328  std::vector<CuMatrix<BaseFloat> > input_derivs(inputs.size());
329 
330  // pass 0 is the forward pass with the un-perturbed features; so is
331  // pass num_directions + 1.
332  // Other passes are with various differently-perturbed versions of
333  // the features.
334  for (int32 pass = 0; pass <= num_directions + 1; pass++) {
335  // the only reason we might need to provide the &nnet parameter is if the
336  // StoreStats() operation had been requested. We made sure no model update
337  // is being performed.
338  NnetComputer computer(compute_opts,
339  computation,
340  nnet,
341  &nnet);
342 
343 
344  // provide the input to the computations.
345  for (size_t i = 0; i < request.inputs.size(); i++) {
346 
347  CuMatrix<BaseFloat> temp(inputs[i]);
348  if (pass > 0 && pass <= num_directions) { // Perturb the input randomly.
349  delta_inputs[i].Resize(inputs[i].NumRows(), inputs[i].NumCols());
350  delta_inputs[i].SetRandn();
351  delta_inputs[i].Scale(delta);
352  // if there are >1 inputs, sometimes set the delta for input 0 to
353  // zero. might sometimes give more accurate test of error in iVector
354  // derivative computation.
355  if (i == 0 && request.inputs.size() > 1 && RandInt(0, 1) == 0)
356  delta_inputs[i].SetZero();
357  temp.AddMat(1.0, delta_inputs[i]);
358  predicted_objf_change[pass] += TraceMatMat(input_derivs[i],
359  delta_inputs[i], kTrans);
360  }
361  computer.AcceptInput(request.inputs[i].name, &temp);
362  }
363 
364  KALDI_LOG << "Running forward computation";
365  computer.Run();
366 
367  const CuMatrixBase<BaseFloat> &output(computer.GetOutput("output"));
368  KALDI_LOG << "Output sum for pass " << pass << " is " << output.Sum();
369  BaseFloat objf = TraceMatMat(output, output_deriv, kTrans);
370  measured_objf[pass] = objf;
371 
372  if (pass == 0) {
373  // We need to compute the input derivatives.
374  CuMatrix<BaseFloat> temp(output_deriv);
375  computer.AcceptInput("output", &temp);
376  KALDI_LOG << "Running backward computation";
377  computer.Run();
378  for (size_t i = 0; i < request.inputs.size(); i++) {
379  input_derivs[i] = computer.GetOutput(request.inputs[i].name);
380  KALDI_LOG << "Input-deriv norm for '" << request.inputs[i].name
381  << "' is " << input_derivs[i].FrobeniusNorm();
382  }
383  }
384  }
385  KALDI_ASSERT(ApproxEqual(measured_objf[0],
386  measured_objf[num_directions + 1]));
387 
388  Vector<BaseFloat> predicted_objf_change_vec(num_directions),
389  measured_objf_change_vec(num_directions);
390  for (int32 d = 0; d < num_directions; d++) {
391  BaseFloat predicted_change = predicted_objf_change[d+1],
392  measured_change = measured_objf[d+1] - measured_objf[0];
393  predicted_objf_change_vec(d) = predicted_change;
394  measured_objf_change_vec(d) = measured_change;
395  }
396  KALDI_LOG << "Vector of predicted objf-change is: "
397  << predicted_objf_change_vec;
398  KALDI_LOG << "Vector of measured objf-change is: "
399  << measured_objf_change_vec;
400  BaseFloat delta_thresh_warn = 0.05, delta_thresh_fail = 0.25;
401  if (!ApproxEqual(predicted_objf_change_vec,
402  measured_objf_change_vec, delta_thresh_fail)) {
403  if (NnetIsRecurrent(nnet)) {
404  KALDI_WARN << "Predicted and measured objf-changes differ too much. "
405  << "(would normally be beyond error threshold, but this "
406  << "nnet is recurrent, so letting it pass.";
407  } else {
408  KALDI_ERR << "Predicted and measured objf-changes differ too much.";
409  }
410  } else if (!ApproxEqual(predicted_objf_change_vec,
411  measured_objf_change_vec, delta_thresh_warn)) {
412  KALDI_WARN << "Predicted and measured objf-changes differ quite a lot";
413  }
414  }
415 }
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
bool need_model_derivative
if need_model_derivative is true, then we&#39;ll be doing either model training or model-derivative compu...
kaldi::int32 int32
std::vector< IoSpecification > inputs
This class represents a matrix that&#39;s stored on the GPU if we have one, and in memory if not...
Definition: matrix-common.h:71
int32 OutputDim(const std::string &output_name) const
Definition: nnet-nnet.cc:677
void ComputeExampleComputationRequestSimple(const Nnet &nnet, ComputationRequest *request, std::vector< Matrix< BaseFloat > > *inputs)
This function computes an example computation request, for testing purposes.
float BaseFloat
Definition: kaldi-types.h:29
int32 MaxOutputTimeInRequest(const ComputationRequest &request)
struct rnnlm::@11::@12 n
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_WARN
Definition: kaldi-error.h:150
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.
void Optimize(const NnetOptimizeOptions &config, const Nnet &nnet, int32 max_output_time_in_request, NnetComputation *computation)
This is the top-level function for optimizing a computation.
Matrix for CUDA computing.
Definition: matrix-common.h:69
A class representing a vector.
Definition: kaldi-vector.h:406
class NnetComputer is responsible for executing the computation described in the "computation" object...
Definition: nnet-compute.h:59
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
std::vector< IoSpecification > outputs
This class creates an initial version of the NnetComputation, without any optimization or sharing of ...
Definition: nnet-compile.h:44
bool NnetIsRecurrent(const Nnet &nnet)
Returns true if &#39;nnet&#39; has some kind of recurrency.
Definition: nnet-utils.cc:1441
void GenerateConfigSequence(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generates a sequence of at least one config files, output as strings, where the first in the sequence...
#define KALDI_LOG
Definition: kaldi-error.h:153
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
Definition: kaldi-math.h:265
void Resize(MatrixIndexT rows, MatrixIndexT cols, MatrixResizeType resize_type=kSetZero, MatrixStrideType stride_type=kDefaultStride)
Allocate the memory.
Definition: cu-matrix.cc:50
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestNnetIo()

void kaldi::nnet3::UnitTestNnetIo ( )

Definition at line 27 of file nnet-nnet-test.cc.

References GenerateConfigSequence(), KALDI_ASSERT, rnnlm::n, kaldi::Rand(), Nnet::Read(), Nnet::ReadConfig(), and Nnet::Write().

Referenced by main().

27  {
28  for (int32 n = 0; n < 100; n++) {
29  struct NnetGenerationOptions gen_config;
30 
31  bool binary = (Rand() % 2 == 0);
32  std::vector<std::string> configs;
33  GenerateConfigSequence(gen_config, &configs);
34  Nnet nnet;
35  std::istringstream is(configs[0]);
36  nnet.ReadConfig(is);
37 
38  std::ostringstream os;
39  nnet.Write(os, binary);
40  const std::string &original_output = os.str();
41  std::istringstream nnet_is(original_output);
42  nnet.Read(nnet_is, binary);
43  std::istringstream nnet_is2(original_output);
44  Nnet nnet2;
45  nnet2.Read(nnet_is2, binary);
46 
47  std::ostringstream os2, os3;
48  nnet.Write(os2, binary);
49 
50  nnet2.Write(os3, binary);
51  if (binary) {
52  KALDI_ASSERT(os2.str() == original_output);
53  KALDI_ASSERT(os3.str() == original_output);
54  }
55  }
56 }
void Write(std::ostream &ostream, bool binary) const
Definition: nnet-nnet.cc:630
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
kaldi::int32 int32
void Read(std::istream &istream, bool binary)
Definition: nnet-nnet.cc:586
struct rnnlm::@11::@12 n
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void GenerateConfigSequence(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generates a sequence of at least one config files, output as strings, where the first in the sequence...

◆ UnitTestNnetMergeExamples()

void kaldi::nnet3::UnitTestNnetMergeExamples ( )

Definition at line 67 of file nnet-example-test.cc.

References GenerateSimpleNnetTrainingExample(), rnnlm::i, KALDI_LOG, MergeExamples(), rnnlm::n, kaldi::RandInt(), and NnetExample::Write().

Referenced by main().

67  {
68  for (int32 n = 0; n < 50; n++) {
69  int32 num_supervised_frames = RandInt(1, 10),
70  left_context = RandInt(0, 5),
71  right_context = RandInt(0, 5),
72  input_dim = RandInt(1, 10),
73  output_dim = RandInt(5, 10),
74  ivector_dim = RandInt(-1, 2);
75 
76  int32 num_egs = RandInt(1, 4);
77  std::vector<NnetExample> egs_to_be_merged(num_egs);
78  for (int32 i = 0; i < num_egs; i++) {
79  NnetExample eg;
80  // sometimes omit the ivector. just tests things a bit more
81  // thoroughly.
82  GenerateSimpleNnetTrainingExample(num_supervised_frames, left_context,
83  right_context, input_dim, output_dim,
84  RandInt(0, 1) == 0 ? 0 : ivector_dim,
85  &eg);
86  KALDI_LOG << i << "'th example to be merged is: ";
87  eg.Write(std::cerr, false);
88  egs_to_be_merged[i].Swap(&eg);
89  }
90  NnetExample eg_merged;
91  bool compress = (RandInt(0, 1) == 0);
92  MergeExamples(egs_to_be_merged, compress, &eg_merged);
93  KALDI_LOG << "Merged example is: ";
94  eg_merged.Write(std::cerr, false);
95  }
96 }
NnetExample is the input data and corresponding label (or labels) for one or more frames of input...
Definition: nnet-example.h:111
void GenerateSimpleNnetTrainingExample(int32 num_supervised_frames, int32 left_context, int32 right_context, int32 output_dim, int32 input_dim, int32 ivector_dim, NnetExample *example)
Low-level function that generates an nnet training example.
kaldi::int32 int32
void Write(std::ostream &os, bool binary) const
struct rnnlm::@11::@12 n
#define KALDI_LOG
Definition: kaldi-error.h:153
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95
void MergeExamples(const std::vector< NnetExample > &src, bool compress, NnetExample *merged_eg)
Merge a set of input examples into a single example (typically the size of "src" will be the minibatc...

◆ UnitTestNnetModelDerivatives()

void kaldi::nnet3::UnitTestNnetModelDerivatives ( )

Definition at line 91 of file nnet-derivative-test.cc.

References NnetComputer::AcceptInput(), kaldi::ApproxEqual(), CachingOptimizingCompiler::Compile(), ComputeExampleComputationRequestSimple(), rnnlm::d, NnetComputeOptions::debug, DotProduct(), GenerateConfigSequence(), NnetComputer::GetOutput(), rnnlm::i, ComputationRequest::inputs, rnnlm::j, KALDI_ERR, KALDI_LOG, KALDI_WARN, kaldi::kTrans, rnnlm::n, ComputationRequest::need_model_derivative, NnetIsRecurrent(), Nnet::OutputDim(), ComputationRequest::outputs, PerturbParams(), NnetComputation::Print(), kaldi::RandInt(), Nnet::ReadConfig(), CuMatrix< Real >::Resize(), NnetComputer::Run(), ScaleNnet(), SetDerivTimesOptions(), SetNnetAsGradient(), CuMatrixBase< Real >::SetRandn(), and kaldi::TraceMatMat().

Referenced by main().

91  {
92  int32 N = 20;
93  for (int32 n = 0; n < N; n++) {
94  struct NnetGenerationOptions gen_config;
95  //gen_config.allow_nonlinearity = false;
96  //gen_config.allow_recursion = false;
97  //gen_config.allow_final_nonlinearity = true;
98 
99  bool limit_deriv_times = (RandInt(0, 2) == 0);
100 
101  std::vector<std::string> configs;
102  GenerateConfigSequence(gen_config, &configs);
103  Nnet nnet;
104  for (size_t j = 0; j < configs.size(); j++) {
105  KALDI_LOG << "Input config[" << j << "] is: " << configs[j];
106  std::istringstream is(configs[j]);
107  nnet.ReadConfig(is);
108  }
109 
110  ComputationRequest request;
111  std::vector<Matrix<BaseFloat> > inputs;
112  ComputeExampleComputationRequestSimple(nnet, &request, &inputs);
113 
114  // make sure that a model-derivative is requested, and an output-derivative
115  // is supplied.
116  request.need_model_derivative = true;
117  request.outputs[0].has_deriv = true;
118  // whether input-derivatives are required or not does not matter,
119  // so leave it as it is in that regard.
120 
121  NnetOptimizeOptions optimize_opts;
122  CachingOptimizingCompilerOptions compiler_opts;
123  if (limit_deriv_times) {
124  SetDerivTimesOptions(request, &optimize_opts);
125  }
126 
127  CachingOptimizingCompiler compiler(nnet, optimize_opts,
128  compiler_opts);
129 
130  const NnetComputation &computation = *(compiler.Compile(request));
131 
132  {
133  std::ostringstream os;
134  computation.Print(os, nnet);
135  KALDI_LOG << "Optimized computation is: " << os.str();
136  }
137 
138  Nnet nnet_deriv(nnet);
139  ScaleNnet(0.0, &nnet_deriv);
140  SetNnetAsGradient(&nnet_deriv); // forces "simple" update and unit
141  // learning rate.
142 
143  int32 num_directions = 4; // must be >= 1. Best if it's >1, will reduce
144  // the probability of random failures.
145 
146  // the order of these vectors is:
147  // [ un-perturbed, perturbed-1, perturbed-2, perturbed-3 ].
148  std::vector<BaseFloat> measured_objf(num_directions + 1, 0.0),
149  predicted_objf_change(num_directions + 1, 0.0);
150  BaseFloat delta = 5.0e-04;
151 
152  // output_deriv is the derivative of the objective function w.r.t. the
153  // (single) output. We make the objf a linear function of the output and
154  // just set the output_deriv to be a random matrix, which defines the
155  // objective function.
156  CuMatrix<BaseFloat> output_deriv;
157  output_deriv.Resize(request.outputs[0].indexes.size(),
158  nnet.OutputDim("output"));
159  output_deriv.SetRandn();
160 
161 
162  NnetComputeOptions compute_opts;
163  if (RandInt(0, 1) == 0)
164  compute_opts.debug = true;
165 
166  // pass 0 is the forward pass with the un-perturbed model.
167  // Other passes are with various differently-perturbed versions of
168  // the model.
169  for (int32 pass = 0; pass <= num_directions; pass++) {
170  Nnet nnet_copy(nnet);
171  if (pass > 0)
172  PerturbParams(delta, &nnet_copy);
173 
174  NnetComputer computer(compute_opts,
175  computation,
176  nnet_copy,
177  (pass == 0 ? &nnet_deriv : &nnet_copy));
178 
179 
180  // provide the input to the computation.
181  for (size_t i = 0; i < request.inputs.size(); i++) {
182  CuMatrix<BaseFloat> temp(inputs[i]);
183  computer.AcceptInput(request.inputs[i].name, &temp);
184  }
185 
186  KALDI_LOG << "Running forward computation";
187  computer.Run();
188 
189  const CuMatrixBase<BaseFloat> &output(computer.GetOutput("output"));
190  KALDI_LOG << "Output sum for pass " << pass << " is " << output.Sum();
191  BaseFloat objf = TraceMatMat(output, output_deriv, kTrans);
192  measured_objf[pass] = objf;
193 
194  if (pass == 0) {
195  // we need to do the backward computation (to get the model derivative)
196  CuMatrix<BaseFloat> temp(output_deriv);
197  computer.AcceptInput("output", &temp);
198  KALDI_LOG << "Running backward computation";
199  computer.Run();
200  } else {
201  // work out the predicted objf-change as dot-product of deriv and
202  // parameter-change. The expression below can be interpreted as
203  // DotProduct(nnet_copy - nnet, nnet_deriv).
204  predicted_objf_change[pass] = DotProduct(nnet_copy, nnet_deriv) -
205  DotProduct(nnet, nnet_deriv);
206  }
207  }
208 
209  Vector<BaseFloat> predicted_objf_change_vec(num_directions),
210  measured_objf_change_vec(num_directions);
211  for (int32 d = 0; d < num_directions; d++) {
212  BaseFloat predicted_change = predicted_objf_change[d+1],
213  measured_change = measured_objf[d+1] - measured_objf[0];
214  predicted_objf_change_vec(d) = predicted_change;
215  measured_objf_change_vec(d) = measured_change;
216  }
217  KALDI_LOG << "Vector of predicted objf-change is: "
218  << predicted_objf_change_vec;
219  KALDI_LOG << "Vector of measured objf-change is: "
220  << measured_objf_change_vec;
221  BaseFloat delta_thresh_warn = 0.05, delta_thresh_fail = 0.25;
222  if (limit_deriv_times) {
223  KALDI_LOG << "Not checking that predicted/measured changes matched "
224  << "because we limited times of derivatives.";
225  } else {
226  if (!ApproxEqual(predicted_objf_change_vec,
227  measured_objf_change_vec, delta_thresh_fail)) {
228  if (NnetIsRecurrent(nnet)) {
229  KALDI_WARN << "Predicted and measured objf-changes differ too much. "
230  << "(would normally be beyond error threshold, but this "
231  << "nnet is recurrent, so letting it pass.";
232  } else {
233  KALDI_ERR << "Predicted and measured objf-changes differ too much.";
234  }
235  }
236  if (!ApproxEqual(predicted_objf_change_vec,
237  measured_objf_change_vec, delta_thresh_warn)) {
238  KALDI_WARN << "Predicted and measured objf-changes differ quite a lot.";
239  }
240  }
241  }
242 }
void ScaleNnet(BaseFloat scale, Nnet *nnet)
Scales the nnet parameters and stats by this scale.
Definition: nnet-utils.cc:312
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
bool need_model_derivative
if need_model_derivative is true, then we&#39;ll be doing either model training or model-derivative compu...
This class enables you to do the compilation and optimization in one call, and also ensures that if t...
void Print(std::ostream &os, const Nnet &nnet) const
kaldi::int32 int32
std::vector< IoSpecification > inputs
This class represents a matrix that&#39;s stored on the GPU if we have one, and in memory if not...
Definition: matrix-common.h:71
void SetDerivTimesOptions(const ComputationRequest &request, NnetOptimizeOptions *opt_config)
int32 OutputDim(const std::string &output_name) const
Definition: nnet-nnet.cc:677
void SetNnetAsGradient(Nnet *nnet)
Sets nnet as gradient by Setting is_gradient_ to true and learning_rate_ to 1 for each UpdatableCompo...
Definition: nnet-utils.cc:292
void ComputeExampleComputationRequestSimple(const Nnet &nnet, ComputationRequest *request, std::vector< Matrix< BaseFloat > > *inputs)
This function computes an example computation request, for testing purposes.
float BaseFloat
Definition: kaldi-types.h:29
struct rnnlm::@11::@12 n
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_WARN
Definition: kaldi-error.h:150
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.
BaseFloat DotProduct(const Nnet &nnet1, const Nnet &nnet2)
Returns dot product between two networks of the same structure (calls the DotProduct functions of the...
Definition: nnet-utils.cc:250
Matrix for CUDA computing.
Definition: matrix-common.h:69
A class representing a vector.
Definition: kaldi-vector.h:406
class NnetComputer is responsible for executing the computation described in the "computation" object...
Definition: nnet-compute.h:59
std::vector< IoSpecification > outputs
void PerturbParams(BaseFloat stddev, Nnet *nnet)
Calls PerturbParams (with the given stddev) on all updatable components of the nnet.
Definition: nnet-utils.cc:199
bool NnetIsRecurrent(const Nnet &nnet)
Returns true if &#39;nnet&#39; has some kind of recurrency.
Definition: nnet-utils.cc:1441
void GenerateConfigSequence(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generates a sequence of at least one config files, output as strings, where the first in the sequence...
#define KALDI_LOG
Definition: kaldi-error.h:153
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
Definition: kaldi-math.h:265
void Resize(MatrixIndexT rows, MatrixIndexT cols, MatrixResizeType resize_type=kSetZero, MatrixStrideType stride_type=kDefaultStride)
Allocate the memory.
Definition: cu-matrix.cc:50
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestNnetOptimize()

static void kaldi::nnet3::UnitTestNnetOptimize ( )
static

Definition at line 295 of file nnet-optimize-test.cc.

References KALDI_LOG, and UnitTestNnetOptimizeInternal().

Referenced by main().

295  {
296  for (int32 srand_seed = 0; srand_seed < 40; srand_seed++) {
297  KALDI_LOG << "About to run UnitTestNnetOptimizeInternal with srand_seed = "
298  << srand_seed;
299  UnitTestNnetOptimizeInternal(srand_seed);
300  }
301 }
static void UnitTestNnetOptimizeInternal(int32 srand_seed)
kaldi::int32 int32
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ UnitTestNnetOptimizeInternal()

static void kaldi::nnet3::UnitTestNnetOptimizeInternal ( int32  srand_seed)
static

Definition at line 194 of file nnet-optimize-test.cc.

References NnetOptimizeOptions::allocate_from_other, NnetOptimizeOptions::backprop_in_place, NnetOptimizeOptions::convert_addition, NnetOptimizeOptions::initialize_undefined, KALDI_ERR, KALDI_SUCCFAIL, NnetOptimizeOptions::max_deriv_time, NnetOptimizeOptions::max_deriv_time_relative, NnetOptimizeOptions::min_deriv_time, NnetOptimizeOptions::move_sizing_commands, NnetOptimizeOptions::optimize_row_ops, NnetOptimizeOptions::propagate_in_place, kaldi::RandInt(), NnetOptimizeOptions::remove_assignments, NnetOptimizeOptions::snip_row_ops, UnitTestNnetOptimizeWithOptions(), and CachingOptimizingCompilerOptions::use_shortcut.

Referenced by UnitTestNnetOptimize().

194  {
195  NnetOptimizeOptions optimize_all;
197 
198  // randomly sometimes set min_deriv and max_deriv to small/large values,
199  // which will cause some of the LimitDerivativeTimes() code to be called
200  // (without really changing anything).
201  if (RandInt(0, 3) == 0) optimize_all.min_deriv_time = -200;
202  if (RandInt(0, 3) == 0) optimize_all.max_deriv_time = 1000;
203 
204  // this is useful for debugging as it removes nans:
205  // optimize_all.initialize_undefined = false;
206  bool success = UnitTestNnetOptimizeWithOptions(srand_seed, optimize_all,
207  compiler_all);
208  if (success)
209  return;
210 
211  // Test failed with full optimization. Slowly retry with various
212  // optimizations switched off.
213  NnetOptimizeOptions optimize = optimize_all;
214  CachingOptimizingCompilerOptions compiler = compiler_all;
215 
216 
217  compiler.use_shortcut = false;
218  bool succ_no_shortcut = UnitTestNnetOptimizeWithOptions(srand_seed, optimize,
219  compiler);
220  compiler = compiler_all;
221 
222 
223  optimize.propagate_in_place = false;
224  bool succ_no_propagate_in_place = UnitTestNnetOptimizeWithOptions(srand_seed, optimize,
225  compiler);
226  optimize = optimize_all;
227 
228  optimize.backprop_in_place = false;
229  bool succ_no_backprop_in_place = UnitTestNnetOptimizeWithOptions(srand_seed, optimize,
230  compiler);
231  optimize = optimize_all;
232 
233  optimize.optimize_row_ops = false;
234  bool succ_no_row_ops = UnitTestNnetOptimizeWithOptions(srand_seed, optimize,
235  compiler);
236  optimize = optimize_all;
237 
238  optimize.convert_addition = false;
239  bool succ_no_convert_addition = UnitTestNnetOptimizeWithOptions(srand_seed, optimize,
240  compiler);
241  optimize = optimize_all;
242 
243  optimize.remove_assignments = false;
244  bool succ_no_remove_assignments = UnitTestNnetOptimizeWithOptions(srand_seed, optimize,
245  compiler);
246  optimize = optimize_all;
247 
248  optimize.initialize_undefined = false;
249  bool succ_no_initialize_undefined = UnitTestNnetOptimizeWithOptions(srand_seed, optimize,
250  compiler);
251  optimize = optimize_all;
252 
253  optimize.allocate_from_other = false;
254  bool succ_no_allocate_from_other = UnitTestNnetOptimizeWithOptions(srand_seed, optimize,
255  compiler);
256  optimize = optimize_all;
257 
258  optimize.move_sizing_commands = false;
259  bool succ_no_move_sizing_commands = UnitTestNnetOptimizeWithOptions(srand_seed, optimize,
260  compiler);
261  optimize = optimize_all;
262 
263  optimize.snip_row_ops = false;
264  bool succ_no_snip_row_ops = UnitTestNnetOptimizeWithOptions(srand_seed, optimize,
265  compiler);
266  optimize = optimize_all;
267 
268 
269  optimize.min_deriv_time = std::numeric_limits<int32>::min();
270  optimize.max_deriv_time = std::numeric_limits<int32>::max();
271  optimize.max_deriv_time_relative = std::numeric_limits<int32>::max();
272  bool succ_no_deriv_time = UnitTestNnetOptimizeWithOptions(srand_seed, optimize,
273  compiler);
274  optimize = optimize_all;
275 
276 
277 #define KALDI_SUCCFAIL(b) ((b) ? "SUCCESS" : "FAILURE")
278  KALDI_ERR
279  << "Test failed with all optimizations enabled. Retried test with the "
280  << "following optimizations turned off:"
281  << "\n use_shortcut ... " << KALDI_SUCCFAIL(succ_no_shortcut)
282  << "\n propagate_in_place ... " << KALDI_SUCCFAIL(succ_no_propagate_in_place)
283  << "\n backprop_in_place ... " << KALDI_SUCCFAIL(succ_no_backprop_in_place)
284  << "\n optimize_row_ops ... " << KALDI_SUCCFAIL(succ_no_row_ops)
285  << "\n convert_addition ... " << KALDI_SUCCFAIL(succ_no_convert_addition)
286  << "\n remove_assignments ... " << KALDI_SUCCFAIL(succ_no_remove_assignments)
287  << "\n initialize_undefined ... " << KALDI_SUCCFAIL(succ_no_initialize_undefined)
288  << "\n allocate_from_other ... " << KALDI_SUCCFAIL(succ_no_allocate_from_other)
289  << "\n move_sizing_commands ... " << KALDI_SUCCFAIL(succ_no_move_sizing_commands)
290  << "\n snip_row_ops ... " << KALDI_SUCCFAIL(succ_no_snip_row_ops)
291  << "\n no_deriv_time ... " << KALDI_SUCCFAIL(succ_no_deriv_time);
292 #undef KALDI_SUCCFAIL
293 }
#define KALDI_SUCCFAIL(b)
static bool UnitTestNnetOptimizeWithOptions(int32 srand_seed, NnetOptimizeOptions opt_config, CachingOptimizingCompilerOptions compiler_config)
#define KALDI_ERR
Definition: kaldi-error.h:147
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestNnetOptimizeWithOptions()

static bool kaldi::nnet3::UnitTestNnetOptimizeWithOptions ( int32  srand_seed,
NnetOptimizeOptions  opt_config,
CachingOptimizingCompilerOptions  compiler_config 
)
static

Definition at line 33 of file nnet-optimize-test.cc.

References NnetComputer::AcceptInput(), kaldi::ApproxEqual(), ComputationChecker::Check(), CheckComputationOptions::check_rewrite, CachingOptimizingCompiler::Compile(), NnetComputation::ComputeCudaIndexes(), ComputeExampleComputationRequestSimple(), Compiler::CreateComputation(), NnetComputeOptions::debug, GenerateConfigSequence(), NnetComputer::GetOutput(), rnnlm::i, ComputationRequest::inputs, rnnlm::j, KALDI_LOG, KALDI_WARN, NnetParametersAreIdentical(), ComputationRequest::outputs, NnetComputation::Print(), kaldi::RandInt(), Nnet::ReadConfig(), ResetGenerators(), NnetComputer::Run(), ScaleNnet(), SetNnetAsGradient(), CuMatrixBase< Real >::SetRandn(), and CuMatrixBase< Real >::Sum().

Referenced by UnitTestNnetOptimizeInternal().

35  {
36 
37  //opt_config.convert_addition = false;
38  //opt_config.remove_assignments = false;
39  //opt_config.move_sizing_commands = false;
40  //opt_config.allocate_from_other = false;
41 
42  srand(srand_seed); // so that we can compare between differnt optimization types
43  // with the randomly generated network staying the same.
44 
45  struct NnetGenerationOptions gen_config;
46 
47  std::vector<std::string> configs;
48  GenerateConfigSequence(gen_config, &configs);
49  Nnet nnet;
50  for (size_t j = 0; j < configs.size(); j++) {
51  KALDI_LOG << "Input config[" << j << "] is: " << configs[j];
52  std::istringstream is(configs[j]);
53  nnet.ReadConfig(is);
54  }
55 
56  ComputationRequest request;
57  std::vector<Matrix<BaseFloat> > inputs;
58  ComputeExampleComputationRequestSimple(nnet, &request, &inputs);
59 
60  NnetComputation computation;
61  Compiler compiler(request, nnet);
62 
63  CompilerOptions opts;
64  compiler.CreateComputation(opts, &computation);
65  {
66  std::ostringstream os;
67  computation.Print(os, nnet);
68  KALDI_LOG << "Generated computation with no optimization or shortcut is: " << os.str();
69  }
70  CheckComputationOptions check_config;
71  // we can do the rewrite check since it's before optimization.
72  check_config.check_rewrite = true;
73  ComputationChecker checker(check_config, nnet, computation);
74  checker.Check();
75 
76  CachingOptimizingCompiler opt_compiler(nnet, opt_config, compiler_config);
77 
78  const NnetComputation &computation_opt = *opt_compiler.Compile(request);
79 
80  {
81  std::ostringstream os;
82  computation_opt.Print(os, nnet);
83  KALDI_LOG << "Optimized computation is: " << os.str();
84  }
85 
86  NnetComputeOptions compute_opts;
87  if (RandInt(0, 1) == 0)
88  compute_opts.debug = true;
89 
90  computation.ComputeCudaIndexes();
91  // computation_opt has already had this function called.
92 
93  Nnet nnet_to_update(nnet); // copy of the nnet that we update... needed to
94  // test the consolidation of backprop commands,
95  // otherwise the optimized and non-optimized
96  // comptuations differ.
97  ScaleNnet(0.0, &nnet_to_update);
98  // with natural gradient, the consolidation would affect the final model
99  // params -> test just the gradient.
100  SetNnetAsGradient(&nnet_to_update);
101 
102  NnetComputer computer(compute_opts,
103  computation,
104  nnet,
105  &nnet_to_update);
106 
107  Nnet nnet_opt(nnet); // copy of the nnet for the optimized computation.
108  // necessary in case backprop changes parameters.
109  Nnet nnet_opt_to_update(nnet_opt);
110  ScaleNnet(0.0, &nnet_opt_to_update);
111  SetNnetAsGradient(&nnet_opt_to_update);
112 
113  // NnetComputer for the optimized version of the computation.
114  NnetComputer computer_opt(compute_opts,
115  computation_opt,
116  nnet_opt,
117  &nnet_opt_to_update);
118 
119  // provide the input to the computations.
120  for (size_t i = 0; i < request.inputs.size(); i++) {
121  CuMatrix<BaseFloat> temp(inputs[i]);
122  KALDI_LOG << "Input sum is " << temp.Sum();
123  computer.AcceptInput(request.inputs[i].name, &temp);
124  CuMatrix<BaseFloat> temp2(inputs[i]);
125  computer_opt.AcceptInput(request.inputs[i].name, &temp2);
126  }
127 
128 
129 
130 
131  KALDI_LOG << "Running non-optimized forward computation";
132  srand(srand_seed);
133  ResetGenerators(&nnet);
134  computer.Run();
135  KALDI_LOG << "Running optimized forward computation";
136  srand(srand_seed);
137  ResetGenerators(&nnet_opt);
138  computer_opt.Run();
139 
140  const CuMatrixBase<BaseFloat> &output(computer.GetOutput("output"));
141  KALDI_LOG << "Output sum (not optimized) is " << output.Sum();
142  const CuMatrixBase<BaseFloat> &output_opt(computer_opt.GetOutput("output"));
143  KALDI_LOG << "Output sum (optimized) is " << output_opt.Sum();
144  if (!ApproxEqual(output, output_opt)) {
145  KALDI_WARN << "Non-optimized and optimized versions of the computation give "
146  << "different outputs: " << output << " vs. " << output_opt;
147  return false;
148  }
149 
150  CuMatrix<BaseFloat> output_deriv(output.NumRows(), output.NumCols());
151  output_deriv.SetRandn();
152  CuMatrix<BaseFloat> output_deriv_opt(output_deriv);
153 
154  if (request.outputs[0].has_deriv) {
155  computer.AcceptInput("output", &output_deriv);
156  computer_opt.AcceptInput("output", &output_deriv_opt);
157 
158  KALDI_LOG << "Running non-optimized backward computation";
159  computer.Run();
160  KALDI_LOG << "Running optimized backward computation";
161  computer_opt.Run();
162  for (size_t i = 0; i < request.inputs.size(); i++) {
163  if (request.inputs[i].has_deriv) {
164  const CuMatrixBase<BaseFloat> &in_deriv =
165  computer.GetOutput(request.inputs[i].name);
166  const CuMatrixBase<BaseFloat> &in_deriv_opt =
167  computer_opt.GetOutput(request.inputs[i].name);
168  KALDI_LOG << "Input-deriv sum for input '" << request.inputs[i].name
169  << "' (non-optimized) is " << in_deriv.Sum();
170  KALDI_LOG << "Input-deriv sum for input '" << request.inputs[i].name
171  << "' (optimized) is " << in_deriv_opt.Sum();
172  if (!ApproxEqual(in_deriv, in_deriv_opt)) {
173  KALDI_WARN << "Non-optimized and optimized versions of the "
174  << "computation give different input-derivs.";
175  return false;
176  }
177  }
178  }
179  }
180 
181  if (!NnetParametersAreIdentical(nnet_to_update,
182  nnet_opt_to_update, 1.0e-05)) {
183  KALDI_WARN << "Neural networks differ after training, between "
184  << "optimized and non-optimized computation.";
185  return false;
186  } else {
187  return true;
188  }
189 }
void ScaleNnet(BaseFloat scale, Nnet *nnet)
Scales the nnet parameters and stats by this scale.
Definition: nnet-utils.cc:312
void ReadConfig(std::istream &config_file)
Definition: nnet-nnet.cc:189
bool NnetParametersAreIdentical(const Nnet &nnet1, const Nnet &nnet2, BaseFloat threshold=1.0e-05)
Used for testing that the updatable parameters in two networks are the same.
This class enables you to do the compilation and optimization in one call, and also ensures that if t...
Real Sum() const
Definition: cu-matrix.cc:3012
void Print(std::ostream &os, const Nnet &nnet) const
std::vector< IoSpecification > inputs
This class represents a matrix that&#39;s stored on the GPU if we have one, and in memory if not...
Definition: matrix-common.h:71
void SetNnetAsGradient(Nnet *nnet)
Sets nnet as gradient by Setting is_gradient_ to true and learning_rate_ to 1 for each UpdatableCompo...
Definition: nnet-utils.cc:292
void ResetGenerators(Nnet *nnet)
This function calls &#39;ResetGenerator()&#39; on all components in &#39;nnet&#39; that inherit from class RandomComp...
Definition: nnet-utils.cc:582
void ComputeExampleComputationRequestSimple(const Nnet &nnet, ComputationRequest *request, std::vector< Matrix< BaseFloat > > *inputs)
This function computes an example computation request, for testing purposes.
#define KALDI_WARN
Definition: kaldi-error.h:150
Matrix for CUDA computing.
Definition: matrix-common.h:69
class NnetComputer is responsible for executing the computation described in the "computation" object...
Definition: nnet-compute.h:59
std::vector< IoSpecification > outputs
This class creates an initial version of the NnetComputation, without any optimization or sharing of ...
Definition: nnet-compile.h:44
void GenerateConfigSequence(const NnetGenerationOptions &opts, std::vector< std::string > *configs)
Generates a sequence of at least one config files, output as strings, where the first in the sequence...
#define KALDI_LOG
Definition: kaldi-error.h:153
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
Definition: kaldi-math.h:265
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestPreconditionDirectionsOnline()

void kaldi::nnet3::UnitTestPreconditionDirectionsOnline ( )

Definition at line 262 of file natural-gradient-online-test.cc.

References CuVectorBase< Real >::AddDiagMatMat(), MatrixBase< Real >::AddVecVec(), kaldi::AssertEqual(), KALDI_ASSERT, kaldi::kNoTrans, kaldi::kTrans, CuMatrixBase< Real >::NumRows(), OnlineNaturalGradientSimple::PreconditionDirections(), OnlineNaturalGradient::PreconditionDirections(), kaldi::Rand(), kaldi::RandInt(), VectorBase< Real >::Scale(), MatrixBase< Real >::Set(), VectorBase< Real >::SetRandn(), MatrixBase< Real >::SetRandn(), OnlineNaturalGradientSimple::SetRank(), OnlineNaturalGradient::SetRank(), kaldi::TraceMatMat(), and OnlineNaturalGradient::TurnOnDebug().

Referenced by main().

262  {
263  MatrixIndexT R = 1 + Rand() % 30, // rank of correction
264  N = (2 * R) + Rand() % 30, // batch size
265  D = R + 1 + Rand() % 20; // problem dimension. Must be > R.
266 
267  // Test sometimes with features that are all-zero or all-one; this will
268  // help to make sure low-rank or zero input doesn't crash the code.
269  bool zero = false;
270  bool one = false;
271  if (Rand() % 3 == 0) zero = true;
272  //else if (Rand() % 2 == 0) one = true;
273 
274  CuVector<BaseFloat> row_prod1(N);
275  BaseFloat gamma1, gamma2;
276  BaseFloat big_eig_factor = RandInt(1, 20);
277  big_eig_factor = big_eig_factor * big_eig_factor;
278  Vector<BaseFloat> big_eig_vector(D);
279  big_eig_vector.SetRandn();
280  big_eig_vector.Scale(big_eig_factor);
281 
282  OnlineNaturalGradientSimple preconditioner1;
283  OnlineNaturalGradient preconditioner2;
284  preconditioner1.SetRank(R);
285  preconditioner2.SetRank(R);
286  preconditioner2.TurnOnDebug();
287 
288  int32 num_iters = 100;
289  for (int32 iter = 0; iter < num_iters; iter++) {
290  Matrix<BaseFloat> M_cpu(N, D);
291  if (one) M_cpu.Set(1.0);
292  else if (!zero) {
293  M_cpu.SetRandn();
294  Vector<BaseFloat> rand_vec(N);
295  rand_vec.SetRandn();
296  M_cpu.AddVecVec(1.0, rand_vec, big_eig_vector);
297  }
298  CuMatrix<BaseFloat> M(M_cpu);
299 
300  CuMatrix<BaseFloat> Mcopy1(M), Mcopy2(M);
301 
302  preconditioner1.PreconditionDirections(&Mcopy1, &row_prod1, &gamma1);
303 
304  preconditioner2.PreconditionDirections(&Mcopy2, &gamma2);
305 
306  BaseFloat trace1 = TraceMatMat(M, M, kTrans),
307  trace2 = TraceMatMat(Mcopy1, Mcopy1, kTrans);
308  AssertEqual(trace1, trace2 * gamma2 * gamma2, 1.0e-02);
309 
310  AssertEqual(Mcopy1, Mcopy2);
311  AssertEqual(gamma1, gamma2, 1.0e-02);
312 
313  // make sure positive definite
314  CuVector<BaseFloat> inner_prods(M.NumRows());
315  inner_prods.AddDiagMatMat(1.0, M, kNoTrans, Mcopy1, kTrans, 0.0);
316  KALDI_ASSERT(inner_prods.Min() >= 0.0);
317  }
318  return;
319 }
kaldi::int32 int32
Keywords for search: natural gradient, naturalgradient, NG-SGD.
This class represents a matrix that&#39;s stored on the GPU if we have one, and in memory if not...
Definition: matrix-common.h:71
void AddDiagMatMat(Real alpha, const CuMatrixBase< Real > &M, MatrixTransposeType transM, const CuMatrixBase< Real > &N, MatrixTransposeType transN, Real beta=1.0)
Add the diagonal of a matrix product: *this = diag(M N), assuming the "trans" arguments are both kNoT...
Definition: cu-vector.cc:611
float BaseFloat
Definition: kaldi-types.h:29
int32 MatrixIndexT
Definition: matrix-common.h:98
void PreconditionDirections(CuMatrixBase< BaseFloat > *R, CuVectorBase< BaseFloat > *row_prod, BaseFloat *scale)
void PreconditionDirections(CuMatrixBase< BaseFloat > *X, BaseFloat *scale)
This call implements the main functionality of this class.
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.
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
A class representing a vector.
Definition: kaldi-vector.h:406
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static void AssertEqual(float a, float b, float relative_tolerance=0.001)
assert abs(a - b) <= relative_tolerance * (abs(a)+abs(b))
Definition: kaldi-math.h:276
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ UnitTestSplitLocations()

void kaldi::nnet3::UnitTestSplitLocations ( bool  verbose)

Definition at line 275 of file nnet-compile-utils-test.cc.

References ComparePair::ComparePair(), ConvertToIndexes(), rnnlm::i, rnnlm::j, KALDI_ASSERT, KALDI_LOG, PrintVectorVectorPair(), kaldi::Rand(), and SplitLocations().

Referenced by main().

275  {
276  int32 minibatch_size = Rand() % 1024 + 100;
277  int32 num_submat_indexes = Rand() % 10 + 1;
278  int32 max_submat_list_size = Rand() % 10 + 1;
279  int32 min_num_kaddrows = Rand() % 2; // minimum number of kAddRows compatible
280  // lists expected in the final split lists. This value will be used to
281  // create input submat_lists so that this is guaranteed
282  max_submat_list_size = min_num_kaddrows + max_submat_list_size;
283 
284  std::vector<std::pair<int32, int32> > all_pairs;
285  all_pairs.reserve(minibatch_size * max_submat_list_size);
286  std::vector<std::vector<std::pair<int32, int32> > >
287  submat_lists(minibatch_size),
288  split_lists;
289  std::vector<int32> submat_indexes(num_submat_indexes);
290  for (int32 i = 0; i < num_submat_indexes; i++) {
291  submat_indexes[i] = Rand();
292  }
293 
294  // generating submat_lists
295  int32 max_generated_submat_list_size = 0;
296  for (int32 i = 0; i < minibatch_size; i++) {
297  int32 num_locations = Rand() % max_submat_list_size + 1;
298  max_generated_submat_list_size =
299  max_generated_submat_list_size < num_locations ?
300  num_locations : max_generated_submat_list_size;
301  submat_lists[i].reserve(num_locations);
302  for (int32 j = 0; j < num_locations; j++) {
303  // note from dan: I edited the following line to resolve a valgrind error
304  // but cannot really understand at this point what this code is doing.
305  if (j <= min_num_kaddrows && j < num_submat_indexes) {
306  // since we need min_num_kaddrows in the split_lists we ensure that
307  // we add a pair with the same first element in all the submat_lists
308  submat_lists[i].push_back(std::make_pair(submat_indexes[j],
309  Rand() % minibatch_size));
310  }
311  submat_lists[i].push_back(
312  std::make_pair(submat_indexes[Rand() % num_submat_indexes],
313  Rand() % minibatch_size));
314  }
315  all_pairs.insert(all_pairs.end(), submat_lists[i].begin(),
316  submat_lists[i].end());
317  }
318 
319  SplitLocations(submat_lists, &split_lists);
320  if (verbose) {
321  KALDI_LOG << "submat_list";
322  PrintVectorVectorPair(submat_lists);
323  KALDI_LOG << "split_lists";
324  PrintVectorVectorPair(split_lists);
325  KALDI_LOG << "===========================";
326  KALDI_LOG << split_lists.size();
327  }
328  int32 num_kaddrows_in_output = 0;
329  int32 first_value;
330  std::vector<int32> second_values;
331  // ensure that elements in submat_lists are also present
332  // in split_lists
333  for (int32 i = 0 ; i < split_lists.size(); i++) {
334  second_values.clear();
335  if (ConvertToIndexes(split_lists[i], &first_value, &second_values)) {
336  // Checking if ConvertToIndexes did a proper conversion of the indexes
337  for (int32 j = 0; j < second_values.size(); j++) {
338  if (split_lists[i][j].first != -1)
339  KALDI_ASSERT((split_lists[i][j].first == first_value) &&
340  (split_lists[i][j].second == second_values[j]));
341  }
342  num_kaddrows_in_output++;
343  }
344  for (int32 j = 0; j < split_lists[i].size(); j++) {
345  if (split_lists[i][j].first == -1)
346  continue;
347  std::vector<std::pair<int32, int32> >::iterator iter =
348  std::find_if(all_pairs.begin(), all_pairs.end(),
349  ComparePair(split_lists[i][j]));
350  KALDI_ASSERT(iter != all_pairs.end());
351  all_pairs.erase(iter);
352  }
353  }
354  KALDI_ASSERT(all_pairs.size() == 0);
355  // ensure that there are at least as many kAddRows compatible split_lists as
356  // specified
357  KALDI_ASSERT(num_kaddrows_in_output >= min_num_kaddrows);
358 }
bool ConvertToIndexes(const std::vector< std::pair< int32, int32 > > &location_vector, int32 *first_value, std::vector< int32 > *second_values)
If it is the case for some i >= 0 that all the .first elements of "location_vector" are either i or -...
kaldi::int32 int32
void SplitLocations(const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
The input to this function is a vector (indexed by matrix-row-index) of lists of pairs (submat_index...
void PrintVectorVectorPair(std::vector< std::vector< std::pair< int32, int32 > > > vec_vec_pair)
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ UnitTestSplitLocationsBackward()

void kaldi::nnet3::UnitTestSplitLocationsBackward ( bool  verbose)

Definition at line 70 of file nnet-compile-utils-test.cc.

References ComparePair::ComparePair(), ConvertToIndexes(), rnnlm::i, rnnlm::j, KALDI_ASSERT, KALDI_LOG, PrintVectorVectorPair(), kaldi::Rand(), and SplitLocationsBackward().

Referenced by main().

70  {
71  int32 minibatch_size = Rand() % 1024 + 100;
72  int32 num_submat_indexes = Rand() % 10 + 1;
73  int32 max_submat_list_size = Rand() % 10 + 1;
74  int32 min_num_kaddrows = Rand() % 2; // minimum number of kAddRows compatible
75  // lists expected in the final split lists. This value will be used to
76  // create input submat_lists so that this is guaranteed
77  max_submat_list_size = min_num_kaddrows + max_submat_list_size;
78 
79  std::vector<std::pair<int32, int32> > all_pairs;
80  all_pairs.reserve(minibatch_size * max_submat_list_size);
81  std::vector<std::vector<std::pair<int32, int32> > >
82  submat_lists(minibatch_size),
83  split_lists;
84  std::vector<int32> submat_indexes(num_submat_indexes);
85  for (int32 i = 0; i < num_submat_indexes; i++) {
86  submat_indexes[i] = Rand();
87  }
88 
89  // generating submat_lists
90  int32 max_generated_submat_list_size = 0;
91  for (int32 i = 0; i < minibatch_size; i++) {
92  int32 num_locations = Rand() % max_submat_list_size + 1;
93  max_generated_submat_list_size =
94  max_generated_submat_list_size < num_locations ?
95  num_locations : max_generated_submat_list_size;
96  submat_lists[i].reserve(num_locations);
97  for (int32 j = 0; j < num_locations; j++) {
98  if (j <= min_num_kaddrows && j < num_submat_indexes)
99  // since we need min_num_kaddrows in the split_lists we ensure that
100  // we add a pair with the same first element in all the submat_lists
101  submat_lists[i].push_back(std::make_pair(submat_indexes[j],
102  Rand() % minibatch_size));
103  submat_lists[i].push_back(
104  std::make_pair(submat_indexes[Rand() % num_submat_indexes],
105  Rand() % minibatch_size));
106  }
107  all_pairs.insert(all_pairs.end(), submat_lists[i].begin(),
108  submat_lists[i].end());
109  }
110 
111  SplitLocationsBackward(submat_lists, &split_lists);
112  // Checking split_lists has all the necessary properties
113  for (int32 i = 0; i < split_lists.size(); i++) {
114  int32 first_value;
115  std::vector<int32> second_values;
116  if (ConvertToIndexes(split_lists[i], &first_value, &second_values)) {
117  // checking for contiguity and uniqueness of .second elements
118  std::vector<int32> occurred_values;
119  int32 prev_value = -10; // using a negative value as all indices are > 0
120  for (int32 j = 0; j < second_values.size(); j++) {
121  if (second_values[j] == -1)
122  continue;
123  if (second_values[j] != prev_value) {
124  std::vector<int32>::iterator iter = std::find(occurred_values.begin(),
125  occurred_values.end(),
126  second_values[j]);
127  KALDI_ASSERT(iter == occurred_values.end());
128  }
129  }
130  } else {
131  std::vector<std::pair<int32, int32> > list_of_pairs;
132  // checking for uniques of elements in the list
133  for (int32 j = 0; j < split_lists[i].size(); j++) {
134  if (split_lists[i][j].first == -1)
135  continue;
136  std::vector<std::pair<int32, int32> >::const_iterator iter =
137  std::find_if(list_of_pairs.begin(), list_of_pairs.end(),
138  PairIsEqualComparator(split_lists[i][j]));
139  KALDI_ASSERT(iter == list_of_pairs.end());
140  list_of_pairs.push_back(split_lists[i][j]);
141  }
142  }
143  }
144  if (verbose) {
145  KALDI_LOG << "submat_list";
146  PrintVectorVectorPair(submat_lists);
147  KALDI_LOG << "split_lists";
148  PrintVectorVectorPair(split_lists);
149  KALDI_LOG << "===========================";
150  }
151  int32 num_kaddrows_in_output = 0;
152  int32 first_value;
153  std::vector<int32> second_values;
154  // ensure that elements in submat_lists are also present
155  // in split_lists
156  for (int32 i = 0 ; i < split_lists.size(); i++) {
157  second_values.clear();
158  if (ConvertToIndexes(split_lists[i], &first_value, &second_values)) {
159  // Checking if ConvertToIndexes did a proper conversion of the indexes
160  KALDI_ASSERT(second_values.size() == split_lists[i].size());
161  for (int32 j = 0; j < second_values.size(); j++) {
162  if (split_lists[i][j].first != -1)
163  KALDI_ASSERT((split_lists[i][j].first == first_value) &&
164  (split_lists[i][j].second == second_values[j]));
165  }
166  num_kaddrows_in_output++;
167  }
168  for (int32 j = 0; j < split_lists[i].size(); j++) {
169  if (split_lists[i][j].first == -1)
170  continue;
171  std::vector<std::pair<int32, int32> >::iterator iter =
172  std::find_if(all_pairs.begin(), all_pairs.end(),
173  ComparePair(split_lists[i][j]));
174  KALDI_ASSERT(iter != all_pairs.end());
175  all_pairs.erase(iter);
176  }
177  }
178  KALDI_ASSERT(all_pairs.size() == 0);
179  // ensure that there are at least as many kAddRows compatible split_lists as
180  // specified
181  KALDI_ASSERT(num_kaddrows_in_output >= min_num_kaddrows);
182 }
bool ConvertToIndexes(const std::vector< std::pair< int32, int32 > > &location_vector, int32 *first_value, std::vector< int32 > *second_values)
If it is the case for some i >= 0 that all the .first elements of "location_vector" are either i or -...
kaldi::int32 int32
void PrintVectorVectorPair(std::vector< std::vector< std::pair< int32, int32 > > > vec_vec_pair)
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
void SplitLocationsBackward(const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
This function has the same interface as SplitLocations(); however, it ensures certain additional prop...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ UnitTestSummarizeVector()

void kaldi::nnet3::UnitTestSummarizeVector ( )

Definition at line 55 of file nnet-parse-test.cc.

References KALDI_LOG, kaldi::kCopyData, Vector< Real >::Resize(), VectorBase< Real >::SetRandn(), and SummarizeVector().

Referenced by main().

55  {
56  // will be eyeballed by a human.
57  Vector<BaseFloat> vec(9);
58  vec.SetRandn();
59  vec(0) = 1024.2343;
60  vec(1) = 0.01;
61  vec(2) = 0.001234;
62  vec(3) = 0.000198;
63  vec(3) = 1.98e-09;
64  vec(4) = 153.0;
65  vec(5) = 0.154;
66  vec(6) = 1.2;
67  vec(7) = 9.2;
68  vec(8) = 10.8;
69 
70  KALDI_LOG << "vec = " << vec << " -> " << SummarizeVector(vec);
71 
72  vec.Resize(20, kCopyData);
73  KALDI_LOG << "vec = " << vec << " -> " << SummarizeVector(vec);
74 }
std::string SummarizeVector(const VectorBase< float > &vec)
Returns a string that summarizes a vector fairly succintly, for printing stats in info lines...
Definition: nnet-parse.cc:111
A class representing a vector.
Definition: kaldi-vector.h:406
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ UnVectorizeNnet()

void UnVectorizeNnet ( const VectorBase< BaseFloat > &  params,
Nnet dest 
)

Copies the parameters from params to *dest.

the dimension of params must be equal to NumParameters(*dest).

Definition at line 401 of file nnet-utils.cc.

References VectorBase< Real >::Dim(), Nnet::GetComponent(), KALDI_ASSERT, KALDI_ERR, kUpdatableComponent, Nnet::NumComponents(), NumParameters(), UpdatableComponent::NumParameters(), Component::Properties(), and UpdatableComponent::UnVectorize().

402  {
403  KALDI_ASSERT(parameters.Dim() == NumParameters(*dest));
404  int32 dim_offset = 0;
405  for (int32 c = 0; c < dest->NumComponents(); c++) {
406  Component *comp = dest->GetComponent(c);
407  if (comp->Properties() & kUpdatableComponent) {
408  // For now all updatable components inherit from class UpdatableComponent.
409  // If that changes in future, we will change this code.
410  UpdatableComponent *uc = dynamic_cast<UpdatableComponent*>(comp);
411  if (uc == NULL)
412  KALDI_ERR << "Updatable component does not inherit from class "
413  "UpdatableComponent; change this code.";
414  int32 this_dim = uc->NumParameters();
415  const SubVector<BaseFloat> this_part(parameters, dim_offset, this_dim);
416  uc->UnVectorize(this_part);
417  dim_offset += this_dim;
418  }
419  }
420 }
kaldi::int32 int32
int32 NumParameters(const Nnet &src)
Returns the total of the number of parameters in the updatable components of the nnet.
Definition: nnet-utils.cc:359
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ UpdateNnetMovingAverage()

void kaldi::nnet3::UpdateNnetMovingAverage ( int32  num_models,
const Nnet nnet,
Nnet moving_average_nnet 
)

Definition at line 66 of file nnet3-combine.cc.

References AddNnet(), KALDI_ASSERT, NumParameters(), and ScaleNnet().

Referenced by main().

67  {
68  KALDI_ASSERT(NumParameters(nnet) == NumParameters(*moving_average_nnet));
69  ScaleNnet((num_models - 1.0) / num_models, moving_average_nnet);
70  AddNnet(nnet, 1.0 / num_models, moving_average_nnet);
71 }
void ScaleNnet(BaseFloat scale, Nnet *nnet)
Scales the nnet parameters and stats by this scale.
Definition: nnet-utils.cc:312
int32 NumParameters(const Nnet &src)
Returns the total of the number of parameters in the updatable components of the nnet.
Definition: nnet-utils.cc:359
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void AddNnet(const Nnet &src, BaseFloat alpha, Nnet *dest)
Does *dest += alpha * src (affects nnet parameters and stored stats).
Definition: nnet-utils.cc:349

◆ UpdateNnetWithMaxChange() [1/2]

bool UpdateNnetWithMaxChange ( const Nnet delta_nnet,
BaseFloat  max_param_change,
BaseFloat  max_change_scale,
BaseFloat  scale,
Nnet nnet,
std::vector< int32 > *  num_max_change_per_component_applied,
int32 num_max_change_global_applied 
)

This function does the operation '*nnet += scale * delta_nnet', while respecting any max-parameter-change (max-param-change) specified in the updatable components, and also the global max-param-change specified as 'max_param_change'.

With max-changes taken into account, the operation of this function is equivalent to the following, although it's done more efficiently:

Nnet temp_nnet(delta_nnet);
ScaleNnet(1.0 / max_change_scale, &temp_nnet);
[ Scale down parameters for each component of temp_nnet as needed so
their Euclidean norms do not exceed their per-component max-changes ]
[ Scale down temp_nnet as needed so its Euclidean norm does not exceed
the global max-change ]
ScaleNnet(max_change_scale, &temp_nnet); // undo the previous scaling.
AddNnet(temp_nnet, scale, nnet);
Parameters
[in]delta_nnetThe copy of '*nnet' neural network that contains the proposed change in parameters. Normally this will previously have been set to: (delta_nnet = parameter-derivative-on-current-minibatch * learning-rate per parameter), with any natural gradient applied as specified in the components; but this may be different if momentum or backstitch are used.
[in]max_param_changeThe global max-param-change specified on the command line (e.g. 2.0), which specifies the largest change allowed to '*nnet' in Euclidean norm. If <= 0, no global max-param-change will be enforced, but any max-change values specified in the components will still be enforced; see UpdatableComponent::MaxChange(), and search for 'max-change' in the configs or nnet3-info output).
[in]max_change_scaleThis value, which will normally be 1.0, is used to scale all per-component max-change values and the global 'max_param_change', before applying them (so we use 'max_change_scale * uc->MaxChange()' as the per-component max-change, and 'max_change_scale * max_param_change' as the global max-change).
[in]scaleThis value, which will normally be 1.0, is a scaling factor used when adding to 'nnet', applied after any max-changes. It is provided for backstitch-related purposes.
[in,out]nnetThe nnet which we add to.
[out]num_max_change_per_component_appliedWe add to the elements of this the count for each per-component max-change.
[out]num_max_change_global_appliedWe to this the count for the global max-change.

Definition at line 2106 of file nnet-utils.cc.

References AddNnetComponents(), VectorBase< Real >::Dim(), UpdatableComponent::DotProduct(), Nnet::GetComponent(), Nnet::GetComponentName(), rnnlm::i, KALDI_ASSERT, KALDI_ERR, KALDI_LOG, KALDI_VLOG, KALDI_WARN, kUpdatableComponent, UpdatableComponent::MaxChange(), Nnet::NumComponents(), NumUpdatableComponents(), Component::Properties(), and VectorBase< Real >::Scale().

Referenced by CollapseModelConfig::CollapseModelConfig(), NnetChainTrainer::TrainInternal(), NnetTrainer::TrainInternal(), NnetChainTrainer::TrainInternalBackstitch(), NnetTrainer::TrainInternalBackstitch(), and UpdateNnetWithMaxChange().

2112  {
2113  KALDI_ASSERT(nnet != NULL);
2114  // computes scaling factors for per-component max-change
2115  const int32 num_updatable = NumUpdatableComponents(delta_nnet);
2116  Vector<BaseFloat> scale_factors = Vector<BaseFloat>(num_updatable);
2117  BaseFloat param_delta_squared = 0.0;
2118  int32 num_max_change_per_component_applied_per_minibatch = 0;
2119  BaseFloat min_scale = 1.0;
2120  std::string component_name_with_min_scale;
2121  BaseFloat max_change_with_min_scale;
2122  int32 i = 0;
2123  for (int32 c = 0; c < delta_nnet.NumComponents(); c++) {
2124  const Component *comp = delta_nnet.GetComponent(c);
2125  if (comp->Properties() & kUpdatableComponent) {
2126  const UpdatableComponent *uc =
2127  dynamic_cast<const UpdatableComponent*>(comp);
2128  if (uc == NULL)
2129  KALDI_ERR << "Updatable component does not inherit from class "
2130  << "UpdatableComponent; change this code.";
2131  BaseFloat max_param_change_per_comp = uc->MaxChange();
2132  KALDI_ASSERT(max_param_change_per_comp >= 0.0);
2133  BaseFloat dot_prod = uc->DotProduct(*uc);
2134  if (max_param_change_per_comp != 0.0 &&
2135  std::sqrt(dot_prod) * std::abs(scale) >
2136  max_param_change_per_comp * max_change_scale) {
2137  scale_factors(i) = max_param_change_per_comp * max_change_scale /
2138  (std::sqrt(dot_prod) * std::abs(scale));
2139  (*num_max_change_per_component_applied)[i]++;
2140  num_max_change_per_component_applied_per_minibatch++;
2141  KALDI_VLOG(2) << "Parameters in " << delta_nnet.GetComponentName(c)
2142  << " change too big: " << std::sqrt(dot_prod) << " * "
2143  << scale << " > " << "max-change * max-change-scale="
2144  << max_param_change_per_comp << " * " << max_change_scale
2145  << ", scaling by " << scale_factors(i);
2146  } else {
2147  scale_factors(i) = 1.0;
2148  }
2149  if (i == 0 || scale_factors(i) < min_scale) {
2150  min_scale = scale_factors(i);
2151  component_name_with_min_scale = delta_nnet.GetComponentName(c);
2152  max_change_with_min_scale = max_param_change_per_comp;
2153  }
2154  param_delta_squared += std::pow(scale_factors(i),
2155  static_cast<BaseFloat>(2.0)) * dot_prod;
2156  i++;
2157  }
2158  }
2159  KALDI_ASSERT(i == scale_factors.Dim());
2160  BaseFloat param_delta = std::sqrt(param_delta_squared);
2161  // computes the scale for global max-change
2162  param_delta *= std::abs(scale);
2163  if (max_param_change != 0.0) {
2164  if (param_delta > max_param_change * max_change_scale) {
2165  if (param_delta - param_delta != 0.0) {
2166  KALDI_WARN << "Infinite parameter change, will not apply.";
2167  return false;
2168  } else {
2169  scale *= max_param_change * max_change_scale / param_delta;
2170  (*num_max_change_global_applied)++;
2171  }
2172  }
2173  }
2174  if ((max_param_change != 0.0 &&
2175  param_delta > max_param_change * max_change_scale &&
2176  param_delta - param_delta == 0.0) || min_scale < 1.0) {
2177  std::ostringstream ostr;
2178  if (min_scale < 1.0)
2179  ostr << "Per-component max-change active on "
2180  << num_max_change_per_component_applied_per_minibatch
2181  << " / " << num_updatable << " Updatable Components."
2182  << " (Smallest factor=" << min_scale << " on "
2183  << component_name_with_min_scale
2184  << " with max-change=" << max_change_with_min_scale <<"). ";
2185  if (param_delta > max_param_change * max_change_scale)
2186  ostr << "Global max-change factor was "
2187  << max_param_change * max_change_scale / param_delta
2188  << " with max-change=" << max_param_change << ".";
2189  KALDI_LOG << ostr.str();
2190  }
2191  // applies both of the max-change scalings all at once, component by component
2192  // and updates parameters
2193  scale_factors.Scale(scale);
2194  AddNnetComponents(delta_nnet, scale_factors, scale, nnet);
2195  return true;
2196 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
void AddNnetComponents(const Nnet &src, const Vector< BaseFloat > &alphas, BaseFloat scale, Nnet *dest)
Does *dest += alpha * src for updatable components (affects nnet parameters), and *dest += scale * sr...
Definition: nnet-utils.cc:322
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_WARN
Definition: kaldi-error.h:150
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156
#define KALDI_LOG
Definition: kaldi-error.h:153
int32 NumUpdatableComponents(const Nnet &dest)
Returns the number of updatable components in the nnet.
Definition: nnet-utils.cc:422

◆ UpdateNnetWithMaxChange() [2/2]

bool UpdateNnetWithMaxChange ( const Nnet delta_nnet,
BaseFloat  max_param_change,
BaseFloat  max_change_scale,
BaseFloat  scale,
Nnet nnet,
MaxChangeStats stats 
)

Definition at line 2269 of file nnet-utils.cc.

References MaxChangeStats::num_max_change_global_applied, MaxChangeStats::num_max_change_per_component_applied, MaxChangeStats::num_minibatches_processed, and UpdateNnetWithMaxChange().

2273  {
2274  bool ans = UpdateNnetWithMaxChange(
2275  delta_nnet, max_param_change, max_change_scale,
2276  scale, nnet,
2277  &(stats->num_max_change_per_component_applied),
2278  &(stats->num_max_change_global_applied));
2279  stats->num_minibatches_processed++;
2280  return ans;
2281 }
bool UpdateNnetWithMaxChange(const Nnet &delta_nnet, BaseFloat max_param_change, BaseFloat max_change_scale, BaseFloat scale, Nnet *nnet, MaxChangeStats *stats)
Definition: nnet-utils.cc:2269

◆ VariableMergingOptimization()

void VariableMergingOptimization ( const NnetOptimizeOptions config,
const Nnet nnet,
NnetComputation computation 
)

This wraps class VariableMergingOptimizer in a simplified interface.

Definition at line 417 of file nnet-optimize.cc.

References VariableMergingOptimizer::MergeVariables().

Referenced by Optimize().

419  {
420  bool changed = true;
421  while (changed) {
422  changed = false;
423  VariableMergingOptimizer opt(config, nnet, computation);
424  if (opt.MergeVariables())
425  changed = true;
426  }
427 }

◆ VectorizeNnet()

void VectorizeNnet ( const Nnet src,
VectorBase< BaseFloat > *  params 
)

Copies the nnet parameters to *params, whose dimension must be equal to NumParameters(src).

Definition at line 378 of file nnet-utils.cc.

References VectorBase< Real >::Dim(), Nnet::GetComponent(), KALDI_ASSERT, KALDI_ERR, kUpdatableComponent, Nnet::NumComponents(), NumParameters(), UpdatableComponent::NumParameters(), Component::Properties(), and UpdatableComponent::Vectorize().

379  {
380  KALDI_ASSERT(parameters->Dim() == NumParameters(src));
381  int32 dim_offset = 0;
382  for (int32 c = 0; c < src.NumComponents(); c++) {
383  const Component *comp = src.GetComponent(c);
384  if (comp->Properties() & kUpdatableComponent) {
385  // For now all updatable components inherit from class UpdatableComponent.
386  // If that changes in future, we will change this code.
387  const UpdatableComponent *uc =
388  dynamic_cast<const UpdatableComponent*>(comp);
389  if (uc == NULL)
390  KALDI_ERR << "Updatable component does not inherit from class "
391  "UpdatableComponent; change this code.";
392  int32 this_dim = uc->NumParameters();
393  SubVector<BaseFloat> this_part(*parameters, dim_offset, this_dim);
394  uc->Vectorize(&this_part);
395  dim_offset += this_dim;
396  }
397  }
398 }
kaldi::int32 int32
int32 NumParameters(const Nnet &src)
Returns the total of the number of parameters in the updatable components of the nnet.
Definition: nnet-utils.cc:359
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ WriteCindexVector()

void WriteCindexVector ( std::ostream &  os,
bool  binary,
const std::vector< Cindex > &  vec 
)

Definition at line 282 of file nnet-common.cc.

References rnnlm::i, kaldi::WriteBasicType(), WriteCindexVectorElementBinary(), and kaldi::WriteToken().

Referenced by UnitTestCindexIo(), and NnetComputation::MatrixDebugInfo::Write().

283  {
284  // This token will make it easier to write back-compatible code if we later
285  // change the format.
286  WriteToken(os, binary, "<I1V>");
287  int32 size = vec.size();
288  WriteBasicType(os, binary, size);
289  if (!binary) { // In text mode we just use the native Write functionality.
290  for (int32 i = 0; i < size; i++) {
291  int32 node_index = vec[i].first;
292  if (i == 0 || node_index != vec[i-1].first) {
293  if (i > 0)
294  os.put(']');
295  os.put('[');
296  WriteBasicType(os, binary, node_index);
297  os.put(':');
298  }
299  vec[i].second.Write(os, binary);
300  if (i == size - 1)
301  os.put(']');
302  }
303  } else {
304  for (int32 i = 0; i < size; i++)
306  }
307 }
kaldi::int32 int32
void WriteToken(std::ostream &os, bool binary, const char *token)
The WriteToken functions are for writing nonempty sequences of non-space characters.
Definition: io-funcs.cc:134
static void WriteCindexVectorElementBinary(std::ostream &os, const std::vector< Cindex > &vec, int32 i)
Definition: nnet-common.cc:162
void WriteBasicType(std::ostream &os, bool binary, T t)
WriteBasicType is the name of the write function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:34

◆ WriteCindexVectorElementBinary()

static void kaldi::nnet3::WriteCindexVectorElementBinary ( std::ostream &  os,
const std::vector< Cindex > &  vec,
int32  i 
)
static

Definition at line 162 of file nnet-common.cc.

References rnnlm::i, KALDI_ERR, Index::n, Index::t, kaldi::WriteBasicType(), and Index::x.

Referenced by WriteCindexVector().

165  {
166  bool binary = true;
167  int32 node_index = vec[i].first;
168  const Index &index = vec[i].second;
169  if (i == 0 || node_index != vec[i-1].first) {
170  // divide using '|' into ranges that each have all the same node name, like:
171  // [node_1: index_1 index_2] [node_2: index_3 index_4] Caution: '|' is
172  // character 124 so we have to avoid that character in places where it might
173  // be confused with this separator.
174  os.put('|');
175  WriteBasicType(os, binary, node_index);
176  }
177  if (i == 0) {
178  // we don't need to be concerned about reserving space for character 124
179  // ('|') here, since (wastefully) '|' is always printed for i == 0.
180  //
181  // we don't use std::abs(index.t) < 125 here because it doesn't have the
182  // right (or even well-defined) behavior for
183  // index.t == std::numeric_limits<int32>::min().
184  if (index.n == 0 && index.x == 0 &&
185  index.t > -125 && index.t < 125) {
186  // handle this common case in one character.
187  os.put(static_cast<signed char>(index.t));
188  } else if (index.t == 0 && index.x == 0 &&
189  (index.n == 0 || index.n == 1)) {
190  // handle this common case in one character.
191  os.put(static_cast<signed char>(index.n + 125));
192  } else { // handle the general case less efficiently.
193  os.put(127);
194  WriteBasicType(os, binary, index.n);
195  WriteBasicType(os, binary, index.t);
196  WriteBasicType(os, binary, index.x);
197  }
198  } else {
199  const Index &last_index = vec[i-1].second;
200  // we don't do if std::abs(index.t - last_index.t) < 124
201  // below because it doesn't work right if the difference
202  // equals std::numeric_limits<int32>::min().
203  if (index.n == last_index.n && index.x == last_index.x &&
204  index.t - last_index.t < 124 &&
205  index.t - last_index.t > -124) {
206  signed char c = index.t - last_index.t;
207  os.put(c);
208  // note: we have to reserve character 124 ('|') for when 'n' or 'x'
209  // changes.
210  } else if (index.t == last_index.t && index.x == last_index.x &&
211  (index.n == last_index.n || index.n == last_index.n + 1)) {
212  os.put(125 + index.n - last_index.n);
213  } else { // handle the general case less efficiently.
214  os.put(127);
215  WriteBasicType(os, binary, index.n);
216  WriteBasicType(os, binary, index.t);
217  WriteBasicType(os, binary, index.x);
218  }
219  }
220  if (!os.good())
221  KALDI_ERR << "Output stream error detected";
222 }
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
void WriteBasicType(std::ostream &os, bool binary, T t)
WriteBasicType is the name of the write function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:34

◆ WriteExamples()

static void kaldi::nnet3::WriteExamples ( const MatrixBase< BaseFloat > &  feats,
const std::vector< ChunkInfo *> &  chunks,
const std::string &  utt,
bool  compress,
int32  num_pdfs,
int32 num_egs_written,
std::vector< NnetExampleWriter *> *  example_writers 
)
static

Definition at line 82 of file nnet3-xvector-get-egs.cc.

References NnetExample::Compress(), NnetIo::indexes, NnetExample::io, KALDI_ERR, KALDI_WARN, ChunkInfo::label, ChunkInfo::name, ChunkInfo::num_frames, MatrixBase< Real >::NumCols(), MatrixBase< Real >::NumRows(), ChunkInfo::output_archive_id, and ChunkInfo::start_frame.

Referenced by main().

85  {
86  for (std::vector<ChunkInfo *>::const_iterator it = chunks.begin();
87  it != chunks.end(); ++it) {
88  ChunkInfo *chunk = *it;
89  NnetExample eg;
90  int32 num_rows = feats.NumRows(),
91  feat_dim = feats.NumCols();
92  if (num_rows < chunk->num_frames) {
93  KALDI_WARN << "Unable to create examples for utterance " << utt
94  << ". Requested chunk size of "
95  << chunk->num_frames
96  << " but utterance has only " << num_rows << " frames.";
97  } else {
98  // The requested chunk positions are approximate. It's possible
99  // that they slightly exceed the number of frames in the utterance.
100  // If that occurs, we can shift the chunks location back slightly.
101  int32 shift = std::min(0, num_rows - chunk->start_frame
102  - chunk->num_frames);
103  SubMatrix<BaseFloat> chunk_mat(feats, chunk->start_frame + shift,
104  chunk->num_frames, 0, feat_dim);
105  NnetIo nnet_input = NnetIo("input", 0, chunk_mat);
106  for (std::vector<Index>::iterator indx_it = nnet_input.indexes.begin();
107  indx_it != nnet_input.indexes.end(); ++indx_it)
108  indx_it->n = 0;
109 
110  Posterior label;
111  std::vector<std::pair<int32, BaseFloat> > post;
112  post.push_back(std::pair<int32, BaseFloat>(chunk->label, 1.0));
113  label.push_back(post);
114  NnetExample eg;
115  eg.io.push_back(nnet_input);
116  eg.io.push_back(NnetIo("output", num_pdfs, 0, label));
117  if (compress)
118  eg.Compress();
119 
120  if (chunk->output_archive_id >= example_writers->size())
121  KALDI_ERR << "Requested output index exceeds number of specified "
122  << "output files.";
123  (*example_writers)[chunk->output_archive_id]->Write(
124  chunk->name, eg);
125  (*num_egs_written) += 1;
126  }
127  }
128 }
NnetExample is the input data and corresponding label (or labels) for one or more frames of input...
Definition: nnet-example.h:111
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Definition: kaldi-matrix.h:67
kaldi::int32 int32
std::vector< Index > indexes
"indexes" is a vector the same length as features.NumRows(), explaining the meaning of each row of th...
Definition: nnet-example.h:42
std::vector< std::vector< std::pair< int32, BaseFloat > > > Posterior
Posterior is a typedef for storing acoustic-state (actually, transition-id) posteriors over an uttera...
Definition: posterior.h:42
#define KALDI_ERR
Definition: kaldi-error.h:147
void Compress()
Compresses any (input) features that are not sparse.
#define KALDI_WARN
Definition: kaldi-error.h:150
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
Definition: kaldi-matrix.h:64
std::vector< NnetIo > io
"io" contains the input and output.
Definition: nnet-example.h:116
Sub-matrix representation.
Definition: kaldi-matrix.h:988

◆ WriteIndexVector()

void WriteIndexVector ( std::ostream &  os,
bool  binary,
const std::vector< Index > &  vec 
)

Definition at line 126 of file nnet-common.cc.

References rnnlm::i, Index::Write(), kaldi::WriteBasicType(), WriteIndexVectorElementBinary(), and kaldi::WriteToken().

Referenced by IndexLessNxt::operator()(), UnitTestIndexIo(), kaldi::nnet3::time_height_convolution::UnitTestTimeHeightConvolutionCompile(), NnetIo::Write(), NnetDiscriminativeSupervision::Write(), IoSpecification::Write(), NnetChainSupervision::Write(), and NnetComputation::Write().

127  {
128  // This token will make it easier to write back-compatible code if we later
129  // change the format.
130  WriteToken(os, binary, "<I1V>");
131  int32 size = vec.size();
132  WriteBasicType(os, binary, size);
133  if (!binary) { // In text mode we just use the native Write functionality.
134  for (int32 i = 0; i < size; i++)
135  vec[i].Write(os, binary);
136  } else {
137  for (int32 i = 0; i < size; i++)
139  }
140 }
static void WriteIndexVectorElementBinary(std::ostream &os, const std::vector< Index > &vec, int32 i)
Definition: nnet-common.cc:45
kaldi::int32 int32
void WriteToken(std::ostream &os, bool binary, const char *token)
The WriteToken functions are for writing nonempty sequences of non-space characters.
Definition: io-funcs.cc:134
void WriteBasicType(std::ostream &os, bool binary, T t)
WriteBasicType is the name of the write function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:34

◆ WriteIndexVectorElementBinary()

static void kaldi::nnet3::WriteIndexVectorElementBinary ( std::ostream &  os,
const std::vector< Index > &  vec,
int32  i 
)
static

Definition at line 45 of file nnet-common.cc.

References rnnlm::i, KALDI_ERR, Index::n, Index::t, kaldi::WriteBasicType(), and Index::x.

Referenced by WriteIndexVector().

48  {
49  bool binary = true;
50  const Index &index = vec[i];
51  if (i == 0) {
52  // we don't use std::abs(index.t) < 125 here because it doesn't have the
53  // right (or even well-defined) behavior for
54  // index.t == std::numeric_limits<int32>::min().
55  if (index.n == 0 && index.x == 0 &&
56  index.t > -125 && index.t < 125) {
57  // handle this common case in one character.
58  os.put(static_cast<signed char>(index.t));
59  } else { // handle the general case less efficiently.
60  os.put(127);
61  WriteBasicType(os, binary, index.n);
62  WriteBasicType(os, binary, index.t);
63  WriteBasicType(os, binary, index.x);
64  }
65  } else {
66  Index last_index = vec[i-1];
67  // we don't do if (std::abs(index.t - last_index.t) < 125)
68  // below because this doesn't work right if that difference
69  // equals std::numeric_limits<int32>::min().
70  if (index.n == last_index.n && index.x == last_index.x &&
71  index.t - last_index.t < 125 &&
72  index.t - last_index.t > -125) {
73  signed char c = index.t - last_index.t;
74  os.put(c);
75  } else { // handle the general case less efficiently.
76  os.put(127);
77  WriteBasicType(os, binary, index.n);
78  WriteBasicType(os, binary, index.t);
79  WriteBasicType(os, binary, index.x);
80  }
81  }
82  if (!os.good())
83  KALDI_ERR << "Output stream error detected";
84 }
#define KALDI_ERR
Definition: kaldi-error.h:147
void WriteBasicType(std::ostream &os, bool binary, T t)
WriteBasicType is the name of the write function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:34

◆ WriteVectorAsChar()

void WriteVectorAsChar ( std::ostream &  os,
bool  binary,
const VectorBase< BaseFloat > &  vec 
)

Definition at line 237 of file nnet-example-utils.cc.

References VectorBase< Real >::Data(), VectorBase< Real >::Dim(), rnnlm::i, KALDI_ASSERT, VectorBase< Real >::Write(), and kaldi::WriteIntegerVector().

Referenced by NnetDiscriminativeSupervision::Write().

239  {
240  if (binary) {
241  int32 dim = vec.Dim();
242  std::vector<unsigned char> char_vec(dim);
243  const BaseFloat *data = vec.Data();
244  for (int32 i = 0; i < dim; i++) {
245  BaseFloat value = data[i];
246  KALDI_ASSERT(value >= 0.0 && value <= 1.0);
247  // below, the adding 0.5 is done so that we round to the closest integer
248  // rather than rounding down (since static_cast will round down).
249  char_vec[i] = static_cast<unsigned char>(255.0 * value + 0.5);
250  }
251  WriteIntegerVector(os, binary, char_vec);
252  } else {
253  // the regular floating-point format will be more readable for text mode.
254  vec.Write(os, binary);
255  }
256 }
kaldi::int32 int32
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void WriteIntegerVector(std::ostream &os, bool binary, const std::vector< T > &v)
Function for writing STL vectors of integer types.
Definition: io-funcs-inl.h:198

◆ YzxVectorIndex()

int32 kaldi::nnet3::YzxVectorIndex ( int32  x,
int32  y,
int32  z,
int32  input_x_dim,
int32  input_y_dim,
int32  input_z_dim 
)
inline

Definition at line 226 of file nnet-combined-component.cc.

References KALDI_PARANOID_ASSERT.

Referenced by ConvolutionComponent::InderivPatchesToInderiv(), and ConvolutionComponent::InputToInputPatches().

229  {
230  KALDI_PARANOID_ASSERT(x < input_x_dim && y < input_y_dim && z < input_z_dim);
231  return (input_y_dim * input_z_dim) * x + (input_y_dim) * z + y;
232 }
#define KALDI_PARANOID_ASSERT(cond)
Definition: kaldi-error.h:206

◆ ZeroComponentStats()

void ZeroComponentStats ( Nnet nnet)

Zeroes the component stats in all nonlinear components in the nnet.

Definition at line 269 of file nnet-utils.cc.

References Nnet::GetComponent(), Nnet::NumComponents(), and Component::ZeroStats().

Referenced by NnetChainTrainer::NnetChainTrainer(), NnetDiscriminativeTrainer::NnetDiscriminativeTrainer(), NnetTrainer::NnetTrainer(), and RecomputeStats().

269  {
270  for (int32 c = 0; c < nnet->NumComponents(); c++) {
271  Component *comp = nnet->GetComponent(c);
272  comp->ZeroStats(); // for some components, this won't do anything.
273  }
274 }
kaldi::int32 int32

◆ ZyxVectorIndex()

int32 kaldi::nnet3::ZyxVectorIndex ( int32  x,
int32  y,
int32  z,
int32  input_x_dim,
int32  input_y_dim,
int32  input_z_dim 
)
inline

Definition at line 234 of file nnet-combined-component.cc.

References KALDI_PARANOID_ASSERT.

Referenced by ConvolutionComponent::InderivPatchesToInderiv(), and ConvolutionComponent::InputToInputPatches().

237  {
238  KALDI_PARANOID_ASSERT(x < input_x_dim && y < input_y_dim && z < input_z_dim);
239  return (input_y_dim * input_z_dim) * x + (input_z_dim) * y + z;
240 }
#define KALDI_PARANOID_ASSERT(cond)
Definition: kaldi-error.h:206

Variable Documentation

◆ computation_checker_warned_unused_input

bool computation_checker_warned_unused_input = false
static

Checks that we never use variables before they are allocated or after they are deallocated, and some other checks that can be done from the MatrixAccesses.

Definition at line 680 of file nnet-analyze.cc.

◆ kNoTime