NLP项目:维基百科文章爬虫和分类【02】 - 语料库转换管道

一、说明

        我的NLP项目在维基百科条目上下载、处理和应用机器学习算法。相关上一篇文章中,展示了项目大纲,并建立了它的基础。首先,一个 Wikipedia 爬网程序对象,它按名称搜索文章,提取标题、类别、内容和相关页面,并将文章存储为纯文本文件。其次,一个语料库对象,它处理完整的文章集,允许方便地访问单个文件,并提供全局数据,如单个令牌的数量。

二、背景介绍

        在本文中,我将继续展示如何创建一个NLP项目,以从其机器学习领域对不同的维基百科文章进行分类。你将了解如何创建自定义 SciKit Learn 管道,该管道使用 NLTK 进行标记化、词干提取和矢量化,然后应用贝叶斯模型来应用分类。所有代码也可以在Jupyter Notebook中看到。

        本文的技术背景是 Python v3.11 和几个附加库,最重要的是 pandas v2.0.1、scikit-learn v1.2.2 和 nltk v3.8.1。所有示例也应该适用于较新的版本。

2.1 需求和使用的 Python 库

        请务必阅读并运行上一篇文章的要求,以便有一个 Jupyter 笔记本来运行所有代码示例。

        对于本文,需要以下库:这些步骤中的每一个都将成为管道对象的一部分,管道对象是读取、预处理、矢量化和聚类文本的顺序过程。我们将在此项目中使用以下 Python 库和对象:

pandas

  • DataFrame用于存储文本、标记和矢量的对象

sk-learn

  • Pipeline对象实现处理步骤链
  • BaseEstimator并生成表示管道步骤的自定义类TransformerMixin

NLTK

  • PlaintextCorpusReader 用于可遍历对象,可访问文档、提供标记化方法并计算有关所有文件的统计信息
  • sent_tokenizer 和 word_tokenizer 用于生成令牌
  • 减少标记的stopword列表

2.2 SciKit Learn Pipeline

        为了便于获得一致的结果和轻松定制,SciKit Learn 提供了 Pipeline 对象。该对象是一系列转换器、实现拟合fittransform变换方法的对象以及实现拟合fit方法的最终估计器。执行管道对象意味着调用每个转换器来修改数据,然后将最终的估计器(机器学习算法)应用于此数据。管道对象公开其参数,以便可以更改超参数,甚至可以跳过整个管道步骤。

         我们将使用此概念来构建一个管道,该管道开始创建语料库对象,然后预处理文本,然后提供矢量化,最后提供聚类或分类算法。为了突出本文的范围,我将在下一篇文章中仅解释转换器步骤,并接近聚类和分类。

三、管道准备

        让我们从大局开始。最终的管道对象将按如下方式实现:

pipeline = Pipeline([('corpus', WikipediaCorpus()),('preprocess', TextPreprocessor()),('tokenizer', Tokenizer()),('encoder', OneHotEncoder())
])

        然后,此管道从一个空的 Pandas 数据帧对象开始,随后将数据添加到该对象,即我们实现如下所示的数据帧对象:

        对于上述每个步骤,我们将使用自定义类,该类从推荐的 ScitKit Learn 基类继承方法。

from sklearn.base import BaseEstimator, TransformerMixin
from nltk.tokenize import sent_tokenize, word_tokenizeclass SciKitTransformer(BaseEstimator, TransformerMixin):def fit(self, X=None, y=None):return selfdef transform(self, X=None):return self

让我们开始实现。

3.1 管道步骤 1:创建语料库

        第一步是重用上一篇文章中解释的 Wikipedia 语料库对象,并将其包装在基类中,并提供两个 DataFrame 列 title 和 raw。在标题列中,我们存储除 .txt 扩展名之外的文件名。在原始列中,我们存储文件的完整内容。

        此转换使用列表推导式和 NLTK 语料库读取器的内置方法。

class WikipediaCorpus(PlaintextCorpusReader):def __init__(self, root_path):PlaintextCorpusReader.__init__(self, root_path, r'.*')class WikipediaCorpus(SciKitTransformer):def __init__(self, root_path=''):self.root_path = root_pathself.corpus = WikipediaReader(self.root_path)def transform(self, X=None):X = pd.DataFrame().from_dict({'title': [filename.replace('.txt', '') for filename in self.corpus.fileids()],'raw': [self.corpus.raw(doc) for doc in corpus.fileids()]})return X

3.2 管道步骤 2:文本预处理

        在 NLP 应用程序中,通常会检查原始文本中不需要的符号,或者可以删除的停用词,甚至应用词干提取和词形还原。

        对于维基百科的文章,我决定将文本分成句子和标记,而不是标记转换,最后将它们重新组合在一起。转换如下:

  • 删除所有停用词
  • 删除所有非ASCII字母,非数字标记
  • 仅保留 .,以及用于序列分隔,;.
  • 使用单个空格删除所有出现的多个空格

        这是 TextPreprocessor 的完整实现。 DataFrame 对象使用 Pandas apply 方法预处理的新列进行扩展。 

class TextPreprocessor(SciKitTransformer):def __init__(self, root_path=''):self.root_path = root_pathself.corpus = WikipediaReader(self.root_path)self.tokenizer = word_tokenizedef preprocess(self, text):preprocessed = ''for sent in sent_tokenize(text):if not len(sent) <= 3:text = ' '.join([word for word in word_tokenize(sent) if not word in stopwords.words("english")])text = re.sub('[^A-Za-z0-9,;\.]+', ' ', text)text = re.sub(r'\s+', ' ', text)# preserve text tokenstext = re.sub(r'\s\.', '.', text)text = re.sub(r'\s,', ',', text)text = re.sub(r'\s;', ';', text)# remove all non character, non number charspreprocessed += ' '+ text.strip()return preprocesseddef transform(self, X):X['preprocessed'] = X['raw'].apply(lambda text: self.preprocess(text))return X

3.3 管道步骤 3-标记化

        现在,使用与之前相同的 NLT word_tokenizer 对预处理后的文本进行再次标记化,但可以使用不同的标记化器实现进行交换。

        和以前一样,通过在预处理列上使用 apply 来扩展 DataFrame,添加一个新列 tokens。

class TextTokenizer(SciKitTransformer):def preprocess(self, text):return [token.lower() for token in word_tokenize(text)]def transform(self, X):X['tokens'] = X['preprocessed'].apply(lambda text: self.preprocess(text))return X

3.4 管道步骤 4:编码器

        对标记化文本进行编码是矢量化的先导。为了使本文保持重点,我将提供一种相当简单的编码方法,该方法计算所有文本的完整词汇表,并对特定文章中出现的所有单词进行独热编码。词汇表的基础是错误的:我使用精炼标记列表作为输入,但也可以使用NLTK-CorpusReader对象中的vocab方法。

class OneHotEncoder(SciKitTransformer):def encode(self, token_series, tokens):one_hot = {}for _, token_list in token_series.items():for token in token_list:one_hot[token] = 0for token in tokens:one_hot[token] = 1return one_hotdef transform(self, X):token_list = X['tokens']X['one-hot-encoding'] = X['tokens'].apply(lambda tokens: self.encode(token_list, tokens))return X

        这种编码非常昂贵,因为每次运行的完整词汇表都是从头开始构建的——这可以在未来的版本中改进。

四、完整的源代码

        以下是完整的示例:

import numpy as np
import pandas as pdfrom nltk.tokenize import sent_tokenize, word_tokenize
from nltk.corpus import stopwords
from sklearn.base import TransformerMixin
from sklearn.pipeline import Pipeline
from  nltk.corpus.reader.plaintext import CategorizedPlaintextCorpusReader
from nltk.tokenize.stanford import StanfordTokenizerclass WikipediaPlaintextCorpus(PlaintextCorpusReader):def __init__(self, root_path):PlaintextCorpusReader.__init__(self, root_path, r'.*')class SciKitTransformer(BaseEstimator, TransformerMixin):def fit(self, X=None, y=None):return selfdef transform(self, X=None):return selfclass WikipediaCorpus(SciKitTransformer):def __init__(self, root_path=''):self.root_path = root_pathself.wiki_corpus = WikipediaPlaintextCorpus(self.root_path)def transform(self, X=None):X = pd.DataFrame().from_dict({'title': [filename.replace('.txt', '') for filename in self.wiki_corpus.fileids()],'raw': [self.wiki_corpus.raw(doc) for doc in corpus.fileids()]})return Xclass TextPreprocessor(SciKitTransformer):def __init__(self, root_path=''):self.root_path = root_pathself.corpus = WikipediaPlaintextCorpus(self.root_path)def preprocess(self, text):preprocessed = ''for sent in sent_tokenize(text):text = ' '.join([word for word in word_tokenize(sent) if not word in stopwords.words("english")])text = re.sub('[^A-Za-z0-9,;\.]+', ' ', text)text = re.sub(r'\s+', ' ', text)# preserve text tokenstext = re.sub(r'\s\.', '.', text)text = re.sub(r'\s,', ',', text)text = re.sub(r'\s;', ';', text)# remove all non character, non number charspreprocessed += ' '+ text.strip()return preprocesseddef transform(self, X):X['preprocessed'] = X['raw'].apply(lambda text: self.preprocess(text))return Xclass TextTokenizer(SciKitTransformer):def preprocess(self, text):return [token.lower() for token in word_tokenize(text)]def transform(self, X):X['tokens'] = X['preprocessed'].apply(lambda text: self.preprocess(text))return Xclass OneHotEncoder(SciKitTransformer):def encode(self, token_series, tokens):one_hot = {}for _, token_list in token_series.items():for token in token_list:one_hot[token] = 0for token in tokens:one_hot[token] = 1return one_hotdef transform(self, X):token_list = X['tokens']X['one-hot-encoding'] = X['tokens'].apply(lambda tokens: self.encode(token_list, tokens))return Xcorpus = WikipediaPlaintextCorpus('articles2')
pipeline = Pipeline([('corpus', WikipediaCorpus(root_path='./articles2')),('preprocess', TextPreprocessor(root_path='./articles2')),('tokenizer', TextTokenizer()),('encoder', OneHotEncoder())
])

管道对象在 Jupyter 笔记本中呈现如下:

五、结论       

        SciKit Learn Pipeline 对象提供了一种将多个转换和机器学习模型堆叠在一起的便捷方法。所有相关的超参数都可以公开并配置以获得可重复的结果。在本文中,您学习了如何通过四个步骤为 Wikipedia 文章创建文本处理管道:a) WikipediaCorpus 用于访问纯文本文件和全局统计信息(例如单词出现次数),b) TextPreprocessor 用于从文本中删除符号和停用词,c) TextTokenizer从预处理的文本创建标记,d) OneHotEncoder 提供简单的统计,总语料库词汇中的单词出现在特定文章中。下一篇文章将继续如何将标记和编码转换为数值向量表示。

参考资料:塞巴斯蒂安

自然语言处理
Nltk

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

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

相关文章

@Mapper与@MapperScan注解

Mapper Mapper Mapper.xml文件 作用在dao&#xff08;mapper&#xff09;层上的一个注解&#xff0c;将接口生成一个动态代理类&#xff0c;有了这个注解就不用 再写Mapper.xml文件 如果缺少这个注解&#xff0c;运行项目就会报相应的错误 Field userMapper in com.example…

electron 升级 v22 遇到问题

Electron 漏洞 https://mp.weixin.qq.com/s/5LpSJb_5uV8EIDOl3fz9Tw 由于 23以上不在支持win 7 8 8.1 所以我选择安装 v22.3.24 electron 22.3.24 node-sass 6.0.1 sass-loader 10.4.1 对应的版本 npm i node-sass6.0.1 --sass_binary_sitehttps://npm.taobao.org/mirrors…

深度学习基础知识 BatchNorm、LayerNorm、GroupNorm的用法解析

深度学习基础知识 BatchNorm、LayerNorm、GroupNorm的用法解析 1、BatchNorm2、LayerNorm3、GroupNorm用法&#xff1a; BatchNorm、LayerNorm 和 GroupNorm 都是深度学习中常用的归一化方式。 它们通过将输入归一化到均值为 0 和方差为 1 的分布中&#xff0c;来防止梯度消失和…

深度神经网络压缩与加速技术

// 深度神经网络是深度学习的一种框架&#xff0c;它是一种具备至少一个隐层的神经网络。与浅层神经网络类似&#xff0c;深度神经网络也能够为复杂非线性系统提供建模&#xff0c;但多出的层次为模型提供了更高的抽象层次&#xff0c;因而提高了模型的能力。深度神经网络是一…

链表(3):双链表

引入 我们之前学的单向链表有什么缺点呢&#xff1f; 缺点&#xff1a;后一个节点无法看到前一个节点的内容 那我们就多设置一个格子prev用来存放前面一个节点的地址&#xff0c;第一个节点的prev存最后一个节点的地址&#xff08;一般是null&#xff09; 这样一个无头双向…

Golang 实现接口和继承

小猴子继承了老猴子&#xff0c;这样老猴子拥有的能力包括字段&#xff0c;方法就会自动的被老猴子继承。 小猴子不需要做任何处理就可以拿到老猴子的字段和它的方法&#xff0c;因为是继承关系。 但是小猴子还会其他的技能&#xff0c;比如还会像小鸟一样飞翔&#xff0c;希…

VR全景营销颠覆传统营销,让消费者身临其境

随着VR的普及&#xff0c;各种VR产品、功能开始层出不穷&#xff0c;并且在多个领域都有落地应用&#xff0c;例如文旅、景区、酒店、餐饮、工厂、地产、汽车等&#xff0c;在这个“内容为王”的时代&#xff0c;VR全景展示也是一种新的内容表达方式。 VR全景营销让消费者沉浸式…

计算机毕业设计选什么题目好?springboot 职业技术学院图书管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

【深度学习实验】卷积神经网络(八):使用深度残差神经网络ResNet完成图片多分类任务

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 构建数据集&#xff08;CIFAR10Dataset&#xff09; a. read_csv_labels&#xff08;&#xff09; b. CIFAR10Dataset 2. 构建模型&#xff08;FeedForward&#x…

SQL开发笔记之专栏介绍

Sql是用于访问和处理数据库的标准计算机语言&#xff0c;使用SQL访问和处理数据系统中的数据&#xff0c;这类数据库包括&#xff1a;Mysql、PostgresSql、Oracle、Sybase、DB2等等&#xff0c;数据库无非围绕着“增删改查”的核心业务进行开发。并且目前绝大多数的后端程序开发…

构建精致 Chrome 插件:开箱即用的 TypeScript 模板 | 开源日报 No.51

tonsky/FiraCode Stars: 72.7k License: OFL-1.1 Fira Code 是一种免费的等宽字体&#xff0c;具有编程连字符。 Fira Code 提供了丰富多样的箭头和标点符号调整功能。Fira Code 支持各种不同的字符变体、风格集和其他字体特性&#xff0c;以满足用户个性化需求。Fira Code …

【Hello Algorithm】暴力递归到动态规划(一)

暴力递归到动态规划&#xff08;一&#xff09; 斐波那契数列的动态规划机器人走路初级递归初级动态规划动态规划 先后选牌问题初级递归初级动态规划动态规划 我们可以一句话总结下动态规划 动态规划本质是一种以空间换时间的行为 如果你发现有重复调用的过程 在经过一次之后把…

Spring是什么?为什么要使用Spring?

目录 前言 一、Spring是什么&#xff1f; 1.1 轻量级 1.2 JavaEE的解决方案 二、为什么要使用Spring 2.1 传统方式完成业务逻辑 2.2 使用Spring模式完成业务逻辑 三、为什么使用Spring&#xff1f; 前言 本文主要介绍Spring是什么&#xff0c;并且解释为何要去使用Spring&…

c语言练习87:合并两个有序数组

合并两个有序数组 合并两个有序数组https://leetcode.cn/problems/merge-sorted-array/ 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff…

动态资源平衡:主流虚拟化 DRS 机制分析与 SmartX 超融合的实现优化

资源的动态调度是虚拟化软件&#xff08;或超融合软件&#xff09;中的一项重要功能&#xff0c;主要指在虚拟化集群中&#xff0c;通过动态改变虚拟机的分布&#xff0c;达到优化集群可用性的目标。这一功能以 VMware vSphere 发布的 Distributed Resource Scheduler&#xff…

day62:ARMday9,I2c总线通信

作业&#xff1a;按键中断实现LED1、蜂鸣器、风扇 key_in.c: #include "key_in.h"void gpio_init() {//RCC使能//GPIOERCC->MP_AHB4ENSETR | (0x1<<4);//GPIOBRCC->MP_AHB4ENSETR | (0x1<<1);//PE10、PB6、PE9输出模式GPIOE->MODER & ~(0…

AutoGPT:让 AI 帮你完成任务事情 | 开源日报 No.54

Significant-Gravitas/AutoGPT Stars: 150.4k License: MIT AutoGPT 是开源 AI 代理生态系统的核心工具包。它采用模块化和可扩展的框架&#xff0c;使您能够专注于以下方面&#xff1a; 构建 - 为惊人之作打下基础。测试 - 将您的代理调整到完美状态。查看 - 观察进展成果呈…

基于SpringBoot的网上订餐系统

基于SpringBoot的网上订餐系统的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 【主要功能】 角色&#xff1a;用户、管理员管理员&#xff1a;登录、个人中心、会员管理、…

TensorFlow入门(十二、分布式训练)

1、按照并行方式来分 ①模型并行 假设我们有n张GPU,不同的GPU被输入相同的数据,运行同一个模型的不同部分。 在实际训练过程中,如果遇到模型非常庞大,一张GPU不够存储的情况,可以使用模型并行的分布式训练,把模型的不同部分交给不同的GPU负责。这种方式存在一定的弊端:①这种方…

sklearn处理离散变量的问题——以决策树为例

最近做项目遇到的数据集中&#xff0c;有许多高维类别特征。catboost是可以直接指定categorical_columns的【直接进行ordered TS编码】&#xff0c;但是XGboost和随机森林甚至决策树都没有这个接口。但是在学习决策树的时候&#xff08;无论是ID3、C4.5还是CART&#xff09;&am…