面向深度學習的文字預處理方法

如今,深度學習引起了人們極大的興趣,尤其是自然語言處理(NLP)。不久前,Kaggle公司開展一場自然語言處理(NLP)競賽,其名稱為“Quora不真誠問題挑戰(Quora Question insincerity Challenge)”。這個競賽指出解決文字分類問題,其目的是透過競賽以及Kaggle專家提供的寶貴核心,使其變得更容易理解。

面向深度學習的文字預處理方法

首先從解釋競賽中的文字分類問題開始。

文字分類是自然語言處理中的一項常見任務,它將不確定長度的文字序列轉換為文字類別。那麼文字分類有什麼作用?可以:

瞭解評論時的情緒

在Facebook等平臺上查詢有害評論

在Quora上查詢不真誠的問題,而目前Kaggle公司正在進行的一項競賽

在網站上查詢虛假評論

確定文字廣告是否會被點選

現在,這些問題都有一些共同點。而從機器學習的角度來看,這些問題本質上是相同的,只是目標標籤發生了變化,並沒有其他的變化。話雖如此,業務知識的新增可以幫助使這些模型更加健壯,這就是在預處理資料以進行測試分類時想要包含的內容。

雖然本文關注的預處理管道主要圍繞深度學習,但其中大部分也適用於傳統的機器學習模型。

首先,在完成所有步驟之前,先了解一下文字資料深度學習管道的流程,以便更進一步瞭解整個過程。

通常從清理文字資料和執行基本 事件驅動架構(EDA)開始。在這裡,嘗試透過清理資料來提高資料質量。還嘗試透過刪除詞彙表外(OOV)的單詞來提高Word2Vec嵌入的質量。前兩個步驟之間通常沒有什麼順序,並且通常在這兩個步驟之間來回切換。

接下來,為可以輸入深度學習模型的文字建立一個表示。然後開始建立模型並訓練它們。最後,在此使用適當的指標評估模型,並獲得領導者的批准以部署模型。如果這些術語現在沒有多大意義,那麼不要擔心,可以嘗試透過本文闡述的過程來解釋它們。

在這裡,先談談單詞嵌入。在為深度學習模型預處理資料時,就必須考慮一下。

Word2Vec嵌入入門

現在需要有一種方法來表示詞彙中的單詞。一種方法是使用one-hot編碼的單詞向量,但這並不是一個很好的選擇。其一個主要原因是one-hot單詞向量無法準確表達不同單詞之間的相似度,例如餘弦相似度。

鑑於one-hot編碼向量的結構,不同單詞之間的相似度總是為0。另一個原因是,隨著詞彙量的增加,這些one-hot編碼向量變得非常大。

Word2Vec透過提供單詞的固定長度向量表示以及捕獲不同單詞之間的相似性和類比關係,克服了上述困難。

Word2vec單詞向量的學習方式允許學習不同的類比。它使人們能夠對以前不可能的單詞進行代數運算。例如:什麼是國王——男人+女人?出來是女王。

Word2Vec向量也幫助找出單詞之間的相似性。如果試圖找到與“good”相似的詞,會發現awesome、great等。正是word2vec的這一特性使其對於文字分類非常寶貴。現在的深度學習網路可以明白“good”和“great”本質上是含義相似的詞。

因此,簡單來說,word2vec為單詞建立向量。因此,對字典中的每個單詞都有一個d維向量。通常使用其他人在維基百科、推特等大型文字語料庫上訓練後提供的預訓練詞向量。最常用的預訓練詞向量是具有300維詞向量的Glove和Fasttext。而在這篇文章中將使用Glove。

文字資料的基本預處理技術

在大多數情況下,觀察到的文字資料並不完全乾淨。來自不同來源的資料具有不同的特徵,這使得文字預處理成為分類管道中最重要的步驟之一。

例如,來自Twitter的文字資料與Quora或某些新聞/部落格平臺上的文字資料完全不同,因此需要區別對待。有用的是,將在本文中討論的技術對於在自然語言處理(NLP)中可能遇到的任何型別的資料都足夠通用。

(1)清除特殊字元和刪除標點符號

預處理管道很大程度上取決於將用於分類任務的word2vec嵌入。原則上,預處理應該與訓練詞嵌入之前使用的預處理相匹配。由於大多數嵌入不提供標點符號和其他特殊字元的向量值,因此要做的第一件事就是去除文字資料中的特殊字元。這些是Quora不真誠問題資料中存在的一些特殊字元,使用替換功能來擺脫這些特殊字元。

#將看到的所有文字分類方法都會用到的一些預處理。

Python

1 puncts = [‘,’, ‘。’, ‘“’, ‘:’, ‘)’, ‘(’, ‘-’, ‘!’, ‘?’, ‘|’, ‘;’, ”‘“, ’$‘, ’&‘, ’/‘, ’[‘, ’]‘, ’>‘, ’%‘, ’=‘, ’#‘, ’*‘, ’+‘, ’\\‘, ’‘, ’~‘, ’@‘, ’‘, ’·‘, ’_‘, ’{‘, ’}‘, ’‘, ’^‘, ’‘, ’`‘, ’<‘, ’→‘, ’°‘, ’‘, ’‘, ’‘, ’‘, ’←‘, ’ב, ’§‘, ’″‘, ’′‘, ’ ‘, ’█‘, ’‘, ’à‘, ’…‘, ’“‘, ’★‘, ’”‘, ’–‘, ’●‘, ’‘, ’‘, ’‘, ’‘, ’‘, ’‘, ’‘, ’‘, ’↑‘, ’±‘, ’‘, ’‘, ’═‘, ’‘, ’║‘, ’―‘, ’‘, ’▓‘, ’—‘, ’‘, ’─‘, ’‘, ’:‘, ’‘, ’⊕‘, ’▼‘, ’‘, ’‘, ’■‘, ’’‘, ’‘, ’¨‘, ’▄‘, ’‘, ’☆‘, ’é‘, ’‘, ’‘, ’¤‘, ’▲‘, ’è‘, ’‘, ’‘, ’‘, ’‘, ’‘‘, ’∞‘, ’‘, ’)‘, ’↓‘, ’、‘, ’│‘, ’(‘, ’‘, ’,‘, ’‘, ’╩‘, ’╚‘, ’‘, ’‘, ’╦‘, ’╣‘, ’╔‘, ’╗‘, ’‘, ’‘, ’‘, ’‘, ’‘, ’≤‘, ’‘, ’√‘,

Python

1def clean_text(x): x = str(x) for punct in puncts: if punct in x: x = x。replace(punct, ’‘) return

這也可以在一個簡單的正則表示式的幫助下完成。但是人們通常喜歡上述做事方式,因為它有助於理解從資料中刪除的字元型別。

Python

1def clean_numbers(x): if bool(re。search(r’\d‘, x)): x = re。sub(’[0-9]{5,}‘, ’#####‘, x) x = re。sub(’[0-9]{4}‘, ’####‘, x) x = re。sub(’[0-9]{3}‘, ’###‘, x) x = re。sub(’[0-9]{2}‘, ’##‘, x) return x

(2)清除數字

為什麼要用#s替換數字?因為大多數嵌入都像這樣預處理了它們的文字。

Python小技巧:在下面的程式碼中使用if語句來預先檢查文字中是否存在數字。就像if總是比re。sub命令快,而且大部分文字都不包含數字。

Python

1 def clean_numbers(x): if bool(re。search(r’\d‘, x)): x = re。sub(’[0-9]{5,}‘, ’#####‘, x)

(3)刪除拼寫錯誤

找出資料中的拼寫錯誤總是有幫助的。由於word2vec中不存在這些詞的嵌入,應該用正確的拼寫替換單詞以獲得更好的嵌入覆蓋率。

以下程式碼工件是對Peter Norvig的拼寫檢查器的改編。它使用單詞的word2vec排序來近似單詞機率,因為谷歌word2vec顯然在訓練語料庫中按照頻率降序排列單詞。可以使用它來找出擁有的資料中的一些拼寫錯誤的單詞。

以下是來自Quora問題相似性挑戰中的CPMP指令碼。

Python

1 import re from collections import Counter import gensim import heapq from operator import itemgetter from multiprocessing import Pool 2model = gensim。models。KeyedVectors。load_word2vec_format(’。。/input/embeddings/GoogleNews-vectors-negative300/GoogleNews-vectors-negative300。bin‘, binary=True) words = model。index2word 3 w_rank = {} for i,word in enumerate(words): w_rank[word] = i 4 WORDS = w_rank 5 def words(text): return re。findall(r’\w+‘, text。lower()) 6 def P(word): ”Probability of `word`。“ # use inverse of rank as proxy # returns 0 if the word isn’t in the dictionary return - WORDS。get(word, 0) 7 def correction(word): ”Most probable spelling correction for word。“ return max(candidates(word), key=P) 8 def candidates(word): ”Generate possible spelling corrections for word。“ return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word]) 9 def known(words): ”The subset of `words` that appear in the dictionary of WORDS。“ return set(w for w in words if w in WORDS) 10 def edits1(word): ”All edits that are one edit away from `word`。“ letters = ‘abcdefghijklmnopqrstuvwxyz’ splits = [(word[:i], word[i:]) for i in range(len(word) + 1)] deletes = [L + R[1:] for L, R in splits if R] transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R)>1] replaces = [L + c + R[1:] for L, R in splits if R for c in letters] inserts = [L + c + R for L, R in splits for c in letters] return set(deletes + transposes + replaces + inserts) 11 def edits2(word): ”All edits that are two edits away from `word`。“ return (e2 for e1 in edits1(word) for e2 in edits1(e1)) 12 def build_vocab(texts): sentences = texts。apply(lambda x: x。split())。values vocab = {} for sentence in sentences: for word in sentence: try: vocab[word] += 1 except KeyError: vocab[word] = 1 return vocab 13 vocab = build_vocab(train。question_text) 14 top_90k_words = dict(heapq。nlargest(90000, vocab。items(), key=itemgetter(1))) 15 pool = Pool(4) corrected_words = pool。map(correction,list(top_90k_words。keys())) 16 for word,corrected_word in zip(top_90k_words,corrected_words): if word!=corrected_word: print

一旦完成了查詢拼寫錯誤的資料,接下來要做的就是使用拼寫錯誤對映和正則表示式函式來替換它們。

Python

1 mispell_dict = {‘colour’: ‘color’, ‘centre’: ‘center’, ‘favourite’: ‘favorite’, ‘travelling’: ‘traveling’, ‘counselling’: ‘counseling’, ‘theatre’: ‘theater’, ‘cancelled’: ‘canceled’, ‘labour’: ‘labor’, ‘organisation’: ‘organization’, ‘wwii’: ‘world war 2’, ‘citicise’: ‘criticize’, ‘youtu ’: ‘youtube ’, ‘Qoura’: ‘Quora’, ‘sallary’: ‘salary’, ‘Whta’: ‘What’, ‘narcisist’: ‘narcissist’, ‘howdo’: ‘how do’, ‘whatare’: ‘what are’, ‘howcan’: ‘how can’, ‘howmuch’: ‘how much’, ‘howmany’: ‘how many’, ‘whydo’: ‘why do’, ‘doI’: ‘do I’, ‘theBest’: ‘the best’, ‘howdoes’: ‘how does’, ‘mastrubation’: ‘masturbation’, ‘mastrubate’: ‘masturbate’, ”mastrubating“: ‘masturbating’, ‘pennis’: ‘penis’, ‘Etherium’: ‘Ethereum’, ‘narcissit’: ‘narcissist’, ‘bigdata’: ‘big data’, ‘2k17’: ‘2017’, ‘2k18’: ‘2018’, ‘qouta’: ‘quota’, ‘exboyfriend’: ‘ex boyfriend’, ‘airhostess’: ‘air hostess’, ”whst“: ‘what’, ‘watsapp’: ‘whatsapp’, ‘demonitisation’: ‘demonetization’, ‘demonitization’: ‘demonetization’, ‘demonetisation’: ‘demonetization’

Python

1def _get_mispell(mispell_dict): mispell_re = re。compile(‘(%s)’ % ‘|’。join(mispell_dict。keys())) return mispell_dict, mispell_re 2 mispellings, mispellings_re = _get_mispell(mispell_dict) def replace_typical_misspell(text): def replace(match): return mispellings[match。group(0)] return mispellings_re。sub(replace, text) 3 # Usage replace_typical_misspell(”Whta is demonitisation“)

(4)消除縮略語

縮略語是採用撇號書寫的單詞。縮略語的例子是“ain’t”或“aren’t”。因為想標準化文字,所以擴充套件這些縮略語是有意義的。下面使用壓縮對映和正則表示式函式完成這項工作。

Python

1 contraction_dict = {”ain‘t“: ”is not“, ”aren’t“: ”are not“,”can‘t“: ”cannot“, ”’cause“: ”because“, ”could‘ve“: ”could have“, ”couldn’t“: ”could not“, ”didn‘t“: ”did not“, ”doesn’t“: ”does not“, ”don‘t“: ”do not“, ”hadn’t“: ”had not“, ”hasn‘t“: ”has not“, ”haven’t“: ”have not“, ”he‘d“: ”he would“,”he’ll“: ”he will“, ”he‘s“: ”he is“, ”how’d“: ”how did“, ”how‘d’y“: ”how do you“, ”how‘ll“: ”how will“, ”how’s“: ”how is“, ”I‘d“: ”I would“, ”I’d‘ve“: ”I would have“, ”I’ll“: ”I will“, ”I‘ll’ve“: ”I will have“,”I‘m“: ”I am“, ”I’ve“: ”I have“, ”i‘d“: ”i would“, ”i’d‘ve“: ”i would have“, ”i’ll“: ”i will“, ”i‘ll’ve“: ”i will have“,”i‘m“: ”i am“, ”i’ve“: ”i have“, ”isn‘t“: ”is not“, ”it’d“: ”it would“, ”it‘d’ve“: ”it would have“, ”it‘ll“: ”it will“, ”it’ll‘ve“: ”it will have“,”it’s“: ”it is“, ”let‘s“: ”let us“, ”ma’am“: ”madam“, ”mayn‘t“: ”may not“, ”might’ve“: ”might have“,”mightn‘t“: ”might not“,”mightn’t‘ve“: ”might not have“, ”must’ve“: ”must have“, ”mustn‘t“: ”must not“, ”mustn’t‘ve“: ”must not have“, ”needn’t“: ”need not“, ”needn‘t’ve“: ”need not have“,”o‘clock“: ”of the clock“, ”oughtn’t“: ”ought not“, ”oughtn‘t’ve“: ”ought not have“, ”shan‘t“: ”shall not“, ”sha’n‘t“: ”shall not“, ”shan’t‘ve“: ”shall not have“, ”she’d“: ”she would“, ”she‘d’ve“: ”she would have“, ”she‘ll“: ”she will“, ”she’ll‘ve“: ”she will have“, ”she’s“: ”she is“, ”should‘ve“: ”should have“, ”shouldn’t“: ”should not“, ”shouldn‘t’ve“: ”should not have“, ”so‘ve“: ”so have“,”so’s“: ”so as“, ”this‘s“: ”this is“,”that’d“: ”that would“, ”that‘d’ve“: ”that would have“, ”that‘s“: ”that is“, ”there’d“: ”there would“, ”there‘d’ve“: ”there would have“, ”there‘s“: ”there is“, ”here’s“: ”here is“,”they‘d“: ”they would“, ”they’d‘ve“: ”they would have“, ”they’ll“: ”they will“, ”they‘ll’ve“: ”they will have“, ”they‘re“: ”they are“, ”they’ve“: ”they have“, ”to‘ve“: ”to have“, ”wasn’t“: ”was not“, ”we‘d“: ”we would“, ”we’d‘ve“: ”we would have“, ”we’ll“: ”we will“, ”we‘ll’ve“: ”we will have“, ”we‘re“: ”we are“, ”we’ve“: ”we have“, ”weren‘t“: ”were not“, ”what’ll“: ”what will“, ”what‘ll’ve“: ”what will have“, ”what‘re“: ”what are“, ”what’s“: ”what is“, ”what‘ve“: ”what have“, ”when’s“: ”when is“, ”when‘ve“: ”when have“, ”where’d“: ”where did“, ”where‘s“: ”where is“, ”where’ve“: ”where have“, ”who‘ll“: ”who will“, ”who’ll‘ve“: ”who will have“, ”who’s“: ”who is“, ”who‘ve“: ”who have“, ”why’s“: ”why is“, ”why‘ve“: ”why have“, ”will’ve“: ”will have“, ”won‘t“: ”will not“, ”won’t‘ve“: ”will not have“, ”would’ve“: ”would have“, ”wouldn‘t“: ”would not“, ”wouldn’t‘ve“: ”would not have“, ”y’all“: ”you all“, ”y‘all’d“: ”you all would“,”y‘all’d‘ve“: ”you all would have“,”y’all‘re“: ”you all are“,”y’all‘ve“: ”you all have“,”you’d“: ”you would“, ”you‘d’ve“: ”you would have“, ”you‘ll“: ”you will“, ”you’ll‘ve“: ”you will have“, ”you’re“: ”you are“, ”you‘ve“: ”you have“}

Python

1 def _get_contractions(contraction_dict): contraction_re = re。compile(’(%s)‘ % ’|‘。join(contraction_dict。keys())) return contraction_dict, contraction_re 2 contractions, contractions_re = _get_contractions(contraction_dict) 3 def replace_contractions(text): def replace(match): return contractions[match。group(0)] return contractions_re。sub(replace, text) 4 # Usage replace_contractions(”this’s a text with contraction“)

除了上述技術外,還有其他文字預處理技術,如詞幹提取、詞形還原和停用詞去除。由於這些技術不與深度學習NLP模型一起使用,在這裡不會討論它們。

表示:序列建立

使深度學習成為自然語言處理(NLP)的“go-to”選擇的原因之一是,實際上不必從文字資料中人工設計特徵。深度學習演算法將一系列文字作為輸入,像人類一樣學習文字結構。由於機器不能理解單詞,因此它們期望以數字形式提供資料。所以想將文字資料表示為一系列數字。

要了解這是如何完成的,需要對Keras Tokenizer功能有所瞭解。可以使用任何其他分詞器,但Keras分詞器是一種流行的選擇。

(1)標記器

簡單來說,標記器(tokenizer)是一個將句子拆分成單詞的實用函式。keras。preprocessing。text。Tokenizer將文字標記(拆分)為標記(單詞),同時僅保留文字語料庫中出現次數最多的單詞。

Python

1#Signature: Tokenizer(num_words=None, filters=‘!”#$%&()*+,-。/:;<=>?@[\\]^_`{|}~\t\n’, lower=True, split=‘ ’, char_level=False, oov_token=None, document_count=0, **kwargs)

num_words引數僅在文字中保留預先指定的單詞數。這很有幫助,因為不希望這個模型透過考慮很少出現的單詞而產生大量噪音。在現實世界的資料中,使用num_words引數留下的大多數單詞通常是拼寫錯誤的。在預設情況下,標記器還會過濾一些不需要的標記並將文字轉換為小寫。

一旦適合資料的標記器還會保留一個單詞索引(可以用來為單詞分配唯一編號的單詞字典),可以透過以下方式訪問它:

tokenizer。word_index

索引字典中的單詞按頻率排序。

所以使用標記器的整個程式碼如下:

Python

from keras。preprocessing。text import Tokenizer ## Tokenize the sentences tokenizer = Tokenizer(num_words=max_features) tokenizer。fit_on_texts(list(train_X)+list(test_X)) train_X = tokenizer。texts_to_sequences(train_X) test_X = tokenizer。texts_to_sequences(test_X)

其中train_X和test_X是語料庫中的文件列表。

(2)序列預處理

通常模型期望每個序列(每個訓練示例)具有相同的長度(相同數量的單詞/標記)。可以使用maxlen引數來控制它。

例如:

Python

train_X = pad_sequences(train_X, maxlen=maxlen) test_X = pad_sequences(test_X, maxlen=maxlen)

現在訓練資料包含一個數字列表。每個列表具有相同的長度。還有word_index,它是文字語料庫中出現次數最多的單詞的字典。

(3)嵌入富集

如上所述,將使用GLoVE Word2Vec嵌入來解釋富集。GLoVE預訓練向量在維基百科語料庫上進行訓練。

這意味著資料中可能出現的某些詞可能不會出現在嵌入中。那麼怎麼處理呢?先載入Glove Embeddings。

Python

1 def load_glove_index(): EMBEDDING_FILE = ‘。。/input/embeddings/glove。840B。300d/glove。840B。300d。txt’ def get_coefs(word,*arr): return word, np。asarray(arr, dtype=‘float32’)[:300] embeddings_index = dict(get_coefs(*o。split(“ ”)) for o in open(EMBEDDING_FILE)) return embeddings_index 2 glove_embedding_index = load_glove_index()

確保將下載這些GLoVE向量的資料夾的路徑。

這個glove_embedding_index包含什麼?它只是一個字典,其中鍵是詞,值是詞向量,而一個長度為300的np。array,其字典的長度大約是10億。由於只需要word_index中單詞的嵌入,將建立一個只包含所需嵌入的矩陣。

Python

1 def create_glove(word_index,embeddings_index): emb_mean,emb_std = -0。005838499,0。48782197 all_embs = np。stack(embeddings_index。values()) embed_size = all_embs。shape[1] nb_words = min(max_features, len(word_index)) embedding_matrix = np。random。normal(emb_mean, emb_std, (nb_words, embed_size)) count_found = nb_words for word, i in tqdm(word_index。items()): if i >= max_features: continue embedding_vector = embeddings_index。get(word) if embedding_vector is not None: embedding_matrix[i] = embedding_vector else: count_found-=1 print(“Got embedding for ”,count_found,“ words。”) return embedding_matrix

上面的程式碼工作正常,但有沒有一種方法可以讓利用GLoVE中的預處理來發揮優勢?

是的。在為glove進行預處理時,創作者沒有將單詞轉換為小寫。這意味著它包含“USA”、“usa”和“Usa”等單詞的多種變體。這也意味著在某些情況下,雖然存在像“Word”這樣的單詞,但不存在小寫形式的類似物,即“word”。

在這裡可以透過使用下面的程式碼來解決這種情況。

Python

1 def create_glove(word_index,embeddings_index): emb_mean,emb_std = -0。005838499,0。48782197 all_embs = np。stack(embeddings_index。values()) embed_size = all_embs。shape[1] nb_words = min(max_features, len(word_index)) embedding_matrix = np。random。normal(emb_mean, emb_std, (nb_words, embed_size)) count_found = nb_words for word, i in tqdm(word_index。items()): if i >= max_features: continue embedding_vector = embeddings_index。get(word) if embedding_vector is not None: embedding_matrix[i] = embedding_vector else: if word。islower(): # try to get the embedding of word in titlecase if lowercase is not present embedding_vector = embeddings_index。get(word。capitalize()) if embedding_vector is not None: embedding_matrix[i] = embedding_vector else: count_found-=1 else: count_found-=1 print(“Got embedding for ”,count_found,“ words。”) return embedding_matrix

上面只是一個例子,說明如何利用嵌入知識來獲得更好的覆蓋率。有時,根據問題的不同,人們還可以透過使用一些領域知識和自然語言處理(NLP)技能向嵌入中新增額外資訊來獲得價值。

例如,可以透過在Python中的TextBlob包中新增單詞的極性和主觀性,向嵌入本身新增外部知識。

Python

1 from textblob import TextBlob word_sent = TextBlob(“good”)。sentiment print(word_sent。polarity,word_sent。subjectivity) # 0。7 0。6

可以使用TextBlob獲取任何單詞的極性和主觀性。因此,可以嘗試將這些額外資訊新增到嵌入中。

Python

1 def create_glove(word_index,embeddings_index): emb_mean,emb_std = -0。005838499,0。48782197 all_embs = np。stack(embeddings_index。values()) embed_size = all_embs。shape[1] nb_words = min(max_features, len(word_index)) embedding_matrix = np。random。normal(emb_mean, emb_std, (nb_words, embed_size+4)) count_found = nb_words for word, i in tqdm(word_index。items()): if i >= max_features: continue embedding_vector = embeddings_index。get(word) word_sent = TextBlob(word)。sentiment # Extra information we are passing to our embeddings extra_embed = [word_sent。polarity,word_sent。subjectivity] if embedding_vector is not None: embedding_matrix[i] = np。append(embedding_vector,extra_embed) else: if word。islower(): embedding_vector = embeddings_index。get(word。capitalize()) if embedding_vector is not None: embedding_matrix[i] = np。append(embedding_vector,extra_embed) else: embedding_matrix[i,300:] = extra_embed count_found-=1 else: embedding_matrix[i,300:] = extra_embed count_found-=1 print(“Got embedding for ”,count_found,“ words。”) return embedding_matrix

工程嵌入是在後期從深度學習模型中獲得更好效能的重要組成部分。通常,會在專案階段多次重新訪問這部分程式碼,同時嘗試進一步改進的模型。在這裡可以展示很多創造力,以提高對word_index的覆蓋率,並在嵌入中包含額外的功能。

更多工程特性

嵌入矩陣的文字預處理方法

人們總是可以新增句子特定的特徵,如句子長度、唯一詞的數量等,作為另一個輸入層,為深度神經網路提供額外的資訊。

例如,建立了這些額外的特徵,作為Quora Insincerity分類挑戰的特徵工程管道的一部分。

Python

1 def add_features(df): df[‘question_text’] = df[‘question_text’]。progress_apply(lambda x:str(x)) df[“lower_question_text”] = df[“question_text”]。apply(lambda x: x。lower()) df[‘total_length’] = df[‘question_text’]。progress_apply(len) df[‘capitals’] = df[‘question_text’]。progress_apply(lambda comment: sum(1 for c in comment if c。isupper())) df[‘caps_vs_length’] = df。progress_apply(lambda row: float(row[‘capitals’])/float(row[‘total_length’]), axis=1) df[‘num_words’] = df。question_text。str。count(‘\S+’) df[‘num_unique_words’] = df[‘question_text’]。progress_apply(lambda comment: len(set(w for w in comment。split()))) df[‘words_vs_unique’] = df[‘num_unique_words’] / df[‘num_words’] return df

結論

自然語言處理(NLP)在深度學習領域仍然是一個非常有趣的問題,因此希望更多的人進行大量的實驗,看看哪些有效,哪些無效。而試圖為任何自然語言處理(NLP)問題的深度學習神經網路的預處理步驟可以提供有益的視角。