python⽂本分类框架_⼿把⼿教你在Python中实现⽂本分类
(附代码、数据集)
本⽂约2300字,建议阅读8分钟。
本⽂将详细介绍⽂本分类问题并⽤Python实现这个过程。
引⾔
⽂本分类是商业问题中常见的⾃然语⾔处理任务,⽬标是⾃动将⽂本⽂件分到⼀个或多个已定义好的类别中。⽂本分类的⼀些例⼦如下:
分析社交媒体中的⼤众情感
鉴别垃圾邮件和⾮垃圾邮件
⾃动标注客户问询
将新闻⽂章按主题分类
⽬录
本⽂将详细介绍⽂本分类问题并⽤Python实现这个过程:
⽂本分类是有监督学习的⼀个例⼦,它使⽤包含⽂本⽂档和标签的数据集来训练⼀个分类器。端到端的⽂本分类训练主要由三个部分组成:
1. 准备数据集:第⼀步是准备数据集,包括加载数据集和执⾏基本预处理,然后把数据集分为训练集和验证集。
特征⼯程:第⼆步是特征⼯程,将原始数据集被转换为⽤于训练机器学习模型的平坦特征(flat features),并从现有数据特征创建新的特征。
2. 模型训练:最后⼀步是建模,利⽤标注数据集训练机器学习模型。
3. 进⼀步提⾼分类器性能:本⽂还将讨论⽤不同的⽅法来提⾼⽂本分类器的性能。
准备好你的机器
先安装基本组件,创建Python的⽂本分类框架。⾸先导⼊所有所需的库。如果你没有安装这些库,可以通过以下官⽅链接来安装它们。
#导⼊数据集预处理、特征⼯程和模型训练所需的库
from sklearn import model_selection, preprocessing, linear_model, naive_bayes, metrics, svm
from sklearn. import TfidfVectorizer, CountVectorizer
from sklearn import decomposition, ensemble
import pandas, xgboost, numpy, textblob, string
from keras.preprocessing import text, sequence
from keras import layers, models, optimizers
⼀、准备数据集
在本⽂中,我使⽤亚马逊的评论数据集,它可以从这个链接下载:
这个数据集包含3.6M的⽂本评论内容及其标签,我们只使⽤其中⼀⼩部分数据。⾸先,将下载的数据加载到包含两个列(⽂本和标签)的pandas的数据结构(dataframe)中。
数据集链接:
#加载数据集
data = open('data/corpus').read()
labels, texts = [], []
for i, line in enumerate(data.split("\n")):
content = line.split()
labels.append(content[0])
texts.append(content[1])
#创建⼀个dataframe,列名为text和label
trainDF = pandas.DataFrame()
trainDF['text'] = texts
trainDF['label'] = labels
接下来,我们将数据集分为训练集和验证集,这样我们可以训练和测试分类器。另外,我们将编码我们的⽬标列,以便它可以在机器学习模型中使⽤:
#将数据集分为训练集和验证集
train_x, valid_x, train_y, valid_y = ain_test_split(trainDF['text'], trainDF['label'])
# label编码为⽬标变量
encoder = preprocessing.LabelEncoder()
train_y = encoder.fit_transform(train_y)
valid_y = encoder.fit_transform(valid_y)
⼆、特征⼯程
接下来是特征⼯程,在这⼀步,原始数据将被转换为特征向量,另外也会根据现有的数据创建新的特征。为了从数据集中选出重要的特征,有以下⼏种⽅式:
计数向量作为特征
TF-IDF向量作为特征单个词语级别
多个词语级别(N-Gram)
词性级别
词嵌⼊作为特征
基于⽂本/NLP的特征
主题模型作为特征
接下来分别看看它们如何实现:
2.1 计数向量作为特征
计数向量是数据集的矩阵表⽰,其中每⾏代表来⾃语料库的⽂档,每列表⽰来⾃语料库的术语,并且每个单元格表⽰特定⽂档中特定术语的频率计数:
#创建⼀个向量计数器对象
count_vect = CountVectorizer(analyzer='word', token_pattern=r'\w{1,}')
count_vect.fit(trainDF['text'])
#使⽤向量计数器对象转换训练集和验证集
xtrain_count = ansform(train_x)
xvalid_count = ansform(valid_x)
2.2 TF-IDF向量作为特征
TF-IDF的分数代表了词语在⽂档和整个语料库中的相对重要性。TF-IDF分数由两部分组成:第⼀部分是计算标准的词语频率(TF),第⼆部分是逆⽂档频率(IDF)。其中计算语料库中⽂档总数除以含有该词语的⽂档数量,然后再取对数就是逆⽂档频率。
TF(t)=(该词语在⽂档出现的次数)/(⽂档中词语的总数)
IDF(t)= log_e(⽂档总数/出现该词语的⽂档总数)
TF-IDF向量可以由不同级别的分词产⽣(单个词语,词性,多个词(n-grams))
词语级别TF-IDF:矩阵代表了每个词语在不同⽂档中的TF-IDF分数。
N-gram级别TF-IDF:N-grams是多个词语在⼀起的组合,这个矩阵代表了N-grams的TF-IDF分数。
词性级别TF-IDF:矩阵代表了语料中多个词性的TF-IDF分数。
#词语级tf-idf
tfidf_vect = TfidfVectorizer(analyzer='word', token_pattern=r'\w{1,}', max_features=5000)
tfidf_vect.fit(trainDF['text'])
xtrain_tfidf = ansform(train_x)
xvalid_tfidf = ansform(valid_x)
# ngram 级tf-idf
tfidf_vect_ngram = TfidfVectorizer(analyzer='word', token_pattern=r'\w{1,}', ngram_range=(2,3), max_features=5000)
tfidf_vect_ngram.fit(trainDF['text'])
xtrain_tfidf_ngram = tfidf_ansform(train_x)
xvalid_tfidf_ngram = tfidf_ansform(valid_x)
#词性级tf-idf
tfidf_vect_ngram_chars = TfidfVectorizer(analyzer='char', token_pattern=r'\w{1,}', ngram_range=(2,3), max_features=5000)
tfidf_vect_ngram_chars.fit(trainDF['text'])
xtrain_tfidf_ngram_chars = tfidf_vect_ansform(train_x)
xvalid_tfidf_ngram_chars = tfidf_vect_ansform(valid_x)
2.3 词嵌⼊
词嵌⼊是使⽤稠密向量代表词语和⽂档的⼀种形式。向量空间中单词的位置是从该单词在⽂本中的上下⽂学习到的,词嵌⼊可以使⽤输⼊语料本⾝训练,也可以使⽤预先训练好的词嵌⼊模型⽣成,词嵌⼊模型有:Glove, FastText,Word2Vec。它们都可以下载,并⽤迁移学习的⽅式使⽤。想了解更多的词嵌⼊资料,可以访问:
接下来介绍如何在模型中使⽤预先训练好的词嵌⼊模型,主要有四步:
1. 加载预先训练好的词嵌⼊模型
2. 创建⼀个分词对象
3. 将⽂本⽂档转换为分词序列并填充它们
4. 创建分词和各⾃嵌⼊的映射
#加载预先训练好的词嵌⼊向量
embeddings_index = {}
for i, line in enumerate(open('data/wiki-news-300d-1M.vec')):
values = line.split()
embeddings_index[values[0]] = numpy.asarray(values[1:], dtype='float32')
#创建⼀个分词器
token = text.Tokenizer()
token.fit_on_texts(trainDF['text'])
word_index = token.word_index
#将⽂本转换为分词序列,并填充它们保证得到相同长度的向量
train_seq_x = sequence.pad_s_to_sequences(train_x), maxlen=70) valid_seq_x = sequence.pad_s_to_sequences(valid_x), maxlen=70) #创建分词嵌⼊映射
embedding_matrix = s((len(word_index) + 1, 300))
for word, i in word_index.items():
embedding_vector = (word)
if embedding_vector is not None:
embedding_matrix[i] = embedding_vector
2.4 基于⽂本/NLP的特征
创建许多额外基于⽂本的特征有时可以提升模型效果。⽐如下⾯的例⼦:
⽂档的词语计数—⽂档中词语的总数量
⽂档的词性计数—⽂档中词性的总数量
⽂档的平均字密度--⽂件中使⽤的单词的平均长度
完整⽂章中的标点符号出现次数--⽂档中标点符号的总数量
整篇⽂章中的⼤写次数—⽂档中⼤写单词的数量
完整⽂章中标题出现的次数—⽂档中适当的主题(标题)的总数量
词性标注的频率分布名词数量
动词数量
形容词数量
副词数量
代词数量
这些特征有很强的实验性质,应该具体问题具体分析。
trainDF['char_count'] = trainDF['text'].apply(len)
trainDF['word_count'] = trainDF['text'].apply(lambda x: len(x.split()))
trainDF['word_density'] = trainDF['char_count'] / (trainDF['word_count']+1)
trainDF['punctuation_count'] = trainDF['text'].apply(lambda x: len("".join(_ for _ in x if _ in string.punctuation))) trainDF['title_word_count'] = trainDF['text'].apply(lambda x: len([wrd for wrd in x.split() if wrd.istitle()]))
trainDF['upper_case_word_count'] = trainDF['text'].apply(lambda x: len([wrd for wrd in x.split() if wrd.isupper()])) trainDF['char_count'] = trainDF['text'].apply(len)
trainDF['word_count'] = trainDF['text'].apply(lambda x: len(x.split()))
trainDF['word_density'] = trainDF['char_count'] / (trainDF['word_count']+1)
trainDF['punctuation_count'] = trainDF['text'].apply(lambda x: len("".join(_ for _ in x if _ in string.punctuation))) trainDF['title_word_count'] = trainDF['text'].apply(lambda x: len([wrd for wrd in x.split() if wrd.istitle()]))
trainDF['upper_case_word_count'] = trainDF['text'].apply(lambda x: len([wrd for wrd in x.split() if wrd.isupper()])) pos_family = {
validation框架'noun' : ['NN','NNS','NNP','NNPS'],
'pron' : ['PRP','PRP$','WP','WP$'],
'verb' : ['VB','VBD','VBG','VBN','VBP','VBZ'],
'adj' : ['JJ','JJR','JJS'],
'adv' : ['RB','RBR','RBS','WRB']
}
#检查和获得特定句⼦中的单词的词性标签数量
def check_pos_tag(x, flag):
cnt = 0
try:
wiki = textblob.TextBlob(x)
for tup in wiki.tags:
ppo = list(tup)[1]
if ppo in pos_family[flag]:
cnt += 1
except:
pass
return cnt
trainDF['noun_count'] = trainDF['text'].apply(lambda x: check_pos_tag(x, 'noun'))
trainDF['verb_count'] = trainDF['text'].apply(lambda x: check_pos_tag(x, 'verb'))
trainDF['adj_count'] = trainDF['text'].apply(lambda x: check_pos_tag(x, 'adj'))
trainDF['adv_count'] = trainDF['text'].apply(lambda x: check_pos_tag(x, 'adv'))
trainDF['pron_count'] = trainDF['text'].apply(lambda x: check_pos_tag(x, 'pron'))

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。