手把手教你用 spacy3 训练中文NER

news2024/9/21 4:30:22

文章目录

  • 模型文件下载
  • 训练模型
    • 准备数据
    • 转化成 doc_bin 格式
    • 模型训练配置
      • 生成初始配置
      • 补全完整配置
    • 开始训练
  • 测试模型
  • 参考文献

模型文件下载

https://github.com/explosion/spacy-models/releases?q=zh&expanded=true
在这里插入图片描述
简单测试一下ner效果,发现根本不能用
在这里插入图片描述

训练模型

准备数据

在这里插入图片描述

转化成 doc_bin 格式

from spacy.tokens import DocBin
from tqdm import tqdm
from spacy.util import filter_spans


nlp = spacy.blank('zh')   # 选择中文空白模型
doc_bin = DocBin()
for training_example in tqdm(TRAIN_DATA):
    text = training_example['text']
    labels = training_example['entities']
    doc = nlp.make_doc(text)
    ents = []
    for start, end, label in labels:
        span = doc.char_span(start, end, label=label, alignment_mode="contract")
        if span is None:
            print("Skipping entity")
        else:
            ents.append(span)
    filtered_ents = filter_spans(ents)
    doc.ents = filtered_ents
    doc_bin.add(doc)


doc_bin.to_disk("train.spacy")

train.spacydev.spacy 分别用来训练和测试

模型训练配置

生成初始配置

模型配置文件不用自己写,直接到官网上点击配置:https://spacy.io/usage/training#quickstart
在这里插入图片描述
通过简单勾选,得到一个初始配置文件 base_config.cfg

# This is an auto-generated partial config. To use it with 'spacy train'
# you can run spacy init fill-config to auto-fill all default settings:
# python -m spacy init fill-config ./base_config.cfg ./config.cfg
[paths]
train = null
dev = null
vectors = "zh_core_web_lg"
[system]
gpu_allocator = null

[nlp]
lang = "zh"
pipeline = ["tok2vec","ner"]
batch_size = 1000

[components]

[components.tok2vec]
factory = "tok2vec"

[components.tok2vec.model]
@architectures = "spacy.Tok2Vec.v2"

[components.tok2vec.model.embed]
@architectures = "spacy.MultiHashEmbed.v2"
width = ${components.tok2vec.model.encode.width}
attrs = ["NORM", "PREFIX", "SUFFIX", "SHAPE"]
rows = [5000, 1000, 2500, 2500]
include_static_vectors = true

[components.tok2vec.model.encode]
@architectures = "spacy.MaxoutWindowEncoder.v2"
width = 256
depth = 8
window_size = 1
maxout_pieces = 3

[components.ner]
factory = "ner"

[components.ner.model]
@architectures = "spacy.TransitionBasedParser.v2"
state_type = "ner"
extra_state_tokens = false
hidden_width = 64
maxout_pieces = 2
use_upper = true
nO = null

[components.ner.model.tok2vec]
@architectures = "spacy.Tok2VecListener.v1"
width = ${components.tok2vec.model.encode.width}

[corpora]

[corpora.train]
@readers = "spacy.Corpus.v1"
path = ${paths.train}
max_length = 0

[corpora.dev]
@readers = "spacy.Corpus.v1"
path = ${paths.dev}
max_length = 0

[training]
dev_corpus = "corpora.dev"
train_corpus = "corpora.train"

[training.optimizer]
@optimizers = "Adam.v1"

[training.batcher]
@batchers = "spacy.batch_by_words.v1"
discard_oversize = false
tolerance = 0.2

[training.batcher.size]
@schedules = "compounding.v1"
start = 100
stop = 1000
compound = 1.001

[initialize]
vectors = ${paths.vectors}

补全完整配置

接下来,需要用命令 spacy init fill-config [初始配置] [完整配置] 把上述初始配置补全为完整的训练配置

python -m spacy init fill-config spacy/base_config.cfg spacy/config.cfg

得到 config.cfg 文件如下,其中做了一些人工改动,例如 paths.vectors 默认选的是 zh_core_web_lg,我改成了 zh_core_web_md

[paths]
train = null
dev = null
vectors = "zh_core_web_md"
init_tok2vec = null

[system]
gpu_allocator = null
seed = 0

[nlp]
lang = "zh"
pipeline = ["tok2vec","ner"]
batch_size = 1000
disabled = []
before_creation = null
after_creation = null
after_pipeline_creation = null
vectors = {"@vectors":"spacy.Vectors.v1"}

[nlp.tokenizer]
@tokenizers = "spacy.zh.ChineseTokenizer"
segmenter = "char"

[components]

[components.ner]
factory = "ner"
incorrect_spans_key = null
moves = null
scorer = {"@scorers":"spacy.ner_scorer.v1"}
update_with_oracle_cut_size = 100

[components.ner.model]
@architectures = "spacy.TransitionBasedParser.v2"
state_type = "ner"
extra_state_tokens = false
hidden_width = 64
maxout_pieces = 2
use_upper = true
nO = null

[components.ner.model.tok2vec]
@architectures = "spacy.Tok2VecListener.v1"
width = ${components.tok2vec.model.encode.width}
upstream = "*"

[components.tok2vec]
factory = "tok2vec"

[components.tok2vec.model]
@architectures = "spacy.Tok2Vec.v2"

[components.tok2vec.model.embed]
@architectures = "spacy.MultiHashEmbed.v2"
width = ${components.tok2vec.model.encode.width}
attrs = ["NORM","PREFIX","SUFFIX","SHAPE"]
rows = [5000,1000,2500,2500]
include_static_vectors = true

[components.tok2vec.model.encode]
@architectures = "spacy.MaxoutWindowEncoder.v2"
width = 256
depth = 8
window_size = 1
maxout_pieces = 3

[corpora]

[corpora.dev]
@readers = "spacy.Corpus.v1"
path = ${paths.dev}
max_length = 0
gold_preproc = false
limit = 0
augmenter = null

[corpora.train]
@readers = "spacy.Corpus.v1"
path = ${paths.train}
max_length = 0
gold_preproc = false
limit = 0
augmenter = null

[training]
dev_corpus = "corpora.dev"
train_corpus = "corpora.train"
seed = ${system.seed}
gpu_allocator = ${system.gpu_allocator}
dropout = 0.1
accumulate_gradient = 1
patience = 1600
max_epochs = 0
max_steps = 20000
eval_frequency = 200
frozen_components = []
annotating_components = []
before_to_disk = null
before_update = null

[training.batcher]
@batchers = "spacy.batch_by_words.v1"
discard_oversize = false
tolerance = 0.2
get_length = null

[training.batcher.size]
@schedules = "compounding.v1"
start = 100
stop = 1000
compound = 1.001
t = 0.0

[training.logger]
@loggers = "spacy.ConsoleLogger.v1"
progress_bar = false

[training.optimizer]
@optimizers = "Adam.v1"
beta1 = 0.9
beta2 = 0.999
L2_is_weight_decay = true
L2 = 0.01
grad_clip = 1.0
use_averages = false
eps = 0.00000001
learn_rate = 0.001

[training.score_weights]
ents_f = 1.0
ents_p = 0.0
ents_r = 0.0
ents_per_type = null

[pretraining]

[initialize]
vectors = ${paths.vectors}
init_tok2vec = ${paths.init_tok2vec}
vocab_data = null
lookups = null
before_init = null
after_init = null

[initialize.components]

[initialize.tokenizer]
pkuseg_model = null
pkuseg_user_dict = "default"

开始训练

python -m spacy train spacy/config.cfg --output ./spacy/ --paths.train ./train.spacy --paths.dev ./dev.spacy

参数:

  • output 输出目录
  • paths.train 训练集文件
  • paths.dev 验证集文件

训练日志:

>>> python -m spacy train spacy/config.cfg --output ./spacy/ --paths.train ./train.spacy --paths.dev ./dev.spacy
ℹ Saving to output directory: spacy
ℹ Using CPU
ℹ To switch to GPU 0, use the option: --gpu-id 0

=========================== Initializing pipeline ===========================
✔ Initialized pipeline

============================= Training pipeline =============================
ℹ Pipeline: ['tok2vec', 'ner']
ℹ Initial learn rate: 0.001
E    #       LOSS TOK2VEC  LOSS NER  ENTS_F  ENTS_P  ENTS_R  SCORE 
---  ------  ------------  --------  ------  ------  ------  ------
  0       0          0.00     49.29    0.00    0.00    0.00    0.00
  0     200        609.43   3515.82    6.61    7.99    5.63    0.07
  0     400       1104.85   3590.05   10.22   10.26   10.19    0.10
  0     600       1120.82   5038.80   16.23   17.95   14.81    0.16
  0     800       1071.70   5578.76   10.95   14.11    8.95    0.11
  0    1000       1151.26   6506.03   20.62   23.73   18.23    0.21
  0    1200       1100.93   6840.94   26.60   32.95   22.30    0.27
  0    1400       2058.58   7959.36   34.93   39.60   31.25    0.35
  0    1600       1642.29   9632.10   40.32   45.09   36.46    0.40
  1    1800       2580.55  11209.10   38.82   47.18   32.98    0.39
  1    2000       2907.86  13187.84   44.31   52.42   38.38    0.44
  1    2200       3575.63  15214.04   42.97   50.06   37.63    0.43
  2    2400       4790.03  18126.32   48.39   51.29   45.80    0.48
  2    2600       5653.69  17209.21   51.27   54.42   48.47    0.51

测试模型

nlp = spacy.load("spacy/model-best")
text = "我的名字是michal johnson,我的手机号是13425456344,我家住在东北松花江上8幢8单元6楼5号房。我叫王大,喜欢去旺角餐厅吃牛角包, 今年买了阿里巴巴的股票,我家住在新洲花园3栋4单元 8988-1室"
doc = nlp(text)

for ent in doc.ents:
    print({
            "start": ent.start,
            "end": ent.end,
            "text": ent.text,
            "entity_group": ent.label_,
        })

在这里插入图片描述

参考文献

  1. https://ubiai.tools/fine-tuning-spacy-models-customizing-named-entity-recognition/
  2. https://spacy.io/usage/training
  3. https://ner.pythonhumanities.com/03_02_train_spacy_ner_model.html

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

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

相关文章

shell进阶之计算编译前后时间(十八)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

Ubuntu 下使用 Scons 交叉编译嘉楠堪智 CanMV K230 大小核 Coremark 程序

在 Ubuntu 下使用 SCons 进行交叉编译嘉楠堪智 CanMV K230 大小核(不同的玄铁 C908 核心)的 C 程序,以 Coremark 程序为例,顺便测试一下大小核和编译器的性能。 2024年3月14日,嘉楠科技宣布推出了全球首款支持 RISC-V…

掌握未来搜索的钥匙:深入解析 Milvus 向量搜索引擎的终极指南!

在大数据时代,向量搜索技术愈发重要。作为一个开源的向量相似性搜索引擎,Milvus 提供了基于向量的相似性搜索功能,广泛应用于机器学习、人工智能等领域。本文将深入介绍 Milvus 的基本概念,包括其介绍、主要作用、使用方法及注意事…

【iOS开发】—— 初识锁

【iOS开发】—— 初识锁 线程安全锁的种类自旋锁定义原理自旋锁缺点OSSpinLock(自旋锁) 互斥锁os_unfair_lockpthread_mutexNSLockNSRecusiveLockSemaphore信号量synchronized 总结两种之间的区别和联系: 线程安全 当一个线程访问数据的时候…

深入理解WPF的ResourceDictionary

深入理解WPF的ResourceDictionary 介绍 在WPF中,ResourceDictionary用于集中管理和共享资源(如样式、模板、颜色等),从而实现资源的重用和统一管理。本文详细介绍了ResourceDictionary的定义、使用和合并方法。 定义和用法 Res…

Android Hanlder 揭密之路- 深入理解异步消息传递机制Looper、Handler、Message三者关系

在Android开发中,Handler作为实现线程间通信的桥梁,扮演着至关重要的角色。无论是在主线程执行UI操作,还是在子线程进行耗时任务,Handler都可以高效地将异步消息分派到对应的线程中执行。 本文将全方位解析Handler的工作原理及实现…

2024数维杯数学建模C题思路代码

2024年数维杯&电工杯思路代码在线文档​https://www.kdocs.cn/l/cdlol5FlRAdE 这道题想要做出好的结果,必须要结合插值法和分布函数来做,主要还是因为勘探点太少,直接用插值法效果不太好,以下是我做的,函数分布可…

Python的while循环

目录 while循环的结构 示例 关键字 break continue while循环的结构 while condition(循环条件): # 循环的内容 循环内容的执行与结束需要通过循环条件控制。 在执行循环之前需要设立一个循环条件的初始值,以便while循环体判断循环条件。…

Loongnix系统替换内核操作

Loongnix系统替换内核操作 一、终端下执行命令 sudo apt search linux-image* 返回结果中格式如: linux-image-4.19.0-19-loongson-3 为最新的内核源码。 二、下载内核源码包 sudo apt source linux-image-4.19.0-19-loongson-3 如提示:E: 您必须在 sources.li…

网络安全等级保护的发展历程

1994年国务院147号令第一次提出,计算机信息系统实行安全等级保护,这也预示着等保的起步。 2007年《信息安全等级保护管理办法》的发布之后。是等保在各行业深耕落地的时代。 2.0是等保版本的俗称,不是等级。等保共分为五级,二级…

C#语音播报(通过CoreAudioAPI完成对扬声器的控制)

1,效果: 作用: 可对当前内容(例如此例中的重量信息)进行语音合成播报 。可设置系统扬声器音量与状态(是否静音),同时根据扬声器状态同步更新当前控件状态与值,实现强制PC扬声器按照指定的音量进行播报&…

Ansible常用变量【上】

转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 在Ansible中会用到很多的变量,Ansible常用变量包括以下几种: 1. 自定义变量——在playbook中用户自定义…

函数重载和函数模板

c语言中函数名字不可重复,但是可以写代码实现 普通的函数重载 这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同和返回值没有关系(因为就像我想调用Add(1,2),Add重载的几个函数仅仅返回值不同,编辑器就不知道去找哪一个,就有歧义了) 情况1-数组 int ave(int*pa,i…

用 Supabase CLI 进行本地开发环境搭建

文章目录 (零)前言(一)Supabase CLI(1.1)安装 Scoop(1.2)用 Scoop 安装 Supabase CLI (二)本地项目环境(2.1)初始化项目(2…

【全开源】微凌客洗护小程序FastAdmin+Uniapp(源码搭建/上线/运营/售后/维护更新)

一款基于FastAdminUniapp开发的洗护小程序系统,适用于线上下单到店核销的业务场景,拥有会员卡、优惠券、充值提现、商户管理等功能,提供Uniapp后台无加密源代码。 线上线下融合:微凌客洗护小程序适用于线上下单到店核销的业务场景…

nacos命名空间的配置

给微服务配置namespace 给微服务配置namespace只能通过修改配置来实现。 例如,修改order-service的application.yml文件: spring:cloud:nacos:server-addr: localhost:8848discovery:cluster-name: HZnamespace: 492a7d5d-237b-46a1-a99a-fa8e98e4b0f…

C语言数据结构 - 选择题集合(二叉树)

一生负气成今日 四海无人对夕阳 目录 树的专辑 树的专辑 1.有n个元素的完全二叉树的深度是( ) A.nlogn B.nlogn1 C.logn D.logn1 答案:D 解析: 设完全二叉树的节点数为 N,高度为 h ,高度为 h 时空的结点…

python零基础知识 - 定义列表的三种方式,循环列表索引值

这一小节,我们将从零基础的角度看一下,python都有哪些定义列表的方式,并且循环这个列表的时候,怎么循环,怎么循环他的索引值,怎么拿到的就是元素值。 说完循环,我们会说一说关键的break和contin…

分布式存储故障导致数据库无法启动故障处理---惜分飞

国内xx医院使用了国外医疗行业龙头的pacs系统,由于是一个历史库,存放在分布式存储中,由于存储同时多个节点故障,导致数据库多个文件异常,数据库无法启动,三方维护人员尝试通通过rman归档进行应用日志,结果发现日志有损坏报ORA-00354 ORA-00353,无法记录恢复,希望我们给予支持 M…

AI智能分析高精度烟火算法EasyCVR视频方案助力打造森林防火建设

一、背景 随着夏季的来临,高温、干燥的天气条件使得火灾隐患显著增加,特别是对于广袤的森林地区来说,一旦发生火灾,后果将不堪设想。在这样的背景下,视频汇聚系统EasyCVR视频融合云平台AI智能分析在森林防火中发挥着至…