【Kaggle微课程】Natural Language Processing - 2.Text Classification

文章目录

    • 1. bag of words
    • 2. 建立词袋模型
    • 3. 训练文本分类模型
    • 4. 预测
    • 练习:
      • 1. 评估方法
      • 2. 数据预处理、建模
      • 3. 训练
      • 4. 预测
      • 5. 评估模型
      • 6. 改进

learn from https://www.kaggle.com/learn/natural-language-processing

NLP中的一个常见任务是文本分类。这是传统机器学习意义上的“分类”,并应用于文本。

包括垃圾邮件检测、情绪分析和标记客户查询。

在本教程中,您将学习使用spaCy进行文本分类。该分类器将检测垃圾邮件,这是大多数电子邮件客户端的常见功能。

  • 读取数据
import pandas as pd
spam = pd.read_csv("./spam.csv")
spam.head(10)

1. bag of words

模型不能直接从原始文本中学习,需要转化成数字特征,最简单的方法是用 one-hot 编码。

举个例子:

  • 句子1 "Tea is life. Tea is love."
  • 句子2 "Tea is healthy, calming, and delicious."

忽略标点后的词表是 {"tea", "is", "life", "love", "healthy", "calming", "and", "delicious"}

通过对每个句子的单词出现的次数进行统计,用向量表示

v1=[2,2,1,1,0,0,0,0]v1=[2,2,1,1,0,0,0,0]v1=[2,2,1,1,0,0,0,0]
v2=[1,1,0,0,1,1,1,1]v2=[1,1,0,0,1,1,1,1]v2=[1,1,0,0,1,1,1,1]

这就是词袋表示,相似的文档将会有相似的词袋向量

还有一种表示法,TF-IDF (Term Frequency - Inverse Document Frequency)

2. 建立词袋模型

使用 spacy 的 TextCategorizer 可以处理词袋的转换,建立一个简单的线性模型,它是一个 spacy 管道

import spacy
nlp = spacy.blank('en') # 建立空模型# Create the TextCategorizer with exclusive classes 
#                        and "bow" architecture
textcat = nlp.create_pipe('textcat',config={"exclusive_classes": True, # 排他的,二分类"architecture": "bow"
})# Add the TextCategorizer to the empty model
nlp.add_pipe(textcat)
# help(nlp.create_pipe)
Help on method create_pipe in module spacy.language:create_pipe(name, config={}) method of spacy.lang.en.English instanceCreate a pipeline component from a factory.name (unicode): Factory name to look up in `Language.factories`.config (dict): Configuration parameters to initialise component.RETURNS (callable): Pipeline component.DOCS: https://spacy.io/api/language#create_pipe
# Add labels to text classifier
textcat.add_label("ham") # 正常邮件
textcat.add_label("spam") # 垃圾邮件

3. 训练文本分类模型

数据获取

train_texts = spam['text'].values
train_labels = [{'cats': {'ham': label == 'ham','spam': label == 'spam'}} for label in spam['label']]

将 文本 和 对应的标签 打包

train_data = list(zip(train_texts, train_labels))
train_data[:3]

输出:

[
('Go until jurong point, crazy.. Available only in bugis n great world la e buffet... Cine there got amore wat...',{'cats': {'ham': True, 'spam': False}}),('Ok lar... Joking wif u oni...', {'cats': {'ham': True, 'spam': False}}),("Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005. Text FA to 87121 to receive entry question(std txt rate)T&C's apply 08452810075over18's",{'cats': {'ham': False, 'spam': True}})
]
  • 准备训练模型
  1. 创建优化器 optimizer nlp.begin_training(),spacy使用它更新模型权重
  2. 数据分批 minibatch
  3. 更新模型参数 nlp.update
from spacy.util import minibatchspacy.util.fix_random_seed(1)
optimizer = nlp.begin_training()# 数据分批
batches = minibatch(train_data, size=8)
# 迭代
for batch in batches:texts, labels = zip(*batch)nlp.update(texts, labels, sgd=optimizer)

这只是一次 epoch

>>> batch = [("1", True),("2", False)]
>>> texts, labels = zip(*batch)
>>> texts
('1', '2')
>>> labels
(True, False)

https://www.runoob.com/python/python-func-zip.html

  • 多次 epochs 迭代
import random
random.seed(1)
spacy.util.fix_random_seed(1)
optimizer = nlp.begin_training()loss = {}
for epoch in range(10):# 每次随机打乱数据random.shuffle(train_data)# 数据分批batches = minibatch(train_data, size=8)# 迭代for batch in batches:texts, labels = zip(*batch)nlp.update(texts, labels, drop=0.3, sgd=optimizer, losses=loss)print(loss)
# help(nlp.update)
Help on method update in module spacy.language:update(docs, golds, drop=0.0, sgd=None, losses=None, component_cfg=None) method of spacy.lang.en.English instanceUpdate the models in the pipeline.docs (iterable): A batch of `Doc` objects.golds (iterable): A batch of `GoldParse` objects.drop (float): The dropout rate.sgd (callable): An optimizer.losses (dict): Dictionary to update with the loss, keyed by component.component_cfg (dict): Config parameters for specific pipelinecomponents, keyed by component name.DOCS: https://spacy.io/api/language#update

输出:

{'textcat': 0.22436044702671132}
{'textcat': 0.41457826484549287}
{'textcat': 0.5661000985640895}
{'textcat': 0.7119002992385974}
{'textcat': 0.8301601885299159}
{'textcat': 0.9572314705652767}
{'textcat': 1.050187804254974}
{'textcat': 1.1268915971417424}
{'textcat': 1.2132206293363608}
{'textcat': 1.3000399094508472}

4. 预测

预测前先要将文本nlp.tokenizer一下

texts = ["Are you ready for the tea party????? It's gonna be wild","URGENT Reply to this message for GUARANTEED FREE TEA"]
docs = [nlp.tokenizer(text) for text in texts]
textcat = nlp.get_pipe('textcat')
scores, _ = textcat.predict(docs)
print(scores)

输出预测概率:

[[9.9999392e-01 6.1252954e-06][4.1843491e-04 9.9958152e-01]]

打印预测标签:

predicted_labels = scores.argmax(axis=1)
print([textcat.labels[label] for label in predicted_labels])
['ham', 'spam']

练习:

在上一个练习中,你为德法尔科餐厅做了一项非常出色的工作,以至于厨师为一个新项目雇佣了你。

餐厅的菜单上有一个电子邮件地址,游客可以在那里对他们的食物进行反馈。

经理希望你创建一个工具,自动将所有负面评价发送给他,这样他就可以修正它们,同时自动将所有正面评价发送给餐厅老板,这样经理就可以要求加薪了。

您将首先使用Yelp评论构建一个模型来区分正面评论和负面评论,因为这些评论包括每个评论的评级。你的数据由每篇评论的正文和星级评分组成。

1-2 星的评级为“负样本”4-5 星的评级为“正样本”3 星的评级是“中性”的,已经从数据中删除。

1. 评估方法

  • 上面方法的优势在于,你可以区分正面邮件和负面邮件,即使你没有标记为正面或负面的历史邮件。
  • 这种方法的缺点是,电子邮件可能与Yelp评论很不同(不同的分布),这会降低模型的准确性。例如,客户在电子邮件中通常会使用不同的单词或俚语,而基于Yelp评论的模型不会看到这些单词。
  • 如果你想知道这个问题有多严重,你可以比较两个来源的词频。在实践中,手动从每一个来源读几封电子邮件就足以判断这是否是一个严重的问题。
  • 如果你想做一些更花哨的事情,你可以创建一个包含Yelp评论和电子邮件的数据集,看看模型是否能从文本内容中分辨出评论的来源。理想情况下,您希望发现该模型的性能不佳,因为这意味着您的数据源是相似的。

2. 数据预处理、建模

  • 数据集切分
def load_data(csv_file, split=0.9):data = pd.read_csv(csv_file)# Shuffle datatrain_data = data.sample(frac=1, random_state=7)texts = train_data.text.valueslabels = [{"POSITIVE": bool(y), "NEGATIVE": not bool(y)}for y in train_data.sentiment.values]split = int(len(train_data) * split)train_labels = [{"cats": labels} for labels in labels[:split]]val_labels = [{"cats": labels} for labels in labels[split:]]return texts[:split], train_labels, texts[split:], val_labelstrain_texts, train_labels, val_texts, val_labels = load_data('../input/nlp-course/yelp_ratings.csv')
  • 查看训练数据
print('Texts from training data\n------')
print(train_texts[:2])
print('\nLabels from training data\n------')
print(train_labels[:2])

输出:

Texts from training data
------
["Some of the best sushi I've ever had....and I come from the East Coast.  Unreal toro, have some of it's available.""One of the best burgers I've ever had and very well priced. I got the tortilla burger and is was delicious especially with there tortilla soup!"]Labels from training data
------
[{'cats': {'POSITIVE': True, 'NEGATIVE': False}}, 
{'cats': {'POSITIVE': True, 'NEGATIVE': False}}]
  • 建模
import spacy
nlp = spacy.blank('en') # 建立空模型# Create the TextCategorizer with exclusive classes 
#                        and "bow" architecture
textcat = nlp.create_pipe('textcat',config={"exclusive_classes": True, # 排他的,二分类"architecture": "bow"
})# Add the TextCategorizer to the empty model
nlp.add_pipe(textcat)# Add NEGATIVE and POSITIVE labels to text classifier
textcat.add_label("NEGATIVE") # 负面邮件
textcat.add_label("POSITIVE") # 正面邮件

3. 训练

from spacy.util import minibatch
import randomdef train(model, train_data, optimizer, batch_size=8):loss = {}random.seed(1)random.shuffle(train_data)batches = minibatch(train_data, size=batch_size)for batch in batches:# train_data is a list of tuples [(text0, label0), (text1, label1), ...]# Split batch into texts and labelstexts, labels = zip(*batch)# Update model with texts and labelsmodel.update(texts, labels, sgd=optimizer, losses=loss)return loss
  • 训练
# Fix seed for reproducibility
spacy.util.fix_random_seed(1)
random.seed(1)# This may take a while to run!
optimizer = nlp.begin_training()
train_data = list(zip(train_texts, train_labels))
losses = train(nlp, train_data, optimizer)
print(losses['textcat'])
  • 测试下效果
text = "This tea cup was full of holes. Do not recommend."
doc = nlp(text)
print(doc.cats)

输出:

{'NEGATIVE': 0.7731374502182007, 'POSITIVE': 0.22686253488063812}

这杯茶不好喝,负类概率大

4. 预测

def predict(nlp, texts): # Use the model's tokenizer to tokenize each input textdocs = [nlp.tokenizer(text) for text in texts]# Use textcat to get the scores for each doctextcat = nlp.get_pipe('textcat')scores, _ = textcat.predict(docs)# From the scores, find the class with the highest score/probabilitypred_labels = scores.argmax(axis=1)return pred_labels

5. 评估模型

def evaluate(model, texts, labels):""" Returns the accuracy of a TextCategorizer model. Arguments---------model: ScaPy model with a TextCategorizertexts: Text samples, from load_data functionlabels: True labels, from load_data function"""# Get predictions from textcat model (using your predict method)predicted_class = predict(model, texts)# From labels, get the true class as a list of integers (POSITIVE -> 1, NEGATIVE -> 0)true_class = [int(label['cats']['POSITIVE']) for label in labels]# A boolean or int array indicating correct predictionscorrect_predictions = (true_class == predicted_class)# The accuracy, number of correct predictions divided by all predictionsaccuracy = sum(correct_predictions)/len(true_class)return accuracy
accuracy = evaluate(nlp, val_texts, val_labels)
print(f"Accuracy: {accuracy:.4f}")

输出:验证集准确率 92.39%

Accuracy: 0.9239
  • 多次迭代训练
# This may take a while to run!
n_iters = 5
for i in range(n_iters):losses = train(nlp, train_data, optimizer)accuracy = evaluate(nlp, val_texts, val_labels)print(f"Loss: {losses['textcat']:.3f} \t Accuracy: {accuracy:.3f}")
Loss: 6.752 	 Accuracy: 0.940
Loss: 4.105 	 Accuracy: 0.947
Loss: 2.904 	 Accuracy: 0.945
Loss: 2.267 	 Accuracy: 0.946
Loss: 1.826 	 Accuracy: 0.944

6. 改进

这里有各种超参数可以调节。最重要的超参数是TextCategorizer 的 architecture

上面使用的最简单的模型,它训练得快,但可能比 CNN 和 ensemble 模型的性能差


我的CSDN博客地址 https://michael.blog.csdn.net/

长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!
Michael阿明

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/473730.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django框架—富文本编辑器

借助富文本编辑器,网站的编辑人员能够像使用offfice一样编写出漂亮的、所见即所得的页面此处以tinymce为例,其它富文本编辑器的使用也是类似的在虚拟环境中安装包 pip install django-tinymce2.6.0安装完成后,可以使用在Admin管理中&#xf…

Python基础(二)--数据类型,运算符与流程控制

目录 Python基础(二)--数据类型,运算符与流程控制 1 数据类型 1.1 Python中的数据类型 1.2 整数类型(int) 1.3 布尔类型 1.4 浮点类型 1.5 复数类型 1.6 类型转换 2 运算符 2.1 算术运算符 2.2 布尔运算符 …

【Kaggle微课程】Natural Language Processing - 3. Word Vectors

文章目录1. 词嵌入 Word Embeddings2. 分类模型3. 文档相似度练习:1. 使用文档向量训练模型2. 文本相似度learn from https://www.kaggle.com/learn/natural-language-processing 1. 词嵌入 Word Embeddings 参考博文:05.序列模型 W2.自然语言处理与词…

Django搜索工具——全文检索

全文检索不同于特定字段的模糊查询,使用全文检索的效率更高,并且能够对于中文进行分词处理haystack:全文检索的框架,支持whoosh、solr、Xapian、Elasticsearc四种全文检索引擎,点击查看官方网站whoosh:纯Py…

LeetCode 787. K 站中转内最便宜的航班(Dijkstra最短路径 + 优先队列)

文章目录1. 题目2. 解题1. 题目 有 n 个城市通过 m 个航班连接。每个航班都从城市 u 开始,以价格 w 抵达 v。 现在给定所有的城市和航班,以及出发城市 src 和目的地 dst,你的任务是找到从 src 到 dst 最多经过 k 站中转的最便宜的价格。 如…

Windows Phone 资源管理与换肤思考

Windows Phone 资源管理与换肤思考 原文 Windows Phone 资源管理与换肤思考 新入手一台Windows 8的笔记本,安装了VS2013后,终于又可以开发WP了。公司暂时不愿意开发WP,那么咱就自行研究吧! 在没有WP开发环境的时候,曾经…

Django完成异步工具——celery

情景:用户发起request,并等待response返回。在本些views中,可能需要执行一段耗时的程序,那么用户就会等待很长时间,造成不好的用户体验,比如发送邮件、手机验证码等使用celery后,情况就不一样了…

Python基础(三)--序列

Python基础(三)--序列 1 序列相关的概念 1.1 什么是序列 序列是一种可迭代对象,可以存储多个数据,并提供数据的访问。 序列中的数据称为元素,Python内置的序列类型有:列表(list)…

项目上线最后工作——布署环境

当项目开发完成后,需要将项目代码放到服务器上,这个服务器拥有固定的IP,再通过域名绑定,就可以供其它人浏览,对于python web开发,可以使用wsgi、apache服务器,此处以wsgi为例进行布署服务器首先…

Python基础(四)--字典与集合

Python基础(四)--字典与集合 1 字典 1.1 什么是字典 字典提供的是一种映射存储的方式。字典分为两个部分,一个是键(key),一个是key所关联的值(value)。,一个键关联&am…

[Kaggle] Spam/Ham Email Classification 垃圾邮件分类(spacy)

文章目录1. 导入包2. 数据预览2. 特征组合3. 建模4. 训练5. 预测练习地址:https://www.kaggle.com/c/ds100fa19 相关博文: [Kaggle] Spam/Ham Email Classification 垃圾邮件分类(RNN/GRU/LSTM) [Kaggle] Spam/Ham Email Classifi…

电商网站(Django框架)—— 大纲内容与基本功能分析

1. 项目架构 2. 数据库表结构 3. 数据库读写分离 4. Django读写分离配置 新建utils/db_router.py 课后阅读资料 http://python.usyiyi.cn/documents/django_182/topics/db/multi-db.html 5. 用户认证模型 注意: AUTH_USER_MODEL配置参数要在第一次迁移数据库之…

Python基础(五)--函数

目录 Python基础(五)--函数 1 函数的作用 1.1 函数定义与调用 1.2 函数的作用 1.3 空语句 2 参数与返回值 2.1 函数的参数 2.2 函数的返回值 2.3 返回多个值 3 参数的默认值 3.1 可选参数 3.2 参数的默认值 4 位置参数与关键字参数 4.1 关键…

LeetCode 1024. 视频拼接(动态规划/贪心)

文章目录1. 题目2. 解题2.1 动态规划2.2 贪心1. 题目 你将会获得一系列视频片段,这些片段来自于一项持续时长为 T 秒的体育赛事。这些片段可能有所重叠,也可能长度不一。 视频片段 clips[i] 都用区间进行表示:开始于 clips[i][0] 并于 clip…

电商网站(Django框架)—— 思维导图

1.用户模块:注册、登录、激活、退出、个人中心、地址 2.商品模块:首页、详情、列表、搜索 3.购物车: 增加、删除、修改、查询 4. 订单模块:确认订单页面、提交订单(下单)、请求支付、查询支付结果、评论 5.…

Python基础(六)--类与对象

目录 Python基础(六)--类与对象 1 类与对象的基本概念 1.1 什么是对象 1.2 什么是类 1.3 类与对象的关系 2 定义与初始化 2.1 类的定义 2.2 对象的初始化 2.3 动态增加属性方法 3 类成员 3.1 类属性与实例属性 3.2 类方法与实例方法 3.3 静态…

HTTP和HTTPS的请求和响应

HTTP协议(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收 HTML页面的方法。 HTTPS(Hypertext Transfer Protocol over Secure Socket Layer)简单讲是HTTP的安全版,在HTTP下加入…

LeetCode 794. 有效的井字游戏(分类讨论)

文章目录1. 题目2. 解题1. 题目 用字符串数组作为井字游戏的游戏板 board。当且仅当在井字游戏过程中,玩家有可能将字符放置成游戏板所显示的状态时,才返回 true。 该游戏板是一个 3 x 3 数组,由字符 " ","X&quo…

Requests: 让 HTTP 服务人类

Requests支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动确定响应内容的编码,支持国际化的 URL 和 POST 数据自动编码。 Requests的文档非常完备,中文文档也相当不错。Requests能完全满足当前…

Python基础(七)--模块和包

目录 Python基础(七)--模块和包 1 模块 1.1 什么是模块 1.2 模块的使用 1.3 模块的搜索路径 1.4 模块的缓存 2 包 2.1 什么是包 2.2 包的使用 3 常用模块 3.1 math 3.2 random 3.3 time 3.4 datetime 3.5 sys Python基础(七&am…