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

news2024/11/20 0:27:07

一、说明

        我的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_tokenize

class SciKitTransformer(BaseEstimator, TransformerMixin):
  def fit(self, X=None, y=None):
    return self

  def 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_path
        self.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_path
        self.corpus = WikipediaReader(self.root_path)
        self.tokenizer = word_tokenize

    def 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 tokens
                text = re.sub(r'\s\.', '.', text)
                text = re.sub(r'\s,', ',', text)
                text = re.sub(r'\s;', ';', text)
                # remove all non character, non number chars
                preprocessed += ' '+ text.strip()
        return preprocessed
    def 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] = 0
            
        for token in tokens:
            one_hot[token] = 1
        return one_hot

    def 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 pd

from 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 StanfordTokenizer

class 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 self
  def transform(self, X=None):
    return self

class WikipediaCorpus(SciKitTransformer):
    def __init__(self, root_path=''):
        self.root_path = root_path
        self.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 X

class TextPreprocessor(SciKitTransformer):
    def __init__(self, root_path=''):
        self.root_path = root_path
        self.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 tokens
            text = re.sub(r'\s\.', '.', text)
            text = re.sub(r'\s,', ',', text)
            text = re.sub(r'\s;', ';', text)
            # remove all non character, non number chars
            preprocessed += ' '+ text.strip()
        return preprocessed

    def transform(self, X):
        X['preprocessed'] = X['raw'].apply(lambda text: self.preprocess(text))
        return X

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

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] = 0
        for token in tokens:
            one_hot[token] = 1
        return one_hot

    def transform(self, X):
        token_list = X['tokens']
        X['one-hot-encoding'] = X['tokens'].apply(lambda tokens: self.encode(token_list, tokens))
        return X

corpus = 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.coloradmin.cn/o/1075961.html

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

相关文章

【毕设选题】深度学习 机器视觉 车位识别车道线检测 - python opencv

0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过…

第二证券:如何选股票的龙头股?

在股票商场中&#xff0c;每个出资者的方针都是可以出资到那些未来可以表现出色并带领整个工作开展的龙头股。选股关于出资者来说非常要害&#xff0c;由于选股不妥或许会导致出资失利。那么&#xff0c;怎么选股票的龙头股呢&#xff1f;本文从多个角度进行剖析&#xff0c;协…

platformIO开发arduino

第一先安装arduino,再在arduino库里面安装第三方库。然后下载vscode,在vscode上安装platformIO&#xff0c;然后点击Quick Access下的Import Arduino Project 然后选择自己的arudino项目&#xff0c;一般在用户的Document下面 进入带有.ino后缀的文件夹里然后点击import就可以将…

C语言每日一题(10) 回形矩阵

题目链接 分析思路 我采用的设计思路是从外围开始向里面赋值&#xff0c;关键在于循环的判断条件&#xff0c;从外围的上下左右行依次赋值&#xff0c;然后再向里继续。 1.取得中心值的方法是&#xff1a;用n/2再向上取整&#xff0c;注意类型的转换&#xff0c;因为如果是整…

软件工程与计算总结(六)需求分析方法

本贴介绍需求分析方法&#xff0c;涉及到诸多实践性的东西&#xff0c;掌握各种图表的绘制是重中之重~ 一.需求分析基础 1.原因 需求获取中得到的信息仅仅解释了用户对软件系统的理解与期待&#xff0c;使用的是实际业务的表达方式&#xff0c;还不是开发者能够立即加以实现…

Ubuntu20.04安装Ipopt的流程介绍及报错解决方法(亲测简单有效)

本文主要介绍在Ubuntu20.04中安装Ipopt库的流程&#xff0c;及过程报错的解决方法&#xff0c;已经有很多关于Ipopt安装的博客&#xff0c;但经过我的测试&#xff0c;很多都失效了&#xff0c;因此&#xff0c;经过探索&#xff0c;我找到可流畅的安装Ipopt的方法&#xff0c;…

一站式数据可视化与分析平台JVS智能BI强大的数据节点功能

在商业智能&#xff08;BI&#xff09;中&#xff0c;数据集是数据的集合&#xff0c;用于分析和报告。数据节点是数据集中的一个重要组成部分&#xff0c;它代表数据集中的一个特定数据点或数据元素。通过使用数据节点&#xff0c;可以对数据进行过滤、分组和计算&#xff0c;…

Netty通信在中间件组件中的广泛使用-Dubbo3举例

Netty是一个高性能异步IO通信框架&#xff0c;封装了NIO&#xff0c;对各种bug做了很好的优化解决。所以很多中间件底层的通信都会使用Netty&#xff0c;比如说&#xff1a;Dubbo3&#xff0c;rocketmq&#xff0c;ElasticSearch等。 比方说&#xff0c;我们使用dubbo作为rpc跨…

批量混剪系统视频闪闪批量剪辑:只需几段素材片段即可批量混剪大量成片,快速制作大量成片的秘密

视频闪闪批量混剪系统&#xff1a;快速制作大量成片的秘密 在今天这个视频内容爆炸的时代&#xff0c;如何快速处理大量的素材并生成优质的成片&#xff0c;是许多视频制作人员面临的挑战。而视频闪闪批量混剪系统&#xff0c;却能帮助你轻松解决这一难题。 视频闪闪批量混剪…

Qt多工程同名字段自动翻译工具

开发背景 项目里不同工程经常会引用同一批公共类&#xff0c;这些类里如果有字段需要翻译&#xff0c;需要在不同的项目里都翻译一遍&#xff0c;比较麻烦冗余。 特此开发了这个小翻译工具&#xff0c;能读取程序目录下的所有ts文件&#xff0c;以类名归类&#xff0c;不同项目…

登陆认证权限控制(1)——从session到token认证的变迁 session的问题分析 + CSRF攻击的认识

前言 登陆认证&#xff0c;权限控制是一个系统必不可少的部分&#xff0c;一个开放访问的系统能否在上线后稳定持续运行其实很大程度上取决于登陆认证和权限控制措施是否到位&#xff0c;不然可能系统刚刚上线就会夭折。 本篇博客回溯登陆认证的变迁历史&#xff0c;阐述sess…

查找算法 —— 斐波拉契查找法

一、介绍 斐波拉契查找法是以分割范围进行查找的&#xff0c;分割的方式是按照斐波拉契级数的方式来分割。好处是&#xff1a;只用到加减运算&#xff0c;计算效率较高一些。 要使用斐波拉契查找首先需要定义一颗斐波拉契查找树&#xff0c;建立规则如下&#xff1a; 1.斐波拉契…

德国鞋履品牌【Birkenstock】申请15亿美元纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;德国鞋履品牌【Birkenstock】近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯达克IPO上市&#xff0c;股票代码为&#xff08;BIRK&#xff09;,Birkens…

Vue-1.9工程化开发和脚手架

开发Vue的两种方式&#xff1a; 1.核心包传统开发模式&#xff1a;基于html/css/js文件&#xff0c;直接引入核心包&#xff0c;开发Vue 2.工程化开发模式&#xff1a;基于构建工具&#xff08;例如&#xff1a;webpack&#xff09;的环境中开发Vue 问题&#xff1a; 1&…

如何安装TortoiseSVN并实现公网提交文件至本地SVN服务器?

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

设计模式16、中介者模式 Mediator

解释说明&#xff1a;中介者模式&#xff08;Mediator Pattern&#xff09;用一个中介对象来封装一系列的对象交互 中介者使各对象不需要显式地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互。 抽象中介者&#xff08;Mediator&#xff0…

Kaadas凯迪仕助力亚运盛会,尽展品牌硬核科技与智能锁行业风采

9月23日至10月8日&#xff0c;亚洲最大规模体育赛事亚运会在杭州举办。作为国际性体育赛事&#xff0c;除赛中的各类竞赛项目外&#xff0c;杭州亚运会前后相关活动也吸引了大众目光的聚焦。 Kaadas凯迪仕智能锁作为此次杭州亚运会官方指定智能门锁&#xff0c;以#凯迪仕守护每…

IP真人识别方法与代理IP检测技术

随着互联网的发展&#xff0c;IP地址在网络安全和数据分析中扮演着重要的角色。为了维护网络的安全性和识别真实用户&#xff0c;IP地址的真实性和来源成为了一个关键问题。 什么是IP真人识别&#xff1f; IP真人识别是一种技术&#xff0c;旨在确定IP地址背后的用户是否为真实…

深入理解RBAC

RBAC是一种基于角色实现访问控制的权限管理机制&#xff0c;通过定义角色和权限、用户和角色、角色和角色之间的关系&#xff0c;实现多层次、细粒度、可复用的权限管理系统。原文: Role-based Access Control (RBAC) Model[1] Bernard HermantUnsplash Avery Pennarun写的&quo…

XML文件详解 (java程序解析XML文件,java程序写XML文件)

XML 的全称是可扩展标记语言&#xff08;eXtensible Markup Language&#xff09; xml本质上是一种数据的格式&#xff0c;可以用来存储复杂的数据结构和数据关系。 使用XML&#xff08;可扩展标记语言&#xff09;有以下几个好处&#xff1a; 可读性强&#xff1a;XML使用标…