HW-DIGIX-2021-赛题2-文章质量PU-BERT联合预测

摘要:

合集:AI案例-自然语言处理-广告和传媒
赛题:HW-DIGIX-2021-赛题2-基于多模型迁移预训练文章质量判别
官网:https://developer.huawei.com/consumer/cn/activity/digixActivity/digixdetail/201621215957378831
AI问题:文本分类问题
数据集:匿名化的文章质量数据集,包括576,454条训练数据和45,285条测试数据。是一种正样本(P)和未标记样本(U)的PU数据集。
数据集发布方:华为
数据集价值:挖掘海量文章质量数据,采用合适的算法精准判定文章质量。
解决方案:PU-BERT联合预测,PU学习高效处理未标记数据问题,bert-base-chinese模型提供强大的语义理解能力。transformers开发框架。

一、赛题描述

AI技术的迭代发展,将加速行业升级,从单场景AI创新向全场景智能数字化迈进。2021 DIGIX全球校园AI算法精英大赛邀请全球校园算法达人共同挑战数字时代前沿命题,为构建万物互联的智能世界贡献全新算法力量。

1)赛题一:基于多目标多视图的用户留存周期预测

2)赛题二:基于多模型迁移预训练文章质量判别

文章质量判别是信息流领域的核心问题,提升文章质量判别的准确率是提升信息流质量和精准推送的核心技术点。在本次大赛中,主办方提供匿名化的文章质量数据,参赛选手基于给定的数据构建文章质量判别模型。希望通过本次大赛挖掘NLP算法领域的人才,推动 NLP算法的发展。

3)赛题三:基于多目标优化的视频推荐

4)赛题四:基于多模态多语言的搜索排序

5)赛题5:小样本菜单识别

本文讨论赛题二。

二、数据集描述

1、数据简介

任务为基于给定的文章数据构建文章质量判别模型。所提供的数据经过脱敏处理,保证数据安全。 该文章质量数据集,包括576,454条训练数据和45,285条测试数据。

对文章质量类型进行分组统计结果如下:

文章质量类型训练集中的标注数据定义
深度事件16,670对各领域重大事件的深度分析、专题报道、脉络构建,事件呈现
人物专栏7,242在某一领域有影响力、成为焦点或热点的人物的访谈、深度挖掘、人生故事
行业解读9,968对某一行业、领域所发生的变化进行现象解说、数据解读、原因剖析、论点论证
物品评测4,381从多个维度对某一物品进行测试评价,展现该物品特点,为人们提供参考
作品分析14,094对经典或者热门作品内容的赏析、解读或者背景挖掘,作品包含文学作品、娱乐影视和综艺作品
攻略文5,517针对不同的生活场景为达到某个目的而展开方法论描述和可行性的指导,有助于读者学习到新知识,解决问题
科普知识文6,337针对不同的专业领域的知识点或现象进行描述、说明以及论证,使得读者获得新知识,增长见识
情感解读7,183针对情感问题或情感事件进行解读分析
治愈系文章3,868呈现美好事物的文章,能引起读者极度舒适,激发愉悦心情的文章
推荐文1,194针对单个或多个文学作品、小说、游戏、动漫作品的汇总、评价比较,介绍推荐文章
其他*不在上述10种类型的文章

2、训练集

基础数据集包含两部分:训练集和测试集。其中训练集给定了该样本的文章质量的相关标签字段:doctype。

训练集文件 doc_quality_data_train.json 的数据格式如下:

FieldTypeDescriptionNote
idString文章ID
titleString文章标题
bodyString文章正文内容
categoryInt文章类别取值范围0-30
doctypeString优质类别索引共计10种

数据样例:

{
"id": "0e7668c6-a98d-11eb-8239-7788095c0b0f",
"title": "篮球——CBA第四阶段:辽宁本钢迎战吉林九台农场银行",
"body": "篮球——CBA第四阶段:辽宁本钢迎战吉林九台农场银行 \n新华社照片,诸暨(浙江),2021年3月26日 \n (体育)(13)篮球——CBA第四阶段:辽宁本钢迎战吉林九台农场银行 \n 3月26日,辽宁本钢队主教练杨鸣在比赛中指挥。 \n 当日,在浙江诸暨举行的2020-2021赛季中国男子篮球职业联赛(CBA)第四阶段第48轮比赛中,辽宁本钢队对阵吉林九台农商银行队。 \n 新华社记者 孟永民 摄",
"category": 1,
"doctype": ""
}

{
  "id": "cc4dbfd2-273d-402e-8fb5-8dd774fe6fcf",
  "title": "19岁嫁给张艺谋,5年生3子,巩俐拿不下的男人她凭什么拿下",
  "body": "19岁嫁给张艺谋,5年生3子,巩俐拿不下的男人她凭什么拿下的文/简单点张艺谋的儿子张壹男19岁了,母亲陈婷在社交网络上为儿子庆生,并感慨19年来第一次没和儿子一起过生日……",
  "category": 8,
  "doctype": "人物专栏"
}

3、测试集

测试集用于计算参赛选手模型的评分指标,参赛选手需要计算出测试集中每个样本文章质量判断及优质文章的类型。测试集文件 doc_quality_data_test.json 的数据样例如下:

{
"id": "9b39a1a5-259b-4daa-a5b8-affb16fc78f8",
"title": "•东莞副市长:力争把横沥镇打造成大湾区新型样板城镇",
"body": "东莞副市长:力争把横沥镇打造成大湾区新型样板城镇14日,2020年广东省世界标准日纪念活动暨东莞市横沥镇“标准化+乡村振兴”活动周正式拉开帷幕,横沥镇获授牌国家新型城镇化标准化试点。。。。统筹 刘辉龙 肖佩佩采写 南都记者 梁锦弟 田玲玲 黄馨莹 黄芳芳摄影 南都记者 刘媚",
"category": 5
}

4、数据集版权许可协议

BY-NC-SA 4.0
数据集发布方:华为
https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh-hans

三、解决方案样例

基于训练集中的有标注的数据可用于构建10分类器,模型思路上为简单的预训练模型微调思路。从训练数据集中,可发现存在大量未标注的训练数据,即没有考虑全‘其他’类别的判定。利用训练好的10分类器对训练数据中提供的无标注数据(即doctype列为空的数据)进行预测,取其中预测概率大于某一配置值(例如0.8)的类别作为正样本,其他的作为负样本。再利用划分出来的正负样本训练文章质量二分类模型用于判别文章的质量,质量差的话预测类别为“其他”,质量优的话再送入训练好的10分类器中进行具体类别判断!

1、工作原理介绍

bert-base-chinese 是 Hugging Face Transformers 库提供的一个预训练 BERT 模型,专门针对中文文本进行了优化。以下是该模型的全面介绍:

核心信息

属性
​模型类型​BERT (Bidirectional Encoder Representations from Transformers)
​语言​中文(简体和繁体)
​发布机构​Google Research(原始架构) + Hugging Face(实现)
​模型大小​约 1.2GB(包含参数和配置文件)
​词汇表大小​21,128 个中文字符和常用符号

主要特点

  1. ​中文优化​​:
    • 专门针对中文文本训练
    • 支持简体和繁体中文
    • 处理中文特有的分词挑战
  2. ​全词掩码(Whole Word Masking)​​:
    • 对完整词语进行掩码(例如:掩码”北京”而不是单个字”北”或”京”)
    • 更符合中文语言特性
  3. ​字符级分词​​:
    • 使用基于字符的分词(而非词级)
    • 解决中文分词歧义问题
  4. ​预训练优势​​:
    • 捕捉深层语义关系
    • 理解上下文依赖
    • 支持迁移学习

2、源码结构

需要按顺序执行如下 Python 源码文件:

  1. 预处理数据: preprocess.py
  2. 训练 Bert 分类器:Train_Bert.py
  3. 预测 U 并输出 RN: Build_PU_data.py
  4. 训练 Binary Classifier: Train_PU_model.py
  5. 预测优质类别索引并输出: submission.csv Joint_Predictor.py

3、运行环境

参考文章《安装深度学习框架PyTorch》。

外部库名称版本号
python3.7.12
pandas1.3.5
numpy1.21.6
beautifulsoup44.13.4
torch1.10.2+cu102
torchaudio0.10.2+cu102
torchvision0.11.3+cu102
transformers4.26.1
joblib1.3.2
scikit-learn0.23.2

四、工作流程

1、预处理数据

源码: preprocess.py

这个Python脚本主要用于对原始训练集和测试集进行预处理,包括数据清洗、标签处理和数据集划分。下面我将详细分析其工作原理:

a、主要功能

  1. 数据清洗:去除正文中可能重复出现的标题,清理空白字符
  2. 数据集划分:将训练集划分为带标记样本集(P)和未知样本集(U)
  3. 标签处理:对带标记样本的标签进行索引化处理
  4. 数据统计:生成标签集和样本数量的统计信息

b、数据处理流程

  1. 输入文件
    • 原始训练集:./data/doc_quality_data_train.json
    • 原始测试集:./data/doc_quality_data_test.json
  2. 输出文件
    • 预处理后的训练集:./data/preprocessed_train.json
    • 预处理后的测试集:./data/preprocessed_test.json
    • 带标记训练集:./data/postive_train.json
    • 未标记训练集:./data/unlabeled_train.json
    • 标签统计信息:./data/positive_info.json
  3. 优质类别索引:预定义的10个类别:人物专栏、作品分析、情感解读等

c、运行结果展示

>python Preprocess.py
Processing File: ./data/doc_quality_data_train.json
576454it [03:57, 2431.03it/s]
duplicate: 573930       no_html: 576274, no_duplicate: 2524

Processing File: ./data/doc_quality_data_test.json
45285it [00:20, 2202.89it/s]
duplicate: 37407         no_html: 45284, no_duplicate: 7878

./data/preprocessed_train.json

===================   The distribution of Positive train data   ===================
6   16670
1   14094
9     9968
0     7242
2     7183
8     6337
4     5517
7     4381
5     3868
3     1194
Name: label, dtype: int64
Preprocess done!

2、训练 Bert 分类器

源码:Train_Bert.py

a. 初始化设置

  • 导入依赖:使用transformers加载BERT模型,torch构建神经网络,json处理数据,自定义Preprocesslogger模块
  • 关键路径配置
    • 预训练BERT路径:./bert-base-chinese/
    • 微调模型保存路径:./model/finetuned_bert.bin
    • 训练数据路径:Preprocess.POSITIVE_TRAIN_FILE_PATH
  • 超参数
    • BATCH_SIZE=2(极小批大小,可能用于调试)
    • EPOCH=1(训练轮数)
import json
import os
import torch
import transformers as tfs
import random
from torch import nn
from torch import optim
from logger import Progbar
import Preprocess

# Bert预训练模型
model_path = "./model/"
FINETUNED_BERT_ENCODER_PATH = os.path.join(model_path, "finetuned_bert.bin")
POSITIVE_TRAIN_FILE_PATH = Preprocess.POSITIVE_TRAIN_FILE_PATH
POSITIVE_TRAIN_INFO_PATH = os.path.join(Preprocess.dataset_path, "positive_info.json")
UNLABELED_TRAIN_FILE_PATH = Preprocess.UNLABELED_TRAIN_FILE_PATH
PRETRAINED_BERT_ENCODER_PATH = "./bert-base-chinese/"
BERT_MODEL_SAVE_PATH = model_path
BATCH_SIZE = 2
EPOCH = 1

b. 核心功能函数

  • 数据预处理
# 定义输入到Bert中的文本的格式,即标题,正文的组织形式
def prepare_sequence(title: str, body: str):
   return (title, body[:256] + "|" + body[-256:])
  • 数据迭代器
    • get_text_and_label_index_iterator():逐行解析JSON数据,生成(文本, 标签)对
    • get_bert_iterator_batch():将数据打包为指定批大小,每批随机打乱顺序
# 迭代器: 逐条读取数据并输出文本和标签
def get_text_and_label_index_iterator(input_path):
   with open(input_path, 'r', encoding="gbk",errors='ignore') as input_file:
       for line in input_file:
           try:
               json_data = json.loads(line)
           except json.JSONDecodeError as e:
               # 打印错误位置附近的文本
               start = max(0, e.pos - 50)
               end = min(len(line), e.pos + 50)
               print(f"JSON解析错误位置: {e.pos}")
               print(f"上下文内容: {line[start:end]}")
               print(f"错误详情: {e}")
               print(f"跳过无法解析的行: {line[:100]}...\n")
               continue

           text = prepare_sequence(json_data["title"], json_data["body"])
           label = json_data['label']

           yield text, label


# 迭代器: 生成一个batch的数据
def get_bert_iterator_batch(data_path, batch_size=32):
   keras_bert_iter = get_text_and_label_index_iterator(data_path)
   continue_iterator = True
   while continue_iterator:
       data_list = []
       for _ in range(batch_size):
           try:
               data = next(keras_bert_iter)
               data_list.append(data)
           except StopIteration:
               continue_iterator = False
       random.shuffle(data_list)

       text_list = []
       label_list = []

       for data in data_list:
           text, label = data
           text_list.append(text)
           label_list.append(label)

       yield text_list, label_list

   return False

c. 模型架构

class BertClassificationModel(nn.Module):
   """Bert分类器模型"""

   def __init__(self, model_path, predicted_size, hidden_size=768):
       super(BertClassificationModel, self).__init__()
       model_class, tokenizer_class = tfs.BertModel, tfs.BertTokenizer
       self.tokenizer = tokenizer_class.from_pretrained(model_path)
       self.bert = model_class.from_pretrained(model_path)
       self.linear = nn.Linear(hidden_size, predicted_size)
       self.dropout = nn.Dropout(p=0.2)

   def forward(self, batch_sentences):
       batch_tokenized = self.tokenizer.batch_encode_plus(batch_sentences, add_special_tokens=True,
                                                          max_length=512,
                                                          pad_to_max_length=True)

       input_ids = torch.tensor(batch_tokenized['input_ids']).cuda()
       token_type_ids = torch.tensor(batch_tokenized['token_type_ids']).cuda()
       attention_mask = torch.tensor(batch_tokenized['attention_mask']).cuda()

       bert_output = self.bert(input_ids=input_ids, token_type_ids=token_type_ids, attention_mask=attention_mask)
       bert_cls_hidden_state = bert_output[0][:, 0, :]
       linear_output = self.dropout(self.linear(bert_cls_hidden_state).cuda()).cuda()
       return linear_output

d. 训练流程

准备阶段

  • 加载标签信息(限定3000个标签,可能为调试)
  • 设置GPU设备:torch.cuda.set_device(0)
  • 初始化模型:BertClassificationModel(PRETRAINED_BERT_ENCODER_PATH, num_labels)
    if os.path.exists(POSITIVE_TRAIN_INFO_PATH):
       labels_set, total_num = Preprocess.get_label_set_and_sample_num(POSITIVE_TRAIN_INFO_PATH, True)
       # 为了性能考虑,截取前面一部分标签
       labels_set = labels_set[:3000]
       total_num = 3000
   else:
       print("Found no positive_info.json, please return the Preprocess.py.")
       exit()

   torch.cuda.set_device(0)

   print("Start training model...")
   # train the model
   steps = get_steps_per_epoch(total_num, BATCH_SIZE)

   bert_classifier_model = BertClassificationModel(PRETRAINED_BERT_ENCODER_PATH, len(labels_set))
   bert_classifier_model = bert_classifier_model.cuda()

优化策略

  • 分层学习率
    • BERT参数:lr=1e-5
    • 分类层参数:lr=1e-4
  • 优化器:Adam + L2正则化(weight_decay=0.001)
  • 学习率调度:每步衰减为前次的60% (StepLR(step_size=per_epoch_steps, gamma=0.6))
  • 损失函数:交叉熵nn.CrossEntropyLoss()
    # 不同子网络设定不同的学习率
   Bert_model_param = []
   Bert_downstream_param = []
   number = 0
   for items, _ in bert_classifier_model.named_parameters():
       if "bert" in items:
           Bert_model_param.append(_)
       else:
           Bert_downstream_param.append(_)
       number += _.numel()
   param_groups = [{"params": Bert_model_param, "lr": 1e-5},
                  {"params": Bert_downstream_param, "lr": 1e-4}]
   optimizer = optim.Adam(param_groups, eps=1e-7, weight_decay=0.001)
   StepLR = torch.optim.lr_scheduler.StepLR(optimizer, step_size=steps, gamma=0.6)
   criterion = nn.CrossEntropyLoss()
   bert_classifier_model.train()
   progbar = Progbar(target=steps)

训练循环

    for epoch in range(EPOCH):
       model_save_path = os.path.join(BERT_MODEL_SAVE_PATH, "model_epoch{}.pkl".format(epoch))
       dataset_iterator = get_bert_iterator_batch(POSITIVE_TRAIN_FILE_PATH, BATCH_SIZE)

       for i, iteration in enumerate(dataset_iterator):
           # 清空梯度
           bert_classifier_model.zero_grad()
           text = iteration[0]
           labels = torch.tensor(iteration[1]).cuda()
           optimizer.zero_grad()
           output = bert_classifier_model(text)
           loss = criterion(output, labels).cuda()
           loss.backward()

           # 更新模型参数
           optimizer.step()
           # 学习率优化器计数
           StepLR.step()
           progbar.update(i + 1, None, None,
                          [("train loss", loss.item()), ("bert_lr", optimizer.state_dict()["param_groups"][0]["lr"]),
                          ("fc_lr", optimizer.state_dict()["param_groups"][1]["lr"])])

           if i == steps - 1:
               break

       # 保存完整的 BERT 分类器模型
       torch.save(bert_classifier_model, model_save_path)
       # 单独保存经 fune-tune 的 BertEncoder模型
       torch.save(bert_classifier_model.bert, FINETUNED_BERT_ENCODER_PATH)
       print("epoch {} is over!\n".format(epoch))

e. 运行结果展示

>python Train_Bert.py
Start training model...
Some weights of the model checkpoint at ./bert-base-chinese/ were not used when initializing BertModel: ['cls.seq_relationship.weight', 'cls.predictions.transform.dense.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.decoder.weight', 'cls.predictions.bias', 'cls.predictions.transform.dense.weight', 'cls.seq_relationship.bias']

  1/1500 [..............................] - ETA: 4408s - train loss: 2.36209 - bert_lr: 0.00001 - fc_lr: 0.00010Be aware, overflowing tokens are not returned for the setting you have chosen, i.e. sequence pairs with the 'longest_first' truncation strategy. So the returned list will always be empty even if some tokens have been removed.
Be aware, overflowing tokens are not returned for the setting you have chosen, i.e. sequence pairs with the 'longest_first' truncation strategy. So the returned list will always be empty even if some tokens have been removed.
  2/1500 [..............................] - ETA: 3129s - train loss: 2.72812 - bert_lr: 0.00001 - fc_lr: 0.00010Be aware, overflowing tokens are not returned for the setting you have chosen, i.e. sequence pairs with the 'longest_first' truncation strategy. So the returned list will always be empty even if some tokens have been removed.

1498/1500 [============================>.] - ETA: 3s - train loss: 3.43204 - bert_lr: 0.00001 - fc_lr: 0.00010Be aware, overflowing tokens are not returned for the setting you have chosen, i.e. sequence pairs with the 'longest_first' truncation strategy. So the returned list will always be empty even if some tokens have been removed.
Be aware, overflowing tokens are not returned for the setting you have chosen, i.e. sequence pairs with the 'longest_first' truncation strategy. So the returned list will always be empty even if some tokens have been removed.
1499/1500 [============================>.] - ETA: 1s - train loss: 2.04987 - bert_lr: 0.00001 - fc_lr: 0.00010Be aware, overflowing tokens are not returned for the setting you have chosen, i.e. sequence pairs with the 'longest_first' truncation strategy. So the returned list will always be empty even if some tokens have been removed.
1500/1500 [==============================] - 2267s - train loss: 2.46442 - bert_lr: 0.00001 - fc_lr: 0.00006
epoch 0 is over!

Training is over!

3、预测未标记数据并输出负样本集

源码: Build_PU_data.py

这个Python脚本的主要功能是使用已训练的BERT分类器预测未标记数据(U),并构建可靠负样本集(RN),最终生成PU(正样本-未标记样本)学习所需的数据集。

PU(正样本-未标记样本/Positive-Unlabeled)数据

对于只有正样本(P)和未标记样本(U)的数据集,没有明确的负样本称为PU数据。在许多实际场景中(如异常检测、医学诊断),负样本难以获取或标注成本高,但未标记数据(可能是正或负)容易获得。

在代码中的作用:

  • 脚本将已标注的正样本(POSITIVE_TRAIN_FILE_PATH)标记为 1
  • 未标记样本(UNLABELED_TRAIN_FILE_PATH)标记为 0(假设它们可能是负样本)。
  • 最终生成两个文件:
    • PU_text.npy:BERT编码后的特征向量。
    • PU_label.npy:对应的PU标签(1=正样本,0=未标记)。

应用场景

  • 垃圾邮件检测:已标注的垃圾邮件(P)+ 未标注的收件箱(U)。
  • 疾病诊断:确诊患者(P)+ 未筛查人群(U)。
  • 代码中的场景:文本分类(如新闻分类),已知部分正类别,其余未标注。

RN(Reliable Negatives,可靠负样本)

从未标记数据(U)中高置信度筛选出的负样本。筛选方法:用已训练的BERT分类器预测未标记数据。选择预测概率极低(如<0.1)的样本作为RN(认为它们不可能是正样本)。

作用:

  • 解决PU学习中“未标记数据可能包含正样本”的模糊性问题。
  • 提供高质量的负样本,提升模型性能。

处理逻辑如下:

a. 主要功能

  • 加载已微调的BERT编码器
  • 对正样本(P)和未标记样本(U)进行编码
  • 构建PU数据集(正样本标记为1,未标记样本标记为0)
  • 将编码后的特征和标签保存为numpy数组文件

b. 关键组件分析

1 数据预处理

  • prepare_sequence(): 与Train_Bert.py中相同,将标题和正文组合成BERT输入格式
  • get_text_and_label_index_iterator(): 读取JSON数据,生成文本迭代器(无标签)
  • get_bert_iterator_batch(): 生成批量数据迭代器,支持最大长度限制

2 模型结构 (MyBertEncoder)

  • 基于微调的BERT模型构建编码器
  • 包含以下组件:
    • BERT tokenizer: 用于文本编码
    • 微调后的BERT模型: 从文件加载
    • 仅输出CLS位置的隐藏状态(768维向量)

3 PU数据构建 (build_pu_data())

初始化:

  • 创建正样本和未标记样本的数据迭代器
  • 未标记样本的batch_size是正样本的2倍
  • 加载MyBertEncoder并设置为评估模式

数据编码:

  • 使用BERT编码器对正样本和未标记样本进行编码
  • 正样本标记为1,未标记样本标记为0
  • 逐步拼接编码结果和标签

数据保存:

  • 将编码特征保存为PU_DATA_TEXT_SAVE_PATH(.npy)
  • 将标签保存为PU_DATA_LABEL_SAVE_PATH(.npy)

c. 关键参数

  • BATCH_SIZE = 2: 正样本批量大小
  • 未标记样本批量大小: BATCH_SIZE*2 = 4
  • 正样本最大数量: 3000
  • 未标记样本最大数量: 10000
  • 最大序列长度: 512 (BERT标准输入长度)

d. 运行结果展示

>python Build_PU_data.py
Start building PU data...
1500it [49:55, 2.00s/it]
PU data build successfully...

4、训练二分类器

源码: Train_PU_model.py

这个Python脚本实现了一个基于Elkanoto算法的PU学习(Positive-Unlabeled learning)分类器,用于处理只有正样本和未标记样本的二分类问题。Elkanoto算法是一种经典的PU学习(Positive-Unlabeled Learning)方法,用于解决只有正样本(P)和未标记样本(U)的二分类问题。其核心思想是通过估计未标记样本中正样本的比例,调整分类器的预测概率,从而实现对未标记样本的分类。

  • 输入数据:”data/PU_text.npy” 和 “data/PU_label.npy”
  • 输出模型到:”./model/pu_model.bin”。

运行 Train_PU_model.py 的输出如下:

>python Train_PU_model.py
Start fitting...
total n_positive: 3000
total n_unlabel:   6000
len of X_positive: (3000, 768)
len of X_unlabeled: (6000, 768)
Fitting done!

5、预测优质类别索引并输出

源码:Joint_Predictor.py

这个Python脚本实现了一个联合预测系统,结合了BERT分类器和PU学习分类器来预测测试集样本的类别,并将结果格式化输出到文件。PU学习高效处理未标记数据问题。BERT提供强大的语义理解能力。

运行 Joint_Predictor.py 的输出如下:

>python Joint_Predictor.py
Start evaluation...
Load bert_classifier model path: ./model/model_epoch0.pkl
Load PU_classifier model path: ./model/pu_model.bin
pandas bar: 100%|████████████████████████████████████████████████████████████████| 5000/5000 [1:01:17<00:00, 1.36it/s]

=================== The distribution of predictions ===================
深度事件   4715
其他       222
攻略文     41
物品评测     12
行业解读     10
Name: predict_doctype, dtype: int64

Evaluation done! Result has saved to: submission.csv

输出结果 submission.csv 的部分数据如下:

id (文章ID)predict_doctype (优质类别索引)
b535b557-cd03-437a-b8cb-09c17fd7980a深度事件
b6a53fce-c6be-4f5c-a8ea-fac5ec5372d8其他

源码开源协议

GPL-v3

五、获取案例套装

需要登录后才允许下载文件包。登录

发表评论