本文将通过神经网络预训练模型实现对情景喜剧笑点的识别
文章目录
前言
任务背景
任务介绍
数据集介绍
数据集属性说明:
训练集:
验证集:
测试集:
评测指标:
由两个指标综合决定,即
步骤
1.数据预处理
思路:首先观察数据集本身,它是来源与情景喜剧对话,在一段对话中,存在不同角色进行交流,产生连续的对白(Utterance)。同一段对话中的对白按顺序出现,存在上下文关系。相比于单句幽默,对话中的幽默可能来自于上下文语境,而非对白内容本身。因此,需要结合上下文语境内容对对白是否幽默作出判断,识别出情景喜剧中的笑点。所以根据其特点设计了三种数据处理方法进行对比。
(1)若对数据集中的sentence不做处理,即只取Sentence和label这两列的数据进行训练,如图:
对应的结果:
(2)结合剧本本身的特点,将Speaker和Sentence这两列合并得到新的sentence,speaker和sentence之间用 : 隔开
对应的结果:
(可以看到确实有些许效果)
(3)考虑上下文关系,将前文和后文都考虑进来,每句话之间用 特殊符号。隔开(当然特殊符号可以选其他的,或者空格代替,但是经过实验我发现用。好可能稍好一些)。至于考虑前文多少句话,后文多少句话,这里经过实验比较,考虑当前语句的上一句和下一句最好。
对应的结果:
(可以看到无论在中文数据集还是英文数据集上都有不小的提升)
代码:
数据处理函数data_process():
#导入库
import pandas as pd
import csv
def data_process(path,filename):
"""
path:string 为你的训练集或验证集的文件路径
filename:string 为处理后的数据文件的存放路径,因为是csv文件,所以以.csv结尾
"""
#读取数据
data_sets=pd.read_csv(path)
#读取Sentence这一列的数据
data=data_sets['Sentence']
#读取Speaker这一列的数据
Speaker=data_sets['Speaker']
#读取Label这一列的数据
label=data_sets['Label']
#考虑上下文信息,head表示考虑当前语句前head条对话,behind表示当前语句后behind-1条对话
ahead=1
behind=2
#将处理后的数据写入filename文件中
with open(filename, 'w', newline='',encoding='utf-8') as file:
writer = csv.writer(file)
#先写入属性名
writer.writerow(["Sentence", "Label"])
#依次读取原始数据每一行数据
for i in range(len(data)):
new_sentence=""
#防止越界
left=max(0,i-ahead)
right=min(len(data),i+behind)
#合并left到right-1条数据
for j in range(left,right):
#先合并Speaker和Sentence这两列数据
speaker_sentence=Speaker[j]+":"+data[j]
#再添到new_sentence中
new_sentence=new_sentence+speaker_sentence+"."
#print(new_sentence)
#写入数据
writer.writerow([new_sentence,int(label[i])])
由于测试集没有Label属性,但又为了方便利用上面的代码,所以给它弄个伪标签
def data_process_test(path,filename):
"""
path:string 为你的训练集或验证集的文件路径
filename:string 为处理后的数据文件的存放路径,因为是csv文件,所以以.csv结尾
"""
#读取数据
data_sets=pd.read_csv(path)
#读取Sentence这一列的数据
data=data_sets['Sentence']
#读取Speaker这一列的数据
Speaker=data_sets['Speaker']
#伪标签
label=[0]*len(data)
#考虑上下文信息,head表示考虑当前语句前head条对话,behind表示当前语句后behind-1条对话
ahead=1
behind=2
#将处理后的数据写入filename文件中
with open(filename, 'w', newline='',encoding='utf-8') as file:
writer = csv.writer(file)
#先写入属性名
writer.writerow(["Sentence", "Label"])
#依次读取原始数据每一行数据
for i in range(len(data)):
new_sentence=""
#防止越界
left=max(0,i-ahead)
right=min(len(data),i+behind)
#合并left到right-1条数据
for j in range(left,right):
#先合并Speaker和Sentence这两列数据
speaker_sentence=Speaker[j]+":"+data[j]
#再添到new_sentence中
new_sentence=new_sentence+speaker_sentence+"."
#print(new_sentence)
#写入数据
writer.writerow([new_sentence,int(label[i])])
调用:
data_process(train_cn_path,"train_cn_data.csv")
data_process(eval_cn_path,"eval_cn_data.csv")
data_process_test(test_cn_path,"test_cn_data.csv")
2.训练
处理好数据集后,就可以将训练集和验证集放入预训练模型中训练(具体内容就不展示了),得到训练好的模型,模型我放在了
EHC幽默识别英文模型-Python文档类资源-CSDN文库https://download.csdn.net/download/qq_53644346/85868692EHC幽默识别中文模型-Python文档类资源-CSDN文库https://download.csdn.net/download/qq_53644346/85868452
以下是使用它的具体方法:
2.1模型加载
from transformers import AutoModelForSequenceClassification, AutoTokenizer
# 模型路径
model_path="C:/Users/86182/Desktop/cn_model_final"
#加载模型
model = AutoModelForSequenceClassification.from_pretrained(model_path, use_auth_token=True)
tokenizer = AutoTokenizer.from_pretrained(model_path, use_auth_token=True)
2.2简单使用
输入一句话,返回的是一个二维张量,值是归一化后的类别概率。
Input_sentence="志国:我能踏实的了么我"
# 输入数据
inputs = tokenizer(Input_sentence, return_tensors="pt")
# 模型输出
outputs = model(**inputs)
print(outputs.logits)
if outputs.logits[0][0]>outputs.logits[0][1]:
print(0)
else:
print(1)
进行简单的处理,既可以得到类别输出:
2.3对test数据集进行预测
def get_result(path,filename):
"""
path处理后的测试集路径
filename为生成的结果文件路径
"""
#读取处理过的测试集
test_sets=pd.read_csv(path)
test_sentences=test_sets['Sentence']
with open(filename, 'w', newline='') as file:
writer = csv.writer(file)
#写入ID和Label属性名
writer.writerow(["ID", "Label"])
for i in range(len(test_sentences)):
inputs = tokenizer(test_sentences[i], return_tensors="pt")
outputs = model(**inputs)
print(outputs.logits)
label=0
if outputs.logits[0][0]>outputs.logits[0][1]:
# print(0)
pass
else:
# print(1)
label=1
writer.writerow([i, label])
3.结果
cn_result.csv
en_result.csv
对比baseline:
以及其他模型:
通过对比,可以看到我的预训练模型效果还是可以的。
不足之处和改进:
1.数据集中的Dialogue_id这一属性我并没有用到,因为数据集自身的特点,每段对话都有一个场景,而Dialogue_id蕴含着场景信息,所以在场景切换时,对数据集当前对话取上下文并不合适,改进方法就是在获取当前对话的上下文时,把Dialogue_id也考虑进来。
2.预训练模型的选择不同,获得的效果也会不同,针对模型的调参本文并没有体现出来
3.对训练集和验证集没有做交叉验证,同时也没有对测试集的预测结果进行集成
总结
本文主要是针对数据集进行处理,通过预训练模型进行训练,而没有详细的讲怎么去构建神经网络模型,以及神经网络的实现过程是什么样的,当然这也是本文的不足吧。但是通过我给出的预训练模型,可以非常简单的完成本次幽默识别的任务,效果也还算不错吧。
最后,如果博客中有什么不对的地方,请多多指教。