# lsptrain **Repository Path**: ykallan/lsptrain ## Basic Information - **Project Name**: lsptrain - **Description**: Longtime Support Project trainer 简易使用预训练模型进行文本分类 - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2023-04-20 - **Last Updated**: 2024-06-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # lsptrain ### Longtime Support Project for train nlp models 基于pytorch的长期支持的文本训练模型 开发目的,只要你有简单的python基础,即可训练出自己的nlp模型,全程傻瓜操作即可 目前支持的功能有: - [x] 1.1文本分类训练 - [x] 1.2文本分类推理 - [x] 2.1文本相似度计算 - [x] 3.1文本信息抽取训练 - [x] 3.2文本信息抽取推理 - [ ] 4.1 命名实体识识别训练(bio-ner) - [ ] 4.1 命名实体识识别推理(bio-ner) ## 安装方法 ```txt pip install lsptrain==0.0.62 -i https://pypi.python.org/simple ``` 目前没有对依赖进行版本限制,开发使用的`torch`版本为`1.11.0`,`transformers`的版本为`4.20.1`,如果在训练过程中报错,可以尝试切依赖版本进行尝试。 对于torch的安装,以及使用显卡进行训练,可以参考[pytorch](https://pytorch.org/get-started),本项目就不过多赘述了。 经过测试,处理中文数据时,使用的预训练模型为`hfl/chinese-roberta-wwm-ext`,个人感觉效果很不错,如有需要可以另行切换其他预训练模型。 众所周知,深度学习对数据量要求较多,建议在训练过程中,尽可能多的提供一些数据投喂给模型。不过过往测试,分类数量不太多的情况下,可能每个类别几十条或几百条,即可得到一个不错的模型。 注意:模型训练与推理,需要torch版本相同,不强行要求使用cpu与gpu,torch版本不同会导致加载预训练模型报错。 ### ps: 使用默认预训练模型,保存的模型权重,大概在400mb左右。 如果每次训练都使用默认的 `label_file_name`,会覆盖之前保存的数据,这个有可能需要注意一下. ## 文本分类训练方法: 文件:`train_script.py` ```python from lsptrain.nlp_classification import train train(train_path="train.txt") ``` 在控制台执行: ```shell python train_script.py ``` 即可。 训练完毕后,会在`train_script.py`脚本同级目录下,生成一个`checkpoint`文件夹,文件夹内包含`catalog_label.txt`文件与`*.pt`文件。 如果不设置`save_best=True`,保存的模型权重名称命名格式为`{job_type}_model_{epoch}_{test_accu}.pt` 其中`catalog_label.txt`为训练样本标签,`*.pt`文件为模型权重,可以通过以下脚本进行部署(只给出关键脚本): ```python # encoding: utf-8 from lsptrain.nlp_classification_predictor import TextClassificationPredictor predictor = TextClassificationPredictor(label_file_name="catalog_label.txt", model_file_name="txt_classification_model_best.pt") while True: text = input("Enter text:") result = predictor.predict(string=text) print(result) ``` 输出内容: ```text running model on device: cpu Enter text:HG标准镀锌4.8级全螺纹螺柱带加厚螺母平垫弹垫,M39-4.0*230,6套/箱 {'confidence': 0.405778169631958, 'label': 'A'} Enter text:HG标准镀锌4.8级全螺纹螺柱带加厚螺母平垫弹垫,M39-4.0*400,5套/箱 {'confidence': 0.4054565131664276, 'label': 'A'} ``` 其中`label`为输入文本预测的分类标签,`confidence`为预测的置信度,`confidence = 0.4054565131664276`可以理解为模型认为有`40.5%`的可能性分类为`A`, 置信度区间为`0-1` ps: 如果`checkpoint`与推理脚本位置不同,则需要指定`save_dir`路径。 数据集格式: ```text 训练样本__训练标签 ``` txt文件的每一行是一条完整的训练数据(样本与标签),如果样本中有换行(`\n`)等,建议提前处理一下。 样本与标签之间,使用双下划线`__`分割,例如: ```text 我今天很开心__积极 我今天很不开心__消极 ``` ### 参数说明 | 参数名称 | 类型 | 是否必填 | 字段描述 | |-----------|-------|------|------------------------------------------| | train_path | str | 是 | 训练集数据,应该为txt文件 | | test_size | float | 否 | 测试集比例,默认0.1 | | encoding | str | 否 | 打开数据字符集,默认为utf-8 | | split_data | str | 否 | 切分数据与标签的分隔符, 默认'__' | | pretrained_model | str | 否 | 预训练模型名称, 默认'hfl/chinese-roberta-wwm-ext' | | learning_rate | float | 否 | 学习率,默认0.0001 | | optimizer | str | 否 | 模型优化函数,默认adam,可选项('adam', 'sgd') | | batch_size | int | 否 | 训练批次大小,如果报错提示out of memory,可以适当调小,默认64 | | save_dir | str | 否 | 训练checkpoint保存路径 | | label_file_name | str | 否 | 保存标签文件名 | | save_best | bool | 否 | 是否只保存最优模型,默认False,每次训练一个epoch都保存一次模型 | | max_length | int | 否 | 默认序列最大长度64,超过部分会被自动截断 | | num_epochs | int | 否 | 训练步数,默认25 | | device | str | 否 | 训练设备。如果可用,默认使用第一块显卡 | | job_type | str | 否 | 任务名称,保存模型开头名称,默认'txt_classification' | ## 文本相似性计算方法 直接创建对象即可计算,由于在创建对象的时候会加载预训练的编码器 `tokenizer`,所以建议只创建一次,多次使用。 ```python from lsptrain.nlp_similarity_predictor import TextSimilarityPredictor string1 = "今天天气很好啊" string2 = "今天天气真不错呢" predictor = TextSimilarityPredictor(pretrained_tokenizer="hfl/chinese-roberta-wwm-ext") result = predictor.predict(string1, string2) print(result) # 0.9285515402978386 string3 = "我开心" string4 = "我不开心" result = predictor.predict(string3, string4) print(result) # 0.8846080193868797 ``` 此计算方法流程为: 1. 两个文本转化为词向量 2. 计算两个词向量的余弦相似度 简单来讲,计算方法为通过字符的对比计算相似性,不是使用经过训练的模型进行推理,所以准确性可能不是特别高。 如果只是基于字符进行比对,使用这个方法完全可以满足需求,并且预训练的模型,效果也都不错。 如果觉得效果不好,或是需要更换预训练的词向量转化模型,在创建`predictor`的时候传入参数`pretrained_tokenizer`即可: ```python from lsptrain.nlp_similarity_predictor import TextSimilarityPredictor pretrained_tokenizer = "your_new_pretrained_tokenizer" predictor = TextSimilarityPredictor(pretrained_tokenizer=pretrained_tokenizer) ``` ## 信息抽取 使用百度的uie进行信息抽取。 基本流程是下载paddle版本的uie模型权重,然后转换成torch版本,继而进行训练推理。 训练方法: ```python from lsptrain.nlp_info_extract.train_scripts import train train_path = "./train.txt" test_path = "./test.txt" pretrained_model = "uie-nano" train(train_path=train_path, test_path=test_path, model=pretrained_model, logging_steps=5, valid_steps=5) ``` 训练使用的预训练模型可选项有: ```python ['uie-base', 'uie-medium', 'uie-mini', 'uie-micro', 'uie-nano', 'uie-medical-base', 'uie-base-en'] ``` 推荐使用`uie-base` 训练结束后会在脚本统计目录创建一个`checkpoint`文件夹,类似的目录结构应为: ```text |-- train.txt |-- test.txt |-- train.py |-- checkpoint |-- model_90 |-- model_95 |-- model_100 |-- model_best ``` 训练集和测试集的数据格式为: ```text {"content": "得力(deli)0010订书钉10#(1000枚/盒)(单位:盒)", "prompt": "型号", "result_list": [{"start": 8, "end": 12, "text": "0010"}]} {"content": "得力(deli)0010订书钉10#(1000枚/盒)(单位:盒)", "prompt": "通用名", "result_list": [{"start": 12, "end": 15, "text": "订书钉"}]} {"content": "得力0010订书钉10#(1000枚/盒)10盒/包(包)", "prompt": "型号", "result_list": [{"start": 2, "end": 6, "text": "0010"}]} ``` 其中`prompt`可以理解为标签,`result_list`中的`text`则是标签对应的文本,`start`是文本在`content`所在的下标, `end`是`start`加上文本的长度,具体的获取方式如下: ```pycon >>> content = "得力(deli)0010订书钉10#(1000枚/盒)(单位:盒)" >>> text = "0010" >>> start = content.index(text) >>> end = start + len(text) >>> start 8 >>> end 12 >>> ``` 模型推理的调用方法为: ```python from lsptrain.nlp_info_extract import UIEPredictor schema = ['品牌', "型号", "通用名", "颜色"] predictor = UIEPredictor(model="uie-nano", schema=schema, task_path="./checkpoint/model_best", max_seq_len=64) text = "得力(deli)0010订书钉10#(1000枚/盒)(单位:盒)" result = predictor(text) print(result) # [{'型号': [{'text': '0010', 'start': 8, 'end': 12, 'probability': 0.99558866}], '通用名': [{'text': '订书钉', 'start': 12, 'end': 15, 'probability': 0.9935523}]}] ``` ## 命名实体识别 基于`bert`与`crf`实现的命名实体识别,ner格式。