利用PaddleNLP进行文本数据脱敏

最近在脱敏一些客服数据,同事用正则进行了一些处理,但是感觉针对人名、数量等信息还是无法处理,例如"北方种植了很多李子树",李子树有可能被识别为人名,又如"美国采购坦克1005台,价值4500万比索",如果之前的正则中没有"台"和"比索"两个词汇,就无法识别。

如果在脱敏过程中忽略了人名、数量等信息,可能造成严重后果。因此尝试使用了paddlenlp中的taskflow进行处理。主要思路就是利用ner工具,识别出所需的信息,并进行替换。整体效果如下:

原始段落:

昆明市公安局毒品中心调查人员江涛和刘明接到市指挥中心通知,前往边境进行毒品打击。10月15日开始在云南省楚雄市刘家洼村进行伏击,随身携带冲锋枪两只,手榴弹4枚。经过13天的等待后,并未抓获嫌疑人。经调查,10月15日傍晚,刘明私自外出会见了可疑分子并交换情报,收受了贿赂4500元,导致抓捕失败。省公安厅查明情况后,决定逮捕刘明。

处理结果:

昆明市公安局毒品中心调查人员【人员_1】和【人员_2】接到【地区_1】指挥中心通知,前往边境进行毒品打击。【时间_1】开始在【地区_2】【地区_3】【地区_4】进行伏击,随身携带冲锋枪【数量_1】,手榴弹【数量_2】。经过13天的等待后,并未抓获嫌疑人。经调查,【时间_2】,【人员_2】私自外出会见了可疑分子并交换情报,收受了贿赂【数量_3】,导致抓捕失败。省公安厅查明情况后,决定逮捕【人员_2】。

在脱敏过程中,如果简单的利用"*"代替原始的敏感内容,可能会造成很多歧义,因此处理时可以参照上面"引用结果"中的形式进行处理。如果不这样处理,可能会影响可读性(阅读者需要自己联想,星号内容究竟是地名还是人名),甚至导致无法阅读(例如上文,将所有的人名都换成星号,你将无法判断是谁会见了可疑分子):

传统处理方式:

昆明市公安局毒品中心调查人员**和**接到***指挥中心通知,前往边境进行毒品打击。******开始在*************进行伏击,随身携带冲锋枪**,手榴弹**。经过13天的等待后,并未抓获嫌疑人。经调查,******,**私自外出会见了可疑分子并交换情报,收受了贿赂*****,导致抓捕失败。省公安厅查明情况后,决定逮捕**。

目前可以处理数量、地名、场所、人名、时间等五种信息,利用正则表达式(replace_long_substrings)还可以处理一些常见的数字/字母混合字符串(例如手机号、订单编号等)。

处理代码如下:

python 复制代码
from paddlenlp import Taskflow
ner= Taskflow("ner")

# 匹配长度超过5个字符的子串,由阿拉伯数字、常见标点符号、英文大小写字母组成,并用星号代替
# 可以针对订单编号、用户手机号等信息进行处理
def replace_long_substrings(s):

    pattern = r'[A-Za-z0-9!@$%^&*()+-_#]{5,}'
    str_index=1
    
    # 使用正则表达式查找所有匹配的子串
    matches = re.findall(pattern, s)
    
    # 遍历所有匹配的子串,替换为5个星号
    for match in matches:
        s = s.replace(match, "【符号串_"+str(str_index)+"】", 1)  # 只替换一次
        str_index+=1
    
    return s

# 判断一个字符串中是否包含中文数字或英文数字
def contains_chinese_and_english_numbers(s):  

    
    # 匹配中文数字的正则表达式  
    chinese_number_pattern = re.compile(r'[一二三四五六七八九十零壹贰叁肆伍陆柒捌玖拾]+')  
      
    # 匹配英文数字的正则表达式  
    english_number_pattern = re.compile(r'[0-9]+')  
      
    # 判断字符串中是否包含中文数字和英文数字  
    contains_chinese_number = chinese_number_pattern.search(s) is not None  
    contains_english_number = english_number_pattern.search(s) is not None  
      
    # 如果字符串同时包含中文数字和英文数字,则返回True,否则返回False  
    return contains_english_number  or contains_chinese_number

# 使用paddle完成敏感信息识别,能够识别数量_单位词(例如45亿元、37个技术提升等)、地名、场所、人名、时间
# 对于楼道单元号,可能处理不干净,比如东东方花园4号楼3单元304,可能无法识别3单元304
def replace_info_with_paddle_ner(s):
    
    # 存储返回结果
    result=[]

    # 敏感信息和替换词的对应关系,例如在一段文本中,
    # 敏感人名"张涛"出现了两次,"刘涛"出现了一次,
    # 需要保证"张涛"被替换为一个符号,例如"人物甲",
    # 刘涛被替换为另一个符号,例如"人物乙"
    entity_dict={}

    num_index=1
    region_index=1
    position_index=1
    name_index=1
    time_index=1
    
    for i in ner(s):
        
        list_0,list_1=list(i)[0],list(i)[1]

        flag=1

        # 针对数量_单位词进行处理
        if list_1=="数量词_单位数量词":
            if not list_0 in entity_dict.keys():
                result.append("【数量_"+str(num_index)+"】")
                entity_dict[list_0]="【数量_"+str(num_index)+"】"
                num_index+=1
            else:
                result.append(entity_dict[list_0])

        # 针对地区和场所进行处理
        elif list_1 =="世界地区类":
            # todo 可能会存在一定的误识别,例如将"吐鲁番苹果"的前个字识别为"地名"
            if not list_0 in entity_dict.keys():
                result.append("【地区_"+str(region_index)+"】")
                entity_dict[list_0]="【地区_"+str(region_index)+"】"
                region_index+=1
            else:
                result.append(entity_dict[list_0])

        # 针对场所进行处理  
        elif list_1=="场所类":
            # todo 可能会存在一定的误识别,例如将"现场"两个字识别为"场所类"
            if not list_0 in entity_dict.keys() :
                result.append("【场所_"+str(position_index)+"】")
                entity_dict[list_0]="【场所_"+str(position_index)+"】"
                position_index+=1
            else:
                result.append(entity_dict[list_0])

        # 针对人名进行处理
        elif list_1=="人物类_实体":
            # todo 可能会存在一定的漏识别,例如生僻名字或者少数民族名字
            if not list_0 in entity_dict.keys():
                result.append("【人员_"+str(name_index)+"】")
                entity_dict[list_0]="【人员_"+str(name_index)+"】"
                name_index+=1
            else:
                result.append(entity_dict[list_0])

        # 针对时间进行处理
        elif list_1=="时间类_具体时间" or list_1=="时间类":
            # 只有包含数字时,才认为是真正的时间。
            # paddle会将"时间"识别为虚假的时间,因此需要额外处理
            
            if contains_chinese_and_english_numbers(list_0):

                if not list_0 in entity_dict.keys():
                    result.append("【时间_"+str(position_index)+"】")
                    entity_dict[list_0]="【时间_"+str(position_index)+"】"
                    position_index+=1
                else:
                    result.append(entity_dict[list_0])
                
            else:
                flag=0
                result.append(list_0)

        # 不属于上面的任意一个分类
        else:
            if flag:
                result.append(list_0)
            
    return "".join(result)

if  __name__=="__main__":

    # 原始文本
    text="""昆明市公安局毒品中心调查人员江涛和刘明接到市指挥中心通知,前往边境进行毒品打击。
            10月15日开始在云南省楚雄市刘家洼村进行伏击,随身携带冲锋枪两只,手榴弹4枚。经过13天的等待后,并未抓获嫌疑人。
            经调查,10月15日傍晚,刘明私自外出会见了可疑分子并交换情报,收受了贿赂4500元,导致抓捕失败。省公安厅查明情况后,决定逮捕刘明。"""
    
    # 获得结果
    print(replace_info_with_paddle_ner(text))
   

目前还存在一些问题,例如开头的"昆明市公安局"被识别成了组织机构,而没有将"昆明市"三个字识别成地名;又如处理结果中,将"云南省楚雄市刘家洼村"识别为"【地区_2】【地区_3】【地区_4】",没有将"云南省""楚雄市""刘家洼村"识别成一个完整的地名。代码中还注明了其他一些可能出现问题的细节,需要不断结合实际数据进行修改。

相关推荐
寒霜雨刃1 天前
【原创】海光Z100 DCU适配vLLM实录(二):W4A16大M Prefill结构重写、GDN融合与长上下文HIP Attention
深度学习·神经网络·amd·rocm·ai infra·海光z100·gfx906
IJCAST1 天前
IJCAST最新一期已经发布
人工智能·深度学习·神经网络
躺柒1 天前
读数据可视化19层次数据
信息可视化·数据挖掘·数据分析·数据可视化·层次数据·层次结构
chunmiao30321 天前
OpenAI 官宣断供 Cursor,AI 编程迎来第一次模型断供
人工智能·深度学习
147API1 天前
评测分数不理想,什么时候值得补蒸馏数据
人工智能·深度学习·机器学习
β添砖java1 天前
深度学习26转置卷积
人工智能·深度学习
JoannaJuanCV1 天前
VLM学习-SFT(监督微调)
深度学习·学习·机器学习·大模型·视觉大模型·vlm·视觉编码器
玩转单片机与嵌入式1 天前
深入浅出TinyML 21:INT8量化改变了模型中的哪些数据?
stm32·深度学习·tinyml
小程序设计1 天前
机械设计之大蒜茎叶粉碎抛送装置设计
人工智能·数据挖掘
满怀冰雪1 天前
23-PaddleClas 数据集、配置文件与训练参数详解
人工智能·python·深度学习·paddlepaddle