python实战(十二)——如何进行新词发现?

部署运行你感兴趣的模型镜像

一、概念

        新词发现是NLP的一个重要任务,旨在从大量的文本数据中自动识别和提取出未在词典中出现的新词或短语,这对于信息检索、文本挖掘、机器翻译等应用具有重要意义,因为新词往往包含了最新的知识和信息。

        随着互联网的不断发展,每一年都有着大量的新兴网络热词。如果在NLP建模过程中这些热词恰好在模型词典中,那么就能较好地保留语义信息,否则这部分信息就会丢失。即便是大模型,在不了解新词的前提下也无法得到一个令人满意的响应。新词发现技术一定程度上为缓解out of vocabulary的问题提供了可行方式。

二、原理及实现

        这里,我们参考广为人知的《互联网时代的社会语言学:基于SNS的文本数据挖掘》中的策略来进行新词发现的讲解。

1、原理

        新词发现的原理主要基于以下几个方面:

(1)词频统计

        新词通常在文本中出现的频率较高,因此可以通过统计词频来初步筛选出可能的新词。

(2)凝固度(Cohesion)

        凝固度用于衡量一个词组内部的紧密程度,常见的方法是计算词组的互信息(Mutual Information, MI)或点互信息(Pointwise Mutual Information, PMI)。高凝固度表示词组内部的词之间关系紧密,也就表明词组内部中的字词常常共同出现,则该词组更有可能是一个新词。

        假设现在我们有一个词组eq?w%20%3D%20w_%7B1%7Dw_%7B2%7D...w_%7Bn%7D,其中eq?w_%7Bi%7D表示词组中的第 i 个字或者词,那么我们可以使用如下公式计算凝固度(示例之一,也可以使用其他常见公式):

eq?Cohesion%28w%29%20%3D%20min%28%5Cfrac%7BP%28w%29%7D%7BP%28w_%7B1%7D%29%20%5Ccdot%20P%28w_%7B2%7D...w_%7Bn%7D%29%7D%2C%20%5Cfrac%7BP%28w%29%7D%7BP%28w_%7B1%7Dw_%7B2%7D%29%20%5Ccdot%20P%28w_%7B3%7D...w_%7Bn%7D%29%7D%2C...%2C%5Cfrac%7BP%28w%29%7D%7BP%28w_%7B1%7D...w_%7Bn-1%7D%29%20%5Ccdot%20P%28w_%7Bn%7D%29%7D%29

        其中,P(w)表示词组w的概率,通过词频除以总次数来得到;分母中的左半部分如eq?P%28w_%7B1%7D%29表示词组的前n个词的概率,而右半部分如eq?P%28w_%7B2%7D...w_%7Bn%7D%29则表示剩余部分的概率。

3、左右熵(Left and Right Entropy)

        左右熵用于衡量一个词组在上下文中的多样性,高左右熵表示词组在不同上下文中出现的多样性较高,是新词的可能性也更大。假设现在我们有一个词组w,那么它的左熵计算公式为:

eq?Left%20Entropy%28w%29%20%3D%20-%5Csum_%7Bc%20%5Cin%20L%28w%29%7DP%28c%7Cw%29logP%28c%7Cw%29

        相应地,右熵的计算公式为:

eq?Right%20Entropy%28w%29%20%3D%20-%5Csum_%7Bc%20%5Cin%20R%28w%29%7DP%28c%7Cw%29logP%28c%7Cw%29

        其中,L(w)表示在词组w左侧出现的上文集合,而R(w)则表示词组w右侧出现的下文集合。P(c|w)表示在词组w左侧或者右侧出现上下文c的条件概率。

2、实现

        由上可知,我们需要找的新词,内部字词顺序应当是稳定的,而其左右出现的词语数目应当是丰富的,那么我们可以通过以下几个步骤来进行新词发现:

  • 文本预处理:对原始文本进行分词、去除停用词、去除标点符号等预处理操作。其中,最为准确的分词方式是N-gram,否则一开始就分错了后面怎么算也找不出这个新词。
  • 特征计算:计算候选词的词频、凝固度和左右熵等特征。
  • 新词筛选:根据特征值排序筛选出可能的新词。

三、python实现

1、导入必要的库

from collections import defaultdict, Counter
import pandas as pd
import jieba
import math

2、编写候选词生成函数

        这里我们使用N-Gram,最大长度为4。

# 生成候选词
def generate_candidates(words, max_len=4):
    candidates = []
    for i in range(len(words)):
        for j in range(1, max_len + 1):
            if i + j <= len(words):
                candidate = ''.join(words[i:i + j])
                candidates.append(candidate)
    return candidates

3、计算凝固度和左右熵

        根据上面说到的公式来推算,加上一些异常处理防止除零即可。

# 计算凝固度
def calculate_cohesion(word, word_freq, total_count):
    if len(word) == 1:
        return 0
    sub_words = [word[:i] for i in range(1, len(word))]
    cohesion_values = []
    for sub_word in sub_words:
        left_freq = word_freq[sub_word]
        right_freq = word_freq[word[len(sub_word):]]
        if left_freq > 0 and right_freq > 0:
            cohesion_values.append(word_freq[word] / (left_freq * right_freq))
    if cohesion_values:
        return min(cohesion_values)
    else:
        return 0

# 计算左右熵
def calculate_entropy(word, words):
    left_context = defaultdict(int)
    right_context = defaultdict(int)
    for i in range(len(words) - len(word) + 1):
        if ''.join(words[i:i + len(word)]) == word:
            if i > 0:
                left_context[words[i - 1]] += 1
            if i + len(word) < len(words):
                right_context[words[i + len(word)]] += 1
    left_entropy = -sum([count / sum(left_context.values()) * math.log(count / sum(left_context.values())) for count in left_context.values()])
    right_entropy = -sum([count / sum(right_context.values()) * math.log(count / sum(right_context.values())) for count in right_context.values()])
    return min(left_entropy, right_entropy)

4、应用

        这里我们使用kaggle上的微博热搜词条数据《MicroBlog-Hot-Search-Labeled》,数据量不大,但是热搜词条最能反映当前的新词热词。

df = pd.read_csv('weibo-hot-search-labeled.csv')
text = df['热搜词条'].tolist()
text = ' '.join(text)

# 字级别分词
words = list(text)

# 计算词频
candidates = generate_candidates(words)
candidates = [li for li in candidates if len(li)>1]
word_freq = Counter(candidates)

# 筛选新词
total_count = sum(word_freq.values())
new_words = []
for word in word_freq:
    if len(word) > 1 and word_freq[word] > 1:
        cohesion = calculate_cohesion(word, word_freq, total_count)
        entropy = calculate_entropy(word, words)
        if cohesion > 0.2 and entropy > 0.5:
            new_words.append((word, word_freq[word], cohesion, entropy))

# 打印新词
# 可以根据自己的需求排序
new_words.sort(key=lambda x: (-x[3], -x[2]))
for word, freq, cohesion, entropy in new_words[:20]:
    print(f"Word: {word}, Frequency: {freq}, Cohesion: {cohesion:.2f}, Entropy: {entropy:.2f}")

        可以看到,结果中有不少词确实是较为新颖,例如综艺词“勤深深”,又或者一些明星、游戏的名称。

6b15a1de30e74240a22d15214e58898c.png

四、总结

        结合新词发现技术,我们在一定程度上能够扩展我们NLP模型的词典,从而更准确地进行分词,进而使得最终生成的文本表示语义信息更为客观合理。当然,新词发现技术也并不是完全准确的,受语料规模等因素的影响,仍然会出现错误识别的问题。这就需要具体问题具体分析,例如可以通过后处理规则或者机器学习/深度学习模型来缓解该问题。

您可能感兴趣的与本文相关的镜像

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值