音声認識メモ(Kaldi)その15(活性化関数 Dan's DNN(nnet2))
活性化関数に関するメモ。
公式サイトの隠れ層に関する説明には、"tanh"(双曲線正接関数)と"p-norm"が登場する。
この”p-norm”というのは、論文によると活性化関数"maxout"からヒントを得た独自版らしい。
「egs/rm/s5/local/run_nnet2.sh」のコメントにも書かれているように、nnet2では、"p-norm"がプライマリレシピとなっている。
「egs/rm/s5/local/run_nnet2.sh」(use_gpu=false)
# This one is on top of 40-dim + fMLLR features, it's a fairly normal tanh system. local/nnet2/run_4c.sh --use-gpu false # **THIS IS THE PRIMARY RECIPE (40-dim + fMLLR + p-norm neural net)** local/nnet2/run_4d.sh --use-gpu false
「local/nnet2/run_4d.sh」は内部で「steps/nnet2/train_pnorm_fast.sh」を呼び出しており、その中で「nnet2bin/nnet-train-simple」コマンドを実行する。
「nnet2bin/nnet-train-simple」コマンド
Train the neural network parameters with backprop and stochastic gradient descent using minibatches. Usage: nnet-train-simple [options] <model-in> <training-examples-in> <model-out>
インプットとなる特徴量が13次元、出力となるpdf-class数が「6」のモデルの構成例は以下のとおり。
全体は7層の構成で、以下のコンポーネント
- AffineComponentPreconditionedOnline
- PnormComponent
- NormalizeComponent
が隠れ層に該当する。
モデル
<Nnet> <NumComponents> 7 <Components> <SpliceComponent> <InputDim> 13 <Context> [ -4 -3 -2 -1 0 1 2 3 4 ]<ConstComponentDim> 0 </SpliceComponent> <FixedAffineComponent> <LinearParams> [ (snip) 117row x 117col ] <BiasParams> [ (snip) 1row x 117col ] </FixedAffineComponent> <AffineComponentPreconditionedOnline> <LearningRate> 0.02 <LinearParams> [ (snip) 1000row x 117col ] <BiasParams> [ (snip) 1row x 117col ] <RankIn> 20 <RankOut> 80 <UpdatePeriod> 4 <NumSamplesHistory> 2000 <Alpha> 4 <MaxChangePerSample> 0.075 </AffineComponentPreconditionedOnline> <PnormComponent> <InputDim> 1000 <OutputDim> 200 <P> 2 </PnormComponent> <NormalizeComponent> <Dim> 200 <ValueSum> [ ] <DerivSum> [ ] <Count> 0 </NormalizeComponent> <AffineComponentPreconditionedOnline> <LearningRate> 0.02 <LinearParams> [ (snip) 6row x 200col ] <BiasParams> [ (snip) 1row x 6col ] <RankIn> 20 <RankOut> 80 <UpdatePeriod> 4 <NumSamplesHistory> 2000 <Alpha> 4 <MaxChangePerSample> 0.075 </AffineComponentPreconditionedOnline> <SoftmaxComponent> <Dim> 6 <ValueSum> [ (snip) 1row x 6col ] <DerivSum> [ (snip) 1row x 6col ] <Count> 396 </SoftmaxComponent> </Components> </Nnet>
「nnet2bin/nnet-train-simple」コマンドの内部処理の流れを確認してみる。
minibatch-sizeは「64」を指定した。
まずは、Propagateから。
コンポーネント「SpliceComponent」により、13次元から117次元にする。
続けて、コンポーネント「FixedAffineComponent」により、無相関化(117次元のまま)
続けて、コンポーネント「AffineComponentPreconditionedOnline」により、次元数を「1000」にする。
ここまでで得られたアウトプットは、64row x 1000colになる。
続いて、コンポーネント「PnormComponent」。デフォルトは「p=2」の2-norm(論文に、これが一番パフォーマンスが良かったとある)
inputが「1000」次元、outputが「200」次元なので、5次元ごとにグループ化する。
グループ化前
グループ化後
続けて、コンポーネント「NormalizeComponent」により正規化する。
続けて、コンポーネント「AffineComponentPreconditionedOnline」により、次元数を「6」にする。
(ここまでで得られたアウトプットは、64row x 6col)
最後に、コンポーネント「SoftmaxComponent」により各pdf-classごとの出力確率を求める。
一番目のフレームの結果
0.1746 0.0040 0.7098 0.0007 0.0889 0.0217
小数点第5位以下は切り捨て
尚、このデータに関しては、4番目のデータ(確率が「0.0007」)が"正解"となる。
この誤差をもとに、Backpropagationによりモデルのパラメータを更新する。