数据分析精选案例:3行代码上榜Kaggle学生评估赛

©作者 | 一峰

现在kaggle学生写作评估赛举办得如火如荼,下面我们来试试如何3行代码上榜kaggle。

01 比赛题目背景

写作是成功的关键技能。但是,根据国家教育进步评估,只有 不到三分之一的高中生是熟练的作家。

在这次kaggle比赛中,将识别学生写作中的元素 。其中,需要自动分割文本并对6至12年级学生的议论文中的议论和修辞元素进行分类 。

在该kaggle句子分类baseline中,我们可以提出2个想法,一个是对句子进行分类,另一个是对句子中的文字进行序列化标注,本文是使用文本分类的方式来快速验证,使用ernie和bert模型进行文本分类。

02 数据探索性分析

比赛一共有7个类别,348053条训练数据

对文本字数统计分析

通过上图可见字数长度范围为0< 字符串长度 < 3500,字数统计量最多的集中在0到500之间,对此我们要开始注意一个点,bert分类模型支持最大的字符串长度是512,一旦超过该长度,后面的字符就会被截断。

对文本存在空值进行分析

TRAIN_PATH ="../input/feedback-prize-2021/train"train_df=pd.read_csv(TRAIN_CSV, dtype={'discourse_id': int,'discourse_start': int,'discourse_end': int,'discourse_type':str})train_df.isnull().sum()

id                    0discourse_id          0discourse_start       0discourse_end         0discourse_text        0discourse_type        0discourse_type_num    0predictionstring      0dtype: int64

可见数据不存在空值

● 标签的平均开始和结束的绝对位置

data = train_df.groupby("discourse_type")[['discourse_end', 'discourse_start']].mean().reset_index().sort_values(by = 'discourse_start', ascending = False)data.plot(x='discourse_type',        kind='barh',        stacked=False,        title='Average start and end position absolute',        figsize=(12,4))plt.show()

由此可知Lead位置排第一,concluding statement结语排在最后的位置,evidence的字符数最长

● 所有论文中的话语类型频率和标签类型的平均字数

fig = plt.figure(figsize=(12,8))ax1 = fig.add_subplot(211)ax1 = train.groupby('discourse_type')['discourse_len'].mean().sort_values().plot(kind="barh")ax1.set_title("Average number of words versus Discourse Type", fontsize=14, fontweight = 'bold')ax1.set_xlabel("Average number of words", fontsize = 10)ax1.set_ylabel("")ax2 = fig.add_subplot(212)ax2 = train.groupby('discourse_type')['discourse_type'].count().sort_values().plot(kind="barh")ax2.get_xaxis().set_major_formatter(FuncFormatter(lambda x, p: format(int(x), ','))) #add thousands separatorax2.set_title("Frequency of Discourse Type in all essays", fontsize=14, fontweight = 'bold')ax2.set_xlabel("Frequency", fontsize = 10)ax2.set_ylabel("")plt.tight_layout(pad=2)plt.show()

由上图可知,evidence的平均字数最长,接近80个字,claim出现频率最高,接近5万条

03 Ernie模型简单介绍

进行上面的数据分析之后,我们开始进行模型选型,既然是文本分类,肯定是无脑bert来一波。

作者无意中发现baidu的ernie号称吊打bert,bert是使用字级别的mask,而ernie使用了短语级别的mask。

在5测试任务中,都比bert取得了较好的成绩,特别是ChnSentiCorp情感分类,训练集高0.6%准确率,测试集高1.1%准确率。

04 Ernie模型训练

我们开始3行代码训练erine模型,上榜kaggle!

# 优化器的选择和参数配置optimizer = paddle.optimizer.Adam(learning_rate=5e-5, parameters=model.parameters())  # fine-tune任务的执行者trainer = hub.Trainer(model=hub.Module(name='ernie_v2_eng_base',                   task='seq-cls', num_classes=num_class), optimizer, checkpoint_dir='/kaggle/working/ckpt', use_gpu=True)  # 配置训练参数,启动训练,并指定验证集trainer.train(train_dataset, epochs=num_epochs, batch_size=batch_size, eval_dataset=dev_dataset, save_interval=1)  

然后,我们开始了漫长的等待。

[2021-12-24 15:33:34,154] [   TRAIN] - Epoch=3/3, Step=10620/10625 loss=0.8742 acc=0.7000 lr=0.000050 step/sec=1.40 | ETA 06:22:27

最后,训练了3个epoch,没想到准确率才70%,损失高达0.8。怀着怀疑的态度进行了提交。

终于上榜了,分数才0.008,排名564/581,还好不是倒数。对此我们使用kaggle上大佬的transformer的bert进行测试。

#定义bert分类模型model = AutoModelForSequenceClassification.from_pretrained(MODEL_CHK, num_labels=NUM_LABELS)#定义参数training_args = TrainingArguments(    output_dir='feeeback-classifier',    learning_rate=2e-5,    per_device_train_batch_size=32,    per_device_eval_batch_size=32,    num_train_epochs=NUM_EPOCHS,    weight_decay=0.01,    report_to="none",    evaluation_strategy="epoch",    save_strategy="epoch",)#定义训练器trainer = Trainer(    model=model,    args=training_args,    train_dataset=ds_train_tokenized,    eval_dataset=ds_val_tokenized,    tokenizer=tokenizer,    #data_collator=data_collator,)#模型训练trainer.train()

又等了不是很久,输出结果,也是出现特别高的损失,训练损失0.9,验证损失0.95。并将预测结果直接提交。

Epoch Training Loss Validation Loss1    1.036200       0.9658962    0.937500      0.954762

竟然0.223?排名519/581。

05 Baseline总结分析和后续工作

经过2个模型的测试和耗时的训练,最后最好的成绩是BERT文本分类的0.223。

对此,我们开始分析原因,尝试其他trick。

字符串长度和数量分布不均衡,某个分类(如evidence)字符串太长和数量多;

文本分类的字符串太长,因为分类任务最多只支持512长度字符串,如果使用超长字符运行,则会出现gpu显存不够的问题,所以我们测试时使用的都是256的字符串,导致训练数据的后面字符特征都被丢弃;

比赛成绩提交只能使用离线环境,预训练模型都得提前准备安装包,特别耗时费力。

总结下来,对于长文本(超过512)的文本分类,bert和erine的总体效果都不佳。

后续需要优化提升的地方:

使用文本增强提高训练数据多样性,如将英文先翻译为其他语言,再翻译回中文,使用近义词替换;

使用支持长文本的预训练模型,如longformer(长文本的bert)和erine-doc;

修改解题思路,将文本分类修改成文本序列化标注(NER)的方式,将数据特征改成序列化标注的形式,使用longformer或者erine-doc进行训练。

参考

[1] https://www.kaggle.com/stephenlu0422/nlp-on-student-writing-eda/edit

[2] https://www.kaggle.com/stephenlu0422/ernie?scriptVersionId=83170296

[3] https://www.kaggle.com/stephenlu0422/feedback-baseline-sentence-classifier-0-226?scriptVersionId=82417881

[4] Yu Sun, Shuohuan Wang, Yukun Li, Shikun Feng,Xuyi Chen, Han Zhang, Xin Tian, Danxiang Zhu, Hao Tian, Hua Wu:ERNIE Enhanced Representation through Knowledge Integration,2019,Apir,19


私信我领取目标检测与R-CNN/数据分析的应用/电商数据分析/数据分析在医疗领域的应用/NLP学员项目展示/中文NLP的介绍与实际应用/NLP系列直播课/NLP前沿模型训练营等干货学习资源。

你可能感兴趣的:(数据分析精选案例:3行代码上榜Kaggle学生评估赛)