2024-05-27|閱讀時間 ‧ 約 26 分鐘

TextToSpeech-神經網路如何理解文字

一.引言

  上篇我們簡單的了解了 TTS 想要達到的目標,但是對於訓練資料的處理、網路架構、損失函數、輸出分析等考慮到篇幅尚未解釋清楚,這篇將針對訓練資料處理中的文字部分進行詳細說明,讓我們開始吧。

二.文字前處理流程

  上篇稍微提到了文字分析,那麼,實際上要做甚麼呢 ?

其實就是我們需要將非中文的表達轉換成中文表達,以及刪除一些對於語音表達無效的字元

例如 :

  • 日期處理 : "2024-05-27" >>> "二零二四年五月二十七日"
  • 縮寫處理 : "NTD100" >>> "新台幣一百元"
  • 符號/空格處理 : "本日推薦 ◎醬油拉麵◎" >>> "本日推薦醬油拉麵"
  • 其他自定義處理

其餘如逗號、句號、問號、驚嘆號等對於句子停頓、語氣等有意義的符號可以保留,我們能夠期待網路能從中學到這些特性。

  但是這樣還不夠,對於神經網路而言,"二零二四年五月二十七日",這樣的輸入是無法處理的,沒轉換成數學表達,就無法參與到神經網路的計算中,那麼如何轉換成數學表達呢?

字典索引

  我們可以建立一個字典庫,根據每個字去定義對應的字典索引。例如:"二零二四年五月二十七日" 可以編碼成 "[10,8,10,12,23,13,31,10,18,15,57]",其中每個數字代表字典中的索引。這樣一來,文字與數字就有了對應關係。

One-hot 編碼

  單純的索引列表仍不足以讓神經網路提取有用的訊息。儘管後續有人提出利用 One-hot 編碼將連續整數轉變成離散型編碼,也就是[0]這個索引若在有10個字的字典庫中,則編碼成[1,0,0,0,0,0,0,0,0,0],只有索引[0]為1,其他則為0的方式編碼,這種編碼方式可以避免順序偏見(即避免某些模型因數值大的索引而給予更大的關注),但無論是字典索引還是 One-hot 編碼,兩者之間的字詞並無關聯性,缺乏語義信息,所以這樣做仍無法解決語義相關性問題,且 One-hot 編碼還有儲存量龐大的問題,通常一個字典庫裏頭的字詞成千上萬,若是使用 One-hot ,則會有大量部分為0,在存儲及計算上都會有浪費問題。

Word Embedding

  為了解決這個問題,有人提出了 Word Embedding 的想法,這也奠定了自然語言處理深度模型的輸入基礎,Word Embedding 使用神經網路訓練詞與詞的關係,並將詞映射到指定維度的向量上,這樣一來,就不用使用與字典同維度的空間去紀錄一個字詞。

Word Embedding 可以捕捉到詞與詞之間的語義關係,這樣即使兩個詞在表面上看起來完全不同,它們的向量表示也能夠反映出它們之間的相關性。這種方法大大提升了神經網路在自然語言處理任務中的效果。

現在如果要快速使用的話,可以使用Word2Vec套件提供的方法訓練你自己的 Word Embedding 模型,以及使用jieba進行詞分割,例如 :

import jieba
from gensim.models import Word2Vec

jieba.load_userdict("Mydict.txt")

# 準備訓練數據
sentences = [
"臺灣鐵路已放棄興建的路線",
"人是一種從動物進化的生物",
"你是英文系的,可以幫我翻譯一下嗎?"
]

# 將句子分詞
tokenized_sentences = [list(jieba.cut(sentence)) for sentence in sentences]
print(tokenized_sentences)

這樣我們切分出的句子便會是

['臺灣', '鐵路', '已', '放棄', '興建', '的', '路線']

['人', '是', '一種', '從', '動物', '進化', '的', '生物']

['你', '是', '英文系', '的', ',', '可以', '幫', '我', '翻譯', '一下', '嗎', '?']

model = Word2Vec(sentences=tokenized_sentences, vector_size=100, 
window=5, min_count=1, sg=0)

# 保存模型
model.save("word2vec.model")

# 加載模型
model = Word2Vec.load("word2vec.model")

# 測試模型
word_vectors = model.wv

# 測試是否符合預期​
print(word_vectors.similarity("人", "鐵路"))
print(word_vectors.similarity("人", "生物"))

# 直接檢視詞向量​
print(word_vectors["人"])

結果人與鐵路的相關性為 -0.027132183;人與生物的相關性為 0.12371957,雖然有拉開,但似乎並沒有很好,這是因為案例只有三句話,需要更多的樣本進行訓練方能獲得較好的結果。

而我們映射完的詞向量可能會長這樣(上方案例為100維不適合展示,這邊以5維為例)

人 : [-0.01270834 -0.14365004 0.20052692 0.0955428 0.18737748]

生物 : [ 0.10361788 0.17437415 -0.02223953 -0.18728271 0.08719231]

這樣一來,我們便充分的利用小維度的向量代表這兩種字詞

實務上,可以使用其他人已經訓練好的模型來進行 Embedding ,若你的詞專業性偏高,也能夠使用此方法訓練出更符合你資料集的 Embedding 模型。

三.結語

  今天介紹了該如何處理文字訓練輸入,但對於 Embedding ,我打算使用單獨的一篇進行詳解其是如何做到將字詞映射到更小維度的向量中,所以這篇只先帶一下套件用起來的功能便利性,以及 Embedding 出現的理由,畢竟這個是自然語言相關的應用中,必不可少的課題,我想好好面對它。


分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.