CNN để nhận dạng âm vị


7

Tôi hiện đang nghiên cứu bài báo này , trong đó CNN được áp dụng để nhận dạng âm vị bằng cách sử dụng biểu diễn trực quan của các ngân hàng bộ lọc log mel và sơ đồ chia sẻ trọng lượng hạn chế.

Hình dung của các ngân hàng bộ lọc log mel là một cách đại diện và bình thường hóa dữ liệu. Họ đề nghị hình dung như một quang phổ với màu RGB, thứ gần nhất tôi có thể nghĩ ra là vẽ nó bằng cách sử dụng matplotlibscolormap cm.jet. Họ (là tờ giấy) cũng đề xuất mỗi khung nên được xếp chồng lên nhau bằng năng lượng bộ lọc [delta delta_delta] của nó. Cái này trông như thế này:

nhập mô tả hình ảnh ở đây

Đầu vào của bao gồm một miếng vá hình ảnh gồm 15 khung hình được đặt hình dạng đầu vào [delta delta_detlta] sẽ là (40,45,3)

Chia sẻ trọng lượng giới hạn bao gồm giới hạn chia sẻ trọng lượng cho một khu vực ngân hàng bộ lọc cụ thể, vì lời nói được diễn giải khác nhau ở khu vực tần số khác nhau, do đó sẽ chia sẻ trọng lượng đầy đủ như áp dụng tích chập thông thường, sẽ không hoạt động.

Việc thực hiện chia sẻ trọng lượng hạn chế của họ bao gồm kiểm soát các trọng số trong ma trận trọng số liên quan đến từng lớp chập. Vì vậy, họ áp dụng một tích chập trên đầu vào hoàn chỉnh. Bài viết chỉ áp dụng một lớp chập vì sử dụng nhiều lớp sẽ phá hủy địa phương của các bản đồ đặc trưng được trích xuất từ ​​lớp chập. Lý do tại sao họ sử dụng năng lượng ngân hàng bộ lọc thay vì hệ số MFCC bình thường là vì DCT phá hủy địa phương của các bộ lọc ngân hàng năng lượng.

nhập mô tả hình ảnh ở đây

Thay vì kiểm soát ma trận trọng số liên quan đến lớp chập, tôi chọn triển khai CNN với nhiều đầu vào. do đó, mỗi đầu vào bao gồm một (phạm vi ngân hàng bộ lọc nhỏ, Total_frames_with_deltas, 3). Vì vậy, ví dụ, trạng thái giấy rằng kích thước bộ lọc là 8 nên tốt, vì vậy tôi đã quyết định phạm vi ngân hàng bộ lọc là 8. Vì vậy, mỗi miếng vá hình ảnh nhỏ có kích thước (8,45,3). Mỗi miếng vá hình ảnh nhỏ được trích xuất với một cửa sổ trượt với sải chân là 1 - vì vậy có rất nhiều sự chồng chéo giữa mỗi đầu vào - và mỗi đầu vào có một lớp chập riêng.

nhập mô tả hình ảnh ở đây

(input_3, input_3, input3, đáng lẽ phải là input_1, input_2, input_3 ...)

Làm theo cách này cho phép sử dụng nhiều lớp chập, vì địa phương không còn là vấn đề nữa, vì nó được áp dụng trong khu vực ngân hàng bộ lọc, đây là lý thuyết của tôi.

Bài viết không nêu rõ nhưng tôi đoán lý do tại sao họ thực hiện nhận dạng âm vị trên nhiều khung là để có một số bối cảnh bên trái và bối cảnh bên phải, vì vậy chỉ có khung giữa được dự đoán / đào tạo. Vì vậy, trong trường hợp của tôi là 7 khung hình đầu tiên được đặt cửa sổ ngữ cảnh bên trái - khung giữa đang được đào tạo và 7 khung hình cuối cùng được đặt là cửa sổ ngữ cảnh bên phải. Vì vậy, cho nhiều khung hình, sẽ chỉ có một âm vị được công nhận là giữa.

Mạng lưới thần kinh của tôi hiện tại trông như thế này:

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)

Vì vậy, bây giờ đến vấn đề ..

Tôi đã đào tạo mạng và chỉ có thể có được xác thực_accuracy cao nhất là 0,17 và độ chính xác sau khi rất nhiều kỷ nguyên kết thúc là 1.0. nhập mô tả hình ảnh ở đây (Lô đất hiện đang được thực hiện)

khung cố định:

nhập mô tả hình ảnh ở đây (cốt truyện vẫn đang được thực hiện)

Tôi không chắc tại sao tôi không nhận được kết quả tốt hơn .. Tại sao tỷ lệ lỗi cao này? Tôi đang sử dụng bộ dữ liệu TIMIT mà những người khác cũng sử dụng .. vậy tại sao tôi lại nhận được kết quả tồi tệ hơn?

Và xin lỗi vì bài viết dài - hy vọng nhiều thông tin hơn về quyết định thiết kế của tôi có thể hữu ích - và giúp hiểu cách tôi hiểu bài viết so với cách tôi đã áp dụng sẽ giúp xác định chính xác lỗi của tôi.


1
Bạn có thể vui lòng giải thích hình dạng đầu vào (40,45,3)? Tôi nghĩ rằng nó phải là (40,15,3) tức là (số ngân hàng bộ lọc, bối cảnh (trái + phải), 3 (tĩnh + delta + delta_delta)).
arduinolover

Tôi nghĩ bạn đúng về nó nên 3 khung hình. nhưng tổng cộng 45 kể từ 15x3 = 45.
Ngân hàng Carlton

Bạn có thể thử và đăng lại các đầu ra? Btw bạn có sử dụng kaldi?
arduinolover

@arduinolover vâng tôi sử dụng kaldi .. Và nó hiện đang chạy. năng lượng fbank được trích xuất bằng cách sử dụng khung kaldi.
Ngân hàng Carlton

Vui lòng xem hướng dẫn này trên CNN để nhận dạng giọng nói github.com/botonchou/libdnn/wiki/iêu
arduinolover

Câu trả lời:


2

Có thể là cấu trúc mạng của bạn:

Bài viết nói rằng thí nghiệm của họ được thực hiện bằng cách sử dụng:

conv
pool
dense
dense
dense(softmax)

Vì vậy, một cái gì đó như thế này cho 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)

Thay đổi vị trí của vòng lặp for trong fws (di chuyển 2 dòng lên) làm cho nó thành một lws (Cộng với một số điều chỉnh với lớp gộp).


Trông có vẻ đơn giản hơn những gì tôi sẽ làm ...
Carlton Banks
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.