文本處理
在現有數據中,文本是最非結構化的形式,裏面有各種各樣的噪聲;如果沒有預處理,文本數據都不能分析。清理和標準化文本的整個過程叫做文本預處理(text preprocessing)其作用是使文本數據沒有噪聲並且可以分析。
具體包含以下三個內容:去噪聲;詞彙歸一化;目標標準化
去噪聲
噪聲是指和需要的輸出沒有關係的文本。例如:語言的停用詞(is,am, the, of等),URLs, 鏈接,社交媒體實體,標點符合和行業特定詞。這一步主要是移除文本中的噪聲因子。
noise_list=['is','a','this','...']
def _remove_noise(input_text):
words = input_text.split()
noise_free_words=[word for word in words if word not in noise_list]
noise_free_text = " ".join(noise_free_words)
return noise_free_text
_remove_noise("this is a sample text")
>>> "sample text"
歸一化
文本噪聲的另一種類型是關於單個單詞所表現的多個表示。
例如:“play”,“player”,“played",“plays” 和 ”playing"是“play"的多種表示形式。雖然他們的含義不一樣,但是上下文中是相似的。這一步就是要把這些各種形式的單詞歸一化。歸一化是具有文本特徵工程的關鍵步驟,因爲它將高緯特徵(N個不同特徵)轉化成低維空間(1特徵)。
最常用的歸一化方法是:
1、詞幹(Steamming):詞幹是消除後綴的一個基本的基於規則的過程,比如 “ing”, “ly”, “es”等。
2、詞元化(Lemmatization): 詞元化是一個有組織性的,逐步地獲得詞根的過程,他利用詞彙(單詞的詞典重要性)和詞法分析(詞法結構和詞法關係)。
from nltk.stem.wordnet import WordNetLemmatizer
lem = WordNetLemmatizer()
from nltk.stem.porter import PorterStemmer
stem = PorterStemmer()
word = "multiplying"
lem.lemmatize(word, 'v')
>>> "multiply"
stem.stem(word)
>>>"multipli"
標準化
文本數據通常包含不存在於任何標準詞彙詞典中的詞或者短語。這些片段不被搜索引擎和模型所識別。
lookup_dict = {'rt':'Retweet','dm':'direct message','awsm':'awesome','luv':'love','...'}
def _look_words(input_text):
words = input_text.split()
new_words = []
for word in words:
if word.lower() in lookup_dict:
word = lookup_dict[word.lower()]
new_words.append(word)
new_text = " ".join(new_words)
return new_text
_lookup_words("RT this is a retweeted tweet by me")
>>>> "Retweet this is a tetweeted tweet by me"
特徵工程
數據經過預處理以後,需要轉化成可用的特徵,文本特徵可用句法分析,實體N-gram, 基於單詞的特徵, 統計特徵和單詞嵌入等方法來構造。
句法分析
句法分析包括語法分析和句子排序中單詞的分析,他們顯示單詞之間的關係。依存語法和詞性標註是文本句法的重要屬性。
依賴樹:句子是由縫在一起的單詞組成。句子中的詞之間的關係是由基本依存語法決定的 。依存語法是一類句法分析,涉及兩個詞 之間的非對稱二元關係。每一個關係都可以用三元組的形式來表示(主語,謂語和賓語)。
詞性標註:除了語法關係外,句子中的 每個詞也與詞性(名詞,動詞,形容詞,副詞等)相關。詞性定義了句子中單詞的用法和功能。
from nltk import word_tokenize, pos_tag
text = "I am learning Natural Language Processing on Analytic Vidhya"
tokens = word_tokenize(text)
print pos_tag(tokens)
>>>[('I','PRP'),('am','VBP'),('learning','VBG'),('Natural','NNP'),('Language',"NNP"),......]
N-gram
基於 N-Gram 的方法是把文章序列,通過大小爲 N 的窗口,形成一個個 Group。然後對這些 Group 做統計,濾除出現頻次較低的 Group,再把這些 Group 組成特徵空間,傳入分類器,進行分類。
def generate_ngrams(text,n):
words = text.split()
output = []
for i in range(len(word)-n +1):
output.append(word[i:i+n])
return output
generate_ngrams("this is a sample text",2)
>>>>[['this','is'],['is','a'],['a','sample'],['sample','text']]
頻次法
記錄每篇文章的次數分佈,然後將分佈輸入機器學習模型,訓練一個合適的分類模型。對這類數據進行分類,需要指出的是:在統計次數分佈時,可合理提出假設,頻次比較小的詞對文章分類的影響比較小。因此,我們可合理地假設閾值,濾除頻次小於閾值的詞,減少特徵空間維度。
TF-IDF
TF-IDF是一種常用的信息檢索問題的加權模型。它的目的是將文本文檔轉化成向量模型,而不是考慮文檔中單詞出現的次數。
from sklearn.feature_extraction.text import TfidfVectorizer
obj = TfidfVectorizer()
corpus = ['This is sample document', 'another random document', 'third sample document text']
X = obj.fit_transform(corpus)
>>>>
(0,1) 0.345
(0,4) ...0.4444
該模型創建詞彙字典併爲每個單詞分配索引。輸出中的每一行包含元組(i, j)和文檔i中索引j的單詞的tf-idf值。
詞嵌入
基於神經網絡的分佈表示又稱爲詞向量、詞嵌入,神經網絡詞向量模型與其它分佈表示方法一樣,均基於分佈假說,核心依然是上下文的表示以及上下文與目標詞之間的關係的建模。
one-hot表示法具有維度過大的缺點,那麼現在將vector做一些改進:
1、將vector每一個元素由整形改爲浮點型,變爲整個實數範圍的表示;
2、將原來稀疏的巨大維度壓縮嵌入到一個更小維度的空間。
Word2Vec 和 GloVe 是兩種比較流行的文本嵌入模型,這些模型以文本語料庫作爲輸入,併產生詞向量作爲輸出。
實現Word2Vec有兩種方式:連續詞袋模型(CBOW)和Skip-Gram
from gensim.models import Word2Vec
sentences = [['data','science'],['vidhya','science','data','analytics'],['machine','learning'],['deep','learning']]
#在詞庫中訓練模型
model = Word2Vec(sentences, min_count = 1)
print(model.similarity('data','science'))
>>>0.1122
print(model['learning'])
>>> array([0.0034,0.00305,......])
他們可以被用作ML模型的特徵向量,用於使用餘弦相似性技術,詞聚類和文本分類技術測試文本相似度。
Word embedding的訓練方法大致可以分爲兩類:一類是無監督或弱監督的預訓練;一類是端對端(end to end)的有監督訓練。無監督或弱監督的預訓練以word2vec和auto-encoder爲代表。這一類模型的特點是,不需要大量的人工標記樣本就可以得到質量還不錯的embedding向量。不過因爲缺少了任務導向,可能和我們要解決的問題還有一定的距離。因此,我們往往會在得到預訓練的embedding向量後,用少量人工標註的樣本去fine-tune整個模型。
相比之下,端對端的有監督模型在最近幾年裏越來越受到人們的關注。與無監督模型相比,端對端的模型在結構上往往更加複雜。同時,也因爲有着明確的任務導向,端對端模型學習到的embedding向量也往往更加準確。例如,通過一個embedding層和若干個卷積層連接而成的深度神經網絡以實現對句子的情感分類,可以學習到語義更豐富的詞向量表達。
參考:https://blog.csdn.net/hxcaifly/article/details/80795484