語(yǔ)音合成學(xué)習(xí)(六)學(xué)習(xí)筆記
文本歸一化
一、介紹
簡(jiǎn)介
文本正則化是將文本數(shù)據(jù)轉(zhuǎn)化為標(biāo)準(zhǔn)形式的過(guò)程,以便于進(jìn)行自然語(yǔ)言處理和文本分析。文本歸一化通常包括以下步驟:
- 文本清理:刪除文本中的無(wú)用信息,如HTML標(biāo)記,特殊字符,URL和標(biāo)點(diǎn)符號(hào)等。
- 大小寫統(tǒng)一:將文本中的所有字符轉(zhuǎn)換為小寫或大寫字母。
- 停用詞過(guò)濾:刪除指定的停用詞,如“的”、“在”、“是”等常用詞語(yǔ)。
- 詞干提取或詞形還原:將不同形式的詞匯轉(zhuǎn)換為其原始形式,如將“running”轉(zhuǎn)換為“run”或?qū)ⅰ癱ats”轉(zhuǎn)換為“cat”。
- 拼寫糾正:修正文本中的拼寫錯(cuò)誤。
文本歸一化的目的是消除文本中的噪聲和不規(guī)則性,提高自然語(yǔ)言處理和文本分析的準(zhǔn)確性和效率。
TN全稱Text Normalization,意思是文本規(guī)整、文本正則化 。
TN是 TTS (Text-to-speech,文本轉(zhuǎn)語(yǔ)音) 系統(tǒng)中的重要組成部分,主要功能是將文本中的數(shù)字、符號(hào)、縮寫等轉(zhuǎn)換成語(yǔ)言文字。如:
# delete english characters
# e.g. "你好aBC" -> "你 好"
# fractionation
# e.g. "現(xiàn)場(chǎng)有7/12的觀眾投出了贊成票" -> "現(xiàn)場(chǎng)有十二分之七的觀眾投出了贊成票"
# time
# e.g. "2:10pm出門" -> "下午兩點(diǎn)十分出門"
- 使用歸一化的好處:
1.提升模型的收斂速度(即加快梯度下降求最優(yōu)解的速度
2.提升模型的精度
在涉及到一些距離計(jì)算的算法時(shí)效果顯著,比如算法要計(jì)算歐氏距離,歸一化可以讓可以讓各個(gè)特征對(duì)結(jié)果做出的貢獻(xiàn)相同,未歸一化就會(huì)造成精度的損失。3.提高準(zhǔn)確性:文本歸一化可以消除文本中的噪聲和不規(guī)則性,如大小寫差異、拼寫錯(cuò)誤、同義詞等,從而提高文本分析的準(zhǔn)確性。
4.降低復(fù)雜性:文本歸一化可以將文本轉(zhuǎn)換為標(biāo)準(zhǔn)格式或標(biāo)準(zhǔn)形式,從而降低文本分析的復(fù)雜性和難度。
5.提高效率:文本歸一化可以將不同形式的詞匯轉(zhuǎn)換為其原始形式,并刪除停用詞等無(wú)用信息,從而提高自然語(yǔ)言處理和文本分析的效率。
6.統(tǒng)一數(shù)據(jù):文本歸一化可以統(tǒng)一不同來(lái)源的文本數(shù)據(jù),使其格式和表達(dá)方式相同,從而方便進(jìn)行后續(xù)的文本分析和處理。
二、常見(jiàn)的歸一化轉(zhuǎn)換規(guī)則與表達(dá)
# 過(guò)濾掉特殊字符
text = re.sub(r'[——《》【】<=>{}()()#&@“”^_|…\\]', '', text)
# 日期表達(dá)式
用 / 或者 - 分隔的 YY/MM/DD 或者 YY-MM-DD 日期
RE_DATE2 = re.compile(r'(\d{4})([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])')
RE_DATE21 = re.compile(r'(\d{4}|\d{2})年'
r'((0?[1-9]|1[0-2])月)?'
r'(((0?[1-9])|((1|2)[0-9])|30|31)([日號(hào)]))?')
# 時(shí)刻表達(dá)式
RE_TIME = re.compile(r'([0-1]?[0-9]|2[0-3])'
r':([0-5][0-9])'
r'(:([0-5][0-9]))?')
# 時(shí)間范圍,如8:30-12:30
RE_TIME_RANGE = re.compile(r'([0-1]?[0-9]|2[0-3])'
r':([0-5][0-9])'
r'(:([0-5][0-9]))?'
r'(~|-)'
r'([0-1]?[0-9]|2[0-3])'
r':([0-5][0-9])'
r'(:([0-5][0-9]))?')
# 分?jǐn)?shù)表達(dá)式
RE_FRAC = re.compile(r'(-?)(\d+)/(\d+)')
# 百分?jǐn)?shù)表達(dá)式
RE_PERCENTAGE = re.compile(r'(-?)(\d+(\.\d+)?)%')
# 整數(shù)表達(dá)式
# 帶負(fù)號(hào)的整數(shù) -10
RE_INTEGER = re.compile(r'(-)' r'(\d+)')
# 編號(hào)-無(wú)符號(hào)整形
# 00078
RE_DEFAULT_NUM = re.compile(r'\d{3}\d*')
# 數(shù)字表達(dá)式
# 純小數(shù)
RE_DECIMAL_NUM = re.compile(r'(-?)((\d+)(\.\d+))' r'|(\.(\d+))')
# 正整數(shù) + 量詞
RE_POSITIVE_QUANTIFIERS = re.compile(r"(\d+)([多余幾\+])?" + COM_QUANTIFIERS)
RE_NUMBER = re.compile(r'(-?)((\d+)(\.\d+)?)' r'|(\.(\d+))')
# 范圍表達(dá)式
RE_RANGE = re.compile(r'((-?)((\d+)(\.\d+)?)|(\.(\d+)))[-~]((-?)((\d+)(\.\d+)?)|(\.(\d+)))')
# 規(guī)范化固話/手機(jī)號(hào)碼
# 手機(jī)
# 移動(dòng):139、138、137、136、135、134、159、158、157、150、151、152、188、187、182、183、184、178、198
# 聯(lián)通:130、131、132、156、155、186、185、176
# 電信:133、153、189、180、181、177
RE_MOBILE_PHONE = re.compile(r"(?<!\d)((\+?86 ?)?1([38]\d|5[0-35-9]|7[678]|9[89])\d{8})(?!\d)")
RE_TELEPHONE = re.compile(r"(?<!\d)((0(10|2[1-3]|[3-9]\d{2})-?)?[1-9]\d{7,8})(?!\d)")
# 全國(guó)統(tǒng)一的號(hào)碼400開(kāi)頭
RE_NATIONAL_UNIFORM_NUMBER = re.compile(r"(400)(-)?\d{3}(-)?\d{4}")
# 溫度表達(dá)式,溫度會(huì)影響負(fù)號(hào)的讀法
# -3°C 零下三度
RE_TEMPERATURE = re.compile(r'(-?)(\d+(\.\d+)?)(°C|℃|度|攝氏度)')
## Normalize unicode characters // 規(guī)范化unicode 字符
def remove_weird_chars(text):
text = unicodedata.normalize('NFKD', text).encode('utf-8', 'ignore').decode(
'utf-8', 'ignore')
return text
## Remove extra linebreaks //刪除額外換行符
def remove_extra_linebreaks(text):
lines = text.split(r'\n+')
return '\n'.join(
[re.sub(r'[\s]+', ' ', l).strip() for l in lines if len(l) != 0])
## Remove extra medial/trailing/leading spaces // 刪除額外的中間/后面/前面的空間
def remove_extra_spaces(text):
return re.sub("\\s+", " ", text).strip()
## Seg the text into words // 分詞
def seg(text):
text_seg = jieba.cut(text)
out = ' '.join(text_seg)
return out
## Remove punctuation/symbols // 除去標(biāo)點(diǎn)符號(hào)
def remove_symbols(text):
text = ''.join(
ch for ch in text if unicodedata.category(ch)[0] not in ['P', 'S'])
return text
## Remove numbers // 除去數(shù)字
def remove_numbers(text):
return re.sub('\\d+', "", text)
## Remove alphabets //除去字母
def remove_alphabets(text):
return re.sub('[a-zA-Z]+', '', text)
## Unify upper/lower cases //轉(zhuǎn)換大小寫
if args.to_upper:
text = text.upper()
if args.to_lower:
text = text.lower()
## export const verbalizeCardinal = (num) => {
// 將基數(shù)詞轉(zhuǎn)換為中文漢字表示
let result = '';
for (let digit of String(num)) {
result += CARDINALS[digit];
}
return result;
}
## export const replaceDate = (match) => {
// 將日期字符串中的數(shù)字轉(zhuǎn)換為中文漢字表示
const year = match[1];
const month = match[3];
const day = match[5];
let result = '';
if (year) {
result += `${verbalizeDigit(year)}年`;
}
if (month) {
result += `${verbalizeCardinal(month)}月`;
}
if (day) {
result += `${verbalizeCardinal(day)}${match[9]}`;
}
return result;
## export const replaceDate2 = (match) => {
// 將日期字符串中的數(shù)字轉(zhuǎn)換為中文漢字表示
const year = match[1];
const month = match[3];
const day = match[4];
let result = '';
if (year) {
result += `${verbalizeDigit(year)}年`;
}
if (month) {
result += `${verbalizeCardinal(month)}月`;
}
if (day) {
result += `${verbalizeCardinal(day)}日`;
}
return result;
## export const replaceTime = (match) => {
const isRange = match[6] !== '-';
const hour = parseInt(match[1]);
const minute = parseInt(match[2]);
const second = match[4] ? parseInt(match[4]) : 0;
const hour2 = isRange ? parseInt(match[6]) : null;
const minute2 = isRange ? parseInt(match[7]) : null;
const second2 = isRange && match[9] ? parseInt(match[9]) : null;
let result = `${num2str(hour)}點(diǎn)`;
if (minute.toString().replace(/^0+/, '') !== '') {
if (minute === 30) {
result += '半';
} else {
result += `${_time_num2str(minute)}分`;
}
}
if (second.toString().replace(/^0+/, '') !== '') {
result += `${_time_num2str(second)}秒`;
}
if (isRange) {
result += '至';
result += `${num2str(hour2)}點(diǎn)`;
if (minute2.toString().replace(/^0+/, '') !== '') {
if (minute2 === 30) {
result += '半';
} else {
result += `${_time_num2str(minute2)}分`;
}
}
if (second2.toString().replace(/^0+/, '') !== '') {
result += `${_time_num2str(second2)}秒`;
}
}
return result;
}
以上主要是對(duì)歸一化的簡(jiǎn)單介紹,也整理了一部分常用的規(guī)則。