首页 > 其他分享 >欺诈文本分类检测(十六):支持分类原因评测改造

欺诈文本分类检测(十六):支持分类原因评测改造

时间:2024-09-26 12:19:52浏览次数:3  
标签:realitys 欺诈 分类 fraud predictions score rouge 文本

1. 引言

经过前文对数据的校正与增强后,我们的预期生成结果中不再仅仅是分类标签,还多了欺诈者和分类原因。这样之前模型评测批量评测两篇文章所封装的evaluate.py脚本就不再满足,需要对脚本进行改造,以支持新输出内容的评测。

新的预期结果中共包含三个信息,由于三个信息的特点不同,需要为每个字段制定不同的评测方式:

  • is_fraud: 属于二分类,继续采用精确率和召回率作为评测指标。
  • fraud_speaker: 属于多分类,多分类没有混淆矩阵,可以使用sklearn包提供的accuracy_score计算准确率作为评测指标。
  • reason: 属于分文生成,由于没有准确值,可以通过rouge_score计算文本串的相似度作为评测指标。

2. rouge指标调研

ROUGE(Recall-Oriented Understudy for Gisting Evaluation)指标是用于评估文本摘要质量的一种常用指标。它通过比较生成的摘要与参考摘要之间的重叠词语或短语来衡量它们之间的相似度。Rouge包含多个子指标:

  • ROUGE-1: 评估生成文本(hypothesis)与参考文本(reference)之间的单词级别的重叠;
  • ROUGE-2: 评估生成文本和参考文本相邻两个词(或字)的重叠情况,它关注的是两个文本中二元组(bigrams)的匹配,以此类推可以推广到ROUGE-N;
  • ROUGE-L:与前两者不同的是,此指标关注的是生成文本与参考文本之间的最长公共子序列(Longest Common Subsequence, LCS),通过最长公共子序列来衡量两个文本之间的相似性,最长公共子序列是指在不改变顺序的情况下,两个序列中都存在的元素的最长序列。

下面来实测一下。

from rouge import Rouge

def rouge_score(predictions, realitys):
    rouge = Rouge()
    return rouge.get_scores(predictions, realitys, avg=True)

先用英文测试。

predictions = "you are a programer."
realitys = "you are the programer."
scores = rouge_score(predictions, realitys)
scores
    {'rouge-1': {'r': 0.75, 'p': 0.75, 'f': 0.749999995},
     'rouge-2': {'r': 0.3333333333333333,
      'p': 0.3333333333333333,
      'f': 0.3333333283333334},
     'rouge-l': {'r': 0.75, 'p': 0.75, 'f': 0.749999995}}
  • 用rouge-1衡量时,predictions和realitys中有[you, are, programer]三个单词相同,生成文本和参考文本都是共4个单词,所以精确率和召回率都是75%;
  • 用rouge-2衡量时,predictions和realitys中只有you are一个二元组相同,生成文本和参考文本都有4个单词(即3个二元组),所以精确率和召回率都是33%;
  • 用rouge-l衡量时,predictions和realitys中的最长公共子序列是['you', 'are', 'programer'],生成文本和参考文本的总长度都是4,所以精确率和召回率都是75%;

下面再用中文测试。

predictions = "你是一个程序员。"
realitys = "你就是那个程序员。"
scores = rouge_score(predictions, realitys)
scores
    {'rouge-1': {'r': 0.0, 'p': 0.0, 'f': 0.0},
     'rouge-2': {'r': 0.0, 'p': 0.0, 'f': 0.0},
     'rouge-l': {'r': 0.0, 'p': 0.0, 'f': 0.0}}

所有指标的精确率、召回率、f1-score都是0。

原因在于:rouge默认只支持按英文标准的空格符号来进行分词,由于上面的中文文本中没有空格,所以被当成一个词来进行重叠度计算,没有任何重叠所以输出是0。

需要引入jieba中文分词库,并封装一个tokenize方法专门用于对文本分词。

import jieba

def tokenize(text):
    return ' '.join(list(jieba.cut(text, cut_all=False)))

上面的tokenize方法中,先使用jieba.cut方法进行分词,再将分词后的序列用空格连接,转换成与英文文本相同的分隔符,以便rouge库能自动分词。

测试分词效果。

tokenized_predictions = tokenize(predictions)
tokenized_realitys = tokenize(realitys)
tokenized_predictions, tokenized_realitys

    ('你 是 一个 程序员 .', '你 就是 那个 程序员 .')

注:jieba分词的详细介绍和用法,请参考:jieba分词初探

对分词后的中文序列计算rouge分数。

scores = rouge_score(tokenized_predictions, tokenized_realitys)
scores
{'rouge-1': {'r': 0.5, 'p': 0.5, 'f': 0.4999999950000001},
 'rouge-2': {'r': 0.0, 'p': 0.0, 'f': 0.0},
 'rouge-l': {'r': 0.5, 'p': 0.5, 'f': 0.4999999950000001}}

4个词中有, 程序员两个词相同,单词重叠率为50%,所以rouge-1的分数为50%。

上面的例子中能够看出,rouge-1和rouge-l的两个指标更贴合我们的场景,但这两个指标有何不同呢?我们换一个例子来看。

tokenized_predictions = tokenize("他首先是一名老师,然后是一名程序员。")
tokenized_realitys = tokenize("他首先是一名程序员,然后是一名老师。")
print(tokenized_predictions, "\n", tokenized_realitys)
scores = rouge_score(tokenized_predictions, tokenized_realitys)
scores
    他 首先 是 一名 老师 , 然后 是 一名 程序员 。 
     他 首先 是 一名 程序员 , 然后 是 一名 老师 。

    {'rouge-1': {'r': 1.0, 'p': 1.0, 'f': 0.999999995},
     'rouge-2': {'r': 0.7777777777777778,
      'p': 0.7777777777777778,
      'f': 0.7777777727777778},
     'rouge-l': {'r': 0.7777777777777778,
      'p': 0.7777777777777778,
      'f': 0.7777777727777778}}

在上面这个例子中,预测序列和参考序列的单词完全相同,只是顺序不同,rouge-1不考虑单词顺序,最长子序列['他', '首先', '是', '一名', '老师', '然后', '是', '一名', '程序员']囊括了所有的词, 所以得出的精确率和召回率均是100%;而rouge-L关注了单词的顺序,所以最长子序列['他', '首先', '是', '一名', '然后', '是', '一名']只有7个词,而参考序列和预测序列的长度是9个词,所以精确率和召回率为77.7%。

由此可见,如果不考虑序列中词的顺序,则选择rouge-1,反之,如果考虑序列中词的顺序,则选择rouge-L。实际场景中,文本的顺序一般都会影响文本所表达的含义,所以为了尽可能准确,我们的场景选择rouge-L。

3. 脚本改造

首先,引入原始的评测脚本evaluate.py

%run evaluate.py

封装用于计算中文rouge分数的方法rouge_zh_score, 它接受两个文本串集合pred_dataset和real_dataset作为参数,返回集合中两两序列相似度的平均分数。

def rouge_zh_score(pred_dataset, real_dataset):
    # 首先,去掉两个集合中的空串,
    filtered_pairs = [(p, r) for p, r in zip(pred_dataset, real_dataset) if p.strip() != "" and r.strip() != ""]  
    filtered_predictions, filtered_realitys = zip(*filtered_pairs) if filtered_pairs else ([], [])  
    # 进行中文分词,因为Rouge分数的计算依赖于分词后的单词序列。
    predictions = [tokenize(text) for text in filtered_predictions]
    realitys = [tokenize(text) for text in filtered_realitys]
    # 计算两个序列的rouge分数
    score = rouge_score(predictions, realitys)
    return score['rouge-l']

注1:两个集合是按下标两两配对的,当出现空串时需要在两个集合中同时去掉相应位置的元素,目的是保持两个集合的配对关系不变。zip方法的作用是将两个集合两两配对,空串去完后还需要用*操作符将配对的集合解包还原为两个集合。

注2:需要去掉空串的原因在于,在计算 ROUGE 分数时,当任意一方字符串为空,将会导致“Hypothesis is empty.”的错误。

测试下rouge_zh_score方法的效果。

predictions = ["你是一个程序员。", "他首先是一名老师,然后是一名程序员。"]
realitys = ["你就是那个程序员。", "他首先是一名程序员,然后是一名老师。"]
rouge_zh_score(predictions, realitys)
    {'r': 0.6888888888888889, 'p': 0.6888888888888889, 'f': 0.6888888838888889}

通过上面测试可以发现,rouge.get_scores方法既支持字符串形式,也支持集合形式,当传的是一个list集合时,它会自动计算集合中所有文本相似度分数的平均值,这是通过参数avg=True来指定的。

下面改造批量评测的run_test_batch方法,返回的结果不再仅仅是labels集合,还包括了speakers和reasons集合。

from typing import List, Dict

def make_str(data):  
    return ','.join(map(str, data)) if isinstance(data, list) else data 

def make_results(dataset):
    return {
       "labels": [item.get('label', item.get('is_fraud', False)) for item in dataset],
        "speakers": [make_str(item.get('fraud_speaker', '')) for item in dataset],
        "reasons": [item.get('reason', '') for item in dataset],
    }


def run_test_batch_v2(model, tokenizer, test_data: List[Dict], batch_size: int = 8, device='cuda'):
    real_outputs, pred_outputs = [], []
    instruction = test_data[0].get('instruction', None)
    pbar = tqdm(total=len(test_data), desc=f'progress')
    
    for i in range(0, len(test_data), batch_size):
        batch_data = test_data[i:i + batch_size]
        batch_inputs = [item['input'] for item in batch_data]
        predictions = predict_batch(model, tokenizer, batch_inputs, device, instruction=instruction)
        
        real_outputs.extend(batch_data)
        pred_outputs.extend(predictions)
        
        pbar.update(len(batch_data))

    pbar.close()
    return make_results(real_outputs), make_results(pred_outputs)

扩展一个evaluate_v2方法,此方法中区分字段走不同的指标计算:

  • is_fraud: 通过sklean包的混淆矩阵来计算精确率和召回率;
  • fraud_speaker: 使用sklearn包提供的accuracy_score方法来计算准确率;
  • reason: 以上面封装的中文rouge分数作为评测指标;
from sklearn.metrics import accuracy_score 

def evaluate_with_model_v2(model, tokenizer, testdata_path, device='cuda', debug=False):
    dataset = load_jsonl(testdata_path)
    real_result, pred_result = run_test_batch_v2(model, tokenizer, dataset, device=device)
    
    precision, recall, accuracy = precision_recall(real_result["labels"], pred_result["labels"], debug=debug)
    print(f"is_fraud字段指标: \nprecision: {precision}, recall: {recall}, accuracy: {accuracy}")
    
    accuracy = accuracy_score(real_result["speakers"], pred_result["speakers"])  
    print(f"fraud_speaker字段指标: \naccuracy: {accuracy}")

    score = rouge_zh_score(pred_result["reasons"], real_result["reasons"])
    print(f"reason字段指标: \nprecision: {score['p']}, recall: {score['r']}, f1-score: {score['f']}")
    
    return real_result, pred_result
    

def evaluate_v2(model_path, checkpoint_path, testdata_path, device='cuda', debug=False):    
    model, tokenizer = load_model(model_path, checkpoint_path, device)
    return evaluate_with_model_v2(model, tokenizer, testdata_path, device, debug)

4. 基座模型测评

先对基座模型进行评测,后续则以基座模型的评测结果作为微调效果的评判依据。

os.environ["CUDA_VISIBLE_DEVICES"] = "0"
device = 'cuda'
testdata_path = '/data2/anti_fraud/dataset/test0902.jsonl'
model_path = '/data2/anti_fraud/models/modelscope/hub/Qwen/Qwen2-1___5B-Instruct'
real_result, pred_result = evaluate_v2(model_path, '', testdata_path, device, debug=True)
    invalid json: 不存在经济诈骗。
    
    分析结果:不存在经济诈骗。在提供的对话中,发言者4只是分享了一个关于商业需求预测的观点,并没有提到任何欺诈行为或企图欺骗他人的情况。因此,可以确定该对话不存在经济诈骗。

    
    经过分析,该对话中不存在明显的经济诈骗行为。发言人的言论主要围绕着旅游统计数据的准确性进行讨论,并提出了可能存在的误差来源。因此,可以判断此对话不存在经济诈骗行为。
    invalid json: 不存在经济诈骗。

    invalid json: 不存在经济诈骗。

    invalid json: 不存在经济诈骗。

    ……

以上分析结果表明,该对话中不存在明显的经济诈骗行为。所有发言者的言论都是关于产品的生产和销售情况的讨论,并且没有涉及到欺诈或非法活动。因此,可以得出结论:此对话不存在经济诈骗行为。
progress: 100%|██████████| 3031/3031 [17:55<00:00,  2.82it/s]
Building prefix dict from the default dictionary ...
Loading model from cache /tmp/jieba.cache
tn:590, fp:903, fn:44, tp:1494
is_fraud字段指标: 
precision: 0.623279098873592, recall: 0.9713914174252276, accuracy: 0.6875618607720224
fraud_speaker字段指标: 
accuracy: 0.6374133949191686
Loading model cost 0.776 seconds.
Prefix dict has been built successfully.
reason字段指标: 
precision: 0.33552894583785237, recall: 0.23240362412953733, f1-score: 0.2638127489291967

注:由于基座模型遵循指令的能力较弱,所以在预测时输出了很多json格式错误,为避免篇幅太长,上面省略和截掉了很多重复的错误的信息,并且在遇到错误时统一使用默认的{“is_fraud”: false}作为返回值。

指标收集如下:

字段指标
is_fraudprecision: 0.6232, recall: 0.9713, accuracy=0.6875
fraud_speakeraccuracy: 0.6374
reasonprecision: 0.3355, recall: 0.2324, f1-score: 0.2638

从上面的指标来看,只有is_fraud字段的 召回率0.9673比较高,但其它指标(如is_fraud字段的精确率,fraud_speaker字段的准确率,reason字段的各项指标)都比较低。

小结:本文通过对rouge指标的调研测试,了解了rouge指标中的rouge-1和rouge-L子指标的区别,并对评测脚本进行了改造升级,以支持分类原因和欺诈者字段的生成质量评测,为后续分类原因和欺诈者字段的训练微调提供了一个效果评测的基准。

参考阅读

标签:realitys,欺诈,分类,fraud,predictions,score,rouge,文本
From: https://blog.csdn.net/xiaojia1001/article/details/142489874

相关文章

  • 垃圾分类智能分析系统
    垃圾分类智能分析系统应用深度学习识别技术,垃圾分类智能分析系统通过前端监控摄像机采集实时视频画面进行实时智能分析识别,不需人为干预,垃圾分类智能分析系统自动识别违规投放行为并现场进行语音提示实时预警。垃圾分类智能分析系统将违规数据同时推送到后端管理平台,垃圾分类智能......
  • 二、软件测试分类
    1.按照测试阶段划分单元测试(UnitTesting):又叫模块测试,对软件组成单位(模块)进行测试,目的就是校验软件基本组成单位的正确性。(负责人:一般由开发自己负责)集成测试(IntegrationTesting):又称组装测试、联合测试,将程序模块采用适当策略组装起来,对集成后的功能和系统的接口进行检测,目的......
  • 信息安全工程师(17)密码体制分类
    前言密码体制,也称为密码系统,是信息安全领域中的一个重要概念,用于解决机密性、数据完整性、认证、身份识别、可控性及不可抵赖性等问题。根据加密和解密所使用的密钥是否相同,密码体制主要可以分为两大类:单钥体制(对称密码体制、秘密密钥密码体制)和双钥体制(非对称密码体制、公开......
  • RusTitW:大规模语言视觉文本识别数据集(猫脸码客 第190期)
    RusTitW:RussianLanguageVisualTextRecognition一、引言在信息爆炸的现代社会,文本作为信息传递的重要载体,扮演着不可或缺的角色。随着计算机视觉与模式识别技术的飞速发展,自动化文本识别(OCR,OpticalCharacterRecognition)技术日益成熟,极大地提升了信息处理的效率与准确性。......
  • java+vue计算机毕设IE绿色城市垃圾分类监管系统【源码+程序+论文+开题】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着城市化进程的加速,城市生活垃圾产生量急剧增加,垃圾分类已成为缓解“垃圾围城”困境、促进资源循环利用、实现绿色可持续发展的重要举措。然而,传统......
  • 大师级调色预设合集!50000+款Lr预设,精心整理,分类清晰,各种风格都有!
       大师级调色预设合集!超过50000种风格,覆盖550多个不同的分类,并且还在持续更新,非常齐全,用一生都足够了。这些预设是我长期筛选和整理的结果,它们分门别类、井井有条,拿来即用,无论是日系风格的清新文艺范,还是INS上的流行网红色调,或是专门针对人像、美食摄影的预设,甚至......
  • 一万字全面解析CRM的定义、分类与核心价值
    1、CRM定义与分类1.1CRM的定义CRM,英文CustomerRelationshipManagement的缩写,中文全称为客户关系管理。通常情况下,人们通常用CRM直接表达客户关系管理软件系统——一个以客户为中心的专门用于管理与客户关系的软件工具,以确保与客户在营销、销售、服务的每一环节上都能实现顺......
  • 文本摘要综述—从统计方法到大型语言模型综述介绍,原文阅读:A Systematic Survey of Tex
    ASystematicSurveyofTextSummarization:FromStatisticalMethodstoLargeLanguageModels文本摘要的系统综述:从统计方法到大型语言模型paper:https://arxiv.org/abs/2406.11289文章目录~原文阅读Abstract1.Introduction1.1.MajorDifferences1.2.MainContri......
  • crnn_migraphx用于端到端地对不定长的文本序列进行识别的OCR模型
    CRNN论文AnEnd-to-EndTrainableNeuralNetworkforImage-basedSequenceRecognitionandItsApplicationtoSceneTextRecognitionhttps://arxiv.org/abs/1507.05717模型结构CRNN模型的主要结构包括基于CNN的图像特征提取模块以及基于双向LSTM的文字序列特征提取......
  • 笔记1 搜索引擎分类,搜索指令
    搜索引擎分类:目录式分类搜索引擎和全文式检索搜索引擎搜索引擎有Google、Baidu、Bing、搜狗、夸克等等......使用减号(-)指令,可以排除含有特定关键词的搜索结果,如搜索“原神-广告”,就能得到包含原神但不包含广告的结果filetype指令可以查询特定格式的文件:关键词+空格+filetype:+do......