NLP中的預處理:使用python進行文本歸一化

2020-12-06 deephub

我們在有關詞幹的文章中討論了文本歸一化。 但是,詞幹並不是文本歸一化中最重要(甚至使用)的任務。 我們還進行了其他一些歸一化技術的研究,例如Tokenization,Sentencizing和Lemmatization。 但是,還有其他一些用於執行此重要預處理步驟的小方法,將在本文中進行討論。

請記住,沒有適用於所有情況的「正確」歸一化方法列表。 實際上,隨著我們對NLP的深入研究,越來越多的人意識到NLP並不像人們想像的那樣具有普遍性。 儘管有許多有趣的通用工具箱和預製管道,但更精確的系統是針對上下文量身定製的系統。

因此,不應將本文歸一化的步驟列表作為硬性規則,而應將其作為對某些文章進行文本歸一化的準則。 還必須指出的是,在極少數情況下,您可能不想歸一化輸入-文本中其中更多變化和錯誤很重要時(例如,考慮測試校正算法)。

了解我們的目標——為什麼我們需要文本歸一化

讓我們從歸一化技術的明確定義開始。 自然語言作為一種人力資源,傾向於遵循其創造者隨機性的內在本質。 這意味著,當我們「產生」自然語言時,我們會在其上加上隨機狀態。 計算機不太擅長處理隨機性(儘管使用機器學習算法已將隨機性的影響降到最低)。

當我們歸一化自然語言時,我們會嘗試減少其隨機性,使其更接近預定義的「標準」。 這有助於減少計算機必須處理的不同信息的數量,從而提高效率。

當我們歸一化自然語言資源時,我們嘗試減少其中的隨機性

在那篇關於詞幹的文章中,我提到了歸一化試圖使事物更接近「正態分布」。 在某種意義上說是正確的,當我們歸一化自然語言輸入時,我們希望以「良好」和「可預測」的形狀使事物「符合預期」,例如遵循正態分布。

除了數學領域之外,我們還可以討論將歸一化數據輸入到我們的NLP系統中的好處

首先,通過減少隨機性,我們減少了待處理的輸入變量,提高了總體性能並避免了誤報(想像一下,如果軟體日誌行中沒有錯字,就會觸發警告。 )。 對於系統和信息檢索任務來說,這是非常正確的(想像一下,如果Google的搜尋引擎僅與您鍵入的單詞完全匹配!)。

其次,尤其是在討論機器學習算法時,如果我們使用的是字詞袋或TF-IDF字典等簡單的舊結構,則歸一化會降低輸入的維數; 或降低載入數據所需的處理量。

第三,歸一化有助於在將輸入傳遞給我們的決策NLP算法之前對其進行處理。 在這種情況下,我們確保我們的輸入將在處理之前遵循「合同」。

最後,如果正確完成,歸一化對於從自然語言輸入中可靠地提取統計數據非常重要-就像在其他領域(例如時間序列分析)一樣,歸一化是NLP數據科學家/分析師/工程師手中重要的一步。

我們歸一化的對象是什麼?

這是一個重要的問題。 在進行文本歸一化時,我們應該確切地知道我們要標歸一什麼以及為什麼要歸一化。 另外,輸入數據的特點有助於確定我們將要用來歸一化輸入的步驟。 我們最感興趣的是兩件事:

句子結構:它總是以標點符號結尾嗎? 會出現重複的標點符號嗎? 我們是否應該刪除所有標點符號? 此外,可以使用更具體的結構(就像主謂賓結構),但很難實現。詞彙: 這是需要注意的核心內容之一。 大多數時候,我們希望我們的詞彙量儘可能小。 原因是,在NLP中,詞彙是我們的主要特徵,而當我們在這些詞彙中的變化較少時,我們可以更好地實現目標。實際上,我們可以通過分解成更簡單的問題來對這兩個方面進行歸一化。 以下是最常見的方法:

→刪除重複的空格和標點符號。

→去除口音(如果您的數據包含來自「外國」語言的變音符號-這有助於減少與編碼類型有關的錯誤)。

→去除大寫字母(通常,使用小寫單詞可獲得更好的結果。但是,在某些情況下,大寫字母對於提取信息(例如名稱和位置)非常重要)。

→刪除或替換特殊字符/表情符號(例如:刪除主題標籤)。

→替換單詞縮寫(英語中很常見;例如:「我」→「我是」)。

→將單詞數字轉換為阿拉伯數字(例如:「二十三」→「 23」)。

→為特殊符號替換(例如:「 $ 50」→「錢」)。

→縮寫標準化(例如:「 US」→「美國」 /「美國」,「 btw」→「順便說一下」)。

→標準化日期格式,社會保險號或其他具有標準格式的數據。

→拼寫糾正(可以說一個單詞可以用無限方式拼寫錯誤,因此拼寫糾正可以通過「更正」來減少詞彙變化)–如果您要處理推特,即時消息和電子郵件等開放用戶輸入的數據,這一點非常重要。

→通過詞幹去除性別/時間/等級差異。

→將稀有單詞替換為更常見的同義詞。

→停止定型化(比歸一化技術更常見的降維技術)。

在本文中,我將只討論其中一部分的實現。

如何做歸一化工作

要選擇我們將要使用的歸一化步驟,我們需要一項特定的任務。 對於本文,我們將假設我們要提取3000個#COVIDIOTS主題標籤的情緒集,以了解人們對COVID-19流行的看法。

我獲得了這些推文,並使用這個名為best-profanity的漂亮工具來審查不好的文字,如果需要,可以將其添加到規範化管道中。 他們也不包含撰寫內容的人。

但是,我並沒有繼續刪除每條推文中的姓名或檢查任何政治立場等,因為這不是本文的目的,並且可以單獨撰寫另一篇文章(關於自動審查)。

在這種情況下,我們要執行以下步驟:刪除重複的空白和標點符號; 縮寫替代; 拼寫更正。 另外,我們已經討論了定形化,下面我們使用它。

在完成代碼部分之後,我們將統計分析應用上述歸一化步驟的結果。

關於規範化的一件重要事情是函數的順序很重要。 我們可以說歸一化是NLP預處理管道中的管道。 如果我們不謹慎,則可能刪除對以後的步驟很重要的信息(例如在定形之前刪除停用詞)。

我們甚至可以將這些步驟分為兩個連續的組:「標記前步驟」(用於修改句子結構的步驟)和「標記後步驟」(僅用於修改單個標記的步驟),以避免重複標記步驟。 但是,為簡單起見,我們使用.split()函數。

將推文解析為字符串列表之後,就可以開始創建函數了。 順便說一句,我在列表周圍使用了一個名為tqdm的漂亮模塊,因此一旦應用歸一化過程,我們就會獲得漂亮的進度條。 以下是所需的導入:

from symspellpy.symspellpy import SymSpell, Verbosityimport pkg_resourcesimport re, string, jsonimport spacyfrom tqdm import tqdm#Or, for jupyter notebooks:#from tqdm.notebook import tqdm

刪除重複的空白和重複的標點符號(和網址):

這一步驟用簡單的正則表達式替換完成。 有改進的餘地,但是可以滿足我們的期望(這樣,我們就不會有多種尺寸的標度和感嘆號標記)。 我們刪除網址,因為這會減少很多我們擁有的不同令牌的數量(我們首先這樣做,因為標點替換可能會阻止它)。

def simplify_punctuation_and_whitespace(sentence_list):norm_sents = [] print("Normalizing whitespaces and punctuation") for sentence in tqdm(sentence_list): sent = _replace_urls(sentence) sent = _simplify_punctuation(sentence) sent = _normalize_whitespace(sent) norm_sents.append(sent) return norm_sentsdef _replace_urls(text): url_regex = r'(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})' text = re.sub(url_regex, "<URL>", text) return textdef _simplify_punctuation(text): """ This function simplifies doubled or more complex punctuation. The exception is '...'. """ corrected = str(text) corrected = re.sub(r'([!?,;])\1+', r'\1', corrected) corrected = re.sub(r'\.{2,}', r'...', corrected) return correcteddef _normalize_whitespace(text): """ This function normalizes whitespaces, removing duplicates. """ corrected = str(text) corrected = re.sub(r"//t",r"\t", corrected) corrected = re.sub(r"( )\1+",r"\1", corrected) corrected = re.sub(r"(\n)\1+",r"\1", corrected) corrected = re.sub(r"(\r)\1+",r"\1", corrected) corrected = re.sub(r"(\t)\1+",r"\1", corrected) return corrected.strip(" ")

縮寫替換

def normalize_contractions(sentence_list):contraction_list = json.loads(open('english_contractions.json', 'r').read()) norm_sents = [] print("Normalizing contractions") for sentence in tqdm(sentence_list): norm_sents.append(_normalize_contractions_text(sentence, contraction_list)) return norm_sentsdef _normalize_contractions_text(text, contractions): """ This function normalizes english contractions. """ new_token_list = [] token_list = text.split() for word_pos in range(len(token_list)): word = token_list[word_pos] first_upper = False if word[0].isupper(): first_upper = True if word.lower() in contractions: replacement = contractions[word.lower()] if first_upper: replacement = replacement[0].upper()+replacement[1:] replacement_tokens = replacement.split() if len(replacement_tokens)>1: new_token_list.append(replacement_tokens[0]) new_token_list.append(replacement_tokens[1]) else: new_token_list.append(replacement_tokens[0]) else: new_token_list.append(word) sentence = " ".join(new_token_list).strip(" ") return sentence

拼寫矯正

現在,這是一個棘手的問題。 它可能會引起一些不需要的更改(大多數可糾正拼寫的詞典缺少重要的上下文單詞,因此他們將它們視為拼寫錯誤)。 因此,您必須有意識地使用它。 有很多方法可以做到這一點。 我選擇使用名為symspellpy的模塊,該模塊的速度非常快(這很重要!),並且可以很好地完成這項工作。 做到這一點的另一種方法是,訓練一個深度學習模型來基於上下文進行拼寫校正,但這完全是另一回事了。

def spell_correction(sentence_list):max_edit_distance_dictionary= 3 prefix_length = 4 spellchecker = SymSpell(max_edit_distance_dictionary, prefix_length) dictionary_path = pkg_resources.resource_filename( "symspellpy", "frequency_dictionary_en_82_765.txt") bigram_path = pkg_resources.resource_filename( "symspellpy", "frequency_bigramdictionary_en_243_342.txt") spellchecker.load_dictionary(dictionary_path, term_index=0, count_index=1) spellchecker.load_bigram_dictionary(dictionary_path, term_index=0, count_index=2) norm_sents = [] print("Spell correcting") for sentence in tqdm(sentence_list): norm_sents.append(_spell_correction_text(sentence, spellchecker)) return norm_sentsdef _spell_correction_text(text, spellchecker): """ This function does very simple spell correction normalization using pyspellchecker module. It works over a tokenized sentence and only the token representations are changed. """ if len(text) < 1: return "" #Spell checker config max_edit_distance_lookup = 2 suggestion_verbosity = Verbosity.TOP # TOP, CLOSEST, ALL #End of Spell checker config token_list = text.split() for word_pos in range(len(token_list)): word = token_list[word_pos] if word is None: token_list[word_pos] = "" continue if not '\n' in word and word not in string.punctuation and not is_numeric(word) and not (word.lower() in spellchecker.words.keys()): suggestions = spellchecker.lookup(word.lower(), suggestion_verbosity, max_edit_distance_lookup) #Checks first uppercase to conserve the case. upperfirst = word[0].isupper() #Checks for correction suggestions. if len(suggestions) > 0: correction = suggestions[0].term replacement = correction #We call our _reduce_exaggerations function if no suggestion is found. Maybe there are repeated chars. else: replacement = _reduce_exaggerations(word) #Takes the case back to the word. if upperfirst: replacement = replacement[0].upper()+replacement[1:] word = replacement token_list[word_pos] = word return " ".join(token_list).strip()def _reduce_exaggerations(text): """ Auxiliary function to help with exxagerated words. Examples: woooooords -> words yaaaaaaaaaaaaaaay -> yay """ correction = str(text) #TODO work on complexity reduction. return re.sub(r'([\w])\1+', r'\1', correction)def is_numeric(text): for char in text: if not (char in "0123456789" or char in ",%.$"): return False return True

合理化

如果您一直關注我的系列文章,那麼您已經知道我已經實現了自己的lemmatizer。 但是,為了簡單起見,我選擇在這裡使用傳統方法。 它快速而直接,但是您可以使用任何其他所需的工具。 我還決定刪除(替換)所有標籤。 對於情感分析,我們並不是真的需要它們。

def lemmatize(sentence_list): nlp = spacy.load('en') new_norm=[] print("Lemmatizing Sentences") for sentence in tqdm(sentence_list): new_norm.append(_lemmatize_text(sentence, nlp).strip()) return new_norm def _lemmatize_text(sentence, nlp): sent = "" doc = nlp(sentence) for token in doc: if '@' in token.text: sent+=" @MENTION" elif '#' in token.text: sent+= " #HASHTAG" else: sent+=" "+token.lemma_ return sent

最後,我們將所有步驟加入「pipeline」函數中:

def normalization_pipeline(sentences): print("##############################") print("Starting Normalization Process") sentences = simplify_punctuation_and_whitespace(sentences) sentences = normalize_contractions(sentences) sentences = spell_correction(sentences) sentences = lemmatize(sentences) print("Normalization Process Finished") print("##############################") return sentences

結果

您可能想知道:應用這些任務的結果是什麼? 我已經運行了一些計數功能並繪製了一些圖表來幫助解釋,但我必須清楚一件事:數字表示不是表達文本歸一化重要性的最佳方法。

相反,當將文本規範化應用於NLP應用程式時,它可以通過提高效率,準確性和其他相關分數來發揮最佳作用。 我將指出一些可以從統計數據中清楚看到的好處。

首先,我們可以清楚地看到不同令牌總數的減少。 在這種情況下,我們將令牌數量減少了約32%。

Distinct words in unnormalized: 15233–80% of the text correspond to 4053 distinct words. Distinct words in normalized: 10437–80% of the text correspond to 1251 distinct words.

現在,通用令牌的數量出現了更大的差異。 這些令牌包括了所有數據的大約80%。 通常,我們通過大約10–20%的令牌範圍構成了文本的80%。

通過應用歸一化,我們將最常見的令牌數量減少了69%! 非常多! 這也意味著我們對此數據的任何機器學習技術都將能夠更好地推廣。

現在,關於文本歸一化的一件重要的事是,為了使文本規範化有用,它必須保留默認的自然語言結構。 我們可以通過數據本身看到這一點。 一個例子是,如果做得好,歸一化後的句子將不會變得越來越小。

在下面的直方圖中顯示了這一點,它表明,儘管歸一化後我們的1尺寸句子較少,而2尺寸句子較多,但其餘分布遵循未歸一化數據的結構(請注意,我們的曲線稍微接近正態分布曲線)。

另一個有助於我們可視化的工具是Boxplot。 它顯示了我們的數據如何分布,包括均值,四分位數和離群值。 總而言之,我們希望我們的中線與未規範化數據的中線相同(或接近)。 我們還希望框(大多數數據的分布)保持在相似的位置。 如果我們能夠增加數據量的大小,這意味著我們在中位數周圍的數據比歸一化之前要多(這很好)。 此外,我們要減少離群值。

結論

我希望在本文中能夠解釋什麼是文本歸一化,為什麼要這樣做以及如何做。

作者:Tiago Duque

deephub翻譯組:孟翔傑

相關焦點

  • 基於Bert和通用句子編碼的Spark-NLP文本分類
    文本分類問題中使用了幾個基準數據集,可以在nlpprogress.com上跟蹤最新的基準。以下是關於這些數據集的基本統計數據。簡單的文本分類應用程式通常遵循以下步驟:文本預處理和清理特徵工程(手動從文本創建特徵)特徵向量化(TfIDF、頻數、編碼)或嵌入(word2vec、doc2vec、Bert、Elmo、句子嵌入等)用ML和DL算法訓練模型。
  • 數值數據的特徵預處理
    : float64為了有效地使用該特徵,我們需要使用以下任何一種方法對該特徵進行預處理。特徵縮放(歸一化)特徵縮放是一種對數據的自變量或特徵範圍進行歸一化的方法。它通常被稱為標準化。與基於樹的模型相比,特徵縮放對非樹模型的影響更大。因此,如果你想使用非基於樹的模型獲得良好的結果,你應該考慮規範化你的數值特徵。有不同的方法來歸一化特徵。
  • 實用Python文本預處理代碼
    本文將討論文本預處理的基本步驟,旨在將文本信息從人類語言轉換為機器可讀格式以便用於後續處理。此外,本文還將進一步討論文本預處理過程所需要的工具。  當拿到一個文本後,首先從文本正則化 (text normalization) 處理開始。
  • 使用PyTorch建立你的第一個文本分類模型
    在本文中,我們將使用PyTorch,它以其快速的計算能力而聞名。因此,在本文中,我們將介紹解決文本分類問題的關鍵點。然後我們將在PyTorch中實現第一個文本分類器!目錄為什麼使用PyTorch進行文本分類? 處理詞彙表外單詞 處理可變長度序列 包裝器和預訓練模型理解問題實現文本分類為什麼使用PyTorch進行文本分類?
  • 入門NLP 項目前,你必須掌握哪些理論知識?
    命名實體識別在大多數應用中,並不需要執行以上所有的預處理步驟。是否需要進行命名實體識別取決於應用的具體業務需求,而詞性標註工作則通常由現代工具自動完成,從而改進歸一化和分詞步驟的某些部分。句子分割預處理工作流程的第一步是將文本分割成多個句子。
  • NLP入門+實戰必讀:一文教會你最常見的10種自然語言處理技術
    程序實現:這裡給出了在python的stemming庫中使用(https://bitbucket.org/mchaput/stemming/src/5c242aa592a6d4f0e9a0b2e1afdca4fd757b8e8a/stemming/porter2.py?
  • NLP之文本分類:「Tf-Idf、Word2Vec和BERT」三種模型比較
    NLP常用於文本數據的分類。文本分類是指根據文本數據內容對其進行分類的問題。我們有多種技術從原始文本數據中提取信息,並用它來訓練分類模型。本教程比較了傳統的詞袋法(與簡單的機器學習算法一起使用)、流行的詞嵌入模型(與深度學習神經網絡一起使用)和最先進的語言模型(和基於attention的transformers模型中的遷移學習一起使用),語言模型徹底改變了NLP的格局。
  • 知識圖譜——用Python代碼從文本中挖掘信息的強大數據科學技術
    圖源:Unsplash攝影:Clem Onojeghuo概覽知識圖譜是數據科學中最吸引人的概念之一學習如何使用Wikipedia頁面中的文本構建知識圖譜在Python中使用流行的spaCy庫在Python中構建知識圖譜
  • 使用一行Python代碼從圖像讀取文本
    但在這裡,情況正好相反——對你來說很瑣碎的任務,比如識別圖像中的貓或狗,對電腦來說真的很難。在某種程度上,我們是天造地設的一對。至少現在是這樣。雖然圖像分類和涉及到一定程度計算機視覺的任務可能需要大量的代碼和紮實的理解,但是從格式良好的圖像中讀取文本在Python中卻是簡單的,並且可以應用於許多現實生活中的問題。
  • 乾貨| 請收下這份2018學習清單:150個最好的機器學習,NLP和Python...
    /courses/NAACL2013/NAACL2013-Socher-Manning-DeepLearning.pdf理解卷積神經網絡在NLP中的應用(wildml.com)http://www.wildml.com/2015/11/understanding-convolutional-neural-networks-for-nlp/
  • ...請收下這份2018學習清單:150個最好的機器學習,NLP和Python教程
    /courses/NAACL2013/NAACL2013-Socher-Manning-DeepLearning.pdf理解卷積神經網絡在NLP中的應用(wildml.com)http://www.wildml.com/2015/11/understanding-convolutional-neural-networks-for-nlp
  • opencv-python圖像預處理-濾波
    為了消除外界環境對圖像採集的幹擾,增強圖像的邊緣及灰度跳變的部分,使圖像變得清晰以及提高圖像處理速度需要對圖像進行預處理操作,主要是對圖像進行濾波和增強操作。使用的方法可以分為空間域處理和頻率域處理兩類。空間域指圖像平面本身,這類圖像處理方法用各種模板直接與圖像進行卷積運算,實現對圖像的處理。
  • 乾貨 | 請收下這份2018學習清單:150個最好的機器學習,NLP和Python教程
    /courses/NAACL2013/NAACL2013-Socher-Manning-DeepLearning.pdf 理解卷積神經網絡在NLP中的應用(wildml.com)http://www.wildml.com/2015/11/understanding-convolutional-neural-networks-for-nlp/
  • 想快速入門NLP?我們測評了15門最火課程,幫你找到最適合的
    Edx-Natural Language Processing Course課程連結:http://www.edx.org/course/natural-language-processing-nlp-2授課方:微軟專業評分:7/10我的建議:這門課程介紹了機器學習和NLP領域中可使用的各種方法,你不光能學到經典算法
  • 斯坦福發布重磅NLP工具包StanfordNLP,支持中文等53種語言
    除了從CoreNLP繼承的功能外,StanfordNLP還包含將一串文本轉換成句子和單詞列表,生成這些單詞的基本形式、它們的詞類和形態學特徵的工具,以及超過70種語言的句法結構。這個軟體包採用高準確性的神經網絡組件構建,這些組件支持用戶使用自己的注釋數據進行高效的訓練和評估。
  • 「Python爬蟲與文本實例技術與應用」培訓班通知
    通過爬蟲獲取的海量信息,我們可以對其進行進一步的分析:市場預測、文本分析、機器學習方法等。     Python作為一門腳本語言,它靈活、易用、易學、適用場景多,實現程序快捷便利,早已經成為程式設計師們的一門編程利器。Python這門程式語言包羅萬象,可以說掌握了python,除了一些特殊環境和高度的性能要求,你可以用它做任何事。
  • Cython 助力 Python NLP 實現百倍加速
    在這篇博客中,他介紹了如何利用 Cython 和 spaCy 讓 Python 在自然語言處理任務中獲得百倍加速。雷鋒網 AI 研習社根據原文進行了編譯。以下給出了一些可能需要採用這種加速策略的場景:你正在使用 Python 給自然語言處理任務開發一個應用級模塊你正在使用 Python 分析一個自然語言處理任務的大型數據集你正在為諸如 PyTorch/TensoFlow 這些深度學習框架預處理大型訓練集,或者你的深度學習模型採用了處理邏輯複雜的批量加載器(Batch loader),它嚴重拖慢了你的訓練速度
  • NLP 新手必看!這是一份覆蓋全面的基於 PyTorch 和 keras 的 NLP...
    項目的 GitHub 地址為:https://github.com/lyeoni/nlp-tutorial。這是一個教你逐步實現和適應簡單的實詞 NLP 任務的教程:項目裡面有 4 個資源:神經機器翻譯、問答匹配、新聞分類和電影分級。這些資源都提供了源碼,對初學者來說,極為友好。初學者可以學會建立自己的模型。
  • NLP三大特徵提取器全梳理:RNN vs CNN vs Transformer
    原創 Synced 機器之心機器之心原創編輯:陳萍在進行 NLP 模型訓練前,請先選擇一個好的特徵提取器。在中我們介紹了自然語言處理的基礎問題——文本預處理的常用步驟。
  • Python視頻教程網課編程零基礎入門數據分析網絡爬蟲全套Python...
    (6套課程) 注:零基礎全能篇中,針對windows和liunx系統均有兩套課程可供選擇學習,單純學python,哪個系統都一樣,初學者只需選擇自己熟悉的系統學習相應課程即可。 因篇幅有限,以下展示的只是課程裡部分內容如對python課程有更多疑問 請諮詢客服 1零基礎入門全能班 01 –python簡介 02 第一個程序 03-python執行方式和pycharm設置 04-程序的注釋和算術運算符 05 程序執行原理 06變量的使用以及類型 07