NER建立模型时出现concat tensors不匹配问题

本文详细解析了在建立NER模型时遇到的TypeError,深入分析了问题根源在于concatV2操作接受的不同类型张量,并给出了修改mask_zero参数的解决方案。

1 问题描述

    在建立NER识别模型时出现:

        TypeError: Tensors in list passed to 'values' of 'ConcatV2' Op have types [bool, float32] that don't all match.       

        

 

2 分析问题

    我们仔细看报错语句,可以看到真正报错的语句为:return tf.concat([to_dense(x) for x in tensors], axis)

        

    我们找到这行代码:

        

    进行断点调试:

          

    可以看到确实存在两个tensor的值类型不一致。

    回过头再来看报错的语句:

          TypeError: Tensors in list passed to 'values' of 'ConcatV2' Op have types [bool, float32] that don't all match.   

          这句话的意思是:传给concatV2操作的values值有两种类型,一直是bool类型,一种是float32类型。 

    从实际代码来看就是下面这一句:

        

    但是上面两个tensor值是哪里传过来的呢?

    经过调试,发现是从mask传过来的值:

        

    bool类型的值是mask,float32类型的值是zeros_like的返回值。

 

3 解决问题

    于是我们将建立模型时的参数:

        model.add(Embedding(len(self.vocab), self.Embedding_dim, mask_zero=True))

    改为:

        model.add(Embedding(len(self.vocab), self.Embedding_dim, mask_zero=False))

    于是,代码可以正常运行了:

     

 

4 问题总结

    (1) 需要认真看每一条报错信息对应代码;

    (2) 打断点调试到报错的语句,查看相应的数据值;

    (3) 怀疑是原始数据的问题导致,mask_zero不能设置为True,有待进一步分析。

<think>我们注意到用户的问题:如何训练自定义的NER模型使用CWS功能。根据之前的回答,我们知道HanLP的训练通常包括分词(CWS)和命名实体识别(NER)两个步骤,但用户希望只训练NER模型,而使用CWS功能(即使用分词模型)。实际上,HanLP的命名实体识别(NER)任务通常依赖于分词结果。但是,用户可能希望直接使用字符级别的NER模型,这样就需要分词步骤。在HanLP中,我们可以训练一个需要分词输入的NER模型,即直接输入字符序列进行NER识别。根据HanLP的文档和代码,训练一个依赖分词的NER模型(即字符级别的NER模型)是完全可行的。我们可以通过以下步骤实现:1.**准备训练数据**:数据格式为每行一个字符和一个标签(BIO或BIOES格式),用空格分隔。注意,这里需要分词,每个字符单独一行,句子之间用空行分隔。示例:```华B-ORG为I-ORG发O布OMOaOtOeO6O0O```2.**训练模型**:使用HanLP的感知机训练器,指定任务为NER,并且确保输入数据是字符级别的格式。3.**使用模型**:在预测,我们直接输入字符串(字符序列),而需要先分词。但是,需要注意的是,HanLP的`PerceptronLexicalAnalyzer`通常同包含分词、词性标注和NER。如果我们只想使用NER,并且想使用分词功能,我们可以单独使用NER模型。然而,在HanLP中,NER模型默认是接受分词后的序列作为输入的。因此,我们需要改变输入方式,使用字符序列作为输入。实际上,HanLP的感知机NER模型可以接受两种输入:一种是分词后的词语序列(每个词语作为一个单位),另一种是字符序列(每个字符作为一个单位)。在训练数据格式上,字符级别的NER训练数据就是每个字符一行,标签为实体标签。因此,训练字符级别的NER模型的方法与之前训练NER模型的方法相同,唯一区别在于训练数据的格式:我们使用字符级别的标注数据,而是词语级别的标注数据。具体训练步骤(Java代码):1.准备训练数据:格式为字符序列的标注(每行:字符[空格]标签)。2.使用`PerceptronTrainer`训练NER模型。3.使用,我们可以通过`PerceptronLexicalAnalyzer`加载NER模型,但是我们需要禁用分词功能。然而,`PerceptronLexicalAnalyzer`的设计是分词、词性标注和NER联合的,所以如果我们禁用分词,我们需要提供字符序列作为输入。另一种方式是,我们可以直接使用训练好的NER模型(`LinearModel`)进行预测,而通过`PerceptronLexicalAnalyzer`。HanLP提供了`PerceptronSegmenter`、`PerceptronPOSTagger`和`PerceptronNERecognizer`三个独立的类。因此,我们可以单独使用`PerceptronNERecognizer`。下面我们将分步骤详细说明:###1.准备训练数据(字符级别)训练数据示例(ner_train.txt):```华B-ORG为I-ORG发O布OMOaOtOeO6O0O中B-ORG国I-ORG科B-ORG学I-ORG院I-ORG发O布O了O新O款O芯O片O```###2.训练模型(Java代码)我们可以使用以下代码训练一个字符级别的NER模型:```javaimportcom.hankcs.hanlp.model.perceptron.PerceptronTrainer;importcom.hankcs.hanlp.model.perceptron.model.LinearModel;publicclassTrainNERModel{publicstaticvoidmain(String[]args){//训练字符级别的NER模型LinearModelnerModel=newPerceptronTrainer().train("path/to/ner_train.txt",//训练数据路径"path/to/ner.bin",//模型保存路径"NER",//任务类型0.3,//开发集比例15//最大迭代次数).getModel();}}```###3.使用训练好的NER模型进行预测我们可以单独使用NER模型进行预测,而依赖于分词:```javaimportcom.hankcs.hanlp.model.perceptron.PerceptronNERecognizer;importjava.util.List;publicclassUseNERModel{publicstaticvoidmain(String[]args)throwsException{//加载NER模型PerceptronNERecognizerrecognizer=newPerceptronNERecognizer("path/to/ner.bin");//输入字符数组(即把字符串拆分为字符数组)Stringsentence="华为发布Mate60";String[]words=newString[sentence.length()];for(inti=0;i<sentence.length();i++){words[i]=String.valueOf(sentence.charAt(i));}//进行NER识别List<String>nerTags=recognizer.recognize(words,null);//第二个参数是词性,因为我们没有分词和词性,所以传null//打印结果for(inti=0;i<words.length;i++){System.out.println(words[i]+"\t"+nerTags.get(i));}}}```输出示例:```华B-ORG为I-ORG发O布OMOaOtOeO6O0O```注意:这种方法完全跳过了分词,直接使用字符序列作为输入。因此,它依赖于任何分词模型。###注意事项-训练数据的格式必须是字符级别的,即每个字符一行,标签为NER标签(如BIO格式)。-在训练,HanLP会自动根据数据格式判断输入是词语级别还是字符级别。如果每行只有一个字符(或一个汉字),那么HanLP会将其视为字符级别训练。-在预测,我们需要将字符串拆分为字符数组,然后输入到`PerceptronNERecognizer.recognize`方法中。这样,我们就实现了使用CWS功能,直接训练和使用NER模型。引用说明:根据引用[1]和[2],HanLP支持自定义模型训练,并且提供了丰富的API。我们参考了HanLP的文档和代码结构,给出了上述解决方案[^1][^2]。§§相关问题§§1.如何评估HanLP训练出的NER模型的性能?2.在字符级别的NER任务中,如何处理多字符实体?3.HanLP的NER模型支持哪些标注格式(如BIO、BIOES)?</think>### 训练自定义 NER 模型依赖 CWS) 在 HanLP 中训练纯 NER 模型依赖分词功能)的核心步骤: #### 1. 准备纯 NER 训练数据 - **格式要求**:字符级标注(每行 `字符 [空格] NER标签`) - **示例** (`ner_train.txt`): ```text 华 B-ORG 为 I-ORG 发 O 布 O M O a O t O e O 6 O 0 O ``` - **关键特点**: - 直接标注字符而非词语 - 使用 BIO/BIOES 标注体系 - 句子间用空行分隔[^3] #### 2. 训练纯 NER 模型(Java) ```java import com.hankcs.hanlp.model.perceptron.PerceptronTrainer; import com.hankcs.hanlp.model.perceptron.model.LinearModel; import com.hankcs.hanlp.model.perceptron.tagset.NERTagSet; public class PureNERTraining { public static void main(String[] args) { // 配置NER标签体系(禁用CWS相关标签) NERTagSet tagSet = new NERTagSet(); tagSet.nerLabels.add("B-ORG"); tagSet.nerLabels.add("I-ORG"); tagSet.nerLabels.add("O"); // 训练纯NER模型 LinearModel nerModel = new PerceptronTrainer() .setTagSet(tagSet) // 指定自定义标签集 .train( "path/to/ner_train.txt", // 训练数据 "path/to/pure_ner.bin", // 模型输出 "NER", // 任务类型 0.3, // 开发集比例 20 // 迭代次数 ).getModel(); } } ``` #### 3. 使用纯 NER 模型预测 ```java import com.hankcs.hanlp.model.perceptron.PerceptronNERecognizer; public class PureNERPrediction { public static void main(String[] args) { // 加载纯NER模型 PerceptronNERecognizer ner = new PerceptronNERecognizer("path/to/pure_ner.bin"); // 输入字符数组(跳过CWS) String text = "华为发布Mate60"; String[] chars = text.split(""); // 拆分为字符数组 // 执行NER预测 String[] tags = ner.recognize(chars, null); // 第二个参数为词性(设为null) // 输出结果 for (int i = 0; i < chars.length; i++) { System.out.println(chars[i] + "\t" + tags[i]); } } } ``` **输出示例**: ``` 华 B-ORG 为 I-ORG 发 O 布 O M O a O t O e O 6 O 0 O ``` #### 关键注意事项 1. **数据预处理**: - 确保文本拆分为**单个字符** - 标签中**要包含**分词相关标签(如 `B-W`,`I-W`) - 使用 `UTF-8` 编码[^2] 2. **模型配置**: - 显式定义 `NERTagSet` 排除 CWS 标签 - 通过 `PerceptronNERecognizer` 直接加载 NER 模型 - 输入必须是**字符数组**而非分词结果[^3] 3. **性能优化**: ```java .setLearningRate(0.1) // 调整学习率 .setMaxIteration(30) // 增加迭代次数 .enableFeature(0.5) // 特征剪枝阈值 ``` > 此方法完全**跳过分词阶段**,直接进行字符级实体识别,适合处理未分词文本或需要避免分词误差的场景[^1]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值