图文并茂,用 Python 实现文本分类

前言

目前网络上已经有大量的文本数据存在,并且每天还有越来越多的文本以电子邮件、社交媒体帖子、聊天内容、网站和文章的形式生成。这些文本都是丰富的信息源。但由于文本的非结构化性质,理解和分析它们是非常困难和耗时的。

因此,大多数公司无法利用这一宝贵的信息来源。而这正好是文本分类等自然语言处理(NLP)的用武之地。

什么是文本分类?

文本分类,也称为文本分组或文本标记,是将文本文档分配给一个或多个类别的过程。它能够以快速、廉价的方式自动构建所有类型的相关文本。通过对文本数据进行分类,我们可以快速了解趋势,并缩小范围进行进一步分析。

假设你入职了一家公司,职责是帮助公司整理客户评论。如果公司客户遍布全球,并且有多种语言编写的评论,那么你需要根据语言将评论进行划分,这有助于你进行下一步工作。

尽管好评令人振奋和满足,但它们很少包含需要立即解决的紧迫问题。所以最好进行情感分析并将评论分为正面和负面。之前做的按语言分类正好有助于创建特定语言的情感分析模型。

一旦有了负面评论,你可以根据里面提到的功能/产品对其进行进一步分类。这可以让不同的团队轻松找到相关的评论,并找出他们做的不对的地方进而进行改进。

文本分类是如何工作的?

有两种广泛的文本分类方法:

  • 手动

  • 自动

手动文本分类需要人工注释员,他们通读文本文档的内容并对其进行标记。如果你认为这种方法只会在处理大量文本时产生问题。其实是不对的,有两个原因:

实时性

速度慢是其中一个问题,手动分类会妨碍我们快速识别和应对关键情况。举个例子,假设一个云服务商或一个API宕机,如果一个人按顺序查看客户支持记录,我们可能需要很长一段时间才能发现他们的服务宕机。

一致性

哪怕是一生中最好的时机,人类也是不完美的。由于睡眠不足、无聊、分心等因素,人类容易犯错误。这些因素可能导致分类不一致。对于关键的应用程序,这些失误可能会让公司损失成千上万的钱。

除了这些缺点之外,人工时间的成本远远高于在云服务器上运行Python脚本。因此,应用自然语言处理和其他人工智能技术进行自动文本分类是大多数情况下的最佳选择。自动分类速度更快,成本效益更高。最重要的是,一旦文本分类模型训练到令人满意的程度,它的性能能一直保持。

有很多方法可以自动对文本文档进行分类,一般归类为以下三种类型:

  • 基于规则的方法

  • 基于机器学习的方法

  • 混合方法

基于规则的方法

基于规则的方法使用一组手动创建的语言规则对文本进行分类。这些规则由每个类别的一个模式或一组模式组成。一种非常简单的方法是根据特定类别单词的出现情况对文档进行分类。

假设你想把新闻文章分为两类:商业科学。要做到这一点,你需要创建两个单词列表,对每个类别进行分类。例如,你可以选择高盛、摩根士丹利、苹果等机构的名称用于商业分类,选择NASA、科学家、研究人员等词汇用于科学分类。

现在,当你想对一篇新闻文章进行分类时,基于规则的分类器将统计与商业相关的词和与科学相关的词的数量。如果与商业相关的单词数量大于与科学相关的单词数量,则文章将被归类为商业,反之亦然。

举个例子,基于规则的分类器将新闻标题"国际空间站:NASA计划如何摧毁它"归类为科学,因为有一个与科学相关的词——'NASA',而没有与商业相关的词。

使用基于规则的系统的最大优点是,外行很容易理解。一旦创建了一个基本系统,它就可以随着时间的推移而逐步改进。但这种优势的另一方面是,开发人员需要对领域有深入的了解才能创建规则。此外,基于规则的分类方法不能很好地扩展,在没有适当测试的情况下添加新规则可能会影响旧规则的结果。

基于机器学习的方法

你可以选择一种基于机器学习的方法,使用过去的经验自动学习规则,而不是手动定义规则。基于机器学习的分类器使用带标签的示例作为训练数据来学习单词/短语和标签之间的关联,即类别。

听起来很容易解决,但在训练机器学习分类器之前,有一个问题需要解决,那就是特征提取。计算机不像我们那样理解文本,它们只理解0和1。比如在计算机视觉问题的场景中,图像以数字的形式存储在内部,表示各个像素的值。

但文本并非如此。因此,训练NLP分类器的第一步是将文本转换为数字向量表示。最常用的文本嵌入方法之一是词袋法。它创建一个向量,统计每个单词在预定义词典中的出现次数。

假设你将字典定义为: "(What,a,sunny,serene,Beauty,day,night)" ,你想创建"What a serene night"的嵌入词向量。你会得到以下的向量表示法:(1,1,0,1,0,0,0,1)

生成所有带标签文本文档的向量表示后,可以使用它们来训练分类器。文本文档的向量带着正确的类别传递给分类器。模型学习文本中不同语言特征与类别之间的关联:

一旦模型被训练到满足需要的性能标准,它就可以用来做出准确的预测。使用相同的特征提取方法创建新文本文档的向量表示,然后分类模型使用这些特征向量来预测文档的类别。

基于机器学习的文本分类方法通常比基于规则的分类器更准确。除此之外,机器学习分类器更容易扩展,因为你可以简单地添加新的训练示例来更新模型。机器学习分类器的唯一问题是它们很难理解和调试。因此,如果出现问题,可能很难找出问题的原因。

混合方法

混合文本分类方法结合了上面两个方法的优点。它们将机器学习分类器的泛化能力与易于理解和调整的基于规则的方法相结合。受益于机器学习模型,混合方法可以学习复杂的规则,任何冲突的分类或不稳定的行为都可以使用规则修复。

例如,根据行业对金融新闻文章进行分类,如制药、金融、汽车、采矿等。要做到这一点,你需要创建一个混合系统。首先,训练一个命名实体识别模型,从新闻文章中提取公司名称。然后,创建每个部门的公司列表。做完这两样,就可以创建一个合格的分类器。

用Transformers&scikit learn对新闻标题进行分类

首先,需要安装spaCy包,spacy-sentence-bert[1]和scikit-learn[2]模块。

数据从这里[3]获取。

你将使用我们一些旧的谷歌新闻数据。新闻数据以JSONL格式存储。通常,你可以使用read_json方法将JSONL文件加载到DataFrame中,并使用lines=True参数,但此处我们的数据结构稍微有点不一样。

每行数据都存储在一个对象中(*{'item':}*)。如果你尝试使用read_json方法直接加载它,它会将所有内容作为一列加载。

import pandas as pd

df = pd.read_json('data.json', lines=True)
print(df)

 

要解决这个问题,可以像读取普通文本文件一样读取该文件,并使用json.loads方法来创建字典列表。

import

data = []
with open('data.json', 'r') as f:
  data = f.readlines()
  
data = [json.loads(item)['Item'] for item in data]

print(data[:2])

 

还有一个问题需要解决. 标题的属性值存储在它自己的对象中。不用担心,可以通过进一步的字典操作来解决。

for i in range(len(data)):
  for key in data[i].keys():
    data[i][key] = data[i][key]["S"]
    
print(data[:2])

 

现在你可以从新闻数据中创建一个DataFrame了。

df = pd.DataFrame(data)

print(df.head())

 

我们来看下所有的主题标签。

print(df.topic.unique())

## OUTPUT
## array(['ENTERTAINMENT', 'BUSINESS', 'NATION', 'SPORTS', 'WORLD',
##     'TECHNOLOGY', 'HEALTH', 'SCIENCE'], dtype=object)

有些属性其实不需要,比如countrylang, or cleaned_url。主题标签中的——“WORLD”和“NATION”的信息量不大,因为它们的定义非常宽松。所以,你可以把它们drop掉。

#drop columns
df = df[['topic','title']]

#drop 'NATION' and 'WORLD" labels
data = df[df['topic'] != 'NATION' or df['topic'] != 'WORLD']

我们再检查下缺失值并删除不完整的条目。

print(data.isnull().sum())

## OUTPUT
## topic    0
## title    1
## dtype: int64

data = data.dropna()

接下来,应该看看我们为每个类别提供了多少训练示例。

counts = data['topic'].value_counts()
counts.plot(kind='bar', legend=False, grid=True, figsize=(8, 5))

 

两大类超过35万篇文章,甚至小的列也有大约4万组数据!

再看看标题长度的分布情况?

import numpy as np

lens = data.title.str.len()
lens.hist(bins = np.arange(0,200,5))

 

看起来还算“正常”。

不开玩笑的说,当使用最先进的BERT transformer模型来创建向量表示时,我建议使用可用数据集的子集来训练模型。

for topic in topics:
  temp_df = data[data['topic'] == topic][:5000]
  df = pd.concat([df, temp_df])

现在,你可以加载BERT句子转换器,并为标题创建向量嵌入。

import spacy_sentence_bert

# load one of the models listed at https://github.com/MartinoMensio/spacy-sentence-bert/
nlp = spacy_sentence_bert.load_model('en_stsb_distilbert_base')
df['vector'] = df['title'].apply(lambda x: nlp(x).vector)

让我们把数据分成训练集和测试集。

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(df['vector'].tolist(), df['topic'].tolist(), test_size=0.33, random_state=42)

最后,可以选择多个机器学习分类器进行训练。

from sklearn.svm import SVC

clf = SVC(gamma='auto')
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
print(accuracy_score(y_test, y_pred))

## OUTPUT
## 0.8392929292929293
from sklearn.ensemble import RandomForestClassifier

clf = RandomForestClassifier(max_depth=9, random_state=0)
clf.fit(X_train, y_train)

y_pred = clf.predict(X_test)
print(accuracy_score(y_test, y_pred))

## OUTPUT
## 0.7471717171717172

支持向量分类器(SVM)的性能位居榜首。你可以用它来预测新新闻标题的主题。

让我们在谷歌新闻的一堆新闻标题上试一试:

headlines = ["Scientists Figured Out How Much Exercise You Need to 'Offset' a Day of Sitting",
 "Marlee Matlin On Her Career And 'CODA' — The Actor's Side – Deadline",
 "Increasing mental health issues a symptom of Victoria's lockdown",
 'Philippines polio outbreak over: UN',
 "Sophie, Countess of Wessex opens up about menopause: ‘It's like somebody's just gone and taken your brain'",
 'Bill Gates tells why he prefers Android mobile over iPhone',
 "'A weight has been lifted' Edinburgh pubs and restaurants react to hospitality rules easing",
 "Mysterious Signal Flashing From Galaxy's Core Baffle Scientists; Where Is There Source of This Radio Waves?",
 "'Tears in their eyes': World erupts over All Blacks' beautiful Maradona tribute",
 "'Packed in like sardines'"]

topics = ['SCIENCE',  'ENTERTAINMENT',  'HEALTH',
 'HEALTH',  'ENTERTAINMENT',  'TECHNOLOGY',  'BUSINESS',
 'SCIENCE',  'SPORTS',  'ENTERTAINMENT']
for headline, topic in zip(headlines, topics):
  print(headline)
  print(f"True Label: {topic}, Predicted Label:{clf.predict(nlp(headline).vector.reshape(1, -1))[0]} \n")

 

结论

现在你应该知道什么是文本分类,它是如何工作的,以及如何训练自己的机器学习文本分类器。那么神经网络用起来会怎样呢?这是个好问题。其实尽管神经网络很好,但对于这项任务来说,却并不是必要的。支持向量机和神经网络都能逼近非线性决策边界,并且它们都能在同一数据集上获得相当优秀的结果。神经网络可能在性能上稍有领先,但需要更多的计算能力、训练数据和时间。

另一方面,支持向量机能够基于唯一的支持向量可靠地识别决策边界。因此,你只需要使用要达到类似性能的神经网络所需的一小部分数据来训练SVM分类器。当然,如果性的任何微小提升对你来说都非常重要,那么可以使用神经网络。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值