前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >网络表情NLP(一)︱颜文字表情实体识别、属性检测、新颜发现

网络表情NLP(一)︱颜文字表情实体识别、属性检测、新颜发现

作者头像
悟乙己
发布2021-12-07 13:49:27
1.2K0
发布2021-12-07 13:49:27
举报
文章被收录于专栏:素质云笔记素质云笔记

这是一篇一本正经无聊的小研究项目。。 互联网现在面临很多新网络文体,比如弹幕文体、小红书的种草文体、网名等,这些超短文本中本身字符特征就比较少,但是表情包占比却很多,这是重要信息呀。 之前参加比赛,一般都是当作停用词直接删掉,在这些超短文本中可就不行了。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关代码可见我的github:py-yanwenzi 相关文章: 网络表情NLP(一)︱颜文字表情实体识别、属性检测、新颜发现 网络表情NLP(二)︱特殊表情包+emoji识别

文章目录

1 混用的几个库

这里混用了几个笔者常用的文本处理的库,

  • jieba_fast,相比jieba,jieba_fast 使用cpython重写了jieba分词库中计算DAG和HMM中的vitrebi函数,速度得到大幅提升
  • flashtext,Flashtext:大规模数据清洗的利器,正则表达式在一个 10k 的词库中查找 15k 个关键词的时间差不多是 0.165 秒。但是对于 Flashtext 而言只需要 0.002 秒。因此,在这个问题上 Flashtext 的速度大约比正则表达式快 82 倍。可参考:python︱flashtext高效关键词查找与替换
  • rouge,Rouge-1、Rouge-2、Rouge-L分别是:生成的摘要的1gram-2gram在真实摘要的1gram-2gram的准确率召回率和f1值,还有最长公共子序列在预测摘要中所占比例是准确率,在真实摘要中所占比例是召回率,然后可以计算出f1值。

1.1 模块一:rouge

rouge是自动文本摘要算法的评估指标:

代码语言:javascript
复制
from rouge import Rouge

a = ["i am a student from xx school"]  # 预测摘要 (可以是列表也可以是句子)
b = ["i am a student from school on china"] #真实摘要

rouge = Rouge()
rouge_score = rouge.get_scores(a, b)
print(rouge_score[0]["rouge-1"])
print(rouge_score[0]["rouge-2"])
print(rouge_score[0]["rouge-l"])

>>> {'f': 0.7999999950222222, 'p': 0.8571428571428571, 'r': 0.75}
>>> {'f': 0.6153846104142012, 'p': 0.6666666666666666, 'r': 0.5714285714285714}
>>> {'f': 0.7929824561399953, 'p': 0.8571428571428571, 'r': 0.75}

该模块是使用在颜文字相似性匹配的时候,当然这边从实验效果来看,2-grams的效果比较好。

1.2 模块二:jieba_fast

使用 c 重写了jieba分词库中的核心函数,速度得到大幅提升。 特点

  • 对两种分词模式进行的加速:精确模式,搜索引擎模式
  • 利用cpython重新实现了 viterbi 算法,使默认带 HMM 的切词模式速度提升 60%左右
  • 利用cpython重新实现了生成 DAG 以及从 DAG 计算最优路径的算法,速度提升 50%左右
  • 基本只是替换了核心函数,对源代码的侵入型修改很少
  • 使用import jieba_fast as jieba 可以无缝衔接原代码。

其中, github:https://github.com/deepcs233/jieba_fast 代码示例:

代码语言:javascript
复制
# encoding=utf-8
import jieba_fast as jieba

text = u'在输出层后再增加CRF层,加强了文本间信息的相关性,针对序列标注问题,每个句子的每个词都有一个标注结果,对句子中第i个词进行高维特征的抽取,通过学习特征到标注结果的映射,可以得到特征到任>      意标签的概率,通过这些概率,得到最优序列结果'

print("-".join(jieba.lcut(text, HMM=True))
print('-'.join(jieba.lcut(text, HMM=False)))

与jieba基本一致

在这里插入图片描述
在这里插入图片描述

1.3 关键词查询组件:flashtext

详情可参考笔者博客:python︱flashtext高效关键词查找与替换

代码语言:javascript
复制
from flashtext import KeywordProcessor

def build_actree(wordlist):
    '''
        AC自动机进行关键词匹配
        构造AC trie
    '''
    actree = KeywordProcessor()
    for index, word in enumerate(wordlist):
        actree.add_keyword(word)     # 向trie树中添加单词
    #self.actree = actree
    return actree

def ac_detect(actree,text,span_info = True):
    '''
        AC自动机进行关键词匹配
        文本匹配
    '''
    region_wds = []
    for w1 in actree.extract_keywords(text,span_info = span_info):
        if len(w1) > 0:
            region_wds.append(w1[0])
    return region_wds

wordlist = ['健康','减肥']
text = '今天你减肥了吗,今天你健康了吗,减肥 = 健康!'
actree = build_actree(wordlist)
%time ac_detect(actree,text)

>>> CPU times: user 41 µs, sys: 0 ns, total: 41 µs
>>> Wall time: 47.2 µs
>>> ['减肥', '健康', '减肥', '健康']

2 颜文字检测与识别

之前文本较多的情况,很多颜文字都是当作停用词进行删除;也有一些对表情进行研究,但是颜文字比较麻烦的一点是,如果是特殊符号,☆,这类的只是一个字符,分词的时候可以分开; 但是颜文字会占用多个字符,分词的时候,自己就会分得非常分散'↖', '(', '^', 'ω', '^', ')', '↗',这个问题就有点像新词发现中出现得问题,如何分词得到有效的实体,颜文字本身就是一种带有情感色彩的实体。

在这里插入图片描述
在这里插入图片描述

所以比较理想的是不同的表情符号可以对应一些实体词,比如颜文字网站中标记的一样。

2.1 颜文字检测

直接上代码来说明使用方式:

代码语言:javascript
复制
# 初始化
json_data = {'w(゚Д゚)w': '啊啊', '(ノへ ̄、)': '抽泣', '( ̄_, ̄ )': '蔑视'}
ywz = yanwenzi(json_data)
    
# 检测位置
text = 'w(゚Д゚)w^O^佳^O^w(゚Д゚)w'
ywz.detect(text,span_info=True)
# [('_啊啊_', 0, 7), ('_啊啊_', 14, 21)]
ywz.detect(text,span_info=False)
# ['_啊啊_', '_啊啊_']
ywz.ywz_replace(text)
# '_啊啊_^O^佳^O^_啊啊_'

该模块初始化的时候,需要将一些{表情:属性}作为输入,笔者这边自己整理了1800+,整理的一部分是抓取的,还有一部分是新颜文发现而补充进去的。初始化输入之后,就会将这些表情包作为关键词进行匹配,同时这里是不支持模糊匹配的,只能精准匹配,譬如^O^如果这边表情没有计入,则不会被匹配到。

这里可以看到,detect将表情包w(゚Д゚)w变成了中文属性_啊啊_,因为_方便分词使用,其中参数span_info代表是否返回角标,便于定位该表情包的文字。

另外,ywz_replace是将文本中的表情包直接替换成中文字,并返回原文。

2.2 颜文字实体分词

代码语言:javascript
复制
ywz.jieba_cut(text)
#['_啊啊_', '^', 'O', '^', '佳', '^', 'O', '^', '_啊啊_']

初始化之后,分词其实就是jieba.cut,这里会分出_啊啊_这样的实体词。

3 新颜文字发现

上面的匹配都是精准匹配,所以需要新颜文字发现,来不断扩充颜文字词典。

3.1 新颜文字发现

代码语言:javascript
复制
text = '璇哥!加油↖(^ω^)↗'
ywz.yanwenzi_find(text,min_n = 2,remove_spacing = True)
>>> ['↖(^ω^)↗']

这里判定的逻辑还是比较简单的,是通过正则的方式,最少3个(min_n )连续的特殊字符;

当然这里要深挖也可以参考:如何精准地识别出文本中的颜文字?glove embedding时候的清洗逻辑

代码语言:javascript
复制
input = input
	.gsub(/https?:\/\/\S+\b|www\.(\w+\.)+\S*/,"<URL>")
	.gsub("/"," / ") # Force splitting words appended with slashes (once we tokenized the URLs, of course)
	.gsub(/@\w+/, "<USER>")
	.gsub(/#{eyes}#{nose}[)d]+|[)d]+#{nose}#{eyes}/i, "<SMILE>")
	.gsub(/#{eyes}#{nose}p+/i, "<LOLFACE>")
	.gsub(/#{eyes}#{nose}\(+|\)+#{nose}#{eyes}/, "<SADFACE>")
	.gsub(/#{eyes}#{nose}[\/|l*]/, "<NEUTRALFACE>")
	.gsub(/<3/,"<HEART>")
	.gsub(/[-+]?[.\d]*[\d]+[:,.\d]*/, "<NUMBER>")
	.gsub(/#\S+/){ |hashtag| # Split hashtags on uppercase letters
		# TODO: also split hashtags with lowercase letters (requires more work to detect splits...)

		hashtag_body = hashtag[1..-1]
		if hashtag_body.upcase == hashtag_body
			result = "<HASHTAG> #{hashtag_body} <ALLCAPS>"
		else
			result = (["<HASHTAG>"] + hashtag_body.split(/(?=[A-Z])/)).join(" ")
		end
		result

当有了单个表情识别,如果在比较多的文本下,就可以根据频次发现一些高频出现的表情包了:

代码语言:javascript
复制
corpus = ['d(ŐдŐ๑)crush', '♪ ٩(。•ˇ‸ˇ•。)۶', '〜( ̄▽ ̄〜)', '木木╭(╯ε╰)╮', 'ToT(^(エ)^)', 'HLYS(ー`´ー)',
 'O(∩_∩)O', '(^^)笔尖', '璇哥!加油↖(^ω^)↗', '蜕变(^_^) \ufeff']
ywz_new_list = ywz.yanwenzi_new_discovery(corpus,min_n = 2,remove_spacing = True,topn = 200)
ywz_new_list

>>> [('(ŐдŐ๑)', 1), ('♪٩(。•ˇ‸ˇ•。)۶', 1), ('〜( ̄▽ ̄〜)', 1), ('╭(╯ε╰)╮', 1),
 ('(^(エ)^)', 1), ('(ー`´ー)', 1), ('(∩_∩)', 1), ('(^^)', 1), ('↖(^ω^)↗', 1), ('(^_^)\ufeff', 1)]

其中,remove_spacing是否移除空格;topn一次性返回top多少的高频表情包

如果有新颜文要新增,那么需要新增到两个模块:分词模块 + 颜文识别模块,

代码语言:javascript
复制
# 新颜文添加到分词词典
yanwenzi_dict_list = [ynl[0] for ynl in ywz_new_list]
ywz.add_words(yanwenzi_dict_list,freq = 100,tag = 'ywz')

# 新颜文添加到检测词典
ywz.actree_add_word(yanwenzi_dict_list,tag = '颜文字')

当然这里遇到的问题,颜文字识别出来,是不带属性的({'↖(^ω^)↗':'_高兴_'}),所以要么就是人工打标然后给入,当然也可以直接list方式,此时属性就会都指定为_颜文字_

3.2 颜文字属性识别

上面3.1提及到一个问题是新颜文字识别出来之后,没有附带上属性,就像实体词没有定义词性一样。 所以,这边通过求相似的方式来找到最相似的表情,将最相似的表情属性,继承过来。这边求相似的方式是使用rouge这是文本摘要评价指标。 从rouge的评分来看,rouge-1太粗糙;rouge-2比较合适, 且几个统计量中,f/p/r,f效果比较好,p/r可能会有比较多的选项,也就是差异性不明显

代码语言:javascript
复制
参数:
    - min_s = 0.35,阈值,一定要相似性大于才会给出;如果是'rouge-1'比较合适的阈值在0.75
    - score_type = 'rouge-2',rouge的得分类型,n-grams
    - stat = 'f',采用的统计量

统计量:
    text_a = '(^_^)'
    new_yanwenzi_find(text_a,min_s = 0.35)
    >>> [['(^&^)/', '噢耶',0.75]]

其中返回的是[最相似颜文字,中文属性,f值]

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1 混用的几个库
    • 1.1 模块一:rouge
      • 1.2 模块二:jieba_fast
        • 1.3 关键词查询组件:flashtext
        • 2 颜文字检测与识别
          • 2.1 颜文字检测
            • 2.2 颜文字实体分词
            • 3 新颜文字发现
              • 3.1 新颜文字发现
                • 3.2 颜文字属性识别
                相关产品与服务
                文字识别
                文字识别(Optical Character Recognition,OCR)基于腾讯优图实验室的深度学习技术,将图片上的文字内容,智能识别成为可编辑的文本。OCR 支持身份证、名片等卡证类和票据类的印刷体识别,也支持运单等手写体识别,支持提供定制化服务,可以有效地代替人工录入信息。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档