NLP是数据科学领域的一个重要的分支,它包含了以一种高效的方式去分析,理解和从文本里提取信息等重要过程。通过利用NLP及其组件,可以组织大量的文本数据,执行大量的自动化任务,并解决各种问题,比如自动摘要,机器翻译,命名实体识别,关系提取,情感分析,语音识别和主题分割等。
在这之前我需要先讲解下一些将会在文章出现的专业术语:
安装NLTK的过程:
安装Pip:
sudo easy_install pip
安装NLTK:
sudo pip install -U nltk
下载NLTK数据:
import nltk
nltk.download()
由于文本是所有数据中最非结构化的形式,所以存在各种类型的噪音,并且在不进行任何预处理的情况下,不容易分析。清洁和标准化文本,使其无噪声和准备分析的过程称为文本预处理。
这个过程主要由以下三步组成:
只要是和输出没有关系的文本都可以看做噪声。
例如:语言的停用词(is,am, the, of等),URLs, 链接,社交媒体实体,标点符合和行业特定词。这一步主要是移除文本中的噪声因子。
噪声去除的一般方法是编写嘈杂实体的字典,并通过迭代文本对象消除噪声字典中存在的标记。
下面代码python实现的方式:
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"
另一种方式是在使用特殊噪声模式时使用正则表达式。我们在前面的一篇文章中详细解释了正则表达式。下面python代码从输入文本中移除正则表达式模式:
def _remove_regex(input_text, regrex_pattern):
urls=re.finditer(regex_pattern, input_text)
for i in urls:
input_text = re.sub(i.group().strip,'', input_text)
return input_text
regrex_pattern = "#[\w]*"
_remove_regex("remove this #hashtag from analytic vidhya", regrex_pattern)
>>>>"remove this from analytic vidhya"
文本噪声的另一种类型是关于单个单词所表现的多个表示。
例如:“play”,“player”,“played",“plays” 和 ”playing"是“play"的多种表示形式。虽然他们的含义不一样,但是上下文中是相似的。这一步就是要把这些各种形式的单词归一化。归一化是具有文本特征工程的关键步骤,因为它将高纬特征(N个不同特征)转化成低维空间(1特征),这是任何ML模型的理想要求。
最常用的归一化方法是:
下面就是利用NLTK包的词干提取和词元化的python代码:
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"
文本数据通常包含不存在于任何标准词汇词典中的词或者短语。这些片段不被搜索引擎和模型所识别 。
一些例子是,首字母缩略词,带有附加词的标签和口语哩语。在 正则 表达式和手工编写的数据字典的帮助下,这种类型的噪声可以被固定。下面的代码使用字典查找方法来替代文中的 社交媒体哩语。
look_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"
从目前为止讨论的三个步骤来看,其他类型的文本预处理包括编码解码噪声,语法检查器和拼写校正等。可以参考:https://www.analyticsvidhya.com/2014/11/text-data-cleaning-steps-python.
为了分析预处理的数据,需要将其转化为特征,根据使用情况,文本特征可以使用分类技术(句法分析,实体n-gram, 基于单词的特征, 统计特征和单词嵌入)来构造。继续阅读来详细了解这些技术。
句法分析包括语法分析和句子排序中单词的分析,他们显示单词之间的关系。依存语法和词性标注是文本句法 的 重要属性。
依赖树:句子是由缝在一起的单词组成。句子中的词之间的关系是由基本依存语法决定的 。依存语法是一类句法分析,涉及两个词 之间的非对称二元关系。每一个关系都可以用三元组的形式来表示(主语,谓语和宾语)。考虑这句英文:“Bills on ports and immigration were submitted by Senator Brownback, Republican of Kansas"。依赖树略:
树显示出“submitted" 是整个句子的根,被两棵子树连着(主语和宾语)。每一棵子树又可以看成一棵单独的依赖树。
这种类型的数,当以自定向下的方式递归解析时,给出了语法关系三元组作为输出,它可以被用作许多NLP问题的特征,比如实体智能分析,参与者和实体识别以及文本分类。Python的StanFordCoreNLP和NLTK依赖文法可以用来生成依赖树。
词性标注:除了语法关系外,句子中的 每个词也与词性(名词,动词,形容词,副词等)相关。词性定义了句子中单词的用法和功能。这是宾夕法尼亚大学定义的所有可能的词性列表。下面的代码使用NLTK对输入文本执行词性标注(它提供了几种事项方式,默认的感知器标注)。
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"),......]
词性标注应用于NLP的几个重要目的如下:
A.词义消歧:有些单词根据用法有多种含义,比如:看下面的两个句子:
'book’是在不同语境中使用的,很明显这两种情况下的词性不一样。在句子1中,‘book’是动词,在句子2中,’book’是名词。
B.改进词性特征:一个学习模型可以在使用词作为特征时学习单词的不同上下文,但是如果词性标记与他们相连,那么语境就被保留,从而产生更强烈的特征,例如:
句子:book my flight, I will read this book.
一般的标记:(‘book’,1), (‘my’,1),(‘flight’,1),(‘I’,1),(‘will’,1),(‘read’,1),(‘this’,1)
带有词性的标记:(’book_VB’,1),(‘my_PRP’,1),(“flight_NN”,1),(“I_PRP”,1),(“will_MD”,1),(“read_VB”,1),(“this_DT”,1),(‘book_NN’,1)
C.归一化和词元化:词性标注是把单词归一化和词元化的基础。
D. 有效地停用词移除:词性标准在停用词移除过程中有非常有效的作用。
实体被定义为句子中最重要的块–名词短语,动词短语或者两则。实体检测算法一般是基于规则的句法分析,字典查找,词性标注和依存句法分析的集成模型。实体检测一般在在自动聊天机器人,内容分析器和消费者洞察中看到。
主题建模和命名实体识别是NLP中的两个关键实体检测方法。
A.命名实体识别(NER)
从文本中检测命名实体,比如:人名,位置名称和公司名称等过程称为NER。
名词短语识别:这一步涉及使用依赖句法分析和词性标注提取文本中所有的名词短语。
短语分类:这是所有提取的名词短语分类为各自的类别(位置,名称等)的分类步骤。谷歌地图API提供可一个消歧位置的好方法。然后,维基百科的开房数据库可以用来识别人名或者公司名称。除此之外,还可以通过结合来自不同来源的信息来查找表和字典。
实体消歧:有时,可能实体分类会错误。因此在结果的顶部创建一个验证层是很有必要的。可以利用知识图谱来达到这个目的,流行的知识图谱有谷歌知识图,IBM Watson等。
B. 主题建模
主题建模是一种自动识别语料库中的主题的过程,它通过无监督的方式导出语料库中的单词之间的隐藏模式。主题被定义为“语料库中共同出现的术语的重复模式”。
LDA是最流行的主题建模技术。下面是python代码使用LDA实现主题建模的代码:
doc1 = "sugar is bad to consume. My sister likes to have sugar, but not my father"
doc2 = "My father spends a lot of time driving my sister around to dance practice"
doc3 = "Doctors suggest that driving many cause increased stress and blood pressure"
doc_complete = [doc1, doc2, doc3]
doc_clean = [doc.split() for doc in doc_complete]
import gensim from gensim
import corpora
#创建我们词料库的术语词典,其中每个唯一的术语被分配索引。
dictionary = corpora.Dictionary(doc_clean)
#利用上述词典将文档列表转化成文档项矩阵
doc_term_matrix = [dictionary.doc2bow(doc) for doc in doc_clean]
Lda = gensim.models.ldamodel.LdaModel
#训练LDA模型
ldamodel = Lda(doc_term_matrix, num_topics=3, id2word = dictionary , passes = 50)
#结果
print(ldamodel.print_topics())
C. N-grams作为特征
n个词的组合称为N-grams,一般更具信息量:
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']]
文本数据还可以直接使用本节中描述的几种技术直接量化为数字:
A. 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值。
B.计数/密度/可读性特征
在模型和分析中也可以使用基于计数或密的特征。这些特征看似微不足道,但在学习模式中显示出巨大的影响。其中的一些特征是:单词计数,句子计数,标点符号和特定于行业的单词计数。其他类型的措施包括可读性措施,如音节计数,烟雾指数和轻松阅读。
词嵌入是表示词作为载体的现代方式,词语嵌入的目的是通过保持词料库中的上下文相似度来将高纬度特征重新定义为低纬度特征向量。他们广泛应用于卷积神经网络和递归神经网络等深度学习模型中。
Word2Vec 和 GloVe 是两种比较流行的文本嵌入模型,这些模型以文本语料库作为输入,并产生词向量作为输出。
Word2Vec 模型由预处理模块,称为连续词袋的浅神经网络和另一个称为skip-gram的深神经网络组成。这些模型被广泛应用于其他NLP问题中。它首先从训练语料库中构造词汇表,然后学习词嵌入表示。下面的代码使用genism包准备词嵌入作为向量:
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模型的特征向量,用于使用余弦相似性技术,词聚类和文本分类技术测试文本相似度。
本节讨论自然语言处理领域中不同的使用情况以及存在的问题。
文本分类是NLP的经典问题之一。最典型的例子包括电子邮件垃圾识别,新闻主题分类,情感分类和搜素引擎对页面的组织 。
文本分类是指在一个固定类别中对文本对象进行系统分类的技术。当数据量太大,特征是用于组织,信息过滤和存储目的时,这是非常有用的。
一个典型 的自然语言分类器由两部分组成:(a)训练;(b)预测。如下图,首先,文本输入是处理和特征提取。机器学习模型然后学习这些特征并用于预测新文本。
这里是一个代码,使用朴素贝叶斯分类器对文本进行分类:
from textblob.classifiers import NaiveBayesClassifier as NBC
from textblob import TextBlob
training_corpus = [
('I am exhuasted of this work','Class_B'),
("I can't cooperate with this", 'Class_B'),
('He is my badest enemy', 'Class_B'),
('My management is poor','Class_B'),
('I love this burger','Class_A'),
('This is an brilliant place','Class_A'),
('This is my best work','Class_A'),
('I feel very good about this dates', 'Class_A'),
('What an awesome view','Class_A'),
('I do not like this dish','Class_B')
]
test_corpus = [
('I am not feeling very well today','Class_B'),
('I feel brilliant','Class_A'),
('Gary is a friend of mine','Class_A'),
("I can't belive I'm doing this",'Class_B')
]
model = NBC(training_corpus)
print(model.classify("Their codes are amazing"))
>>>> 'Class_A'
print(model.accuracy(test_corpus))
>>>0.83
sklearn 也提供了一个用于文本分类的框架:
from sklearn.feature_extraction.text
import TfidfVectorizer from sklearn.metrics
import classification_report
from sklearn import svm
#为SVM准备数据
train_data = []
train_labels = []
for row in training_corpus:
train_data.append(row[0])
train_labels.append(row[1])
test_data = []
test_labels = []
for row in test_corpus:
test_data.append(row[0])
test_labels.append(row[1])
#创建特征向量
vectorizer = TfidfVectorizer(min_df = 4, max_df = 0.9)
#训练特征向量
train_vectors = vectorizer.fit_transform(train_data)
#把模型应用到测试数据中去
test_vectors = vectorizer.transform(test_data)
#用SVM来呈现分类
model = svm.SVC(kernel='linear')
model.fit(train_vectors, train_labels)
prediction = model.predict(test_vectors)
>>>> ['Class_A','Class_A',.....]
print(classification_report(test_labels, prediction))
文本分类是在很大程度上依赖于特征的质量和数量,而应用机器学习模型总是包含越来越多的训练数据是一个很好地实践。
NLP的一个重要领域是文本对象的匹配以及找到相似性。文本匹配的重要应用包括自动拼写校正,数据重复删除和基因组分析等。
根据需求,有多种文本匹配技术可以使用。这一部分详细描述了重要的技术。
A.LevenShtein距离
两个字符串之间的LevenShtein距离定义为将一个字符串转化为另一个字符串所需的最小编辑次数。而允许的编辑操作是插入,删除或者替换某单个字符。下面代码实现:
def levenshtein(s1, s2):
if len(s1)>len(s2):
s1,s2 = s2,s1
distances = range(len(s1)+1)
for index2,char2 in enumerate(s2):
newDistances = [index2+1]
for index1, char1 in enumerate(s1):
if char1 == char2:
newDistances.append(distances[index1])
else:
newDistances.append(1+ min(distances[index1], distances[index1+1], newDistances[-1]))
distances = newDistances
return distances[-1]
print(levenshtein('analyze','analyse'))
B.语音匹配
语音匹配算法将关键字作为输入(人的姓名,位置名称等),并生产一个字符串,该字符串识别一组语音上相似的词。它对于搜索大型文本库,纠正拼写错误和匹配相关名称是非常有用的。Soundex和Metaphone是用于此目的的两种主要的语音算法。Python的Fuzzy用于计算不同单词的Soundex字符串:
import fuzzy
soundex = fuzzy.Soundex(4)
print(soundex('ankit'))
print(soundex('aunkit'))
C.弹性字符串匹配
一个完整的文本匹配系统包括不同的流水线算法来计算各种文本变化。正则表达式也有助于这个目的。另一种常见的技术包括精确字符串匹配,区划匹配和紧凑匹配。
D.余弦相似度
当文本是一个符号代表的矢量余弦相似:
import math
from collections import Counter
def get_cosine(vec1,vec2):
common = set(vec1.keys()) & set(vec2.keys())
numerator = sum([vec1[x]* vec2[x] for x in common])
sum1 = sum([vec1[x]**2 for x in vec1.keys()])
sum2 = sum([vec2[x]**2 for x in vec2.keys()])
denominator = math.sqrt(sum1)*math.sqrt(sum2)
if not denominator:
return 0.0
else:
reurn float(numerator)/denominator
def text_to_vector(text):
words = text.split()
return Counter(words)
text1 = 'This is an article on analytics vidhya'
text2 = 'article on analytics vidhya is about natural language processing'
vector1 = text_to_vector(text1)
vector2 = text_to_vector(text2)
print(get_cosine(vector1, vector2))
参考: