自然语言处理
自然语言处理基础
自然语言处理技术概述
-
自然语言(Natural Language)
是指汉语,俄语,英语等随着人类社会的发展演化而来的语言,有别与人工语言(如计算机编程语言等,)它是人类交流的主要工具。
-
人工语言
是一种由人类设计和创建的语言,通常不是由自然语言演化而来,作为编程语言、机器人控制语言等特定领域的工具。
-
自然语言处理(Natural Language Processing,NLP)
是一门以人类社会的语言信息(如文本和语音)为主要研究对象,利用计算机技术来分析、处理、理解和生成人类语言,融合了计算机科学,人工智能,语言学,数学等内容的交叉学科,其最终目的市突破人类与计算机的交流瓶颈,提升热泪沟通的速度和效率。
-
NLP在人工智能领域的地位

-
NLP的应用

-
NLP两大核心任务
- 自然语言理解(Natural Language Understanding,NLU):研究的是计算机如何理解自然语言文本中包含的意义,将识别出来的文本信息转换成机器可以理解的语义表示。
- 自然语言生成(NaturalLanguageGeneration,NLG):研究的是计算机如何生成自然语言文本表达给定的意图、思想等,生成需要回复给用户的自然语言文本。
-
NLU与NLG关系

-
NLP三个层面分析
-
词法分析(LexicalAnalysis)
也叫词处理,是对输入文本进行单词级别的处理。这个过程包括分词、词性标注和命名实体识别等。分词是将输人文本分割成一个个单独的单词或短语,在此基础上才能进行后续的相关分析;词性标注是对每个单词赋予其对应的词性,如名词、动词、形容词等。一般来说,相同词性的词在句法中具有相似的位置,承担着类似的角色;命名实体识别是对文本中的人名、地名、机构团体名称等进行识别,分析出文本中具有特定意义的实体。
在词法分析阶段,一些关键术语包括:正/逆向最大匹配法、双向最大匹配法、正则表达式、隐马尔可夫模型、条件随机场模型、维特比算法等,这些算法是实现高效词法分析的关键。 -
句法分析(Syntactic Analysis)
是对单词组成的句子进行语法和结构上的分析。这个过程包括词组结构、句法结构和语义结构分析。词组结构分析是将单词组合成短语的过程;句法结构分析是将短语组合成句子的过程;语义结构分析是对句子的深层语义关系进行分析。语义分析通常以句法分析的输出结果作为输入,以便获得更多指示信息。
在句法分析阶段,一些关键术语包括:转移网络、递归神经网络、概率分布上下文无关语法等,这些算法是实现准确句法分析和语义理解的关键。 -
语义分析(SemanticAnalysis)
是对句子进行语义级别的处理。这个过程包括关系抽取和情感分析等,最终目的是理解句子表达的真实语义。关系抽取是在文本中的实体之间建立关联;情感分析是对文本中的情感倾向进行分析。
在语义分析阶段,一些关键术语包括:语义角色标注、基于逻辑表达的语义分析、关系抽取算法、情感分析算法等,这些算法是实现准确语义理解和情感分析的关键。
-
发展历程

-
萌芽期
1936年:艾伦-麦席森-图灵首次提出”图灵机“概念
1940~1950年:克劳德-艾尔伍德-香农把离散马科夫过程的概率模型应用于语言自动机
1952年:美国贝尔实验室开始探索语音识别系统。
1956年:埃弗拉姆-诺姆-乔姆斯基提出上下文无关语法,并将它应用于NLP中。
-
发展期
1960年后:法国格勒诺布尔大学的著名数学家沃古瓦开始了自动翻译系统的研制。
1990年后:在计算机技术的快速发展下,基于统计的NLP取得了相当程度的成果,开始在不同的领域里大放异彩。
1994年:万维网协会成立:在互联网的冲击下,产生了很多原来没有的计算模型,大数据和各种统计模型应运而生。
-
繁荣期
2006年,以杰弗里-辛顿为首的科学家历经20年努力,提出里神经网络深度学习算法。
雅虎搜索、谷歌、百度,以及大量的基于万维网的应用和各种社交工具,在不同的方面促进了NLP的发展进步
研究内容和应用场景
-
机器翻译
机器翻译旨在将一种自然语言的文本自动翻译成另一种自然语言的文本。
机器翻译利用计算机程序处理和分析文本,并使用语言规则、统计模型和人工智能算法等方法,将源语言(原始语言)文本转换成目标语言(所需翻译的语言)文本。
机器翻译的应用非常广泛,包括国际贸易、外交、跨文化交流、科学研究、语言学习等自然语言处理任务。
应用场景:翻译软件
翻译软件可以利用机器翻译技术将不同语言之间的文字、语音和图像内容进行快速自动翻译,实现跨语言交流。
例如,翻译软件的应用场景包括出境旅游、海外学习、国际商务等多个领域,可以为用户提供便捷和准确的翻译服务,提高用户的体验和交流效率。
机器翻译技术的应用和效果需要结合具体的语言和领域来进行评估和优化,尤其需要注意语言的差异性和翻译质量的保障。
-
问答系统
智能问答是一种人工智能技术,旨在帮助用户快速、准确地获得所需信息。
它使用自然语言处理、信息检索和机器学习等方法,可以理解用户提出的自然语言问题,并根据问题内容自动地在大规模数据源中寻找最佳答案。
智能问答系统可以广泛应用于在线客服、智能助手、搜索引擎、教育、医疗等自然语言处理任务。
应用场景:智能客服
智能客服机器人可以利用自然语言处理和机器学习等技术,对用户提出的问题进行理解和分析,并自动给出准确的答案和解决方案。
智能客服机器人的应用场景包括金融服务、电商售后、医疗咨询等多个领域,可以为用户提供快速便捷的服务,提高用户的满意度和信任度,坚持以人民为中心的发展思想。
智能问答技术的应用和效果需要结合具体的场景和需求来进行评估和优化,尤其需要注意语义理解和答案准确性等问题。
-
文本分类
文本分类旨在将文本分为预定义的类别或标签。
文本分类技术可以利用自然语言处理、机器学习、深度学习等方法,自动学习和识别文本的特征,然后将其分类到相应的类别中。
文本分类技术被广泛应用于新闻分类、情感分析、垃圾邮件过滤、产品分类等应用场景。
应用场景:
电商平台
文本分类技术可以自动学习和识别商品的特征,如商品名称、描述、图片等信息,并将其分类到相应的类别中,如服装、家具、电子产品等类别。
目前国内的主流电商平台已经广泛应用文本分类技术,从而提高了商品搜索的效率和准确性,促进了电商行业的快速发展。
-
信息抽取
信息抽取旨在从文本数据中自动提取结构化信息,如实体、关系和事件等。
信息抽取技术涉及自然语言处理、机器学习、数据挖掘和人工智能等多个领域,可以帮助人们快速准确地从大量的非结构化数据中获取有用信息。
信息抽取技术被广泛应用于搜索引擎、商业情报、新闻媒体、金融分析、医疗诊断等自然语言处理任务。
-
文本摘要
自动摘要旨在从文本数据中自动提取最重要的信息,生成一段简洁准确的摘要内容。
自动摘要技术涉及自然语言处理、机器学习、数据挖掘和人工智能等多个领域,可以帮助人们快速获取信息、节省时间和劳动成本。
自动摘要技术被广泛应用于新闻媒体、网络搜索、商业情报、金融分析、科学研究等自然语言处理任务。
应用场景:
新闻聚合应用APP
新闻聚合应用App利用自动摘要技术对海量的新闻内容进行处理和分析,自动抽取出新闻的核心内容和关键信息,并生成简洁明了的摘要。
通过自动摘要技术,新闻聚合应用App可以实现个性化推荐和快速阅读,从而提高用户的体验和满意度。
自动摘要技术的应用和效果需要结合具体的场景和需求来进行评估和优化,尤其需要注意信息准确性和可读性等问题。
-
话题推荐
话题推荐旨在根据用户的兴趣和需求,自动推荐相关的话题和内容,帮助用户快速获取所需信息并扩展知识面。
话题推荐技术涉及自然语言处理、机器学习、数据挖掘等多个领域,可以通过分析用户的搜索历史、浏览记录、社交网络等数据,来自动推荐与用户兴趣相关的话题和内容。
话题推荐技术被广泛应用于搜索引擎、社交媒体、新闻媒体等自然语言处理任务。
应用场景:社交媒体推荐
社交媒体可以利用话题推荐技术自动分析和识别用户感兴趣的话题,并向用户推荐相关的话题和内容。
社交媒体的话题推荐算法可以根据用户的兴趣和行为习惯,自动学习和调整推荐结果,从而提高用户的参与度和留存率。
话题推荐技术的应用和效果需要结合具体的场景和需求来进行评估和优化,尤其需要注意推荐的准确性和多样性等问题。
-
主题词识别
主题词识别旨在从文本数据中识别出最能代表该文本主题的关键词。主题词识别可以帮助人们快速理解文本的主题和重点,从而更好地获取有用信息。
主题词识别技术利用自然语言处理和机器学习等方法,根据文本的语法、语义、上下文等信息,自动提取出与文本主题相关的关键词。
主题词识别技术被广泛应用于搜索引擎、新闻媒体、社交媒体等自然语言处理任务。
应用场景:情感分析,短视频平台
短视频平台可以利用主题词识别技术对用户发布的视频进行情感分析,自动识别和分类出视频中包含的主题词和情感倾向,如欢乐、悲伤、惊喜等。
短视频平台的情感分析算法可以根据用户的观看历史和行为习惯,自动学习和调整分析结果,从而为用户推荐更加符合其兴趣和情感需求的短视频内容。可以提高短视频平台的用户体验和留存率。
主题词识别技术的应用和效果需要结合具体的场景和需求来进行评估和优化,尤其需要注意情感的多样性和表达方式的差异性等问题。
-
知识库构建
知识库构建旨在从大量的非结构化文本数据中自动抽取和组织出有用的知识,并将其存储在结构化的知识库中。
知识库构建技术可以通过自然语言处理、机器学习和数据挖掘等方法,自动从文本中抽取出实体、属性、关系和事件等信息,从而帮助人们快速获取和理解知识。
知识库构建技术被广泛应用于搜索引擎、智能问答、机器翻译、语义搜索、智能客服等自然语言处理任务。
应用场景:智能教育,在线教育平台
在线教育平台可以利用知识库构建技术,将丰富的教育资源组织成一个结构化的知识库,供教师和学生进行知识点的查询和学习。
知识库构建技术可以根据不同学科和教学阶段,自动学习和优化知识库的内容和结构,从而提高教学效果和学习成效。推进教育数字化,建设全民终身学习的学习型社会、学习型大国。
知识库构建技术的应用和效果需要结合具体的场景和需求来进行评估和优化,尤其需要注意知识的准确性和多样性等问题。
-
深度文本表示
深度文本表示旨在将自然语言文本表示为向量空间中的向量,从而实现文本的语义理解和文本分类等任务。
深度文本表示技术利用深度学习模型,如卷积神经网络、循环神经网络和Transformer等,通过多层神经网络模拟文本在向量空间中的表达,将词汇和语法结构转化为数学向量表示,从而提取出文本的重要语义信息。
深度文本表示技术被广泛应用于文本分类、情感分析、实体识别、关系抽取等自然语言处理任务。
应用场景:智能搜索引擎
搜索引擎可以利用深度文本表示技术,将用户输入的查询语句和网页内容进行深度理解和匹配,从而提高搜索结果的相关性和准确性。
搜索引擎的深度文本表示算法可以自动学习和提取出文本的特征和语义信息,包括词汇、句法和语境等多个方面,从而更加精准地理解用户的搜索意图和需求。
深度文本表示技术的应用和效果需要结合具体的领域和场景来进行评估和优化,尤其需要注意对文本的语义理解和表示的准确性、可解释性等问题。
-
命名实体识别
命名实体识别旨在自动识别文本中的实体,如人名、地名、组织机构名、时间、数字等,并将其分类到预定义的类别中。
命名实体识别技术利用自然语言处理和机器学习等方法,通过分析文本的语法、语义、上下文等信息,自动抽取出与实体相关的词汇,并将其分类到预定义的实体类型中。
命名实体识别技术被广泛应用于搜索引擎、情报分析、智能客服、金融分析等自然语言处理任务。
应用场景:金融产品推荐,银行理财产品
银行的命名实体识别算法可以自动识别和抽取出客户在交易中涉及到的命名实体,如股票名称、基金名称、债券名称等,从而实现更加精准的客户分析和风险控制。
命名实体识别技术在金融行业中的应用具有重要的价值,可以提高客户的投资收益和风险管理能力,促进金融行业的发展和稳定。
命名实体识别技术的应用和效果需要结合具体的场景和需求来进行评估和优化,尤其需要注意对命名实体的识别准确性和多样性等问题。
-
文本生成
文本生成(Text Generation)是一种自然语言处理技术,旨在通过计算机程序自动生成符合语法和语义规则的文本内容,可以是一句话、一段话,甚至是一篇文章。
文本生成技术利用自然语言处理、机器学习、神经网络等方法,学习和模拟人类语言的规律和模式,生成符合语言习惯和文化背景的语言输出。
文本生成技术被广泛应用于对话系统、智能客服、自动化写作、机器翻译、音乐创作等自然语言处理任务。
应用场景:智能写作工具
智能写作工具可以利用文本生成技术,自动生成符合要求的文章、短文和广告文案等。用户可以通过指定文章的主题、风格、字数、段落数等参数,得到一篇满足要求的文章,从而提高文案编写的效率和质量。
文本生成技术在智能写作领域中具有重要的应用价值,可以大幅度降低人工编写文本的时间和成本,促进信息产业的发展和创新。
文本生成技术的应用和效果需要结合具体的场景和需求来进行评估和优化,尤其需要注意文本的流畅性和自然度等问题。
-
文本分析
文本分析旨在对大量的非结构化文本数据进行处理和分析,从中提取出有用的信息。
文本分析技术可以利用自然语言处理、机器学习、数据挖掘等方法,自动识别和分类文本中的实体、情感、主题、关系等信息,从而帮助人们理解和应对文本数据中的挑战和机遇。
文本分析技术被广泛应用于市场调研、风险管理、智能客服、智能搜索等自然语言处理任务。
应用场景:主题建模
主题建模可以帮助用户从大量文本数据中自动发现主题或话题,并识别文本中隐含的语义信息和关系。
主题建模技术可以结合机器学习、深度学习等技术来实现,如概率主题模型、深度神经网络等,可以根据不同的数据特点和分析目标进行选择和调优。
文本分析技术在主题建模中的应用也需要考虑数据的多样性和异构性等问题,需要对文本数据进行预处理和清洗,选择合适的特征和模型进行分析和建模,以达到更好的效果和效率。
开发环境工具(Python环境)
-
NLTK
NLTK是一个Python中用于自然语言处理的工具包,它包含了一些用于处理文本数据的模型和算法,可用于处理如分词、词性标注、句法分析、语义分析、情感分析等任务。
NLTK支持多种语言,并提供了丰富的数据集和语料库,方便用户进行自然语言处理的研究和应用。
NLTK的文档和教程也比较详细,有助于用户快速入门和使用。
-
jieba
jieba是一款流行的基于Python的中文分词库,提供了简单易用的分词功能,支持四种分词模式:精确模式、全模式、搜索引擎模式、paddle模式,并支持繁体分词及自定义词典。jieba库还有C++/Java等十几种编程语言的版本,从PC端到移动端都可以支持。
-
spaCy
SpaCy是一个高效且功能强大的自然语言处理工具,能够进行分词、命名实体识别、词性标注、依存句法分析等任务。
SpaCy在处理速度上较快,在性能和准确率方面表现也较好,因此在实际应用中得到了广泛的应用。
SpaCy的特点是它支持多种语言,并提供了一些方便的接口和API,便于用户快速使用。
-
Gensim
Gensim是一个Python中用于处理文本数据的工具包,它可以帮助用户进行主题建模、相似度计算、词向量构建、文本聚类等任务。
Gensim的主要功能是构建词向量,通过Word2Vec等模型,Gensim可以将文本中的词转换成高维向量,从而使得文本可以进行计算和比较。
Gensim还支持多种语言和多种数据格式,如文本、XML等格式
-
HanLP
HanLP是一个基于Java实现的中文自然语言处理工具包,它也提供了Python语言的支持,可以帮助用户进行中文分词、词性标注、命名实体识别、句法分析等任务。
HanLP使用了一些比较先进的技术和算法,如CRF算法和深度学习等,在中文处理效果和速度上有一定的优势。
HanLP提供了一个方便易用的界面和API,也支持多种操作系统和语言。
-
TorchText
主要用于文本数据的预处理和文本分类、情感分析等自然语言处理任务。
Torchtext可以实现自动化数据的加载、数据的处理和训练数据集的构建,也可以通过使用其内置的词向量和词表构建词嵌入。
同时,Torchtext还提供了多种数据集处理方法和文本数据预处理功能。
项目开发流程

-
预料获取
利用已经构建好的数据集或第三方语料库。
获取网上数据。
制定数据收集策略获取数据。
与第三方合作获取数据。
-
预料预处理
-
预料清洗
**去除数据中非文本部分。**大多数情况下,获取到的文本数据存在很多无用的部分,如爬取的一些HTML代码、CSS标签和无用标点符号等,这些无用信息都需要分步骤去除。少量的非文本内容可以直接用Python的正则表达式删除,复杂的非文本内容可以通过Python的BeautifulSoup库去除。
-
中文分词
由于中文文本没有像英文单词空格隔开,不能直接像英文那样通过空格和标点符号完成分词,所以一般使用分词算法完成分词。常用的中文分词工具有很多,如jieba、FoolNLTK、HanLP、THULAC、NLPIR、LTP等。
-
词性标注
将自然语言中的每个词语与其所属的语法范畴(即词性)对应起来,如名词、动词、形容词等,常用的词性标注方法有基于规则的算法、基于统计的算法等。
-
去停用词
停用词是在文本处理中需要被过滤掉的一些常见词汇,如连词、介词、助词、代词、数词、形容词等,停用词通常对文本分析并无多大意义。中文文本中存在大量的虚词、代词,或者没有特定含义的动词、名词时,在文本分析过程中需要去掉。
-
-
文本向量化
文本数据经过预处理出去数据中非文本部分、中文分词和去停用词后,人无法直接将文本用于任务计算和模型训练,需要通过某些处理手段将文本量化为特征向量。课时调用的模型:
词袋模型(Bag of Words);
独热表示;
TF-IDF表示;
n元语法(n-gram)模型;
Word2vec模型等。
-
模型构建
在文本向量化后,根据文本分析的需求选择合适的模型,过于复杂的模型往往不是最优的选择,因为模型的复杂度和模型训练时间正相关,模型复杂度越高,模型训练时间越长,结果精度可能与简单模型差别不大。使用的模型主要包含机器学习和深度学习两种
机器学习模型:KNN、SVM、NaiveBayes、决策树、K-Means等。
**深度学习模型:**RNN、CNN、LSTM、Seq2Seq、FastText、TextCNN等。
-
模型训练
训练时可先使用小批量数据进行试验,避免出现直接使用大批量数据训练而导致训练时间过长等问题。
注意3个问题:
在训练集上表现很好,但在测试集上表现很差的过拟合问题;
模型不能很好地拟合数据的欠拟合问题;
防止出现梯度消失和梯度爆炸等问题。
-
模型评估
评价指标主要有准确率(Accuracy)、精确率(Logloss)、召回率、F1值、ROC曲线、AUC曲线等。
分类模型:准确率、精确率、AUC等。
同一种评价方法也往往适用于多种类的模型。对于实际的生产环境,模型性能评价的侧重点也不一样,不同的业务场景对模型的性能有不同的要求。
语音信号处理技术
语音信号处理技术概述
-
语音信号处理
语音信号处理是研究用数字信号处理技术对语音信号进行处理的一门学科,它以语音学与数字信号处理技术为基础,和心理学、生理学、语言学、计算机科学、通信与信息科学模式识别、人工智能等学科联系紧密,是涉及面很广的交叉学科。语音信号处理技术的发展依赖上述这些学科的发展,而语音信号处理技术的进步也会促进这些学科的进步。
-
语音信号处理的目的
- 通过处理(如语音信号预处理、数字化、特征提取等)得到一些反映语音信号重要特征的语音参数,以便高效地传输或存储语音信号信息。如siri、小爱同学
- 通过处理的某种运算达到某种用途的要求,如语音合成、语音识别等。
-
语音信号处理总体流程

发展历程
-
萌芽期
最初,人们将注意力放在语音信号的分析和合成上。
20世纪50年代,人们开始研究如何从语音信号中提取出语音特征,并将其用于语音识别。
20世纪70年代,出现了第一个语音识别系统,但它的准确性很低,只能识别出极少量的词汇。
-
发展期
20世纪80年代,语音处理技术得到了迅速发展,出现了基于神经网络的语音识别系统,准确率得到了显著提高。
20世纪90年代,语音处理技术进一步发展,出现了新的算法和方法,如隐马尔可夫模型(HMM)和高斯混合模型(GMM)。这些算法和方法被广泛应用于语音识别、语音合成、语音增强等领域。
-
繁荣期
21世纪以来,随着计算机技术和机器学习技术的快速发展,语音处理技术得到了进一步的发展。
深度学习技术的引入使得语音识别和语音合成的准确率和效果得到了显著提高。
同时,自然语言处理和语音处理技术的结合,使得语音识别和理解更加准确和精确。
此外,人们开始研究基于语音的情感分析、说话人识别等新的应用领域,推动了语音处理技术的不断发展和创新。
研究内容和应用场景
-
语音识别(ARS)
语音识别是指将语音信号转换为文字或语义信息的过程。
在语音信号处理方面,语音识别研究关注的主要问题是如何有效地将语音信号转换为数字信号,以便于计算机进行处理。
在自然语言处理方面,语音识别研究主要关注的问题是如何将语音信号转换为自然语言文本或语义信息。
语言识别是语音处理的重要应用之一。语音识别技术可以应用于语音控制、语音搜索、语音翻译等领域。
应用场景:语音助手
例如,使用语音助手向智能音箱发出指令:“播放音乐”或“增加音量”。
在语言助手应用场景中,语音识别技术可以将用户的语音指令转化为相应的文本,再由自然语言处理技术解析文本指令,从而实现语音交互。
-
语音合成
语音合成是一种人机交互技术,它将电脑内部的文字或语音指令转换成可听的人类语音,使计算机能够模拟人的语音和音乐表现能力,以便更好地与人类进行交互和沟通。
它需要多个学科的知识结合,包括语言学、信号处理、模式识别、计算机科学等。
语音合成技术可以应用于语音提示、语音导航等领域。
应用场景:自动朗读系统
例如,读书软件可以打开听书模式,自动朗读书籍内容。
在自动朗读系统应用场景中,自然语言处理技术会将文本转化为语音信号,再由语音合成技术将语音信号转化为声音,从而实现语音交互。
-
语音增强
语音增强是指对**低质量的语音信号进行处理,提高信号的清晰度和质量****。
语音增强的研究内容有语音信号降噪,去除噪声;增强语音信号的特征,如声音的清晰度、响度等;生源定位和跟踪,确定语音信号的源头位置和运动轨迹,以便更好地进行语音增强和信号分离。此外,研究如何在语音增强的同时提高语音识别的准确率也是一个重要的方向。
语音增强技术可以应用于语音通信、语音会议等领域。
应用场景:录音和广播
在录音和广播领域,语音增强技术可以提高录音质量,减少环境噪声、风吹声等对语音的干扰,使录音或广播的内容更加清晰、易于听取。
通过应用语音增强技术,可以提升语音信号的品质和可识别性,改善语音交互的效果,在各种语音应用场景中提供更好的用户体验和功能性。
-
声音识别
声音识别是指识别不同声音的能力,包括背景噪声、环境声音和人声等。
其主要研究内容包括语音信号处理、语音特征提取、声学模型训练,以及语言模型训练等方面。
声音识别技术可以应用于安防领域、环境监测等领域。
应用场景:出入口身份验证
通过识别不同的声音来源,将人的声音特征用于身份验证和鉴别,声音识别技术可以应用于出入口控制系统,如公司大门、安全区域、特定场所的身份验证。
该应用通过分析和比对访问者的声音特征,能够快速准确地识别合法人员,并且授权其进入或离开特定区域。
开发环境工具(Python环境)
-
Wave
Wave支持许多不同的音频格式,如WAV、AIFF和MP3等。
Wave提供了读取和写入WAV文件的功能,并允许用户对音频信号进行基本操作,如采样率转换、截断、归一化等。
Wave的优点是它易于使用,不需要安装额外的库,适合初学者入门。
-
librosa
Librosa是一个开源的Python库,专门用于音频和音乐信号处理,是深度学习中音频处理的重要工具之一,可用于语音识别、情感识别等任务。
Librosa提供了一系列功能,如读取、处理、可视化音频文件,以及实现一些音频特征提取和转换,如梅尔频率倒谱系数(MFCC)、光谱质心等。它可以用于许多不同的音频应用中,如音乐信息检索、语音识别等。
Librosa支持多种音频格式,如WAV、MP3、FLAC等。
-
Torchaudio
Torchaudio是PyTorch的一个扩展库,用于音频和语音信号处理。Torchaudio提供了一系列音频处理函数,如音频读取、变换、增强、转换等函数,以及支持多种音频格式的解码器。
Torchaudio与PyTorch紧密集成,可以直接处理音频数据,方便深度学习中的音频分类、语音识别等任务。
TorchAudio可以用于读取和写入音频文件、应用数字信号处理、生成声音、提取音频特征等。
-
PaddleSpeech
PaddleSpeech是飞桨(PaddlePaddle)的一个扩展库,专门用于语音信号处理和语音识别。
提供了一些预训练模型,如DeepSpeech2、Transformer-Transducer等,以及音频处理函数,如音频读取函数read_wav、音频特征提取函数transform、语音增强函数SpecAugment等。
PaddleSpeech支持多种任务,如语音识别、语音合成等。
项目开发流程

-
音频加载
在语音处理中,需要将音频文件加载到内存中,以便后续处理。
音频文件通常是以WAV、MP3等格式保存的,可以使用相应的库或工具来读取对应格式的音频文件。
-
数据预处理
- 需要进行采样率转换,将原始语音信号的采样率调整为模型所需的采样率;
- 进行去噪处理,通过降低或消除背景噪音来提高语音信号的质量;
- 进行音频分割,将长的语音信号分割成较短的音频段,以便后续处理;
- 进行音量归一化,调整音频的音量级别,使其在一定范围内统一。
语音数据预处理有助于提高语音信号的质量,并为特征提取和语音识别阶段提供更好的输入。
-
特征提取
将音频数据转化为数值特征,以便后续的建模和分析。
常用的语音特征包括短时能量、过零率、梅尔频率倒谱系数(MFCC)等。
MFCC是目前应用较为广泛的一种特征,可以通过将音频信号转化为频谱图,并在此基础上应用一系列滤波器、对数变换等操作来计算得到。
-
模型构建
模型构建是指根据任务需求选择合适的模型,并进行模型设计和实现。
语音处理中,常用的模型包括基于传统机器学习方法的模型(如支持向量机、决策树等)和基于深度学习的模型(如卷积神经网络、循环神经网络等)。
-
模型训练
需要使用标注好的语音数据对模型进行训练。
训练数据通常被分为训练集、验证集和测试集。
•训练集用于训练模型参数,验证集用于调整模型参数和选择最佳模型;
•测试集用于评估模型的性能。
-
模型评估
评价指标包括准确率、召回率、F1值等。
在语音处理中,还需要使用一些特定的评价指标来评估模型的性能,如音频识别任务中的识别率、语音合成任务中的自然度和流畅度等。
根据评价结果,可以对模型进行优化和改进
部署Python开发环境
安装Anaconda
-
下载Anaconda安装包。通过官方镜像或国内镜像源下载历史版本,本项目将安装2020.07版本的Anaconda。此处将通过清华镜像源下载Anaconda安装包,即打开清华大学TUNA网站,并单击“开源镜像站”图标。

mirrors.tuna.tsinghua.edu.cn -
在镜像列表中找到“anaconda”选项,并单击进入。

-
在anaconda列表中,单击“archive/”进入Anaconda历史版本页面。

-
在archive列表中,找到“Anaconda3-2020.07”开头的文件,选择与自己计算机对应的操作系统版本,并进行下载。本项目以Windows操作系统为例,单击“07-Windows-x86_64.exe”即可进行下载。

-
Anaconda安装包下载完成后,双击已下载好的安装包,单击“Next”按钮。

-
单击“I Agree”按钮,同意相关协议并进入下一步。

-
选择图所示的“All Users(requires admin privileges)”单选按钮,并单击“Next”按钮进入下一步。

-
单击“Browse”按钮,选择合适的安装路径(注:路径名称最好为全英文),选择完成后单击“Next”按钮进入下一步。

- 在图中,第一个选项表示Anaconda自动添加环境变量,本项目将不做勾选,因为自动添加环境变量后,使用时有可能会出现问题,以致于后续需要手动添加环境变量;第二个选项表示Anaconda使用的Python版本为3.8,此处将勾选以配置Python 3.8,然后单击“Install”按钮,开始安装。

-
安装完成后,将会出现“Installation Compelete”提示,此时单击“Next”。

-
单击图中的“Finish”按钮即可完成Anaconda安装。

配置环境变量
-
在系统搜索栏中搜索“环境变量”,单击“编辑系统环境变量”;在“高级”列表下,单击“环境变量”按钮。

-
在“系统变量”下,找到并选中“Path”变量,单击“编辑”按钮,弹出“编辑环境变量”对话框。

-
单击“新建”按钮,将Anaconda的安装路径加入环境变量中,随后单击“确定”按钮完成环境变量的添加。

-
检验Anaconda是否安装成功:
-
打开CMD,在CMD中输入“python”并回车后,将会启动Python解释器,并列出版本号信息和一些帮助信息,以及一个命令提示符“>>>”,等待用户输入Python代码,则表示Python环境配置成功。

-
关闭Python解释器,在CMD中输入“conda info”命令,将会显示当前conda环境的信息。若显示如图所示的信息,则说明Anaconda完成安装,否则需要到安装路径下找到uninstall文件卸载重装。

-
配置NLP环境
-
在Anaconda Prompt中安装NLTK库
pip install nltk -
安装自然语言及语音信号处理常用库
库名 安装命令 jieba pip install jieba sklearn-crfsuite pip install sklearn-crfsuite pandas pip install pandas Gensim pip install gensim NumPy pip install numpy PyPDF2 pip install PyPDF2 pyhanlp pip install pyhanlp scikit-learn pip install scikit-learn Matplotlib pip install matplotlib NLP pip install snownlp Imageio pip install imageio WordCloud pip install wordcloud hanlp_restful pip install hanlp_restful snowNLP pip install snownlp Beautiful Soup pip install bs4 openpyxl pip install openpyxl -
查看所有安装的库(包含Anaconda自带标准库)
pip list -
NLTK数据包装载
import nltk nltk.download('punkt') nltk.download('stopwords') nltk.download('averaged_perceptron_tagger') nltk.download('wordnet') nltk.download('punkt_tab') -
测试NLTK库
#测试一 import nltk # 导入自然语言工具包(NLTK)库,提供文本处理功能 # 示例文本 text = "Hello, World! This is a sample text for NLP analysis." # 定义待处理的原始文本字符串 # 1. 分词处理 tokens = nltk.word_tokenize(text) # word_tokenize()函数:将文本拆分为单词和标点符号的列表 # 处理过程:识别单词边界,处理缩写和标点符号 # 输出示例:['Hello', ',', 'World', '!', 'This', ...] print(tokens) # 打印分词结果 # 2. 停用词过滤 stop_words = set(nltk.corpus.stopwords.words('english')) # stopwords.words('english'):加载英语停用词列表(常见无意义词汇如"is","a"等) # 转换为set提高查询效率 filtered_tokens = [token for token in tokens if token.lower() not in stop_words] # 列表推导式过滤停用词: # 1. 将每个token转为小写 # 2. 检查是否不在停用词集合中 # 3. 保留非停用词的原始形式(保留大小写) print(filtered_tokens) # 打印过滤后的词列表 # 3. 词性标注 pos_tags = nltk.pos_tag(tokens) # pos_tag()函数:为每个token标注词性(Part-of-Speech) # 使用Penn Treebank标签集: # - NN(名词), VB(动词), JJ(形容词)等 # 处理过程:基于上下文概率模型预测 print(pos_tags) # 打印带词性标注的元组列表 # 示例:[('Hello', 'NNP'), (',', ','), ('World', 'NNP'), ...] #测试二 import nltk # 导入自然语言工具包(NLTK)库,提供文本处理功能 # 示例文本 text1 = "I love natural language processing" # 定义待处理的原始文本字符串 # 1. 分词处理 (Tokenization) tokens = nltk.word_tokenize(text1) # word_tokenize()函数:基于Penn Treebank分词标准 # 处理过程:识别单词边界,处理特殊符号和缩写 # 注意:首次使用需下载punkt分词模型(nltk.download('punkt')) print("分词结果是:", tokens) # 输出示例:['I', 'love', 'natural', 'language', 'processing'] # 2. 停用词过滤 (Stopword Removal) stop_words = set(nltk.corpus.stopwords.words('english')) # stopwords.words():加载预定义的英语停用词列表 # 转换为集合(set)提高查询效率(O(1)时间复杂度) # 注意:首次使用需下载stopwords语料库(nltk.download('stopwords')) filtered_tokens = [token for token in tokens if token.lower() not in stop_words] # 列表推导式实现过滤: # 1. token.lower()统一转为小写比较 # 2. 保留不在停用词集合中的词汇 # 3. 保留原始大小写形式输出 print('去停用词结果:', filtered_tokens) # 输出示例:['love', 'natural', 'language', 'processing'] # 3. 词性标注 (POS Tagging) pos_tags = nltk.pos_tag(filtered_tokens) # pos_tag()函数:使用Penn Treebank标签集 # 标注原理:基于预训练的序列标注模型 # 常见标签:NN(名词), VB(动词), JJ(形容词)等 # 注意:首次使用可能需下载averaged_perceptron_tagger print("词性标注的结果:", pos_tags) # 输出示例:[('love', 'VB'), ('natural', 'JJ'), ('language', 'NN'), ('processing', 'NN')] # 补充说明:完整流程需确保已下载NLTK数据包 # nltk.download(['punkt', 'stopwords', 'averaged_perceptron_tagger'])
-
验证jieba库
import jieba text2 = "我喜欢自然语言处理!" jieba.lcut(text2)
-
语音信号处理常见库
库名 安装命令 Librosa pip install librosa python-speech-features pip install python-speech-features SciPy pip install scipy hmmlearn pip install hmmlearn pyttsx3 pip install pyttsx3 pathlib2 pip install pathlib2 soundfile pip install soundfile yacs pip install yacs
安装PyTorch框架
安装显卡驱动
-
安装NVIDIA图形驱动程序,进入NVDIA官网(www.nvidia.cn)选择对应显卡的版本,下载相应的显卡驱动安装包,随后选择精简,单击“下一步”即可开始安装。

-
NVDIA驱动安装完成后,打开CMD输入“nvidia-smi”命令,即可查看CUDA版本。

-
验证CUDA是否安装成功,可以通过CMD输入“nvcc --version”与“set cuda”命令进行查看,前者可以显示安装的CUDA版本号,后者可以查看CUDA设置的环境变量。

-
安装好CUDA后,若需要使用GPU加速深度学习计算,则建议安装cuDNN;若只使用CPU进行运算,则可以直接进入下一步安装PyTorch。进入NVIDIA开发者网站NVIDIA.DEVELOPER网页,搜索“cuDNN”,即可搜索进入cuDNN下载页面。

-
单击“Download cuDNN”进入下载网页(注意:该步骤需要读者自行注册账号才能下载),再选择对应安装的CUDA的版本进行下载即可。

-
cuDNN下载好以后,将所得的文件进行解压,然后将文件复制到CUDA的安装目录下,通常在路径C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\版本号下,若有文件,则覆盖原有文件即可。
安装PyTorch框架
-
进入PyTorch官网(pytorch.org/get-started/previous-versions),找到官网中的“Previous versions of PyTorch”按钮,并单击进入历史版本下载界面,找到与CUDA版本对应的PyTorch安装命令,本项目将安装1.4.0版本的PyTorch。

-
复制Linux and Windows下的代码,在开始菜单栏下,打开“Anaconda Prompt”,并将复制后的代码进行粘贴后运行,即可成功安装PyTorch。
conda install pytorcn==2.2.0 torchvision==0.17.0 torchaudio==2.2.0 pytorch-cuda=12.1 -c pytorch -c nvidia在所有库安装完成后,打开“Anaconda Prompt”,输入“conda list”命令,即可查看所有已经安装的库,其中,包含Anaconda自带的标准库,可以清晰查看到本项目安装后的PyPDF2和pyhanlp库。

-
验证PyTorch库
import torch x = torch.rand(6,3) print(x) torch.cuda.is_available()
安装PaddlePaddle框架
-
安装PaddlePaddle和相关依赖,在PaddlePaddle官网(www.paddlepaddle.org.cn)的“安装”栏目下,找到PaddlePaddle的安装命令。此处选择Windows操作系统、pip安装方法、CPU设备,表示计划在没有GPU加速的Windows系统环境中进行PaddlePaddle的使用和开发。

-
在CMD中运行以下命令,使用pip安装PaddlePaddle 2.4.2版本,即可安装PaddlePaddle深度学习框架及其相关依赖。

-
安装PaddleAudio和PaddleSpeech库,它们都是基于PaddlePaddle深度学习框架开发的语音处理库,因此在安装它们之前,需要确保已经成功安装了PaddlePaddle深度学习框架。注意:在该步骤中,不需要进行其他环境的配置。
在CMD中运行以下命令,使用pip安装PaddleSpeech 1.2.0和PaddleAudio 1.0.1。
pip install paddlespeech==1.2.0 pip install paddleaudio==1.0.1
-
验证PaddleAudio库(提前准备音频文件)
import paddleaudio as pa audio,sr = pa.load('../data/NLP.wav') print(f'采样率:{sr}') print(f'音频形状:{audio.shape}')
使用Python正则表达式包
-
文件的打开和关闭
open(文件路径,打开模式)
文件路径:使用绝对路径或相对路径
打开模式:只读,写入,追加等。
模式 描述 r 以只读方式打开文件,文件指针会放在文件开头,如果文件不存在,则报错。默认打开方式 w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,这里需要注意的是原有内容会被删除。如果该文件不存在,则创建新文件。 a 打开一个文件用于追加,如果该文件已经存在,文件指针会放在文件的结尾,也就是说,新的内容将会被写入到已有内容之后,如果文件不存在,则创建新文件并写入。 # 打开文件 f1 = open('D:/test.txt','r') f2 = open('D:/test.txt','w') f3 = open('D:/test.txt','a') -
文件操作
方法 描述 file.read([size]) 从文件读取指定的字节数,如果size未给定或给负值,则读取整个文件 file.readline() 读取一行内容 file.readlines([size]) 读取所有行并返回列表,如果给定size的值,则读取对应行数 file.write(str) 将字符串写入文件,如果要写入字符串以外的数据,需先将其转换为字符串 file.tell() 返回当前文件指针的位置 f.close 关闭文件 -
异常处理
文件读写时可能出现IO读写异常,一旦出错,close()无法执行
try: f = open('file.txt') except IOError as e: print(e) else: print('wrong') finally: if f: f.close()with方法自动调用close()
with open('123.txt','r') as f: data = f.read() -
字符串运算
操作符 说明 + 字符串连接 * 重复输出字符串 [] 通过索引获取字符串中字符 [:] 截取字符串中的一部分 in 成员运算符,如果字符串中包含给定的字符返回True not in 成员运算符,如果字符串中不包含给定的字符串返回True r/R 原始字符串,所有的字符串都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符。 原始字符串除在字符串的第一个引号前加上字母“r”(不分大小写)以外,与普通字符串有着几乎完全相同的语法。 % 格式字符串 split 拆分字符串 join 合并字符串 replace 字符串替换 a = "Hello" b = "Python“ print("a + b 输出结果:", a + b) #HelloPython print("a * 2 输出结果:", a * 2) #HelloHello print("a[1] 输出结果:", a[1]) #e print("a[1:4] 输出结果:", a[1:4]) #ell #成员运算法 if( "H" in a) : print("H 在变量 a 中") #H 在变量 a 中 else : print("H 不在变量 a 中") if( "M" not in a) : print("M 不在变量 a 中") #M 不在变量 a 中 else : print("M 在变量 a 中") #原始字符串 print (r'\n') #\n print (R'\n') #\n #拆分字符串 str1 = "one,two,three" strlist = s.split(",") for list in strlist: print(list) #one two three #合并字符串 str2 = ['one','two','three'] strs = ','.join(str2) print(strs) #查找字符串-str对象自带方法 #语法:str.replace(old,new[,max]) old = 'Hello World' new = old.replace('World','Python') print(new) # 查找字符串-Python正则表达式查找 # 语法:re.sub(pattern,repl,string,count=0) # pattern:正则中的模式字符串 # repl:替换的字符串,也可为一个函数 # string:要被查找替换的原始字符串 # count:模式匹配后替换的最大次数,默认为0,表示替换所有的匹配 import re s='cat1 cat2 cat3 in the xxx' print(re.sub('cat[0-9]','CAT',s)) -
正则表达式
re模块
正则表达式是对字符串进行模糊匹配,提取需要的字符串部分,对所有语言都通用。
Re模块是python独有的匹配字符串的模块,该模块提供的很多功能是基于正则表达式实现的。
发
re.match():从字符串的起始位置匹配一个字符串
re.match(pattern, string, flags)
Pattern: 正则表达式
String: 表示要匹配的字符串
Flags:标志位,可选,用于控制正则表达式的匹配方式
re.S:在python中“.”可以匹配除了换行符的所有字符,使用该标志后,可以匹配所有字符,包括换行符;
re.I:字符串在匹配的时候不区分大小写;
print(re.match('www', 'www.runoob.com')) print(re.match('www', 'www.runoob.com').span()) print(re.match('www','www.runoob.com').group()) print(re.match('com', 'www.runoob.com')) print(re.match('....run','www.runoob.com')) print(re.match('.....run','\nwww.runoob.com')) print(re.match('.....run','\nwww.runoob.com',re.S)) print(re.match('WWW.run','www.runoob.com')) print(re.match('WWW.run','www.runoob.com',re.I))re,search(regex,string):扫描整个字符串并返回第一个成功匹配的字符串
regex:匹配的正则表达式
string:要匹配的字符串
print(re.search('www', 'www.runoob.com')) print(re.search('www', 'www.runoob.com').span()) print(re.search('www','www.runoob.com').group()) print(re.search('com', 'www.runoob.com')) -
获取包含“自然语言处理”的句子
import re regex = "自然语言处理" text_string = "NLP(Natural Language Processing,自然语言处理)是计算机科学领域以及人工智能领域的一个重要的研究方向。NLP指的是对人类语言进行自动的计算处理,是在机器语言和人类语言之间沟通的桥梁,以实现人机交流的目的。自然语言处理有两个核心任务,一个是自然语言理解,另外一个是自然语言生成。自然语言理解是希望计算机可以理解自然语言,简单来说,就是理解语言、文本等,提取出有用的信息。自然语言生成根据提供的数据、文本、图表、音频、视频等,生成人类可以理解的自然语言形式的文本。" lines = text_string.split("。") for line in lines: if re.search(regex, line) is not None: print(line) -
正则表达式中特殊符号含义
符号 含义 . 匹配除换行符外的任意字符 ^ 匹配开始的字符 $ 匹配结束的字符 [] 匹配多个字符 [^] 匹配不在[]中的字符 * 匹配一个字符串0次或者无限次 + 匹配一个字符串1次回这无限次 ? 匹配一个字符串0次或1次 {m} 匹配一个字符串m次 {n,} 匹配一个字符串至少n次 {m,n} 匹配一个字符串m到n次 \s 匹配空白字符 \w 匹配任意字母、数字、下划线 \W 匹配除字母、数字、下划线以外的任意字符 \d 匹配数字0到9 \D 匹配数字以外的任意字符 import re regex1 = 'a..' #匹配包含'a..'的字符串 regex2 = '^a' #匹配以'a'开头的字符串 regex3 = 'c$' #匹配以'c'结尾的字符串 regex4 = '[ab]' #匹配包含'a'或者'b'的字符串 text_string = '!a a b c ab bc ac abc abcd' lines = text_string.split(' ') print("匹配包含'a..'的字符串") for line in lines: if re.search(regex1, line) is not None: print(line, end=' ') print("\n匹配以'a'开头的字符串") for line in lines: if re.search(regex2, line) is not None: print(line, end=' ') print("\n匹配以'c'结尾的字符串") for line in lines: if re.search(regex3, line) is not None: print(line, end=' ') print("\n匹配包含'a'或者'b'的字符串") for line in lines: if re.search(regex4, line) is not None: print(line, end=' ') # 匹配数字形式字符串 strings = ['born in 1995','There are 5280 feet to a mile','Happy new year 2020!'] for str in strings: if re.search('[1-2][0-9]{3}',str): print(str) # 返回所有匹配参加鞥给的字符串 re.findall('[a-z]','abcd123') -
根据标点符号进行分句
-
使用Python分句
def cut_sentences(content): """将包含中文标点的文本分割成句子列表 参数: content: 待分割的文本字符串 返回: 分割后的句子列表 """ # 定义句子结束标志符号 end_flag = ['?', '!', '。', '…', '.'] content_len = len(content) sentences = [] # 存储分割后的句子 tmp_char = '' # 临时存储当前正在处理的字符 # 遍历文本中的每个字符 for idx, char in enumerate(content): tmp_char += char # 将当前字符加入临时字符串 # 处理文本末尾情况 if (idx + 1) == content_len: sentences.append(tmp_char) break # 遇到句子结束标志时处理 if char in end_flag: next_idx = idx + 1 # 处理右引号特殊情况 if content[next_idx] == '”': tmp_char += content[next_idx] # 确保不是连续结束标志 if content[next_idx] not in end_flag: # 处理左引号特殊情况 if tmp_char[0] == '”': tmp_char = tmp_char[1:] sentences.append(tmp_char) tmp_char = '' # 重置临时字符串 return sentences content = "句号。问号?叹号!“双引号。”英文省略号......汉语省略号……" sentences = cut_sentences(content) print('\n'.join(sentences)) -
使用正则表达式
import re def cut_sent(para): para = re.sub('([,。!?\?])([^“‘])',r"\1\n\2",para) para = re.sub('(\.{6})([^”‘])',r"\1\n\2",para) para = re.sub('(\…{2})([^“’])',r"\1\n\2",para) para = re.sub('([。!?\?][”‘])([^,。!?\?])',r'\1\n\2',para) para = para.rsplit("\n") return para content = "逗号,句号。问号?叹号!英文省略号......汉语省略号……" sentences = cut_sent(content) print('\n'.join(sentences)) # ============================================= # 正则表达式替换规则注释说明 # 功能:对中文文本进行分句处理,按标点规则插入换行符 # ============================================= # 规则1:中文标点或英文问号后换行(排除左引号情况) # 匹配模式:([,。!?\?])([^“‘]) # - 第1组:捕获中文标点(,。!?)或英文问号(?) # - 第2组:匹配非左引号(“或‘)的任意字符 # 替换结果:保留原标点 + 换行符 + 后续字符 para = re.sub('([,。!?\?])([^“‘])', r"\1\n\2", para) # 规则2:连续6个英文句点后换行(排除右引号情况) # 匹配模式:(\.{6})([^”‘]) # - 第1组:捕获6个连续英文句点(......) # - 第2组:匹配非右引号(”或‘)的任意字符 para = re.sub('(\.{6})([^”‘])', r"\1\n\2", para) # 规则3:连续2个中文省略号后换行(排除左引号情况) # 匹配模式:(\…{2})([^“’]) # - 第1组:捕获2个中文省略号(……) # - 第2组:匹配非引号(“或’)的任意字符 para = re.sub('(\…{2})([^“’])', r"\1\n\2", para) # 规则4:标点+右引号组合后换行(排除连续标点情况) # 匹配模式:([。!?\?][”‘])([^,。!?\?]) # - 第1组:捕获标点+右引号组合(。” 或 !”等) # - 第2组:匹配非标点的任意字符 para = re.sub('([。!?\?][”‘])([^,。!?\?])', r'\1\n\2', para) # 最终处理:按换行符分割文本为句子列表 # 使用rsplit从右侧分割,避免末尾空字符串 para = para.rsplit("\n")
-
语料库
语料库概述
定义:为某一个或多个应用而专门收集的、有一定结构的、有代表性的、可以被计算机程序检索的、具有一定规模的语料集合。
实质:经过科学取样和加工的大规模电子文本库。
语料库特征
存放的是真实出现过的语言材料;
是以计算机为载体,承载语言知识的基础资源;
是对真实语料进行加工、分析和处理的资源。
语料库原则
**代表性:**语料库应该尽可能地代表目标语言或领域的多样性,这意味着它涵盖各种不同的主题、语言风格、地区性语言等。这样的语料库能够满足不同应用的需求,并减少偏见或歧视性。
**高质量:**语料库中的文本应该是高质量的,即没有拼写错误、语法错误或不合适的内
容,这可以通过对数据进行清洗、标注等来实现。
**有规模:**语料库的规模也很重要,一般来说,越大越好,因为更多的数据通常意味着更好的泛化性能和覆盖范围。
**维护更新:**语料库应该定期维护更新,及时反映语言的变化和新兴的话题。这有助于保持模型的性能和适用性。
**版权和隐私:**在构建语料库时,必须遵守版权法和其他相关法律法规。最好使用可公开获取的、免版税的文本数据,或者获取授权以使用受版权保护的内容。同时,要注意隐私问题,确保语料库中的文本不包含个人或机构团体的敏感信息,进行适当的名化处理。
语料库的分类

**平衡结构语料库:**预先设计语料库中语料的类型。定义好每种类型语料所占的比例。按定义好的比例去采集组成语料库。
**自然随机结构语料库:**根据语言数据再现实生活中的自然分布情况组织的,没有特意调整文本数量使其平衡。例如,《圣经》语料库、狄更斯著作语料库、英国著名作家语料库,北京大学开发的《人命日报》语料库等。
**通用语料库:**涵盖了广泛的主题和领域,适用于一般性研究和应用。例如,可以包含多种主题和 领域的文本数据,如新闻报道、网络论坛帖子、小说、科技文献等,也可以包含各种形式的文本,包括书面文本、口语文本,图像注释等。
**专用语料库:**限于某一领域,为了某种专门的目的而采集,主要有:新闻语料;科技语料库;中小学语料库;北京口语语料库。
**共时语料库:**为了对语言进行共时研究而建立的语料库。无论所采集语料的时间段有多长,只要研究的是一个时间平面上的元素或元素的关系,则是共时研究。中文地区汉语共时语料库:采用共时性视窗模式,剖析来自中文地区有代表性的定量中文媒体语料。
**历时语料库:**为了对语言进行历时研究而建立的语料库。研究一个历时切面中元素与元素关系的演化。原国家语委建设的国家现代汉语语料库:收录的是1919年-至今的现代汉语的代表性语料。
案例:语料库的读取与分析
from nltk import FreqDist # 直接导入FreqDist类
from collections import Counter
with open('./classics/西游记.txt', 'r', encoding='utf-8') as f: # 打开文本
fiction = f.read() # 读取文本
len(set(fiction)) # 统计总用词量
len(fiction) / len(set(fiction)) # 平均每个词的使用次数
print("总用词量为:" , len(set(fiction)))
print("平均每个词的使用次数为:", len(fiction) / len(set(fiction)))
print("唐僧的使用次数为:", fiction.count('唐僧'))
print("孙悟空的使用次数为:", fiction.count('孙悟空'))
print("白龙马的使用次数为:", fiction.count('白龙马'))
print("部分文本为:", fiction[1112:1206]) # 查看《西游记》部分文本
fdist = FreqDist(fiction) # 生成fiction文本的词频
print("前30个高频词或高频标识符为:", fdist.most_common(30)) # 统计前30个高频词或高频标识符
W = Counter(fiction)
#分解式
result = []
for w in W.values():
if w<100:
result.append(w)
print('测试',len(result))
# 查询词频在0~99的词量
print("词频在0~99的词量为:", len([w for w in W.values() if w < 100]))
# 查询词频在101~999的词量
print("词频在101~999的词量为:", len([w for w in W.values() if w > 100 and w < 1000]))
# 查询词频在1001~4999的词量
print("词频在1001~4999的词量为:", len([w for w in W.values() if w > 1000 and w < 5000]))
# 查询词频在5000以上的词量
print("词频在5000以上的词量为:", len([w for w in W.values() if w > 5000]))
中文分词
概念
**中文分词:**将汉字序列按照一定规范逐个切分为词序列。
Ø英文:单词之间以空格为自然分隔符,分词自然地以空格为分隔符进行切分。
Ø中文:依靠一定技术和方法寻找类似英文中空格作用的分隔符。
中文分词的难点
(1)分词歧义消解:分词歧义是指在一个句子中,一个字串可以有不同的切分方法。
(2)未登录词的识别:这里的未登录词指的是没有在训练数据中出现过的词,包括各类专有名词、缩写词、新增词汇等。
(3)错别字、谐音字规范化:当处理网络文本或语言转化的文本时,不可避免的存在一些错别字或者是谐音词,谐音字。
(4)分词粒度问题:分词粒度的选择长期以来一直是困扰分词研究的一个难题。
分词方法
-
基于规则的分词方法
基于规则的分词方法又称为机械分词方法,主要是通过维护词典,在切分句子时,将句子中的每个可能的词与词典中的词进行逐一对比,找到则切分,否则不切分。
- 正向最大匹配法
正向最大匹配法(Maximum Match Method,MM法)的基本思想为:假定分词词典中的最长词有i个汉字字符,则用被处理文档的当前字段中的前i个字作为匹配字段,查找字典。
如果字典中有这样的一个词,则匹配成功,匹配字段被作为一个词切分出来。
如果字典找不到这样一个词,则匹配失败,将匹配字段的最后一个字去掉,将剩余的个字段作为匹配字段重新进行匹配处理。直到匹配成功或匹配字段剩余一个字。这样就完成了一轮匹配,然后取下一个长度为i的字段进行匹配处理,直到文档被扫描完成为止。


- 逆向最大匹配法
逆向最大匹配法(Reverse Maximum Match Method,RMM)的基本原理和MM法相同,不同点在于切分词的方向与MM法相反。
逆向最大匹配法从被处理文档的末端开始匹配扫描,词典最长的词的长度为i,每次取最末端的i个字符作为匹配字段,若匹配失败,则去掉字段的最前面一个字,继续匹配。
在实际处理时,先将文档和词典进行倒排处理,生成逆序文档和逆序词典;然后,根据逆序词典,对逆序文档用正向最大匹配法处理即可。


- 双向最大匹配法
双向最大匹配法是将正向匹配法和逆向匹配法得到的分词结果进行比较,然后选取分词结果中词数较少的作为最终的分词结果。
双向最大匹配的规则:
·如果正反向分词结果词数不同,则选取分词数量较少的那个2。
·如果分词数量相同,分词结果相同,则说明没有歧义,可任意返回一个;如果分词数量相同,分词结果不同,就返回单字数量较少的那个。
-
基于统计的分词方法
-
n元语法模型
基于n元模型的分词方法又称为全切分路径选择方法,其基本思想是:将所有可能的切分表示为一个有向无环图,这里的有向指全部路径都始于第一个字、止于最后一个字,无环指节点之间不构成闭环。每一个可能的切分词语作为图中的一个节点。有向图中任何一个从起点到终点的路径构成一个句子的词语切分,路径数目随着句子的长度指数增长。这种方法的目标是从指数级别的搜索空间中求解出一条最优路径。以输入句子“自然语言处理”为例,图2-1给出了基于二元语法的有向无环图。
基于n-1阶马尔可夫链的一种概率语言模型,通过n个词语出现的概率来推断语句的结构。

1. 核心思想:用“上下文”猜下一个词
n-元模型就像个“文字接龙游戏”,它通过统计历史数据中前n-1个词的出现规律,来预测下一个词。比如:
- **二元模型(Bigram)**:只依赖前一个词。
例:输入“今天天气”,模型会统计“天气”后面常接“很好”“很差”等词,选择概率最高的“很好”作为预测结果12。 - **三元模型(Trigram)**:依赖前两个词。
例:输入“今天天气很”,模型会统计“天气很”后面常接“好”“热”“冷”等词,最终选择“好”23。
00:09 N-gram的核心思路00:28 N-gram的三个关键特点00:55 N-gram的应用场景01:08 总结与口诀
2. 实际应用:输入法预测
当你用手机输入“我”时,输入法会基于二元模型(如“我”常接“喜欢”“爱”“们”等)给出候选词;若继续输入“喜欢”,三元模型会结合“我 喜欢”预测后续词(如“吃”“读书”)23。
3. 局限性:机械记忆的弊端
- 数据稀疏问题:若语料中没出现过“火星 天气”,模型会无法预测,需用“平滑技术”强行分配概率34。
- 忽略长距离依赖:比如“虽然…但是…”的转折关系,n-元模型可能无法捕捉15。
4. 对比案例:合理 vs 不合理句子
- 合理句:“猫 在 垫子上”(概率高,因“在垫子上”常接“猫”)1。
- 不合理句:“垫子 在 猫”(概率低,因“在猫”极少出现)
- 隐马尔可夫模型(HMM)
**核心逻辑:看不见的“配方”和看得见的“成品”**
想象你每天买煎饼果子,但不知道老板用了什么秘方(隐藏状态),只能通过成品(可观察表现)猜配方1。
- 隐藏状态:比如老板偷偷切换“加辣酱”或“加甜面酱”,但你看不到操作过程。
- 可观察表现:你拿到手的煎饼果子是“辣味”或“甜味”,通过味道反推老板用了哪种酱2。
2. **关键参数:老板的“套路”**
- 转移概率:比如今天用辣酱,明天有70%概率继续用辣酱,30%概率换甜酱。
- 输出概率:辣酱配方有90%概率做出辣味煎饼,10%概率翻车(甜味)。
3. 实际例子:语音识别
你说“你好”,手机听到的是声音波形(可观察表现),但HMM会猜你实际说了哪个词(隐藏状态)
4. **局限性:老板的“记忆只有1秒”**
HMM假设“明天的酱料只取决于今天”(马尔可夫性),无法记住前天是否加过香菜3。
5. 对比案例
- 合理:连续3天吃到辣味煎饼→HMM会高概率推测“老板最近在用辣酱”。
- 不合理:若煎饼突然变成“螺蛳粉味”,HMM会懵(模型未训练过这种输出)
-
分词工具jieba库
-
概述
jieba工具包的分词结合了基于规则和基于统计这两种方法。首先基于前缀词典构建包含全部可能分词结果的有向无环图,然后使用动态规划的方法找到最大概率路径,并将其作为最终的分词结果。对于未登录词,使用了基于汉字成词的HMM模型,采用了Viterbi算法进行推导。
-
jieba库优点
•社区活跃。在实际生产实践中遇到的问题能够在社区反馈并得到解决,适合长期使用。
•功能丰富。jiebe工具包是一个开源框架,不仅仅可以实现分词,还提供了很多其他算法,例如关键词提取、词性标注等。
•多种编程语言实现。jieba官方提供了多平台多语言支持,而且还提供了很多热门社区项目的扩展插件。在实际项目中,可以进行扩展。
•操作简单。jieba工具包的API不多,需要进行的配置简单,方便上手。
-
部分函数
函数 功能 描述 jieba.cut 分词 用于分词,输入参数为待分词的文本字符串,输出为一个可迭代的生成器,每次迭代返回一个分词后的词语 jieba.cut_for_search 搜索引擎分词 适用于搜索引擎分词,使用了更加细致的分词算法,输出结果与cut()略有不同 jieba.add_word 向分词词典中添加新词 用于向分词词典中添加新词,参数为新词和词频,可以手动调整分词效 jieba.load_userdict 加载用户自定义分词词典 加载用户自定义分词词典,增加分词的准确性 jieba.get_FREQ 返回词语的词频 返回词语的词频,可以用于分析词语的重要性 -
分词模式
•精确模式:将句子最精确地切开,适合文本分析。
•全模式:把句子中所有的可以成词的词语都扫描出来,速度非常快,但不能解决歧义。
•搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词,同时也支持自定义字典。
-
案例实施
#使用三种分词模式进行中文分词 import jieba # 构造文本 text = '张家口职业技术学院是由河北省教育厅设立的一所全日制综合性专科层次职业院校' # 精确模式分词 # sentence,接收str,表示需要进行分词的文本内容。无默认值 # cut_all,接收bool,表示是否采用全模式分词。默认为False seg_list = jieba.cut(sentence=text,cut_all=False,HMM=True) print('精确模式:\n','/'.join(seg_list)) # 全模式分词 seg_list = jieba.cut(sentence=text,cut_all=True,HMM=True) print('全模式:\n','/'.join(seg_list)) # 搜索引擎模式分词 seg_list = jieba.cut_for_search(sentence=text,HMM=True) print('搜索引擎模式:\n','/'.join(seg_list)) ########################################################################################### # cut和cut_for_search命令均返回一个可迭代的生成器,在命令前加一个l,可以使输出为list # 精确模式 words = jieba.lcut('武汉市长江大桥') print('精确模式:',words) # 全模式 words = jieba.lcut('武汉市长江大桥',cut_all=True) print('全模式:',words) # 搜索引擎模式 words = jieba.lcut_for_search('武汉市长江大桥') print('搜索引擎模式:',words) ########################################################################################## # 自行添加未登录词 jieba.add_word('武汉市长江大桥') words = jieba.lcut('武汉市长江大桥') print(words) ########################################################################################## # 写入自定义词典 #自定义词典的格式为’词 词频 词性‘,词频词性可省略 with open("userdict.txt", 'w', encoding='utf-8') as f: f.write("南京市长江大桥") # 加载自定义词典 jieba.load_userdict('userdict.txt') words = jieba.lcut("南京市长江大桥") print(words) ########################################################################################### # 从词典中删除词 word1 = jieba.lcut("南京市长江大桥") print(word1) jieba.del_word("长江大桥") word2 = jieba.lcut("南京市长江大桥") print(word2) -
误差分析
不常见的词被分成两个词
改进方法一:像词典中加入不常见词
word1 = jieba.lcut('干什么中学,干中学呗') print(word1) jieba.add_word("干中学") word2 = jieba.lcut("干什么中学,干中学呗") print(word2)改进方法二:提高不常见词的词频
word1 = jieba.lcut('干什么中学,干中学呗') print(word1) jieba.suggest_freq("干中学",True) word2 = jieba.lcut("干什么中学,干中学呗") print(word2)分词不完全
改进方法一:删除高频词
word1 = jieba.lcut('今天天气不错') print(word1) jieba.del_word('今天天气') word1 = jieba.lcut('今天天气不错') print(word1)改进方法二:强调低频词
word1 = jieba.lcut('今天天气不错') print(word1) jieba.suggest_freq(('今天','天气'),True) word1 = jieba.lcut('今天天气不错') print(word1) -
去停用词统计词频
# author:"Hiway" # datetime:2025/10/16 16:54 """ 中文文本词频统计工具 功能:统计指定文本中的词语出现频率,输出TopK高频词 并支持停用词过滤功能 """ # 导入中文分词库 import jieba # 设置要输出的高频词数量 topK = 10 # 读取文本文件(使用UTF-8编码) # 注意:文件路径需要根据实际情况修改 file_context = open('D:/text_data/西游记.txt', encoding="utf-8").read() # 使用jieba进行中文分词 # lcut方法返回分词后的词语列表 words = jieba.lcut(file_context) # ===== 词频统计部分 ===== # 初始化空字典用于存储词频统计结果 data = {} # 遍历分词后的词语列表 for chara in words: # 如果词语已在字典中,则计数+1 if chara in data: data[chara] += 1 # 否则初始化该词语的计数为1 else: data[chara] = 1 # 对词频统计结果进行排序 # items()获取字典的键值对 # key=lambda x: x[1]表示按值(出现次数)排序 # reverse=True表示降序排列 data = sorted(data.items(), key=lambda x: x[1], reverse=True) # 输出前topK个高频词 print("原始高频词(包含停用词):") print(data[:topK]) # ===== 停用词处理部分 ===== # 读取停用词文件(每行一个停用词) # strip()去除每行两端的空白字符 stopwords = [line.strip() for line in open('stopwords.txt', 'r', encoding='utf-8').readlines()] # 添加换行符到停用词列表 stopwords.append('\n') # 初始化空列表用于存储过滤后的词语 word = [] # 遍历排序后的词频统计结果 for i, k in data: # 如果词语不在停用词列表中 if i not in stopwords: # 将该词语添加到结果列表 word.append(i) # 输出过滤停用词后的前topK个高频词 print("\n过滤停用词后的高频词:") print(word[:topK])
词性标注
词性标注
根据句子中的上下文信息对句子中的成分做简单分析,区分出名词,动词,形容词等词性。词性标注的准确与否会直接影响自然语言处理系统中后续的句法分析,语义分析。
词性标注的方法
基于规则的标注方法:
基于规则的标注方法是出现较早的一种词性标注方法,该方法需要获取能够表达一定的上下文关系及其相关语境的规则库。获取一个好的规则库是比较困难的,主要的获取方式是人工编制包含繁杂的语法或语义信息的词典和规则系统,这比较费时费力,并且难以保证规则的准确性
基于统计的标注方法:
基于统计的标注方法于20世纪70年代末~80年代初开始得到应用。该方法主要通过概率统计的方法进行自动词性标注。基于统计的标注方法又分为基于最大熵的词性标注方法、基于统计最大概率输出的词性标注方法和基于HMM的词性标注方法。基于统计的标注方法能够抑制小概率事件的发生,但会收到长距离搭配上下文的限制,有时基于规则的标注方法更容易实现。
词性标注工具
jieba词性标注是一种基于规则与基于统计相结合的词性标注方法,具有效率高,处理能力强的特点。
现代汉语词分类:
词性标注规范(PKU(北大)词性标注集)
PKU(北大)词性标注集
jieba库实现词性标注的流程
对于汉字,jieba 会基于前缀词典构建有向无环图,计算最大概率路径,并在前缀字典中查找所分词的词性。如果没有找到对应的词性那么将其标注为“x”,表示未知词性。如果在标注过程中遇到未知词性的汉字,且该词为未录词,那么 jieba 会通过 HMM 模型进行词性标注。
对于非汉字,jieba 使用正则表达式判断词的类型,并赋予对应的词性。其中,“m”表示数字,“eng”表示英文词,“x”表示未知词性。
总的来说,jieba 的词性标注功能基于jieba 分词,通过前缀词典和 HMM 模型对汉字进行词性标注,对非汉字通过正则表达式进行词性标注,从而实现中文文本的分词和词性标注。
实例:文本词性标注
import jieba.posseg as pseg
sentence = '职业教育大有可为'
words = pseg.cut(sentence)
print('词性标注结果为:')
for word,flag in words:
print(word+' - '+flag)
关键词提取
关键词提取是指从文本中自动识别并提取出具有代表性和重要性的词语或短语。这些关键词通常能够概括文本的主题和内容,对于理解文本、文本摘要生成、信息检索等任务具有重要意义。关键词提取技术主要用于新闻阅读、广告推荐、历史文化研究、论文索引等领域。
关键词提取算法
有监督的文本关键词提取算法人工成本较高,出于成本考虑现有的文本关键词提取主要采用无监督关键词提取。无监督的文本关键词提取算法不需要人工标注的语料,利用某些方法发现文本中比较重要的词作为关键词,进行关键词提取。
无监督关键词提取算法分为基于特征统计的算法、基于词图模型的算法和基于主题模型的算法,具体包括TF-IDF算法、TextRank 算法、LSA 模型、PLSA 模型和LDA 模型,如图2-9所示。此时,模型不需要使用带有标记的训练数据,而是依赖文本本身的特征进行关键词提取。
基于特征统计的算法
TF-IDF算法是基于统计的算法,拥有简单又迅速的优点。TF-IDF算法的主要思想是字词的重要性随着它在文档中出现次数的增加而上升,并随着它在语料库中出现频率的升高而下降
•词频(TF):某词在文档中出现的次数/文档中的总词数。
•逆文档频率(IDF):所有文档的总数/包含该词的文档数,取对数。
TF-IDF示例
文档1:“科技/公司/推出/新款/智能手机/系统/更新/用户/体验/功能/优秀/产品/创新/”。 文档2:“农民/种植/蔬菜/水果/收获/销售/产量/农业/市场/价格/波动/农产品/投入/”。 文档3:“教授/发表/研究/论文/探讨/人工智能/技术/应用/领域/优秀/成果/创新/科研/”。 计算‘科技’词频 TF(科技) = 1/13 计算‘科技’逆文档频率 IDF(科技) = log3/1+1=log3/2=0.0405 计算TF-IDF TF-IDF(科技)=TF(科技)*IDF(科技)=1/13*0.0405=0.031基于词图模型的算法
TextRank算法是一种基于图的文本排序算法,它可以用于自动摘要和提取关键词。与TF-IDF算法相比,TextRank算法不同之处在于,它不需要依靠现有的文档集提取关键词,只需利用局部词汇之间的关系对后续关键词进行排序,随后从文本中提取词或句子,实现提取关键词和自动摘要。TextRank算法的基本思想来自Google的PageRank算法
基于主题模型的算法
主题模型算法认为文档是由主题组成的,而主题是词的一个概率分布,即每个词都是通过“文档以一定的概率选择某个主题,再在这个主题中以一定的概率选择某个词”这一过程得到的。主题模型算法能自动分析每个文档,统计文档内的词语,根据统计的信息断定当前文档含有哪些主题,以及每个主题所占的比例各为多少。常见的主题模型算法主要有LSA、概率潜在语义分析(Probabilistic Latent Semantic Analysis,PLSA)、LDA,以及基于深度学习的lda2vec等
TF-IDF算法提取关键字
pip install scikit-learn #安装依赖
# author:"Hiway"
# datetime:2025/10/23 16:53
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
# 待处理的中文文本
text = "学习是一种宝贵的财富,它能够拓展我们的视野、增长我们的知识、提升我们的能力。当我们学习的时候,我们不仅能够认识到世界的奥秘,也能够更好地适应和理解社会的发展和变化。因此,我们应该时刻保持对学习的热爱,不断探索新的知识和技能。"
# 使用jieba库进行分词
words = list(jieba.cut(text))
print('分词结果:\n', words)
# 将分词结果转为字符串格式
words_str = " ".join(words)
# 创建TfidfVectorizer对象
vectorizer = TfidfVectorizer()
# 计算TF-IDF值
tfidf_matrix = vectorizer.fit_transform([words_str])
print('TF-IDF值:\n', tfidf_matrix)
# 提取关键词的数量
top_n = 5
# 获取TF-IDF值矩阵中最大值对应的索引
indices = np.argsort(tfidf_matrix.toarray(), axis=1)[:, -top_n:]
# 获取词汇表
feature_names = np.array(vectorizer.get_feature_names_out())
# 提取关键词
keywords = feature_names[indices]
print('关键词:\n', keywords)
示例:关键词提取案例(TF-IDF算法)
# author:"Hiway"
# datetime:2025/10/22 10:53
import jieba.posseg
import math
import operator
def read_txt_file(file_path):
"读取txt文件,返回文件内容"
with open(file_path, 'r', encoding='utf-8') as f: # file_path: 文件路径
content = f.read()
return content
file_path = 'input.txt'
content=read_txt_file(file_path)
print(content)
def Stop_words():
# 创建一个空列表,用于存储停用词
stopword = []
data = []
# 打开停用词文件
f = open('../class2/stopwords.txt',encoding='utf-8')
# 逐行读取文件中的内容
for line in f.readlines():
# 去除行末的换行符,并将处理后的字符串添加到data列表中
data.append(line.strip())
# 将data列表中的字符串添加到stopword列表中
for i in data:
# 去除字符串末尾的换行符,并将处理后的字符串添加到stopword列表中
output = i.replace('\n', '')
stopword.append(output)
# 返回停用词列表
return stopword
# 调用Stop_words函数,并输出停用词列表
print('停用词列表(前5个):\n', Stop_words()[0:])
def Filter_word(text):
original_words = [] # 原始词列表
filter_word = [] # 过滤后的词列表
stopword = Stop_words() # 获取停用词列表
text = jieba.posseg.cut(text) # 使用jieba词性标注对文本进行分词
for word, flag in text: # 遍历文档中的每一个词及其词性
original_words.append(word) # 将词添加到原始词列表中
if flag.startswith('n') is False: # 如果当前词性不是名词,跳过该词
continue
if not word in stopword and len( word) > 1: # 如果当前词不在停用词列表中且长度大于1,那么将其添加到过滤后的词列表中
filter_word.append(word)
return original_words, filter_word # 返回原始词列表和过滤后的词列表
original_words, filter_word = Filter_word(content) # 调用Filter_word函数处理文本
print("过滤前的词列表:", original_words[0:10]) # 打印过滤前的词列表前10个词
print("过滤后的词列表:", filter_word[0:10]) # 打印过滤后的词列表前10个词
# 加载文档集,对文档集过滤词和停用词
def Filter_words():
document = []
for line in open('toutiao_word_corpus.txt', 'r', encoding='utf8'):
segment = jieba.posseg.cut(line.strip())
filter_words = []
stopword = Stop_words()
for word, flag in segment:
if flag.startswith('n') is False:
continue
if not word in stopword and len(word) > 1:
filter_words.append(word)
document.append(filter_words)
print('过滤后的语料库:',document)
return document
def tf_idf():
# 统计TF值,即每个词在文本中出现的频率
tf_dict = {}
original_words, filter_word = Filter_word(content) # 通过Filter_word函数去除停用词等无用词汇,返回文本中的单词列表
for word in filter_word:
if word not in tf_dict:
tf_dict[word] = 1
else:
tf_dict[word] += 1
for word in tf_dict:
tf_dict[word] = tf_dict[word] / len(content) # 计算每个词的频率,即出现次数除以总单词数
# 统计IDF值,即每个词在所有文本中出现的频率倒数的对数
idf_dict = {}
document = Filter_words() # 通过Filter_words函数获取所有文本,每个文本都是一个单词列表
doc_total = len(document) # 计算文本总数
for doc in document:
for word in set(doc):
if word not in idf_dict:
idf_dict[word] = 1
else:
idf_dict[word] += 1
for word in idf_dict:
idf_dict[word] = math.log(doc_total / (idf_dict[word] + 1)) # 计算每个词的IDF值
# 计算TF-IDF值,即每个词的TF值乘以其IDF值
tf_idf_dict = {}
for word in filter_word:
if word not in idf_dict:
idf_dict[word] = 0 # 若一个词在所有文本中都没有出现过,则其IDF值为0
tf_idf_dict[word] = tf_dict[word] * idf_dict[word]
# 提取前10个关键词,并输出结果
keyword = 10
print('TF-IDF模型提取出的关键词:')
for key, value in sorted(tf_idf_dict.items(),
key=operator.itemgetter(1),
reverse=True)[:keyword]:
print(key + '/', end='')
tf_idf()
# Filter_words()

命名实体识别
命名实体识别中的“命名实体”一般是指文本中具有特别亦已或指代行非常强的实体,可分为实体类、时间类和数字类3大类,以及人名、地名、机构团体、时间、日期、货币和百分比7个小类。
命名实体识别的方法
基于规则的方法:
通过人工编写规则来匹配文本中的实体,如基于正则表达式的方法、基于词典匹配的方法等。此方法精度较高,但需要耗费大量的人力、物力来构建规则和词典,并且对于新的实体类型或变化的语言习惯,需要不断地更新规则。
基于统计的方法:
基于统计的方法主要包括隐马尔可夫模型、最大熵马尔可夫模型、支持向量机、条件随机场等。此方法可以自动学习文本中的特征和规律,适用于大规模的语料库,但需要大量的训练数据和计算资源。
基于深度学习的方法:
近年来,随着深度学习技术的发展,基于深度学习的方法也被广泛应用于命名实体识别任务中,如基于循环神经网络的方法、基于卷积神经网络的方法、基于Transformer 的方法等。此方法可以自动提取文本中的特征,并且具有较高的准确率和泛化能力,但同样需要大量的训练数据和计算资源。
命名实体标注符号
B-begin,I-inside,O-outside
B-X代表实体X的开头
I-X代表实体的结尾
O代表不属于任何类型的Person-PER:人名
Lication-LOC:地名
Organization-ORG:机构名称
B-PER I-PER B-LOC I-LOC B-ORG I-ORG O
人名首部 人名内部 地名首部 地名内部 机构团体首部 机构团体内部 其他
上机案例
# author:"Hiway"
# datetime:2025/10/29 10:50
import jieba.posseg as pseg
# 进行命名实体识别的文本
text = '清华大学迎来中国首个原创虚拟学生--华智冰'
# 使用jieba进行词性标注
words=pseg.cut(text)
# 自定义命名实体识别规则
entity_rules = {'nr':'PER','ns':'LOC','nt':'ORG'}
# 定义一个空列表用于存储命名实体及其标记
entities = []
# 遍历分词结果,识别命名实体并标注
for word,flag in words:
if flag in entity_rules:
entities.append((word,'B-'+entity_rules[flag]))
for i in range(1,len(word)):
entities.append((word[i],'I-'+entity_rules[flag]))
else:
for char in word:
entities.append((char,'O'))
# 输出命名实体识别结果
for char,label in entities:
print(char+'\t'+label)

基于LTP的词性标注和命名实体识别
LTP是由哈工大研发的一个中文语言技术平台,它提供一系列中文自然语言处理工具用户可以使用这些工具对中文文本进行分词、词性标注、句法分析等工作。从应用角度来看,LTP 为用户提供下列组件:
1)针对单一自然语言处理任务,生成统计机器学习模型的工具。
2)针对单一自然语言处理任务,调用模型进行分析的编程接口。
3)系统可调用的,用于中文语言处理的模型文件。
4)针对单一自然语言处理任务,基于云端的编程接口。
pyltp的安装
pip install pyltp
模型下载
http://ltp.ai/download.html

LTP的主要模型
SentenceSplitter:分句模型,将一个段落通过“。”“?”“!”等形式分开。
Segmentor:分词模型,支持用户使用自定义词典。分词外部词典本身是一个文本文件每行指定一个词,编码须为 UTF-8。
Postagger:词性标注模型,显示每个词的词性,输入可以为一个词,也可以为多个词组成的列表。LTP中采用了863词性标注集
标记 词性 举例 a adjective 美丽 b other noun-modifier 大型,西式 c conjunction 和,虽然 d adverb 很 e exclamation 哎 g morpheme 茨,甥 h prefix 阿,伪 i idiom 百花齐放 j abbreviation 公检法 k suffix 界,率 m number 一,第一 n general noun 苹果 nd direction noun 右侧 nh person name 杜甫,汤姆 Ni organization name 保险公司 nl location noun 城郊 ns geographical name 北京 nt temporal noun 近日,明代 nz other proper noun 诺贝尔奖 o onomatopoeia 哗啦 p preposition 在,把 q quantity 个 r pronoun 我们 u auxiliary 的,地 v verb 跑,学习 wp punctuation ,。! ws foreign words CPU x non-lexeme 萄,翱 NamedEntityRecognizer:命名实体模型,ltp命名实体类型为:人名(Nh),地名(NS),机构名(Ni)。LTP采用BIESO标注体系,其命名实体标记如下:
标记 含义 B 实体开始词 I 实体中间词 E 实体结束词 S 单独成实体 O 不构成实体 Parser:依存句法分析模型。
模型加载
from pyltp import Segmentor, Postagger, Parser, NamedEntityRecognizer
#加载分词模型
segmentor = Segmentor("ltp_data_v3.4.0/cws.model")
#加载命名实体识别模型
recognizer = NamedEntityRecognizer('ltp_data_v3.4.0/ner.model')
#加载依存语法分析模型
parser = Parser("ltp_data_v3.4.0/parser.model")
#加载词性标注模型
postagger = Postagger("ltp_data_v3.4.0/pos.model")
分句
#分句
from pyltp import SentenceSplitter
content = '句号。问句?叹号!“双引号。”汉语省略号......'
sents = SentenceSplitter.split(content)
for sent in sents:
print(sent)
分词
#分词
from pyltp import Segmentor, Postagger, Parser, NamedEntityRecognizer
#加载分词模型
segmentor = Segmentor("ltp_data_v3.4.0/cws.model")
words = segmentor.segment('庐山,位于江西省九江市南,雄峙于长江之滨、鄱阳湖畔,东距鄱阳湖长岭-屏峰卡口7千米,是一座变质岩断石山,其拔地而起,主峰大汉阳峰高程1474米。庐山不仅风景秀丽,而且文化内涵深厚,更集教育名山、文化名山、宗教名山、政治名山于一身。从司马迁“南登庐山”,到陶渊明、李白、白居易、苏轼、王安石、黄庭坚、陆游、朱熹、康有为、胡适、郭沫若等文坛巨匠或陈运和等诗文名家1500余位登临庐山,留下4000余首诗词歌赋。1996年,庐山被联合国教科文组织确定为世界文化遗产,列入《世界遗产名录》。')
for word in words:
print(word, end='\\')
segmentor.release()
词性标注
#加载词性标注模型
postagger = Postagger("ltp_data_v3.4.0/pos.model")
postags = postagger.postag(words)
for word, postag in zip(words, postags):
print(word, postag, end='\\')
命名实体识别
#加载命名实体识别模型
recognizer = NamedEntityRecognizer('ltp_data_v3.4.0/ner.model')
netags = recognizer.recognize(words, postags)
for word, netag in zip(words, netags):
print(word, netag, end='\\')
提取命名体
# ========== 实体提取和合并 ==========
# 这个模块的目的是从命名实体识别结果中提取出完整的人名、地名和机构名
# 由于LTP会将多字实体拆分成B-I-E标签,我们需要将这些片段重新组合成完整的实体
# 创建三个集合来存储提取出的实体
# 使用set()集合类型的好处:自动去重,避免重复的实体
# persons: 存储所有人名实体
# places: 存储所有地名实体
# orgs: 存储所有机构名实体
persons, places, orgs = set(), set(), set()
# 初始化索引变量i,用于遍历词语列表
# i代表当前正在处理的词语在words列表中的位置索引
i = 0
# 开始遍历所有的实体标签和对应的词语
# 使用zip函数将netags(实体标签列表)和words(词语列表)配对遍历
# 每次循环会同时得到一个实体标签tag和对应的词语word
for tag, word in zip(netags, words):
# 创建临时索引j,用于在发现多字实体开头时向后查找实体结束位置
# j从当前索引i开始,用于遍历多字实体的后续部分
j = i
# ========== 处理人名实体 (Nh = Name of Person) ==========
# 检查当前标签是否包含"Nh",表示这是一个人名相关的标签
# 可能的值:B-Nh(人名开始), I-Nh(人名中间), E-Nh(人名结束), S-Nh(单字人名)
if "Nh" in tag:
# 情况1:单字人名 (S-Nh)
# S代表Single,表示这个实体只有一个字
# 例如:"张" -> S-Nh
if str(tag).startswith('S'):
# 单字人名直接加入persons集合
persons.add(word)
# 情况2:多字人名的开始 (B-Nh)
# B代表Begin,表示这是多字实体的第一个字
# 例如:"诸葛"中的"诸" -> B-Nh,"葛" -> I-Nh,"亮" -> E-Nh
elif str(tag).startswith('B'):
# 初始化union_person变量,用于拼接完整的人名
# 首先加入当前这个B标签的字(人名的第一个字)
union_person = word
# 开始向后遍历,寻找人名的结束位置
# 循环条件:当前j位置的标签不是E-Nh(人名结束标签)
# 只要还没找到结束标签,就继续向后查找
while netags[j] != 'E-Nh':
# j索引加1,移动到下一个词语
j += 1
# 安全检查:确保j没有超出词语列表的范围
if j < len(words):
# 将当前j位置的词语拼接到union_person中
# 这些应该是I-Nh(中间字)或者最后的E-Nh字
union_person += words[j]
else:
# 如果j超出了列表范围,说明实体不完整,跳出循环
break
# 循环结束后,union_person中存储了完整的人名
# 将其添加到persons集合中
persons.add(union_person)
# ========== 处理地名实体 (Ns = Name of Place) ==========
# Ns代表地名,处理逻辑与人名完全相同
if "Ns" in tag:
# 单字地名 (S-Ns)
if str(tag).startswith('S'):
places.add(word)
# 多字地名的开始 (B-Ns)
elif str(tag).startswith('B'):
# 初始化地名拼接变量
union_place = word
# 向后遍历寻找地名结束位置
while netags[j] != 'E-Ns':
j += 1
if j < len(words):
union_place += words[j]
else:
break
# 将完整地名加入集合
places.add(union_place)
# ========== 处理机构名实体 (Ni = Name of Institution) ==========
# Ni代表机构名,处理逻辑与人名、地名相同
if "Ni" in tag:
# 单字机构名 (S-Ni)
if str(tag).startswith('S'):
orgs.add(word)
# 多字机构名的开始 (B-Ni)
elif str(tag).startswith('B'):
# 初始化机构名拼接变量
union_org = word
# 向后遍历寻找机构名结束位置
while netags[j] != 'E-Ni':
j += 1
if j < len(words):
union_org += words[j]
else:
break
# 将完整机构名加入集合
orgs.add(union_org)
# 重要:将主索引i加1,移动到下一个词语
# 这样下次循环会处理下一个词语
i += 1
# ========== 输出提取结果 ==========
# 将集合转换为列表并打印,这样输出格式更整洁
# 集合转换为列表后可以按顺序显示(虽然集合本身是无序的)
# 打印所有提取到的人名
print("人名:", list(persons))
# 打印所有提取到的地名
print("地名:", list(places))
# 打印所有提取到的机构名
print("机构名:", list(orgs))
课后练习
提取下述素材种的地址信息:
涠洲岛位于广西壮族自治区北海市北部湾海域中部,是广西最大的海岛,素有南海“蓬菜岛”之称。涠洲岛是火山喷发堆凝而成的岛屿,有海蚀、海积及溶岩等景观,一半火山,一半海洋,涠洲岛拥有极高的资源组合度和稀缺性,岛上鳄鱼山、滴水丹屏、石螺口海滩、暮崖、五彩滩、贝壳沙滩、南湾街、斜阳岛等景点各具特色,寻火山遗迹,看日出日落,观渔船在海天一线中穿梭,感受岛上原汁原味的慢生活,壮观、意与浪漫相得益彰。较于城市,涠洲多了一份静谧,较于其他海岛,洲多了一份温柔。无需专业设备无需滤镜处理就能拍出惊艳的照片,因为洲岛本身就是一幅美丽的画作。近十年来,洲岛致力于景区生态环境整治、基础设施建设与景区服务质量提升工作,洲岛南湾鳄山景区于2020年12月正式晋升为国家5A级景区,旖旎的风光搭配有温度、有情怀的旅游服务,涠洲岛的优质化开发推动着北部湾国际滨海度假胜地转型升级,为广西“三地两带一中心”旅游新格局的构建提供了内生动力。
# author:"Hiway" # datetime:2025/11/13 15:58 from pyltp import Segmentor,Postagger,NamedEntityRecognizer # 分词操作 # 加载分词模型 segmentor=Segmentor('../ltp_data_v3.4.0/cws.model') text = open('input.txt','r',encoding='UTF-8').read() words=segmentor.segment(text) # 词性标注 # 加载词性标注的模型 postagger=Postagger('../ltp_data_v3.4.0/pos.model') postags=postagger.postag(words) #将分词结果作为参数进行传递 # 命名实体识别 # 加载模型 recognizer=NamedEntityRecognizer('../ltp_data_v3.4.0/ner.model') netags=recognizer.recognize(words,postags) #将分词结果与词性标注结果作为参数传递 places = set() # 定义词语遍历索引值 i = 0 # 遍历分词结果及实体命名标识集 for tag,word in zip(netags,words): # 定义临时索引 j = i # 提取地址名 if 'Ns' in tag: if str(tag).startswith('S'): places.add(word) elif str(tag).startswith('B'): union_place = word # 循环查找被拆分开的完整人名,循环结束的标志找到E-Nh while netags[j] != 'E-Ns': j+=1 # 判断分词长度,防止超过结果长度 if j<len(words): union_place+=words[j] places.add(union_place) i=i+1 print("地名:",places)
句法分析
句法分析(Parsing)是自然语言处理中的关键技术之一,其基本任务是对输入的文本以句子为单位进行分析,确定句子的句法结构或句子中词汇之间的依存关系,对句法进行句法分析的目的一方面是帮助理解句子的含义,另一方面也是为了更高级的自然语言处理任务提供支持,例如及其翻译、情感分析等。
句法分析的难点
(1)歧义:自然语言区别于人造语言的一个主要特点就在于它往往存在大量的歧义现象。人类可以根据经验消除歧义,而机器不能。
(2)搜索空间:句法分析的候选树会随着句子的增多呈指数增长,搜索空间巨大。因此必须有高效的算法来保证在较短的时间内搜索到模型的最优解。
句法分析分类
句法分析是从输入的单词序列得到句法结构的过程,而句法结构一般用树状数据结构表示,称为句法分析树或句法树,实现该过程的工具或者程序称为句法分析器(Parser)。根据句法结构的表示形式不同,最常见的句法分析任务可以分为以下俩种:
(1) 短语结构句法分析,作用是识别出句子中的短语结构以及短语之间的层次句法关系。
(2) 依存句法分析,作用是识别句子中词汇与词汇之间的相互依存关系。
不同类型的句法分析体现在句法结构的表示形式不同,实现过程的复杂程度也有所不同。其中,依存句法分析属于浅层句法分析,实现过程相对简单,能提供的信息也相对较少。而深层文法句法分析可以提供大量的句法和语义信息,但分析器运行复杂度较高。短语结构句法分析介于依存句法分析和深层文法句法分析之间。
短语结构句法分析
短语结构句法分析又称为成分句法分析,通常说的句法分析就是短语结构句法分析。一般以句法分析树来表示句法分析的结果。
- 基于规则:基于规则的方法的基本思路是,由人工组织语法规则,建立语法知识库,通过条件约束和检查来实现句法结构歧义的消除。这种方法在处理大规模真实文本时,会存在语法规则覆盖有限、系统可迁移差等问题。
- 基于统计:基于统计的句法分析方法,统计句法分析的本质是对候选树的评价方法,给合理的句法树赋予一个较高的分值,给不合理的句法树一个较低的评分,这样就可以利用候选句法树的分值来进行消歧。
PCFG
目前研究最多的统计句法分析方法是PCFG(Probabilistic Context Free Grammar),也是现在句法分析中常用的方法,这种方法既有规则方法的特点,又运用了概率信息,因此也可以认为是规则方法和统计方法的结合。
PCFG是基于概率的短语结构分析方法,是上下文无关算法(Context Free Grammar,CFG)的扩展。下面是使用PCFG求解最优句法树的过程。
规则集
汉语成分标记对应的标注集(清华树库)
给定句子 S : astronomers saw stars with ears ,得到两个句法树
计算两棵句法树的概率如下 :
依存句法分析
**依存句法分析通过分析语言单位内成分之间的依存关系揭示其句法结构。**直观来讲,依存句法分析识别句子中的“主谓宾”、“定状补”这些语法成分,并分析各成分之间的关系。
依存句法分析主张句子中核心动词是支配其他成分的中心成分。而它本身却不受其他任何成分的支配,所有受支配成分都以某种关系从属于支配者。
依存语法的结构没有非终结点,词与词之间直接发生依存关系,构成一个依存对,其中一个是核心词,也叫支配词,另一个叫修饰词,也叫从属词。依存关系用一个有向弧表示,叫做依存弧。依存弧的方向为由从属词指向支配词。
依存句法分析的五个条件:
(1)一个句子中只有一个成分是独立的;
(2)句子的其他成分都从属于某一成分;
(3)任何一个成分都不能依存于两个或两个以上的成分;
(4)如果成分A直接从属成分B,而成分C在句子中位于A和B之间,那么,成分C或者从属于A,或者从属于B,或者从属于A和B之间的某一成分;
(5)中心成分左右两边的其他成分相互不发生关系。
依存关系可以细分为不同的类型,表示两个词之间的具体句法关系。依存句法分析标注关系 ( 共15种)
![]()
基于PCFG的句法分析
这一节将采用Stanford parser来演示基于PCFG的句法分析方法。Stanford parser 是由斯坦福大学自然语言处理小组开发的开源句法分析器,是基于概率统计句法分析的一个 Java 实现。Stanford parser的优点在于:
•既是一个高度优化的概率上下文无关文法和词汇化依存分析器,也是一个词汇化上下文无关文法分析器。
•基于权威可靠的宾州树库(Penn Treebank)作为分析器的训练数据,目前已面向英文、中文、德文、阿拉伯文、意大利文、保加利亚文、葡萄牙文等语种提供句法分析功能。
•提供了多样化的分析输出形式,除句法分析树输出外,还支持分词和词性标注文本输出、短语结构树输出、斯坦福依存关系输出等。
•分析器内置了分词工具、词性标注工具、基于自定义树库的分析器训练工具等句法分析辅助程序。
•通过设置不同的运行参数,可实现句法分析模型选择、自定义词性标记集、文本编码设置和转换、语法关系导入和导出等功能的定制。
案例实施(基于 PCFG的语法分析)
Stanford parser的底层是由Java实现的,因此需要确保安装JDK。需要注意的是,在安装好JDK后,需要配置环境变量。除此之外,Stanford parser的Python封装是在NLTK库中实现的,因此,需要安装NLTK库。NLTK是一款Python的自然语言处理工具,但主要针对英文,对中文的支持较差。
jdk安装和配置
Jdk的安装和配置的详细步骤:首先,下载JDK(下载地址:https://www.oracle.com/java/technologies/javase-downloads.html)点击对应版本进行下载,如图4-3所示。
这里的版本是Java SE 8,点击“Oracle JDK”进行下载,如图4-4所示。
配置Java的环境变量:“此电脑”右键选择“属性”,点击“高级系统设置”,“环境变量”,对Windows系统的系统变量进行配置,如图4-5所示。
第一步,在系统变量中,新建JAVA_HOME变量,变量值填写jdk的安装目录,默认的安装目录是:C:\Program Files\Java\jdk1.8.0_271,如图4-6所示。
第二步,编辑Path变量,在Path变量值的最后输入“%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;”,如图4-7所示。
测试是否安装成功,“Windows”+“R”,输入cmd,进入命令行界面,输入:java -version和javac,能够成功输出信息则说明安装成功,如图4-8所示。
在命令行输入:pip install nltk,安装完成后,需要下载相关的NLTK data:
选择需要的语料库和预训练模型进行下载。如果下载失败,可以选择手动安装。输入: pip install stanfordnlp
记录“Searched in”下的任一个地址。打开https://github.com/nltk/nltk_data,如图4-11所示。
下载其中的第二个文件夹packages,内容如图4-12所示。将下载好的文件夹下的所有内容拷贝到之前“Searched in”下的任一地址。这里需要注意的是,拷贝文件夹下的内容,而不是文件夹。
查看是否正确下载NLTK data,如果下载成功,输入“import nltk.book”,如果出现如图4-13所示的内容则表示安装成功。
将每个文件夹下的所有压缩文件解压,完成了NLTK的安装。
(3)下载Stanford parser的jar包
需要的Stanford parser的jar包主要有两个:stanford-parser.jar和stanford- parser-4.2.0(版本号)-models.jar。下载地址为:https://nlp.stanford.edu/software/lex-parser.shtml#Download。
点击“Download Stanford Parser version 4.2.0”进行下载,如图4-14所示,下载成功后进行解压,得到一个文件夹“stanford-parser-full-2020-11-17”。
Stanford parser目前提供了5个中文文法:chinesePCFG、chineseFactored、xinhuaPCFG、xinhuaFactored和xinhuaFactoredSegmenting。其中前四个都需要先分词,只有最后一个内置了分词,不需要先进行分词。
import jieba # 定义要处理的中文文本 # string = "9月9日上午纳达尔在亚瑟·阿什球场击败俄罗斯球员梅德韦杰夫" string = "毒蛇毒毒蛇毒蛇会不会被毒蛇的毒毒死" # 使用jieba进行中文分词 # cut_all=False: 使用精确模式,只输出最可能的分词结果 # HMM=True: 启用隐马尔可夫模型进行未登录词识别 seg_list = jieba.cut(string, cut_all=False, HMM=True) # 将分词结果用空格连接成字符串 seg_str = ' '.join(seg_list) # 打印分词结果 print(seg_str) # PCFG句法分析 - 使用斯坦福解析器 from nltk.parse import stanford import os # 设置Java环境路径 - 斯坦福解析器需要Java运行环境 java_path = "D:/couse/tools\jdk/bin/java.exe" os.environ['JAVAHOME'] = java_path # 定义斯坦福解析器相关文件路径 root = './stanford-parser-full-2020-11-17/' parser_path = root + 'stanford-parser.jar' # 解析器主程序 model_path = root + 'stanford-parser-4.2.0-models.jar' # 语言模型文件 # PCFG模型路径 - 中文概率上下文无关文法模型 pcfg_path = 'edu/stanford/nlp/models/lexparser/chinesePCFG.ser.gz' # 初始化斯坦福解析器 parser = stanford.StanfordParser( path_to_jar=parser_path, # 解析器jar文件路径 path_to_models_jar=model_path, # 模型jar文件路径 model_path=pcfg_path # 中文PCFG模型路径 ) # 对分词后的文本进行句法分析 sentence = parser.raw_parse(seg_str) # 遍历分析结果并输出 for line in sentence: print(line) # 打印句法树结构 line.draw() # 可视化显示句法树
实现短语结构句法分析的可视化还可以选择使用“stanford-parser-full-2020-11-17”文件夹下的lexparser-gui.bat文件,双击打开该文件。其中,“Load File”是要进行句法分析的文件,“Load Parser”是使用的模型。依然选用chinesePCFG进行句法分析,对“9 月 9 日 上午 纳达尔 在 亚瑟 · 阿什 球场 击败 俄罗斯 球员 梅德 杰夫”进行句法分析,加载文件和模型后,点击“Parse”,如图所示。
案例实施(依存句法分析)
基于LTP的依存句法分析
LTP提供了依存句法分析模型。使用LTP实现依存句法分析时,需要在词性标注的基础上进行。因此首先需要进行分词和词性标注。
sent = "9月9日上午纳达尔在亚瑟·阿什球场击败俄罗斯球员梅德韦杰夫" # 分词 from pyltp import Segmentor segmentor = Segmentor('../class3/ltp_data_v3.4.0/cws.model') # 初始化实例 words = list(segmentor.segment(sent)) # 分词 segmentor.release() # 释放模型 print("分词:", words) # 词性标注 from pyltp import Postagger postagger = Postagger('../class3/ltp_data_v3.4.0/pos.model') # 初始化实例 postags = postagger.postag(words) # 词性标注 tags = list(''.join(postags)) postagger.release() # 释放模型 print("词性标注:", tags)在词性标注的基础上,进行依存句法分析。
# 依存句法分析 from pyltp import Parser parser = Parser('../class3/ltp_data_v3.4.0/parser.model') # 初始化实例 arcs = parser.parse(words, postags) #句法分析 # 根据实际结构调整访问方式 for arc in arcs: # 根据实际结构调整 print(f"头索引: {arc[0]}, 关系: {arc[1]}") rely_id = [arc[0] for arc in arcs] relation = [arc[1] for arc in arcs]为更加清楚的显示依存关系,提取每个词的父节点,及他们之间的依存关系:
print("依存句法分析2:") heads = ['Root' if id == 0 else words[id-1] for id in rely_id] # 匹配依存父节点词语 for i in range(len(words)): print(relation[i] + '(' + words[i] + ', ' + heads[i] + ')')
HanLP依存句法分析1
# 1. 导入库 import hanlp # 2. 加载模型(首次运行自动下载) print("正在加载模型,第一次使用需要下载(约30秒)...") parser = hanlp.load(hanlp.pretrained.dep.CTB9_DEP_ELECTRA_SMALL) print("模型加载完成!") # 3. 分析简单句子 sentence = "我喜欢学习自然语言处理。" print(f"\n分析句子:{sentence}") # 4. 执行依存分析 result = parser(sentence) # 5. 打印结果 print("\n=== 依存分析结果 ===") for i, word in enumerate(result): head_word = result[word['head']-1]['form'] if word['head'] > 0 else 'ROOT' print(f"{i+1:2d}. {word['form']:5s} → {head_word:5s} [{word['deprel']:6s}]")
依存关系树
依存句法分析结果保存
# 导入HanLP自然语言处理库 import hanlp # 导入系统库,用于获取Python版本信息 import sys # 1. 加载模型 - 使用HanLP预训练的依存句法分析模型 # CTB9_DEP_ELECTRA_SMALL是在CTB9中文树库上训练的轻量级模型 parser = hanlp.load(hanlp.pretrained.dep.CTB9_DEP_ELECTRA_SMALL) # 2. 分析句子 - 定义要分析的中文句子 sentence = "我们学习人工智能技术。" # 对句子进行依存句法分析,返回分析结果 result = parser(sentence) # 打印原始结果结构,帮助理解返回数据的格式 print("原始结果结构查看:") print(result) # 打印整个结果对象 print("\n第一个词的所有键:") # 空行后打印提示信息 # 检查结果是否非空,然后打印第一个词的详细信息 if len(result) > 0: # 将第一个词转换为字典格式,查看所有可用的键名 print(dict(result[0])) # 查看实际键名,了解数据结构 # 3. 修正的保存函数(通用版) def save_result_fixed(sentence, result, filename): """ 保存结果到文件(自动适应不同键名) 参数: sentence: str - 原始句子 result: list - HanLP分析结果 filename: str - 要保存的文件名 功能: 将依存分析结果保存为易读的文本格式 """ # 使用utf-8编码打开文件进行写入 with open(filename, 'w', encoding='utf-8') as f: # 写入句子内容 f.write(f"句子:{sentence}\n") # 写入表头,使用制表符分隔 f.write("序号\t词语\t词性\t关系\t上级ID\n") # 写入分隔线,使输出更美观 f.write("-" * 40 + "\n") # 遍历结果中的每个词语,enumerate从1开始计数 for i, word in enumerate(result, 1): # 处理字典或对象 - 统一转换为字典格式 if isinstance(word, dict): # 检查word是否为字典类型 word_dict = word # 已经是字典,直接使用 else: word_dict = dict(word) # 不是字典,转换为字典 # 获取词性(尝试不同可能的键名) # 使用get方法按优先级尝试不同的键名,都找不到则返回'未知' pos = word_dict.get('upos') or word_dict.get('pos') or word_dict.get('postag') or '未知' # 获取词语本身 form = word_dict.get('form') or word_dict.get('word') or '未知' # 获取依存关系类型 deprel = word_dict.get('deprel') or word_dict.get('dependency') or '未知' # 获取上级词语的ID(索引),如果没有则默认为0(根节点) head = word_dict.get('head') or 0 # 将一行数据写入文件,使用制表符分隔各字段 f.write(f"{i}\t{form}\t{pos}\t{deprel}\t{head}\n") # 保存完成后打印提示信息 print(f"结果已保存到:{filename}") # 5. 运行主程序 print("\n" + "=" * 50) # 打印分隔线 print("开始分析句子...") # 程序开始提示 print(f"句子:{sentence}") # 显示要分析的句子 # 调用保存函数,将结果保存到指定文件 save_result_fixed(sentence, result, "my_analysis.txt") # 6. 查看分析结果(控制台显示) # 以下代码已被注释,如需在控制台显示详细结果可以取消注释 # print("\n分析结果预览:") # for i, word_info in enumerate(result, 1): # # 统一转换为字典格式 # word_dict = dict(word_info) if not isinstance(word_info, dict) else word_info # # # 获取上级词语的索引 # head_idx = word_dict.get('head', 0) # # 根据索引找到上级词语,如果是根节点则显示'ROOT' # head_word = result[head_idx - 1].get('form') if head_idx > 0 else 'ROOT' # # # 格式化输出:序号. 当前词 → 上级词 [依存关系] # print(f"{i:2d}. {word_dict.get('form'):4s} → {head_word:4s} " # f"[{word_dict.get('deprel', '?'):6s}]")
练习
# author:"Hiway" # datetime:2025/12/3 12:15 # student_exercise.py import hanlp # 1. 加载模型 parser = hanlp.load(hanlp.pretrained.dep.CTB9_DEP_ELECTRA_SMALL) # 2. 练习句子列表 sentences = [ "猫抓老鼠。", "老师在教室上课。", "小明昨天买了一本书。", "红色的苹果很好吃。" ] # 3. 分析每个句子 print("=== 依存句法分析练习 ===\n") for i, sent in enumerate(sentences, 1): print(f"【句子{i}】{sent}") result = parser(sent) # 显示结果 print("词语\t关系\t→\t上级词语") print("-" * 30) for word in result: head_idx = word['head'] head_word = result[head_idx - 1]['form'] if head_idx > 0 else 'ROOT' print(f"{word['form']:4s}\t{word['deprel']:6s}\t→\t{head_word:4s}")
基于HanLP的依存句法分析2(可视化)
绘制依存句法分析的结果,使用HanLP来实现,需要注意的是使用时,需要确保已经安装并配置好JDK。安装方式为:pip install pyhanlp。在首次运行时会自动下载data.zip。
下载完成后会自动解压,并开始任务。如果在下载data.zip时报错,可以选择手动下载(下载地址:https://github.com/hankcs/HanLP/releases),并放置到要求的路径下(输入),重新运行,同样会自动完成解压。
使用HanLP进行依存句法分析:
from pyhanlp import HanLP para_sen = "9月9日上午纳达尔在亚瑟·阿什球场击败俄罗斯球员梅德韦杰夫" sentence = HanLP.parseDependency(para_sen) # print(sentence) # 输出依存文法的结果 txt文件,在windows系统下的 Dependency Viewer.exe 打开文件 path = "text_return.txt" with open(path, "w", encoding='utf-8') as f: f.write(str(sentence)) print("path:%s" % (path))得到了依存句法分析的结果后,使用Dependency Viewer(下载地址:http://nlp.nju.edu.cn/tanggc/tools/DependencyViewer.html)来实现依存关系可视化。下载完成后,打开软件,点击“file
read conll file”,找到刚刚保存的text_return.txt,打开得到如下依存句法分析可视化结果图,如图所示。
点击“Show Tree View”可以得到树形图,可以通过“Save Image”保存树形图。
文本向量化
为了让计算机可以理解语言,需要将自然语言都转换成计算机可以处理的数据结构这个过程称为文本表示。文本表示是自然语言处理以及语义计算的基础,文本表示的效果会直接影响到自然语言处理系统的性能。在自然语言处理研究领域,文本向量化就是文本表示的一种重要方式,也就是将文本表示为一系列能够表达文本语义的向量。无论是中文还是英文,词语都是表达语义的最基本的单位。因此,对文本向量化的研究大多是基于词向量化实现的。
one-hot编码
one-hot编码(独热编码)是特征工程中最常用的方法之一,是最简单的词向量化方法。
当给定10000个单词的词汇表,为每个单词分配一个索引,例如black的索引为2409,那么将black表示为一个10000维的向量[0,…,0,1,0…,0],其中1位于第2409个位置,其余位置均为0。
缺点:
(1)随着语料库词语的增加,词向量的维度高且稀疏。如果语料库中包含10000个单词,那么每个词语都需要使用10000维的向量来表示,也就是说除了当前词语位置为1,其余位置均为0,这种方法得到的词向量是高维且稀疏的。
(2)无法计算词与词之间的相似性 。
词袋
词袋(Bag Of Word)模型是最早的以词语为基本处理单元的文本向量化方法。在使用独热编码得到词向量后,将文本中出现的每个单词的词向量进行相加,可以得到文本的向量化表示。
对于“the cat is black”,首先需要找到每个词的索引,然后使用长度为10000的向量进行表示,将所有词语的向量进行求和,即可将文本向量化
缺点:
1)矩阵维度高且稀疏。如果语料库中包含10000个单词,那么每个文本都需要使用10000维的向量来表示,例如,对于“tecatisblack”得到的向量中,只有4个位置不为0.其余位置均为0,这样高维且稀疏的向量会严重影响计算速度。与此同时,当语料库出现新的词语时,所有的向量表示都会发生改变。
2)只是将词语符号化,不保留词序信息,不包含任意的语义信息。例如有两句话“小明给了小红一个苹果”和“小红给了小明一个苹果”,使用词袋模型进行文本向量化的结果相同,但语义相差较大。词袋模型案例
# author:"Hiway" # datetime:2025/12/10 11:08 import numpy as np import pandas as pd import jieba import re from gensim import corpora def onehot_matrix(): # 定义文本文件路径 file_path = 'data/sample_data.txt' # 存储清洗后的文档 docs = [] # 读取文件内容 with open(file_path, 'r', encoding="utf-8") as f: # 读取所有行 sents = f.readlines() print(sents) # 遍历每一行文本 for sent in sents: # 使用正则表达式移除标点符号: # 移除英文标点:. ! / , $ % ^ * ( + " ' \n 等 # 移除中文标点:——!,。?、~@#¥%……&*()等 string = re.sub("[\.\!\/_,$%^*(+\"\'\\n]+|[+——!,。?、~@#¥%……&*()]", "", sent) # 将清洗后的文本添加到文档列表 docs.append(string) # 存储所有单词的列表 words = [] # 处理每个文档 for i in range(len(docs)): # 将文档按空格分割成单词列表(假设文本已用空格分词) docs[i] = docs[i].split(" ") # 将当前文档的所有单词添加到总单词列表中 words += docs[i] # 创建词汇表: # 1. set(words):获取所有不重复的单词 # 2. key=words.index:按照单词首次出现的顺序排序 # 3. sorted:排序后返回列表 vocab = sorted(set(words), key=words.index) # V:词汇表大小(唯一单词的数量) V = len(vocab) # M:文档数量 M = len(docs) # 初始化one-hot向量:长度为词汇表大小,数据类型为整数 onehot = np.zeros(V, dtype=int) # 初始化词袋矩阵:M行(文档数)× V列(词汇表大小) bow = np.zeros((M, V), dtype=int) # 使用gensim库创建词典 # Dictionary接受一个列表的列表,每个子列表代表一个文档的单词 dict = corpora.Dictionary([words]) # 打印词典的单词到ID的映射关系 print(dict.token2id) # 生成每个词的one-hot向量并打印 print("one-hot向量:") # 遍历词汇表中的每个单词 for i, word in enumerate(vocab): # 将当前位置设置为1(表示该单词存在) onehot[i] = 1 # 打印单词及其对应的one-hot向量 print(word, list(onehot)) # 重置one-hot向量,为下一个单词做准备 onehot = np.zeros(V, dtype=int) # 构建词袋矩阵 # 遍历每个文档 for i, doc in enumerate(docs): # 遍历文档中的每个单词 for word in doc: # 检查单词是否在词汇表中 if word in vocab: # 获取单词在词汇表中的索引位置 pos = vocab.index(word) # 在词袋矩阵的相应位置计数加1 bow[i][pos] += 1 # 将词袋矩阵转换为列表的列表格式并返回 return [list(i) for i in bow] # 调用函数 onehot_matrix()
word2vec
词嵌入(Word Embedding)是文本向量化的一种,指把一个维数为所有词数量的高维空间向量嵌人一个维数低得多的连续向量空间中,每个单词或词组被映射为实数域上的向量。2013年,谷歌的一个团队发明了一套工具 word2vec 来进行词嵌入。该工具训练向量空间模型的速度较快,得到的词向量也可以较好地表达不同词之间的相似和类比关系。word2vec 主要包含两个浅层的神经网络模型,分别是CBOW(Continues Bagof Words)模型和 Skip-gram 模型。
CBOW模型
CBOW模型是一个三层的神经网络。该模型的特点在于已知上下文,输出对当前单词的预测,且上下文所有的词对当前词语出现的概率的影响的权重是一样的。
CBOW模型具体的计算方式如图6-4所示,其输入为上下文的one-hot向量,其中语料库词语数量为V,上下文单词个数为C,取上下文各词的词向量的平均值作为输入,输入权重矩阵W和输入相乘得到隐藏层,再将得到的矩阵与输出的权重矩阵相乘,得到一个列向量。在最后一层加入softmax,将向量转化为概率输出。该向量中概率最大的单词对应的索引就是预测的中间词。
Skip-gram模型
Skip-gram模型与CBOW模型正好相反,该模型的特点在于根据当前词语来预测上下文概率。
输入为从目标词的上下文选择一个词,将其词向量组成上下文的表示
Word2vec实操
# author:"Hiway" # datetime:2025/12/11 15:41 import collections from gensim.models import word2vec from gensim.models import KeyedVectors def stat_words(file_path, freq_path): """ 统计文本文件中每个词的出现频率 参数: file_path (str): 输入文本文件路径,每行是用空格分隔的词汇 freq_path (str): 输出词频统计文件路径 功能: 1. 读取文本文件 2. 按空格分割每行的词汇 3. 统计每个词的出现次数 4. 按词频从高到低排序 5. 将词频信息保存到指定文件 返回: word_counts: Counter对象,包含所有词汇及其频次 """ fr = open(file_path, 'r', encoding='utf-8') # 读取文件所有行,每行是一个字符串 lines = fr.readlines() # 将每行按空格分割成词汇列表,strip()去除首尾空白符 text = [line.strip().split(' ') for line in lines] fr.close() # 关闭文件 # 创建Counter对象用于统计词频 word_counts = collections.Counter() # 遍历每个内容行,更新词频统计 for content in text: # Counter.update()方法将列表中的元素加入统计 word_counts.update(content) # 对词频进行排序:most_common()返回(词, 频次)列表,再按频次降序排列 word_freq_list = sorted(word_counts.most_common(), key=lambda x: x[1], reverse=True) # 打开文件用于写入词频信息 fw = open(freq_path, 'w', encoding='utf-8') # 遍历排序后的词频列表 for i in range(len(word_freq_list)): # 将元组中的元素转换为字符串并用空格连接 # 例如:('苹果', 10) -> '苹果 10' content = ' '.join(str(word_freq_list[i][j]) for j in range(len(word_freq_list[i]))) fw.write(content + '\n') fw.close() def get_word_embedding(input_corpus, model_path): """ 训练Word2Vec词向量模型 参数: input_corpus (str): 训练语料文件路径 model_path (str): 模型保存路径 功能: 1. 读取语料文件 2. 训练Word2Vec模型 3. 保存训练好的模型 模型参数说明: sentences: 训练语料 vector_size=100: 词向量维度为100 window=8: 上下文窗口大小为8 min_count=3: 忽略出现次数小于3的词 epochs=8: 训练迭代次数为8轮 """ # Text8Corpus: gensim提供的文本语料读取器,按空格分词 sentences = word2vec.Text8Corpus(input_corpus) # 创建并训练Word2Vec模型 model = word2vec.Word2Vec(sentences, vector_size=100, window=8, min_count=3, epochs=8) # 保存完整模型(包含训练状态) model.save(model_path) # 以word2vec格式保存词向量(兼容其他工具) model.wv.save_word2vec_format(model_path, binary=False) # 程序主入口 if __name__ == '__main__': # 语料文件路径,每行是用空格分隔的词汇 corpus_path = 'data/toutiao_word_corpus.txt' # 词频统计结果保存路径 freq_path = 'data/words_freq_info1.txt' # 统计词频并保存 word_list = stat_words(corpus_path, freq_path) # 模型保存路径 model_path = 'toutiao_word_embedding1.bin' # 训练词向量模型 get_word_embedding(corpus_path, model_path) # ============ 以下为模型使用示例 ============ # 加载训练好的词向量模型 # KeyedVectors: gensim中存储词向量的容器 model = KeyedVectors.load_word2vec_format(model_path) # 获取"西红柿"的词向量(100维的numpy数组) print(model['西红柿']) # 输出词向量维度信息 print("每个词用%d个数字来表示" % len(model['西红柿'])) # 计算两个词的余弦相似度(值在-1到1之间,越大越相似) print('similarity(西红柿,番茄) = {}'.format(model.similarity("西红柿", "番茄"))) print('similarity(西红柿,苹果) = {}'.format(model.similarity("西红柿", "苹果"))) # 找出与"大学"最相似的10个词 # most_similar返回(词, 相似度)的列表 most_sim = model.most_similar("大学", topn=10) print('The top10 of 大学: {}'.format(most_sim)) # 找出不属于同一类别的词 # doesnt_match从一组词中找出最不相关的词 test_words = '女生 老师 会计师 程序员 律师 医生' test_words_result = model.doesnt_match(test_words.split()) print('不是同一类别的词为: %s' % test_words_result)
"""
统计文本文件中每个词的出现频率 参数: file_path (str): 输入文本文件路径,每行是用空格分隔的词汇 freq_path (str): 输出词频统计文件路径 功能: 1. 读取文本文件 2. 按空格分割每行的词汇 3. 统计每个词的出现次数 4. 按词频从高到低排序 5. 将词频信息保存到指定文件 返回: word_counts: Counter对象,包含所有词汇及其频次 """ fr = open(file_path, 'r', encoding='utf-8') # 读取文件所有行,每行是一个字符串 lines = fr.readlines() # 将每行按空格分割成词汇列表,strip()去除首尾空白符 text = [line.strip().split(' ') for line in lines] fr.close() # 关闭文件 # 创建Counter对象用于统计词频 word_counts = collections.Counter() # 遍历每个内容行,更新词频统计 for content in text: # Counter.update()方法将列表中的元素加入统计 word_counts.update(content) # 对词频进行排序:most_common()返回(词, 频次)列表,再按频次降序排列 word_freq_list = sorted(word_counts.most_common(), key=lambda x: x[1], reverse=True) # 打开文件用于写入词频信息 fw = open(freq_path, 'w', encoding='utf-8') # 遍历排序后的词频列表 for i in range(len(word_freq_list)): # 将元组中的元素转换为字符串并用空格连接 # 例如:('苹果', 10) -> '苹果 10' content = ' '.join(str(word_freq_list[i][j]) for j in range(len(word_freq_list[i]))) fw.write(content + '\n') fw.close()def get_word_embedding(input_corpus, model_path):
“”"
训练Word2Vec词向量模型
参数:
input_corpus (str): 训练语料文件路径
model_path (str): 模型保存路径
功能:
1. 读取语料文件
2. 训练Word2Vec模型
3. 保存训练好的模型模型参数说明: sentences: 训练语料 vector_size=100: 词向量维度为100 window=8: 上下文窗口大小为8 min_count=3: 忽略出现次数小于3的词 epochs=8: 训练迭代次数为8轮 """ # Text8Corpus: gensim提供的文本语料读取器,按空格分词 sentences = word2vec.Text8Corpus(input_corpus) # 创建并训练Word2Vec模型 model = word2vec.Word2Vec(sentences, vector_size=100, window=8, min_count=3, epochs=8) # 保存完整模型(包含训练状态) model.save(model_path) # 以word2vec格式保存词向量(兼容其他工具) model.wv.save_word2vec_format(model_path, binary=False)程序主入口
if name == ‘main’:
# 语料文件路径,每行是用空格分隔的词汇
corpus_path = ‘data/toutiao_word_corpus.txt’
# 词频统计结果保存路径
freq_path = ‘data/words_freq_info1.txt’
# 统计词频并保存
word_list = stat_words(corpus_path, freq_path)
# 模型保存路径
model_path = ‘toutiao_word_embedding1.bin’
# 训练词向量模型
get_word_embedding(corpus_path, model_path)============ 以下为模型使用示例 ============
加载训练好的词向量模型
KeyedVectors: gensim中存储词向量的容器
model = KeyedVectors.load_word2vec_format(model_path)
获取"西红柿"的词向量(100维的numpy数组)
print(model[‘西红柿’])
输出词向量维度信息
print(“每个词用%d个数字来表示” % len(model[‘西红柿’]))
计算两个词的余弦相似度(值在-1到1之间,越大越相似)
print(‘similarity(西红柿,番茄) = {}’.format(model.similarity(“西红柿”, “番茄”)))
print(‘similarity(西红柿,苹果) = {}’.format(model.similarity(“西红柿”, “苹果”)))找出与"大学"最相似的10个词
most_similar返回(词, 相似度)的列表
most_sim = model.most_similar(“大学”, topn=10)
print(‘The top10 of 大学: {}’.format(most_sim))找出不属于同一类别的词
doesnt_match从一组词中找出最不相关的词
test_words = ‘女生 老师 会计师 程序员 律师 医生’
test_words_result = model.doesnt_match(test_words.split())
print(‘不是同一类别的词为: %s’ % test_words_result)
更多推荐






































read conll file”,找到刚刚保存的text_return.txt,打开得到如下依存句法分析可视化结果图,如图所示。








所有评论(0)