音素認識のためのCNN


7

私は現在、このドキュメントを研究しています。CNNは、ログメルフィルターバンクの視覚的表現を使用した音素認識、および制限された重み共有スキームに適用されます。

ログメルフィルターバンクの視覚化は、データを表現および正規化する方法です。彼らは私が使用してそれをプロットすることであろうと出てくる可能性が最も近いRGBの色とスペクトログラムとして可視化することをお勧めmatplotlibsカラーマップをcm.jet。それらは(紙であるため)、各フレームを[静的デルタdelta_delta]フィルターバンクエネルギーでスタックする必要があることも示唆しています。これは次のようになります。

ここに画像の説明を入力してください

15フレームセットの画像パッチで構成される[静的デルタdelta_detlta]入力形状は、(40,45,3)になります。

制限された重みの共有は、重みの共有を特定のフィルターバンク領域に制限することで構成されます。これは、音声が異なる周波数領域で異なって解釈されるため、通常の畳み込みが適用されるため、完全な重みの共有は機能しません。

制限された重み共有の実装は、各畳み込み層に関連付けられた重み行列の重みを制御することで構成されます。したがって、完全な入力に畳み込みを適用します。複数を使用すると、たたみ込み層から抽出された特徴マップの局所性が破壊されるため、紙はたった1つのたたみ込み層のみを適用します。それらが通常のMFCC係数ではなくフィルターバンクエネルギーを使用する理由は、DCTがフィルターバンクエネルギーの局所性を破壊するためです。

ここに画像の説明を入力してください

畳み込み層に関連付けられた重み行列を制御する代わりに、複数の入力を使用してCNNを実装することを選択します。したがって、各入力は(小さなフィルターバンク範囲、total_frames_with_deltas、3)で構成されます。したがって、たとえば、用紙サイズは8のフィルターサイズが適切であると述べたため、フィルターバンクの範囲を8に決定しました。したがって、各小さな画像パッチのサイズは(8、45、3)です。小さな画像パッチのそれぞれは、ストライドが1のスライディングウィンドウで抽出されます。そのため、各入力間に多くのオーバーラップがあり、各入力には独自の畳み込み層があります。

ここに画像の説明を入力してください

(input_3、input_3、input3、input_1、input_2、input_3 ...である必要があります)

この方法を使用すると、複数の畳み込み層を使用できるようになります。これは、局所性が問題にならないためです。フィルターバンク領域内に適用されるため、これは私の理論です。

紙はそれを明示的に述べていませんが、彼らが複数のフレームで音素認識を行う理由は、いくつかの左コンテキストと右コンテキストがあるため、中央のフレームのみが予測/トレーニングされているためです。したがって、私の場合、最初の7フレームは左のコンテキストウィンドウに設定されています。中央のフレームはトレーニングされており、最後の7フレームは右のコンテキストウィンドウに設定されています。したがって、複数のフレームが与えられた場合、1つの音素だけが中央であると認識されます。

私のニューラルネットワークは現在、次のようになっています。

def model3():

    #stride = 1
    #dim = 40
    #window_height = 8
    #splits = ((40-8)+1)/1 = 33
    next(test_generator())
    next(train_generator(batch_size))

    kernel_number = 200#int(math.ceil(splits))
    list_of_input = [Input(shape = (window_height,total_frames_with_deltas,3)) for i in range(splits)]
    list_of_conv_output = []
    list_of_conv_output_2 = []
    list_of_conv_output_3 = []
    list_of_conv_output_4 = []
    list_of_conv_output_5 = []
    list_of_max_out = []
    for i in range(splits):
        #list_of_conv_output.append(Conv2D(filters = kernel_number , kernel_size = (15,6))(list_of_input[i]))
        #list_of_conv_output.append(Conv2D(filters = kernel_number , kernel_size = (window_height-1,3))(list_of_input[i]))
        list_of_conv_output.append(Conv2D(filters = kernel_number , kernel_size = (window_height,3), activation = 'relu')(list_of_input[i]))
        list_of_conv_output_2.append(Conv2D(filters = kernel_number , kernel_size = (1,5))(list_of_conv_output[i]))
        list_of_conv_output_3.append(Conv2D(filters = kernel_number , kernel_size = (1,7))(list_of_conv_output_2[i]))
        list_of_conv_output_4.append(Conv2D(filters = kernel_number , kernel_size = (1,11))(list_of_conv_output_3[i]))
        list_of_conv_output_5.append(Conv2D(filters = kernel_number , kernel_size = (1,13))(list_of_conv_output_4[i]))
        #list_of_conv_output_3.append(Conv2D(filters = kernel_number , kernel_size = (3,3),padding='same')(list_of_conv_output_2[i]))
        list_of_max_out.append((MaxPooling2D(pool_size=((1,11)))(list_of_conv_output_5[i])))

    merge = keras.layers.concatenate(list_of_max_out)
    print merge.shape
    reshape = Reshape((total_frames/total_frames,-1))(merge)

    dense1 = Dense(units = 1000, activation = 'relu',    name = "dense_1")(reshape)
    dense2 = Dense(units = 1000, activation = 'relu',    name = "dense_2")(dense1)
    dense3 = Dense(units = 145 , activation = 'softmax', name = "dense_3")(dense2)
    #dense4 = Dense(units = 1, activation = 'linear', name = "dense_4")(dense3)


    model = Model(inputs = list_of_input , outputs = dense3)
    model.compile(loss="categorical_crossentropy", optimizer="SGD" , metrics = [metrics.categorical_accuracy])

    reduce_lr=ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=3, verbose=1, mode='auto', epsilon=0.001, cooldown=0)
    stop  = EarlyStopping(monitor='val_loss', min_delta=0, patience=5, verbose=1, mode='auto')

    print model.summary()

    raw_input("okay?")
    hist_current = model.fit_generator(train_generator(batch_size),
                        steps_per_epoch=10,
                        epochs = 10000,
                        verbose = 1,
                        validation_data = test_generator(),
                        validation_steps=1)
                        #pickle_safe = True,
                        #workers = 4)

それで、今問題が来ます。

私はネットワークをトレーニングしており、0.17の最高のvalidation_accuracyを取得することができました。多くのエポックの後の精度は最終的に1.0になりました。 ここに画像の説明を入力してください (現在作中である)

固定フレーム:

ここに画像の説明を入力してください (まだ作られているプロット)

なぜより良い結果が得られないのかわかりません。なぜこの高いエラー率ですか?他のデータセットも使用しているTIMITデータセットを使用しています。なぜ結果が悪化するのですか?

そして、長い投稿で申し訳ありません-私の設計決定の詳細情報が役立つことを願って-私が論文をどのように理解したのか、どのように適用したのかを理解することは、私の間違いがどこにあるのかを特定するのに役立ちます。


1
入力形状(40,45,3)について教えてください。(40,15,3)、つまり(フィルターバンクの数、コンテキスト(左+右)、3(静的+デルタ+デルタ_デルタ))である必要があると思います。
arduinolover

私はあなたがそれについて正しいと思う3フレーム。しかし、全体で45 45 = 15x3以来
カールトン銀行

出力を再投稿してみてください。ところでカルディを使うの?
arduinolover

@arduinoloverはい、私はkaldiを使用します。現在実行中です。fbankエネルギーは、kaldiフレームワークを使用して抽出されます。
Carlton Banks

音声認識のためのCNNでこのチュートリアルを行ってください github.com/botonchou/libdnn/wiki/...
arduinolover

回答:


2

あなたのネットワーク構造かもしれません:

この論文では、彼らの実験は以下を使用して行われていると述べています。

conv
pool
dense
dense
dense(softmax)

したがって、fwsの場合は次のようになります。

def fws():
    #Input shape: (batch_size,40,45,3)
    #output shape: (1,15,50)
    # number of unit in conv_feature_map = splitd

    filter_size = 8
    pooling_size = 28
    stride_step = 2
    pool_splits = ((splits - pooling_size)+1)/2
    conv_featur_map = []
    pool_feature_map = []
    print "Printing shapes"


    list_of_input = [Input(shape = (window_height,total_frames_with_deltas,3)) for i in range(splits)]


    #convolution
    shared_conv = Conv2D(filters = 150, kernel_size = (filter_size,45), activation='relu')
    for i in range(splits):
        conv_featur_map.append(shared_conv(list_of_input[i]))

    #Pooling
    input = Concatenate()(conv_featur_map)
    input = Reshape((splits,-1))(input)
    pooled = MaxPooling1D(pool_size = pooling_size, strides = stride_step)(input)

    #reshape = Reshape((3,-1))(pooled)

    #fc
    dense1 = Dense(units = 1000, activation = 'relu',    name = "dense_1")(pooled)
    dense2 = Dense(units = 1000, activation = 'relu',    name = "dense_2")(dense1)
    dense3 = Dense(units = 50 , activation = 'softmax', name = "dense_3")(dense2)

fwsでforループの位置を変更すると(2行上に移動)、lwsになります(さらに、プーリングレイヤーでいくつかの調整が行われます)。


それは私が行っていたものよりもはるかに単純に見えます...
カールトンバンクス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.