Sintesis pidato jaringan saraf menggunakan arsitektur Tacotron 2, atau "Dapatkan keselarasan atau mati coba"



Tim kami diberi tugas: mengulangi hasil kerja jaringan syaraf tiruan sintesis bicara Tacotron2 kepengarangan DeepMind. Ini adalah kisah tentang jalan setapak yang kami lewati saat pelaksanaan proyek.

Tugas sintesis pidato komputer telah lama menarik bagi para ilmuwan dan pakar teknis. Namun, metode klasik tidak memungkinkan sintesis ucapan, tidak dapat dibedakan dari manusia. Dan di sini, seperti di banyak daerah lain, pembelajaran mendalam datang untuk menyelamatkan.

Mari kita lihat metode sintesis klasik.

Sintesis Bicara Konsatenatif


Metode ini didasarkan pada fragmen audio pendek pra-perekaman, yang kemudian digabungkan untuk menciptakan ucapan yang koheren. Ternyata sangat bersih dan jelas, tetapi sama sekali tanpa komponen emosional dan intonasional, yaitu, itu terdengar tidak wajar. Dan semuanya karena tidak mungkin mendapatkan rekaman audio dari semua kata yang mungkin diucapkan dalam semua kombinasi emosi dan prosodi yang mungkin. Sistem concatenative membutuhkan basis data besar dan kombinasi hard-coding untuk membentuk kata-kata. Mengembangkan sistem yang andal membutuhkan banyak waktu.

Sintesis pidato parametrik


Aplikasi TTS concatenational terbatas karena persyaratan data yang tinggi dan waktu pengembangan. Oleh karena itu, metode statistik dikembangkan yang mengeksplorasi sifat data. Ini menghasilkan ucapan dengan menggabungkan parameter seperti frekuensi, spektrum amplitudo, dll.

Sintesis parametrik terdiri dari dua tahap.

  1. Pertama, fitur linguistik, seperti fonem, durasi, dll., Diekstraksi dari teks.
  2. Kemudian, untuk vocoder (sistem yang menghasilkan bentuk gelombang), fitur diekstraksi yang mewakili sinyal ucapan yang sesuai: cepstrum, frekuensi, spektogram linier, spektrogram kapur.
  3. Parameter yang dikonfigurasi secara manual ini, bersama dengan fitur linguistik, ditransfer ke model vocoder, dan melakukan banyak transformasi kompleks untuk menghasilkan gelombang suara. Pada saat yang sama, vocoder mengevaluasi parameter bicara, seperti fase, prosodi, intonasi, dan lainnya.

Jika kita dapat memperkirakan parameter yang menentukan ucapan pada setiap unitnya, maka kita dapat membuat model parametrik. Sintesis parametrik membutuhkan data dan kerja keras yang jauh lebih sedikit daripada sistem concatenative.

Secara teoritis, semuanya sederhana, tetapi dalam praktiknya ada banyak artefak yang mengarah pada suara teredam dengan suara "berdengung", yang sama sekali tidak terdengar seperti suara alami.

Faktanya adalah bahwa pada setiap tahap sintesis kami membuat kode yang sulit untuk beberapa fitur dan berharap untuk mendapatkan pidato yang terdengar realistis. Tetapi data yang dipilih didasarkan pada pemahaman kita tentang bicara, dan pengetahuan manusia tidak mutlak, oleh karena itu, tanda-tanda yang diambil tidak akan selalu menjadi solusi terbaik.

Dan di sini Deep Learning memasuki lokasi dengan segala keindahannya.

Deep neural networks adalah alat yang ampuh yang, secara teoritis, dapat memperkirakan fungsi kompleks yang berubah-ubah, yaitu, membawa beberapa ruang data input X ke dalam ruang data output Y. Dalam konteks tugas kami, masing-masing akan berupa teks dan audio dengan ucapan.

Pra-pemrosesan data


Untuk memulainya, kita akan menentukan apa yang kita miliki sebagai input dan apa yang ingin kita dapatkan pada output.

Input akan berupa teks, dan output akan menjadi spektrogram kapur . Ini adalah representasi tingkat rendah yang diperoleh dengan menerapkan transformasi Fourier cepat ke sinyal audio diskrit. Harus segera dicatat bahwa spektogram yang diperoleh dengan cara ini masih perlu dinormalisasi dengan mengompresi rentang dinamis. Ini memungkinkan Anda mengurangi hubungan alami antara suara paling keras dan paling tenang dalam rekaman. Dalam percobaan kami, penggunaan spektrogram dikurangi hingga kisaran [-4; 4] terbukti menjadi yang terbaik.


Gambar 1: Spektrum kapur dari sinyal audio ucapan berkurang hingga kisaran [-4; 4].

Sebagai set data pelatihan, kami memilih dataset LJSpeech , yang berisi 13.100 trek audio selama 2-10 detik. dan file dengan teks yang sesuai dengan ucapan bahasa Inggris yang direkam pada audio.

Suara menggunakan transformasi di atas dikodekan ke dalam spektrogram kapur. Teks tersebut dipatok dan diubah.

menjadi urutan bilangan bulat. Saya harus segera menekankan bahwa teks dinormalisasi: semua angka ditulis secara verbal, dan kemungkinan singkatan diuraikan, misalnya: "Mrs. Robinson "-" Missis Robinson ".

Jadi, setelah preprocessing, kita mendapatkan set array numpy dari urutan numerik dan spektogram kapur yang direkam dalam file npy pada disk.

Sehingga pada tahap pelatihan semua dimensi dalam tensor patch bertepatan, kami akan menambahkan paddings ke urutan pendek. Untuk urutan dalam bentuk teks, ini akan disediakan untuk padding 0, dan untuk spektrogram, bingkai yang nilainya sedikit lebih rendah dari spektogram minimum yang ditentukan oleh kami. Ini direkomendasikan untuk mengisolasi bantalan ini, memisahkannya dari kebisingan dan keheningan.

Sekarang kami memiliki data yang mewakili teks dan audio yang cocok untuk diproses oleh jaringan saraf tiruan. Mari kita lihat arsitektur Net prediksi fitur, yang dengan nama elemen pusat dari seluruh sistem sintesis akan disebut Tacotron2.

Arsitektur


Tacotron 2 bukan satu jaringan, tetapi dua: Net prediksi fitur dan NN-vocoder WaveNet . Artikel asli, serta visi kami sendiri tentang pekerjaan yang dilakukan, memungkinkan kami untuk mempertimbangkan Net prediksi fitur sebagai biola pertama, sementara vocoder WaveNet berperan sebagai sistem periferal.

Tacotron2 adalah arsitektur urutan ke urutan . Ini terdiri dari encoder (encoder), yang menciptakan beberapa representasi internal dari sinyal input (simbol token), dan decoder (decoder), yang mengubah representasi ini menjadi spektrogram kapur. Juga elemen yang sangat penting dari jaringan adalah apa yang disebut PostNet , yang dirancang untuk meningkatkan spektrogram yang dihasilkan oleh decoder.


Gambar 2: Arsitektur Jaringan Tacotron 2.

Mari kita pertimbangkan lebih detail blok-blok jaringan dan modul-modulnya.

Lapisan encoder pertama adalah lapisan Embedding. Berdasarkan urutan bilangan alami yang mewakili karakter, ia menciptakan vektor multidimensi (512 dimensi).

Selanjutnya, vektor embedding dimasukkan ke dalam blok tiga lapisan konvolusional satu dimensi. Setiap lapisan menyertakan 512 filter dengan panjang 5. Nilai ini adalah ukuran filter yang baik dalam konteks ini, karena menangkap karakter tertentu, serta dua tetangganya sebelumnya dan dua tetangganya berikutnya. Setiap lapisan konvolusional diikuti oleh normalisasi mini-batch dan aktivasi ReLU.

Tensor yang diperoleh setelah blok konvolusional diterapkan pada lapisan LSTM dua arah, masing-masing 256 neuron. Meneruskan dan mengembalikan hasil digabungkan.

Dekoder memiliki arsitektur berulang, yaitu, pada setiap langkah berikutnya, output dari langkah sebelumnya digunakan. Di sini mereka akan menjadi satu bingkai spektogram. Elemen penting lain, jika bukan kunci, dari sistem ini adalah mekanisme perhatian yang lembut (terlatih) - teknik yang relatif baru yang semakin populer. Pada setiap langkah dekoder, perhatian untuk membentuk vektor konteks dan memperbarui bobot perhatian menggunakan:

  • proyeksi keadaan tersembunyi sebelumnya dari jaringan RNN dari decoder pada lapisan yang terhubung penuh,
  • proyeksi output encoder ke lapisan yang terhubung penuh,
  • serta aditif (terakumulasi pada setiap langkah waktu decoder) menjadi perhatian.

Gagasan perhatian harus dipahami sebagai berikut: "bagian mana dari data encoder yang harus digunakan pada langkah dekoder saat ini".


Gambar 3: Skema mekanisme perhatian.

Pada setiap langkah dekoder, vektor konteks C i dihitung (ditunjukkan sebagai "output encoder yang dihadiri" pada gambar di atas), yang merupakan produk dari output encoder ( h ) dan bobot perhatian ( α ):



di mana α ij adalah bobot perhatian yang dihitung dengan rumus:



di mana e ij adalah apa yang disebut "energi", rumus perhitungan yang tergantung pada jenis mekanisme perhatian yang Anda gunakan (dalam kasus kami, itu akan menjadi tipe hibrida, menggunakan baik perhatian berbasis lokasi dan perhatian berbasis konten). Energi dihitung dengan rumus:

e ij = v aT tanh (Ws i-1 + Vh j + Uf i, j + b)

dimana:
  • s i-1 - status tersembunyi sebelumnya dari jaringan LSTM dari decoder,
  • α i-1 - bobot perhatian sebelumnya,
  • h j adalah status tersembunyi dari enkoder,
  • W , V , U , v a dan b adalah parameter pelatihan,
  • f i, j - tanda-lokasi yang dihitung dengan rumus:

    f i = F * α i-1

    di mana F adalah operasi konvolusi.


Untuk pemahaman yang jelas tentang apa yang terjadi, kami menambahkan bahwa beberapa modul yang dijelaskan di bawah mengasumsikan penggunaan informasi dari langkah sebelumnya dari decoder. Tetapi jika ini adalah langkah pertama, maka informasi akan menjadi tensor dari nilai nol, yang merupakan praktik umum ketika membuat struktur perulangan.

Sekarang pertimbangkan algoritma operasi .

Pertama, output dekoder dari langkah waktu sebelumnya dimasukkan ke dalam modul PreNet kecil, yang merupakan tumpukan dua lapisan 256 neuron yang terhubung penuh, bergantian dengan lapisan putus dengan kecepatan 0,5. Fitur khusus dari modul ini adalah bahwa dropout digunakan di dalamnya tidak hanya pada tahap pelatihan model, tetapi juga pada tahap output.

Output PreNet dalam gabungan dengan vektor konteks yang diperoleh sebagai hasil dari mekanisme perhatian dimasukkan ke input ke jaringan LSTM dua-lapisan searah, 1024 neuron di setiap lapisan.

Kemudian, gabungan output dari lapisan LSTM dengan vektor konteks yang sama (dan mungkin berbeda) dimasukkan ke dalam lapisan yang terhubung penuh dengan 80 neuron, yang sesuai dengan jumlah saluran spektogram. Lapisan terakhir dari dekoder ini membentuk bingkai spektrogram yang diprediksi oleh bingkai. Dan hasilnya sudah disediakan sebagai input ke langkah waktu berikutnya dari decoder di PreNet.

Mengapa kami menyebutkan dalam paragraf sebelumnya bahwa vektor konteks mungkin sudah berbeda? Salah satu pendekatan yang mungkin adalah menghitung ulang vektor konteks setelah keadaan laten jaringan LSTM diperoleh pada langkah ini. Namun, dalam percobaan kami, pendekatan ini tidak membenarkan dirinya sendiri.

Selain memproyeksikan ke lapisan 80-neuron yang sepenuhnya terhubung, rangkaian output dari lapisan LSTM dengan vektor konteks dimasukkan ke dalam lapisan yang sepenuhnya terhubung dengan satu neuron, diikuti oleh aktivasi sigmoid - ini adalah lapisan "stop token prediksi". Dia memprediksi kemungkinan bahwa frame yang dibuat pada langkah dekoder ini adalah final. Lapisan ini dirancang untuk menghasilkan spektrogram tidak tetap, tetapi panjang sewenang-wenang pada tahap output model. Yaitu, pada tahap output, elemen ini menentukan jumlah langkah dari decoder. Ini dapat dianggap sebagai classifier biner.

Output dari decoder dari semua langkahnya akan menjadi spektrogram yang diprediksi. Namun, ini belum semuanya. Untuk meningkatkan kualitas spektrogram, ia dilewatkan melalui modul PostNet, yang merupakan tumpukan lima lapisan konvolusional satu dimensi dengan masing-masing 512 filter dan dengan ukuran filter 5. Normalisasi batch dan aktivasi tangen mengikuti setiap lapisan (kecuali yang terakhir). Untuk kembali ke dimensi spektrogram, kami melewatkan data output post-net melalui lapisan yang terhubung penuh dengan 80 neuron dan menambahkan data yang diterima dengan hasil awal dari decoder. Kami mendapatkan spektrogram kapur yang dihasilkan dari teks. Untung

Semua modul konvolusional diregulasi dengan lapisan putus dengan laju 0,5, dan lapisan berulang dengan metode Zoneout yang lebih baru dengan laju 0,1. Ini cukup sederhana: alih-alih menerapkan keadaan laten dan keadaan sel yang diperoleh pada langkah saat ini ke langkah waktu berikutnya dari jaringan LSTM, kami mengganti bagian dari data dengan nilai-nilai dari langkah sebelumnya. Ini dilakukan pada tahap pelatihan dan pada tahap penarikan. Dalam kasus ini, hanya keadaan tersembunyi (yang diteruskan ke langkah LSTM berikutnya) yang diekspos ke metode Zoneout di setiap langkah, sedangkan output sel LSTM pada langkah saat ini tetap tidak berubah.

Kami memilih PyTorch sebagai kerangka pembelajaran yang mendalam. Meskipun pada saat implementasi jaringan itu dalam keadaan pra-rilis, tetapi sudah merupakan alat yang sangat kuat untuk membangun dan melatih jaringan saraf tiruan. Dalam pekerjaan kami, kami menggunakan kerangka kerja lain seperti TensorFlow dan Keras. Namun, yang terakhir dibuang karena kebutuhan untuk menerapkan struktur kustom non-standar, dan jika kita membandingkan TensorFlow dan PyTorch, maka ketika menggunakan yang kedua, tidak ada perasaan bahwa model tersebut diambil dari bahasa Python. Namun, kami tidak berusaha untuk menyatakan bahwa salah satu dari mereka lebih baik dan yang lain lebih buruk. Penggunaan kerangka kerja tertentu mungkin tergantung pada berbagai faktor.

Jaringan dilatih oleh metode backpropagation. ADAM digunakan sebagai pengoptimal, Mean Square Error sebelum dan sesudah PostNet, serta Binary Cross Entropy di atas nilai aktual dan prediksi lapisan Stop Token Prediction, digunakan sebagai fungsi kesalahan. Kesalahan yang dihasilkan adalah jumlah sederhana dari ketiganya.

Model ini dilatih pada GPU GeForce 1080Ti tunggal dengan memori 11 GB.

Visualisasi


Ketika bekerja dengan model sebesar itu, penting untuk melihat bagaimana proses pembelajaran berjalan. Dan di sini TensorBoard menjadi alat yang praktis. Kami melacak nilai kesalahan di kedua pelatihan dan iterasi validasi. Selain itu, kami menampilkan target spektogram, spektogram prediksi pada tahap pelatihan, prediksi spektogram pada tahap validasi, dan penyelarasan, yang merupakan bobot perhatian terakumulasi secara aditif dari semua langkah pelatihan.

Ada kemungkinan bahwa pada awalnya perhatian Anda tidak akan terlalu informatif:


Gambar 4: Contoh skala perhatian yang kurang terlatih.

Tetapi setelah semua modul Anda mulai bekerja seperti arloji Swiss, Anda akhirnya akan mendapatkan sesuatu seperti ini:


Gambar 5: Contoh skala perhatian yang berhasil dilatih.

Apa artinya bagan ini? Pada setiap langkah dari decoder, kami mencoba untuk memecahkan kode satu frame spektogram. Namun, tidak jelas informasi apa yang perlu digunakan pembuat enkode pada setiap langkah dekoder. Dapat diasumsikan bahwa korespondensi ini akan langsung. Misalnya, jika kita memiliki urutan teks input 200 karakter dan spektrogram 800 frame yang sesuai, maka akan ada 4 frame untuk setiap karakter. Namun, Anda harus mengakui bahwa pidato yang dihasilkan berdasarkan spektogram semacam itu akan sepenuhnya tanpa kealamian. Kami mengucapkan beberapa kata lebih cepat, beberapa lebih lambat, di suatu tempat kami jeda, tetapi di suatu tempat kami tidak. Dan menganggap semua konteks yang mungkin tidak mungkin. Itulah sebabnya perhatian adalah elemen kunci dari keseluruhan sistem: ia mengatur korespondensi antara langkah dekoder dan informasi dari pembuat enkode untuk mendapatkan informasi yang diperlukan untuk menghasilkan bingkai tertentu. Dan semakin besar nilai bobot perhatian, semakin "perhatian harus dibayarkan" ke bagian yang sesuai dari data enkoder saat membuat bingkai spektrogram.

Pada tahap pelatihan, ini juga akan berguna untuk menghasilkan audio, dan tidak hanya secara visual mengevaluasi kualitas spektogram dan perhatian. Namun, mereka yang telah bekerja dengan WaveNet akan setuju bahwa menggunakannya sebagai vocoder pada tahap pelatihan akan menjadi kemewahan yang tidak dapat diterima dalam hal waktu. Oleh karena itu, disarankan untuk menggunakan algoritma Griffin-Lim , yang memungkinkan rekonstruksi sebagian sinyal setelah transformasi Fourier yang cepat. Kenapa sebagian? Faktanya adalah bahwa ketika kita mengubah sinyal menjadi spektrogram, kita kehilangan informasi fase. Namun, kualitas audio yang diperoleh akan cukup untuk memahami ke arah mana Anda bergerak.

Pelajaran yang dipetik


Di sini kita akan berbagi beberapa pemikiran tentang membangun proses pengembangan, mengirimkannya dalam format tips. Beberapa dari mereka cukup umum, yang lain lebih spesifik.

Tentang organisasi alur kerja :

  • Gunakan sistem kontrol versi, jelaskan dan jelaskan semua perubahan. Ini mungkin tampak seperti rekomendasi yang jelas, tetapi tetap saja. Saat mencari arsitektur optimal, perubahan terus-menerus terjadi. Dan setelah menerima beberapa hasil perantara yang memuaskan, pastikan untuk membuat diri Anda sebagai pos pemeriksaan sehingga Anda dapat dengan aman melakukan perubahan berikutnya.
  • Dari sudut pandang kami, dalam arsitektur seperti itu orang harus mematuhi prinsip-prinsip enkapsulasi: satu kelas - satu modul Python. Pendekatan ini tidak umum dalam tugas ML, tetapi ini akan membantu Anda menyusun kode dan mempercepat proses debug dan pengembangan. Baik dalam kode dan visi arsitektur Anda, membaginya menjadi blok, blok menjadi modul, dan modul menjadi beberapa lapisan. Jika modul memiliki kode yang menjalankan peran tertentu, maka gabungkan menjadi metode kelas modul. Ini adalah kebenaran umum, tetapi kami tidak terlalu malas untuk mengatakannya lagi.
  • Berikan dokumentasi bergaya numpy dengan dokumentasi . Ini akan sangat menyederhanakan pekerjaan untuk Anda dan kolega Anda yang akan membaca kode Anda.
  • Selalu gambar arsitektur model Anda. Pertama, ini akan membantu Anda memahaminya, dan kedua, pandangan sisi arsitektur dan hiperparameter model akan memungkinkan Anda untuk dengan cepat mengidentifikasi ketidakakuratan dalam pendekatan Anda.
  • Lebih baik bekerja sebagai tim. Jika Anda bekerja sendirian, tetap kumpulkan rekan kerja dan diskusikan pekerjaan Anda. Paling tidak, mereka dapat mengajukan pertanyaan yang akan mengarahkan Anda pada beberapa pemikiran, tetapi secara maksimal mereka akan menunjuk ke ketidakakuratan spesifik yang tidak memungkinkan Anda untuk berhasil melatih model.
  • Trik lain yang bermanfaat sudah dikaitkan dengan preprocessing data. Misalkan Anda memutuskan untuk menguji beberapa hipotesis dan membuat perubahan yang sesuai dengan model. Tetapi memulai kembali pelatihan, terutama sebelum akhir pekan, akan berisiko. Pendekatan awalnya mungkin salah dan Anda akan membuang waktu. Lalu apa yang harus dilakukan? Menambah ukuran jendela Fast Fourier Transform. Parameter default adalah 1024; tingkatkan 4, atau bahkan 8 kali. Ini akan "memeras" spektogram dalam jumlah waktu yang tepat dan sangat mempercepat pembelajaran. Audio yang dipulihkan dari mereka akan memiliki kualitas yang lebih rendah, tetapi ini bukan tugas Anda sekarang? Dalam 2-3 jam Anda sudah bisa mendapatkan keselarasan ("alignment" dari skala perhatian, seperti yang ditunjukkan pada gambar di atas), ini akan menunjukkan kebenaran arsitektur dari pendekatan dan itu sudah dapat diuji pada data besar.

Model bangunan dan pelatihan :

  • Kami berhipotesis bahwa jika bets tidak dibentuk secara acak, tetapi berdasarkan panjangnya, mereka akan mempercepat proses pelatihan model dan membuat spektogram yang dihasilkan lebih baik. Asumsi logis, yang didasarkan pada hipotesis bahwa semakin banyak sinyal yang bermanfaat (dan bukan padding) diumpankan ke jaringan pelatihan, semakin baik. Namun, pendekatan ini tidak membenarkan dirinya sendiri, dalam percobaan kami, kami tidak dapat melatih jaringan dengan cara ini. Ini mungkin karena hilangnya keacakan dalam pemilihan contoh untuk pelatihan.
  • Gunakan algoritma inisialisasi parameter jaringan modern dengan beberapa kondisi awal yang dioptimalkan. Misalnya, dalam percobaan kami, kami menggunakan Inisialisasi Berat Seragam Xavier. Jika dalam modul Anda, Anda perlu menggunakan normalisasi dengan mini-batch dan beberapa fungsi aktivasi, maka mereka harus bergantian satu sama lain dalam urutan ini. Memang, jika kita menerapkan, misalnya, aktivasi ReLU, maka kita segera kehilangan semua sinyal negatif yang harus terlibat dalam proses normalisasi data batch tertentu.
  • Dari langkah pembelajaran tertentu, gunakan tingkat pembelajaran yang dinamis. Ini sangat membantu mengurangi nilai kesalahan dan meningkatkan kualitas spektogram yang dihasilkan.
  • Setelah membuat model dan upaya yang gagal untuk melatihnya pada batch dari seluruh kumpulan data, akan berguna untuk mencoba melatihnya pada satu batch. , alignment, ( ). , , .

    . . , – . , . , .
  • RNN- . . , . ? LSTM- -.
  • , LSTM-, « »: « , LSTM-. «» bf. , , , LSTM- ft 1/2. , : , «» 1/2, . bf , 1 2: ft ».
  • seq2seq- . — , . ? , ( ).
  • Sekarang rekomendasi spesifik untuk kerangka PyTorch. Meskipun lapisan LSTM dalam dekoder, pada kenyataannya, adalah sel LSTM-nya, yang menerima informasi hanya untuk satu elemen urutan pada setiap langkah dekoder, disarankan untuk menggunakan kelas torch.nn.LSTMCell daripada torch.nn.LSTMCell . Alasannya adalah bahwa backend LSTM diimplementasikan di perpustakaan CUDNN di C, dan LSTMCell dalam Python. Trik ini akan memungkinkan Anda untuk meningkatkan kecepatan sistem secara signifikan.

Dan di akhir artikel, kami akan membagikan contoh-contoh generasi bicara dari teks-teks yang tidak terkandung dalam set pelatihan.

Source: https://habr.com/ru/post/id436312/


All Articles