文本分类概述

分类算法的文本特征提取和预处理非常重要。在本节中,由于大多数文档都包含很多杂音,因此我们开始讨论文本清理。在这一部分中,我们讨论文本特征提取的两种主要方法-词嵌入和加权词。

文字清理和预处理
在自然语言处理(NLP)中,大多数文本和文档包含许多对于文本分类来说是多余的词,例如停用词,拼写错误,语等。在本节中,我们简要说明一些文本的技术和方法。清洁和预处理文本文件。在诸如统计和概率学习方法之类的许多算法中,噪声和不必要的功能会对整体性能产生负面影响。因此,消除这些功能非常重要。

令牌化

令牌化是将文本流分解为单词,短语,符号或称为令牌的任何其他有意义元素的过程。此步骤的主要目标是提取句子中的单个单词。除文本分类外,在文本挖掘中,有必要在执行文档标记化的管道中合并一个解析器。例如:

句子:After sleeping for four hours, he decided to sleep for another four

我们可以分解为:{‘After’, ‘sleeping’, ‘for’, ‘four’, ‘hours’, ‘he’, ‘decided’, ‘to’, ‘sleep’, ‘for’, ‘another’, ‘four’}

from nltk.tokenize import word_tokenize
text = "After sleeping for four hours, he decided to sleep for another four"
tokens = word_tokenize(text)
print(tokens)

停用词

社交媒体(例如Twitter,Facebook等)上的文本和文档分类通常受文本语料库的嘈杂性质(缩写,不规则形式)影响。

from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
example_sent = "This is a sample sentence, showing off the stop words filtration."
stop_words = set(stopwords.words('english'))
word_tokens = word_tokenize(example_sent)
filtered_sentence = [w for w in word_tokens if not w in stop_words]
filtered_sentence = []
for w in word_tokens:
    if w not in stop_words:
        filtered_sentence.append(w)
print(word_tokens)
print(filtered_sentence)

输出:
[‘This’, ‘is’, ‘a’, ‘sample’, ‘sentence’, ‘,’, ‘showing’,
‘off’, ‘the’, ‘stop’, ‘words’, ‘filtration’, ‘.’]
[‘This’, ‘sample’, ‘sentence’, ‘,’, ‘showing’, ‘stop’,
‘words’, ‘filtration’, ‘.’]

大写

句子可以混合使用大写和小写字母。 多个句子组成一个文本文档。 为了减少问题空间,最常见的方法是将所有内容都减小为小写。 这会将所有单词带入同一文档中的同一空间,但通常会将某些单词的含义更改,例如“ US”改为“ us”,其中第一个代表美利坚合众国,第二个代表代词。 为了解决这个问题,可以使用语和缩写转换器。

text = "The United States of America (USA) or America, is a federal republic composed of 50 states"
print(text)
print(text.lower())

输出:
“The United States of America (USA) or America, is a federal republic composed of 50 states”
“the united states of america (usa) or america, is a federal republic composed of 50 states”

语和缩写

executing语和缩写词可能会在执行预处理步骤时引起问题。 缩写词是单词的缩写形式,例如Support Vector Machine的SVM代表。 处理这些单词的常用方法是将它们转换为形式语言。

噪音消除

作为预处理步骤的另一个问题是清除噪音。 文本文档通常包含标点符号或特殊字符之类的字符,它们对于文本挖掘或分类目的不是必需的。 虽然标点符号对于理解句子的含义至关重要,但它会对分类算法产生负面影响。
这是从文本中消除标准杂音的简单代码:

def text_cleaner(text):
    rules = [
        {r'>\s+': u'>'},  # remove spaces after a tag opens or closes
        {r'\s+': u' '},  # replace consecutive spaces
        {r'\s*<br\s*/?>\s*': u'\n'},  # newline after a <br>
        {r'</(div)\s*>\s*': u'\n'},  # newline after </p> and </div> and <h1/>...
        {r'</(p|h\d)\s*>\s*': u'\n\n'},  # newline after </p> and </div> and <h1/>...
        {r'<head>.*<\s*(/head|body)[^>]*>': u''},  # remove <head> to </head>
        {r'<a\s+href="([^"]+)"[^>]*>.*</a>': r'\1'},  # show links instead of texts
        {r'[ \t]*<[^<]*?/?>': u''},  # remove remaining tags
        {r'^\s+': u''}  # remove spaces at the beginning
    ]
    for rule in rules:
    for (k, v) in rule.items():
        regex = re.compile(k)
        text = regex.sub(v, text)
    text = text.rstrip()
    return text.lower()

拼写校正

预处理步骤的可选部分是纠正拼写错误的单词。 为了解决此问题,已引入了不同的技术,例如基于哈希的和上下文相关的拼写校正技术。

from autocorrect import spell
print spell('caaaar')
print spell(u'mussage')
print spell(u'survice')
print spell(u'hte')

输出:
caesar
message
service
the

Stemming

文字词干修饰是通过使用不同的语言过程(例如词缀(词缀的增加))来修饰单词以获得其变体。 例如,“studying”一词的词干是“study”,即“-ing”

from nltk.stem import PorterStemmer
from nltk.tokenize import sent_tokenize, word_tokenize
ps = PorterStemmer()
example_words = ["python","pythoner","pythoning","pythoned","pythonly"]
for w in example_words:
print(ps.stem(w))

输出:
python
python
python
python
pythonli

词嵌入(在之前的文章具体解释过)

已经提出了不同的词嵌入程序来将这些字母组合转换为机器学习算法的可消耗输入。 执行这种嵌入的一种非常简单的方法是term-frequency〜(TF),其中每个单词都将映射到一个数字,该数字对应于整个语料库中该单词的出现次数。 还使用了其他术语频率函数,将词频表示为布尔值或对数标度数字。 在这里,每个文档都将转换为包含该文档中单词出现频率的相同长度的向量。 尽管这种方法看似非常直观,但它受到以下事实的困扰:在语言文献中非常常用的特定单词可能会主导这种单词表示形式。

语境化的词表示

ELMo是一种深层的上下文化单词表示形式,它可以同时建模(1)单词使用的复杂特征(例如语法和语义),以及(2)这些用法如何在语言上下文之间变化(即建模多义性)。这些单词向量是深度双向语言模型(biLM)内部状态的学习功能,双向语言模型已在大型文本语料库上进行了预训练。可以轻松地将它们添加到现有模型中,并在各种具有挑战性的NLP问题(包括问题回答,文本含义和情感分析)中显着改善现有技术。

ELMo表示为:

上下文:每个单词的表示形式取决于使用该单词的整个上下文。
深度:词表示法结合了深度预训练神经网络的所有层。
基于字符:ELMo表示完全基于字符,允许网络使用形态学线索来为训练中未曾见过的词汇外标记形成可靠的表示。

根据您的用例,可以通过三种方式将ELMo表示集成到下游任务中。

  1. 使用字符输入即时从原始文本计算表示形式。 这是最通用的方法,将处理任何输入文本。 它也是计算上最昂贵的。
  2. 预计算并缓存上下文无关的令牌表示形式,然后使用biLSTM输入数据来计算上下文相关的表示形式。 此方法的计算费用比#1少,但仅适用于固定的指定词汇表。
  3. 预计算整个数据集的表示形式并保存到文件中。

快速文字

fastText是一个用于高效学习单词表示和句子分类的库。

model:

最新的最先进的英语单词向量。
在Wikipedia和Crawl上训练的157种语言的单词向量。
语言识别和各种监督任务的模型。

加权词

词频

术语频率是单词袋,它是文本特征提取的最简单技术之一。该方法基于对每个文档中单词的数量进行计数并将其分配给特征空间。
术语频率-逆文档频率
通过Tf-idf可以数学表示一个文档中术语的权重。
在这里插入图片描述
其中N是文档数,df(t)是语料库中包含术语t的文档数。第一部分将提高召回率,第二部分将提高单词嵌入的准确性。尽管tf-​​idf试图克服文档中通用术语的问题,但它仍然遭受其他一些描述性限制。即,tf-idf无法解释文档中单词之间的相似性,因为每个单词都以索引的形式出现。近年来,随着更复杂的模型(例如神经网络)的发展,提出了可以纳入概念的新方法,例如词的相似性和语音标记的一部分。这项工作使用了word2vec和Glove这两种已成功用于深度学习技术的最常用方法。

特征提取技术的比较

加权词

优点:
易于计算
使用它轻松计算2个文档之间的相似度
提取文档中最具描述性的术语的基本指标
使用未知词(例如语言中的新词)
局限性:
它不捕获文本中的位置(语法)
它没有捕获文本中的含义(语义)
常用字词会影响结果(例如“ am”,“ is”等)

TF-IDF
优点:
易于计算
使用它轻松计算2个文档之间的相似度
提取文档中最具描述性的术语的基本指标
通用字词不会因IDF而影响结果(例如“ am”,“ is”等)
局限性:
它不捕获文本中的位置(语法)
它没有捕获文本中的含义(语义)

Word2Vec
优点:
它捕获单词在文本中的位置(语法)
它捕获单词(语义)中的含义
局限性:
它无法从文本中捕获单词的含义(无法捕获多义性)
它无法从语料库中捕获词汇量不足的单词

GloVe(预培训)
优点:
它捕获单词在文本中的位置(语法)
它捕获单词(语义)中的含义
在庞大的语料库上训练
局限性:
它无法从文本中捕获单词的含义(无法捕获多义性)
存储的内存消耗
它无法从语料库中捕获词汇量不足的单词

GloVe(训练有素)
优点:
这非常简单,例如,强制词向量以捕获向量空间中的亚线性关系(性能优于Word2vec)
对于频繁出现的单词对(例如停用词,例如“ am”,“ is”等),较低的权重。
局限性:
存储的内存消耗
需要庞大的语料库来学习
它无法从语料库中捕获词汇量不足的单词
它无法从文本中捕获单词的含义(无法捕获多义性)

快速文字
优点:
适用于稀有词(稀有字符n-gram,仍与其他词共享)
用字符级的n-gram解决词汇量不足的单词
局限性:
它无法从文本中捕获单词的含义(无法捕获多义性)
存储的内存消耗
与GloVe和Word2Vec相比,计算成本更高

语境化的词表示
优点:
它从文本中捕获单词的含义(结合上下文,处理多义性)
局限性:
存储的内存消耗
显着提高了下游任务的性能。与其他相比,计算上更昂贵
需要为所有LSTM和前馈层嵌入另一个单词
它无法从语料库中捕获词汇量不足的单词
仅适用于句子和文档级别(不适用于单个单词级别)

降维

主成分分析(PCA)
主成分分析(PCA)是多变量分析和降维中最流行的技术。 PCA是一种识别数据大致位于其中的子空间的方法。 这意味着找到不相关的新变量,并最大化方差以保留尽可能多的可变性。
从具有75000个功能的tf-idf到2000个组件的文本数据集(20newsgroups)上的PCA示例:

from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
def TFIDF(X_train, X_test, MAX_NB_WORDS=75000):
    vectorizer_x = TfidfVectorizer(max_features=MAX_NB_WORDS)
    X_train = vectorizer_x.fit_transform(X_train).toarray()
    X_test = vectorizer_x.transform(X_test).toarray()
    print("tf-idf with", str(np.array(X_train).shape[1]), "features")
    return (X_train, X_test)
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target
X_train,X_test = TFIDF(X_train,X_test)
from sklearn.decomposition import PCA
pca = PCA(n_components=2000)
X_train_new = pca.fit_transform(X_train)
X_test_new = pca.transform(X_test)
print("train with old features: ",np.array(X_train).shape)
print("train with new features:" ,np.array(X_train_new).shape)
print("test with old features: ",np.array(X_test).shape)
print("test with new features:" ,np.array(X_test_new).shape)

线性判别分析(LDA)
线性判别分析(LDA)是另一种用于数据分类和降维的常用技术。 当类内频率不相等且已根据随机生成的测试数据评估了它们的性能时,LDA特别有用。 依赖于类和依赖于类的变换是LDA中的两种方法,分别使用了类间差异与类内差异的比率以及整体方差与类内差异的比率。

from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
def TFIDF(X_train, X_test, MAX_NB_WORDS=75000):
    vectorizer_x = TfidfVectorizer(max_features=MAX_NB_WORDS)
    X_train = vectorizer_x.fit_transform(X_train).toarray()
    X_test = vectorizer_x.transform(X_test).toarray()
    print("tf-idf with", str(np.array(X_train).shape[1]), "features")
    return (X_train, X_test)
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target
X_train,X_test = TFIDF(X_train,X_test)
LDA = LinearDiscriminantAnalysis(n_components=15)
X_train_new = LDA.fit(X_train,y_train)
X_train_new =  LDA.transform(X_train)
X_test_new = LDA.transform(X_test)
print("train with old features: ",np.array(X_train).shape)
print("train with new features:" ,np.array(X_train_new).shape)
print("test with old features: ",np.array(X_test).shape)
print("test with new features:" ,np.array(X_test_new).shape)

随机投影

随机投影或随机特征是一种降维技术,主要用于非常大的数据集或非常高的特征空间。 文本和文档,尤其是带有加权特征提取的文本和文档,可能包含大量的基础特征。 许多研究人员针对用于文本挖掘,文本分类和/或降维的文本数据解决了随机投影问题。 我们开始回顾一些随机投影技术。

from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
def TFIDF(X_train, X_test, MAX_NB_WORDS=75000):
    vectorizer_x = TfidfVectorizer(max_features=MAX_NB_WORDS)
    X_train = vectorizer_x.fit_transform(X_train).toarray()
    X_test = vectorizer_x.transform(X_test).toarray()
    print("tf-idf with", str(np.array(X_train).shape[1]), "features")
    return (X_train, X_test)
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target
X_train,X_test = TFIDF(X_train,X_test)
from sklearn import random_projection
RandomProjection = random_projection.GaussianRandomProjection(n_components=2000)
X_train_new = RandomProjection.fit_transform(X_train)
X_test_new = RandomProjection.transform(X_test)
print("train with old features: ",np.array(X_train).shape)
print("train with new features:" ,np.array(X_train_new).shape)
print("test with old features: ",np.array(X_test).shape)
print("test with new features:" ,np.array(X_test_new).shape)

自动编码器
自动编码器是一种经过训练的神经网络技术,可尝试将其输入映射到其输出。 自动编码器作为降维方法通过神经网络的强大可理解性取得了巨大的成功。 主要思想是,输入层和输出层之间的一个隐藏层具有较少的神经元,可以用来减少特征空间的尺寸。 自动编码器特别适用于包含许多功能的文本,文档和序列,可以帮助更快,更有效地处理数据。

from keras.layers import Input, Dense
from keras.models import Model
# this is the size of our encoded representations
encoding_dim = 1500
# this is our input placeholder
input = Input(shape=(n,))
# "encoded" is the encoded representation of the input
encoded = Dense(encoding_dim, activation='relu')(input)
# "decoded" is the lossy reconstruction of the input
decoded = Dense(n, activation='sigmoid')(encoded)
# this model maps an input to its reconstruction
autoencoder = Model(input, decoded)
# this model maps an input to its encoded representation
encoder = Model(input, encoded)
encoded_input = Input(shape=(encoding_dim,))
# retrieve the last layer of the autoencoder model
decoder_layer = autoencoder.layers[-1]
# create the decoder model
decoder = Model(encoded_input, decoder_layer(encoded_input))
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')

文字分类技术

罗基奥分类
Rocchio算法的第一个版本由rocchio于1971年推出,用于在查询全文数据库时使用相关性反馈。 从那时起,许多研究人员研究并开发了这种用于文本和文档分类的技术。 此方法为每个信息单词使用TF-IDF权重,而不是一组布尔特征。 Rocchio的算法使用一组训练的文档,为每个类别构建一个原型向量,该向量是属于某个类别的所有训练文档向量上的平均向量。 然后,它将把每个测试文档分配给一个类,该类具有与测试文档和每个原型向量之间的最大相似性。
在最接近的质心分类器中,我们将文本用作输入数据,以使用tf-idf向量进行分类,该分类器称为Rocchio分类器。

from sklearn.neighbors.nearest_centroid import NearestCentroid
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target
text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', NearestCentroid()),
                     ])
text_clf.fit(X_train, y_train)
predicted = text_clf.predict(X_test)
print(metrics.classification_report(y_test, predicted))

boostingand bagging
Boosting是一种集成学习元算法,主要用于减少监督学习中的方差。 基本上,这是一门机器学习算法,可以将弱学习者转化为强学习者。bagging是基于迈克尔·凯恩斯和莱斯利·瓦莱恩特(1988,1989)提出的问题。 弱学习者被定义为仅与真实分类稍微相关的分类(与随机猜测相比,它可以更好地标记示例)。 相反,学习能力强的人是与真实分类任意相关的分类器。

from sklearn.ensemble import GradientBoostingClassifier
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target
text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', GradientBoostingClassifier(n_estimators=100)),
                     ])
text_clf.fit(X_train, y_train)
predicted = text_clf.predict(X_test)
print(metrics.classification_report(y_test, predicted))
from sklearn.ensemble import BaggingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target
text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', BaggingClassifier(KNeighborsClassifier())),
                     ])
text_clf.fit(X_train, y_train)
predicted = text_clf.predict(X_test)
print(metrics.classification_report(y_test, predicted))

朴素贝叶斯分类器
朴素的贝叶斯文本分类已在工业和学术界使用了很长时间(由托马斯·贝叶斯(Thomas Bayes)于1701-1761年间引入)。 但是,从1950年代开始就对文本和文档分类进行了研究。 朴素贝叶斯分类器(NBC)是在信息检索中广泛使用的生成模型。 许多研究人员针对他们的应用解决并开发了该技术。 我们从NBC的最基本版本开始,该版本是通过计算文档中单词的数量而使用术语频率(单词包)特征提取技术开发的

from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target
text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', MultinomialNB()),
                     ])
text_clf.fit(X_train, y_train)
predicted = text_clf.predict(X_test)
print(metrics.classification_report(y_test, predicted))

K近邻
在机器学习中,k最近邻算法(kNN)是用于分类的非参数技术。 在过去的几十年中,许多方法将这种方法用于自然语言处理(NLP)中作为文本分类技术。

from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target
text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', KNeighborsClassifier()),
                     ])
text_clf.fit(X_train, y_train)
predicted = text_clf.predict(X_test)
print(metrics.classification_report(y_test, predicted))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值