前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于bert训练自己的分词系统

基于bert训练自己的分词系统

作者头像
西西嘛呦
发布2022-09-23 17:27:59
5100
发布2022-09-23 17:27:59
举报

前言

在中文分词领域,已经有着很多优秀的工具,例如:

  • jieba分
  • SnowNLP
  • 北京大学PKUse
  • 清华大学THULAC
  • HanLP
  • FoolNLTK
  • 哈工大LTP
  • 斯坦福分词器CoreNLP
  • BaiduLac

这里,我们不使用上述的工具,而是利用bert训练一个自己的分词器。

数据预处理

首先我们查看下初始的数据:data/sighan2005/raw_data/training.txt

代码语言:javascript
复制
1998年  ,  中国  人民  将  满怀信心  地  开创  新  的  业绩  。  尽管  我们  在  经济社会  发展  中  还  面临  不少  困难  ,  但  我们  有  *理论  的  指引  ,  有  改革  开放  近  20  年  来  取得  的  伟大  成就  和  积累  的  丰富  经验  ,  还有  其他  的  各种  有利  条件  ,  我们  一定  能够  克服  这些  困难  ,  继续  稳步前进  。  只要  我们  进一步  解放思想  ,  实事求是  ,  抓住  机遇  ,  开拓进取  ,  建设  有  中国  特色  社会主义  的  道路  就  会  越  走  越  宽广  。  
实现  祖国  的  完全  统一  ,  是  海内外  全体  中国  人  的  共同  心愿  。  通过  中  葡  双方  的  合作  和  努力  ,  按照  “  一国两制  ”  方针  和  中国澳门  《  基本法  》  ,  1999年  12月  中国澳门  的  回归  一定  能够  顺利  实现  。  
中国台湾  是  中国  领土  不可分割  的  一  部分  。  完成  祖国  统一  ,  是  大势所趋  ,  民心所向  。  任何  企图  制造  “  两  个  中国  ”  、  “  一中一台  ”  、  “  中国台湾  独立  ”  的  图谋  ,  都  注定  要  更  失败  。  希望  中国台湾  当局  以  民族  大义  为重  ,  拿  出  诚意  ,  采取  实际  的  行动  ,  推动  两岸  经济  文化  交流  和  人员  往来  ,  促进  两岸  直接  通邮  、  通航  、  通商  的  早日  实现  ,  并  尽早  回应  我们  发出  的  在  一个  中国  的  原则  下  两岸  进行  谈判  的  郑重  呼吁  。  
环顾  全球  ,  日益  密切  的  世界  经济  联系  ,  日新月异  的  科技  进步  ,  正在  为  各国  经济  的  发展  提供  历史  机遇  。  但是  ,  世界  还  不  安宁  。  南北  之间  的  贫富  差距  继续  扩大  ;  局部  冲突  时有发生  ;  不  公正  不  合理  的  旧  的  国际  政治经济  秩序  还  没有  根本  改变  ;  发展中国家  在  激烈  的  国际  经济  竞争  中  仍  处于  弱势  地位  ;  人类  的  生存  与  发展  还  面临  种种  威胁  和  挑战  。  和平  与  发展  的  前景  是  光明  的  ,  21  世纪  将  是  充满  希望  的  世纪  。  但  前进  的  道路  不  会  也  不  可能  一帆风顺  ,  关键  是  世界  各国  人民  要  进一步  团结  起来  ,  共同  推动  早日  建立  公正  合理  的  国际  政治经济  新  秩序  。  
中国  政府  将  继续  坚持  奉行  独立自主  的  和平  外交  政策  ,  在  和平共处  五  项  原则  的  基础  上  努力  发展  同  世界  各国  的  友好  关系  。  中国  愿意  加强  同  联合国  和  其他  国际  组织  的  协调  ,  促进  在  扩大  经贸  科技  交流  、  保护  环境  、  消除  贫困  、  打击  国际  犯罪  等  方面  的  国际  合作  。  中国  永远  是  维护  世界  和平  与  稳定  的  重要  力量  。  中国  人民  愿  与  世界  各国  人民  一道  ,  为  开创  持久  和平  、  共同  发展  的  新  世纪  而  不懈努力  !  
在  这  辞旧迎新  的  美好  时刻  ,  我  祝  大家  新年  快乐  ,  家庭  幸福  !  
谢谢  !  (  新华社  北京  12月  31日  电  )  
在  十五大  精神  指引  下  胜利  前进  ——  元旦  献辞  

这里面每一行是一段文本。一段文本中不同的词是以两个空格进行分隔的。接下来,我们要将数据处理成我们需要的样子。在data/sighan2005/raw_data/下新建一个process.py

代码语言:javascript
复制
import json
from pprint import pprint

max_seq_len= 512
# -1:索引为0-511,-2:去掉CLS和SEP,+1:词索引到下一位
max_seq_len = max_seq_len - 1 - 2 + 1

with open("training.txt", "r", encoding="utf-8") as fp:
    data = fp.readlines()

res = []
i = 0
for d in data:
    d = d.strip().split("  ")
    dtype = "word"
    start = 0
    tmp = []
    labels = []
    j = 0
    for word in d:
        start = len("".join(tmp))
        tmp.append(word)
        end = start + len(word)
        labels.append(["T{}".format(j), dtype, start, end, word])
        j += 1
        if end > max_seq_len:
            sub_tmp = tmp[:-1]
            sub_labels = labels[:-1]
            end = start + len("".join(sub_tmp))
            text = "".join(sub_tmp)
            res.append({
                "id": i,
                "text": text,
                "labels": sub_labels
            })

            start = 0
            tmp = [word]
            end = len("".join(tmp))
            labels = [["T{}".format(0), dtype, 0, end, word]]
            i += 1

    if tmp:
        text = "".join(tmp)
        res.append({
            "id": i,
            "text": text,
            "labels": labels
        })
        i += 1

with open("../mid_data/train.json", 'w', encoding="utf-8") as fp:
    json.dump(res, fp, ensure_ascii=False)

labels = ["word"]
with open("../mid_data/labels.json", 'w', encoding="utf-8") as fp:
    json.dump(labels, fp, ensure_ascii=False)

nor_ent2id = {"O":0, "B-word":1, "I-word":2, "E-word":3, "S-word":4}
with open("../mid_data/nor_ent2id.json", 'w', encoding="utf-8") as fp:
    json.dump(nor_ent2id, fp, ensure_ascii=False)

with open("test.txt", "r", encoding="utf-8") as fp:
    data = fp.readlines()

res = []
i = 0
for d in data:
    d = d.strip().split("  ")
    dtype = "word"
    start = 0
    tmp = []
    labels = []
    j = 0
    for word in d:
        start = len("".join(tmp))
        tmp.append(word)
        end = start + len(word)
        labels.append(["T{}".format(j), dtype, start, end, word])
        j += 1
        if end > max_seq_len:
            sub_tmp = tmp[:-1]
            sub_labels = labels[:-1]
            end = start + len("".join(sub_tmp))
            text = "".join(sub_tmp)
            res.append({
                "id": i,
                "text": text,
                "labels": sub_labels
            })

            start = 0
            tmp = [word]
            end = len("".join(tmp))
            labels = [["T{}".format(0), dtype, 0, end, word]]
            i += 1

    if tmp:
        text = "".join(tmp)
        res.append({
            "id": i,
            "text": text,
            "labels": labels
        })
        i += 1

with open("../mid_data/test.json", 'w', encoding="utf-8") as fp:
    json.dump(res, fp, ensure_ascii=False)

上述需要我们自己定义一个max_seq_len,然后会对句子进行切分,最后会在data/sighan2005/mid_data/下生成以下文件:train.json、test.json、labels.json、nor_ent2id.json。其中train.json部分数据如下:

代码语言:javascript
复制
[{"id": 0, "text": "迈向充满希望的新世纪——一九九八年新年讲话(附图片1张)", "labels": [["T0", "word", 0, 2, "迈向"], ["T1", "word", 2, 4, "充满"], ["T2", "word", 4, 6, "希望"], ["T3", "word", 6, 7, "的"], ["T4", "word", 7, 8, "新"], ["T5", "word", 8, 10, "世纪"], ["T6", "word", 10, 12, "——"], ["T7", "word", 12, 17, "一九九八年"], ["T8", "word", 17, 19, "新年"], ["T9", "word", 19, 21, "讲话"], ["T10", "word", 21, 22, "("], ["T11", "word", 22, 23, "附"], ["T12", "word", 23, 25, "图片"], ["T13", "word", 25, 26, "1"], ["T14", "word", 26, 27, "张"], ["T15", "word", 27, 28, ")"]]},]

labels.json是实体标签,这里就是一个["word"]。nor_ent2id是实体对应的BIOES标签,这里是:{"O": 0, "B-word": 1, "I-word": 2, "E-word": 3, "S-word": 4}。

有了这些数据之后,就可以生成bert所需要的数据了,具体代码在preprocess.py里面。这里面我们要定义以下参数:

代码语言:javascript
复制
dataset = "sighan2005"
args.max_seq_len = 512  # 和之前process.py里面保持一致

运行之后部分样例如下:

代码语言:javascript
复制
*** train_example-1 ***
[CLS] 迈 向 充 满 希 望 的 新 世 纪 [UNK] [UNK] 一 九 九 八 年 新 年 讲 话 ( 附 图 片 1 张 ) [SEP]
text: [CLS] 迈 向 充 满 希 望 的 新 世 纪 — — 一 九 九 八 年 新 年 讲 话 ( 附 图 片 1 张 ) [SEP]
token_ids: [101, 6815, 1403, 1041, 4007, 2361, 3307, 4638, 3173, 686, 5279, 100, 100, 671, 736, 736, 1061, 2399, 3173, 2399, 6382, 6413, 8020, 7353, 1745, 4275, 8029, 2476, 8021, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
attention_masks: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
token_type_ids: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
labels: [0, 1, 3, 1, 3, 1, 3, 4, 4, 1, 3, 1, 3, 1, 2, 2, 2, 3, 1, 3, 1, 3, 4, 4, 1, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
length: 512

实际上我们会将每一个词转换为B(词的开头)I(词的中间)E(词的结尾)S(单独的一个字)标签,比如针对于"迈向",其对应的标签就是B-word,E-word,如果是单个的字,则是S-word。最后会在data/sighan2005/final_data下生成train.pkl和dev.pkl。

训练、验证、测试和预测

主代码在main.py里面,其中:

代码语言:javascript
复制
bertForNer = BertForNer(args, train_loader, dev_loader, dev_loader, id2query)
bertForNer.train()

model_path = './checkpoints/{}_{}/model.pt'.format(model_name, args.data_name)
bertForNer.test(model_path)
"""
{"id": 5, "text": "在1998年来临之际,我十分高兴地通过中央人民广播电台、中国国际广播电台和中央电视台,向全国各族人民,向中国香港特别行政区同胞、澳门和台湾同胞、海外侨胞,向世界各国的朋友们,致以诚挚的问候和良好的祝愿!", "labels": [["T0", "word", 0, 1, "在"], ["T1", "word", 1, 6, "1998年"], ["T2", "word", 6, 8, "来临"], ["T3", "word", 8, 10, "之际"], ["T4", "word", 10, 11, ","], ["T5", "word", 11, 12, "我"], ["T6", "word", 12, 14, "十分"], ["T7", "word", 14, 16, "高兴"], ["T8", "word", 16, 17, "地"], ["T9", "word", 17, 19, "通过"], ["T10", "word", 19, 21, "中央"], ["T11", "word", 21, 23, "人民"], ["T12", "word", 23, 25, "广播"], ["T13", "word", 25, 27, "电台"], ["T14", "word", 27, 28, "、"], ["T15", "word", 28, 30, "中国"], ["T16", "word", 30, 32, "国际"], ["T17", "word", 32, 34, "广播"], ["T18", "word", 34, 36, "电台"], ["T19", "word", 36, 37, "和"], ["T20", "word", 37, 39, "中央"], ["T21", "word", 39, 42, "电视台"], ["T22", "word", 42, 43, ","], ["T23", "word", 43, 44, "向"], ["T24", "word", 44, 46, "全国"], ["T25", "word", 46, 48, "各族"], ["T26", "word", 48, 50, "人民"], ["T27", "word", 50, 51, ","], ["T28", "word", 51, 52, "向"], ["T29", "word", 52, 54, "中国香港"], ["T30", "word", 54, 56, "特别"], ["T31", "word", 56, 59, "行政区"], ["T32", "word", 59, 61, "同胞"], ["T33", "word", 61, 62, "、"], ["T34", "word", 62, 64, "澳门"], ["T35", "word", 64, 65, "和"], ["T36", "word", 65, 67, "台湾"], ["T37", "word", 67, 69, "同胞"], ["T38", "word", 69, 70, "、"], ["T39", "word", 70, 72, "海外"], ["T40", "word", 72, 74, "侨胞"], ["T41", "word", 74, 75, ","], ["T42", "word", 75, 76, "向"], ["T43", "word", 76, 78, "世界"], ["T44", "word", 78, 80, "各国"], ["T45", "word", 80, 81, "的"], ["T46", "word", 81, 83, "朋友"], ["T47", "word", 83, 84, "们"], ["T48", "word", 84, 85, ","], ["T49", "word", 85, 87, "致以"], ["T50", "word", 87, 89, "诚挚"], ["T51", "word", 89, 90, "的"], ["T52", "word", 90, 92, "问候"], ["T53", "word", 92, 93, "和"], ["T54", "word", 93, 95, "良好"], ["T55", "word", 95, 96, "的"], ["T56", "word", 96, 98, "祝愿"], ["T57", "word", 98, 99, "!"]]}
"""
        
raw_text = "在1998年来临之际,我十分高兴地通过中央人民广播电台、中国国际广播电台和中央电视台,向全国各族人民,向中国香港特别行政区同胞、澳门和台湾同胞、海外侨胞,向世界各国的朋友们,致以诚挚的问候和良好的祝愿!"
logger.info(raw_text)
bertForNer.predict(raw_text, model_path)

分别是训练、测试和预测,如需只运行相关功能,注释掉其它代码即可。运行指令:

代码语言:javascript
复制
!python main.py \
--bert_dir="../model_hub/chinese-bert-wwm-ext/" \
--data_dir="./data/sighan2005/" \
--data_name='sighan2005' \
--log_dir="./logs/" \
--output_dir="./checkpoints/" \
--num_tags=5 \
--seed=123 \
--gpu_ids="0" \
--max_seq_len=512 \
--lr=3e-5 \
--crf_lr=3e-2 \
--other_lr=3e-4 \
--train_batch_size=16 \
--train_epochs=3 \
--eval_batch_size=16 \
--lstm_hidden=128 \
--num_layers=1 \
--use_lstm='False' \
--use_crf='True' \
--dropout_prob=0.3 \
--dropout=0.3 

最后我们来看看结果:

代码语言:javascript
复制
precision:0.9667 recall:0.9549 micro_f1:0.9608
          precision    recall  f1-score   support

    word       0.97      0.95      0.96    104371

micro-f1       0.97      0.95      0.96    104371

在1998年来临之际,我十分高兴地通过中央人民广播电台、中国国际广播电台和中央电视台,向全国各族人民,向中国香港特别行政区同胞、澳门和台湾同胞、海外侨胞,向世界各国的朋友们,致以诚挚的问候和良好的祝愿!
Load ckpt from ./checkpoints/bert_crf_sighan2005/model.pt
Use single gpu in: ['0']
{'word': [('在', 0), ('1998年', 1), ('来临', 6), ('之际', 8), (',', 10), ('我', 11), ('十分', 12), ('高兴', 14), ('地', 16), ('通过', 17), ('中央', 19), ('人民', 21), ('广播', 23), ('电台', 25), ('、', 27), ('中国', 28), ('国际', 30), ('广播', 32), ('电台', 34), ('和', 36), ('中央', 37), ('电视台', 39), (',', 42), ('向', 43), ('全国', 44), ('各族', 46), ('人民', 48), (',', 50), ('向', 51), ('中国香港', 52), ('特别', 54), ('行政区', 56), ('同胞', 59), ('、', 61), ('澳门', 62), ('和', 64), ('台湾', 65), ('同胞', 67), ('、', 69), ('海外', 70), ('侨胞', 72), (',', 74), ('向', 75), ('世界各国', 76), ('的', 80), ('朋友', 81), ('们', 83), (',', 84), ('致以', 85), ('诚挚', 87), ('的', 89), ('问候', 90), ('和', 92), ('良好', 93), ('的', 95), ('祝愿', 96), ('!', 98)]}

到此,我们的基于bert的分词就全部完成了。

补充

代码地址:https://github.com/taishan1994/pytorch_bert_bilstm_crf_ner

要先下载预训练模型和项目同级的model_hub下,这里使用的是hugging face上面的roberta。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-08-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 数据预处理
  • 训练、验证、测试和预测
  • 补充
相关产品与服务
NLP 服务
NLP 服务(Natural Language Process,NLP)深度整合了腾讯内部的 NLP 技术,提供多项智能文本处理和文本生成能力,包括词法分析、相似词召回、词相似度、句子相似度、文本润色、句子纠错、文本补全、句子生成等。满足各行业的文本智能需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档