【问题标题】:Unable to detect gibberish names using Python无法使用 Python 检测乱码名称
【发布时间】:2018-11-12 13:37:22
【问题描述】:

我正在尝试构建可以将帐户名称分类为合法或乱码的 Python 模型。在这种特殊情况下,大写并不重要,因为一些合法的帐户名称可能由全部大写或全部小写字母组成。

免责声明:这只是一项内部研究/实验,不会对分类结果采取任何实际行动。

在我看来,有 2 个可能的特征可以将帐户名称显示为可疑、乱码或两者兼有:

  1. 名称或名称中的奇怪/随机拼写由纯数字或大部分数字组成。符合这些条件的帐户名称示例如下:128、127、h4rugz4sx383a6n64hpo、tt、t66、t65、asdfds

  2. 该名称有 2 个组成部分(假设没有一个名称将包含超过 2 个组成部分),并且这两个组成部分的拼写和发音非常相似。符合这些条件的帐户名称示例如下:Jala Haja、Hata Yaha、Faja Kaja

如果帐户名称同时满足上述两个条件(即“asdfs lsdfs”、“332 333”),它也应被视为可疑。

另一方面,合法的帐户名不需要同时包含名字和姓氏。它们通常是来自流行语言的名称,例如罗马/拉丁语(即西班牙语、德语、葡萄牙语、法语、英语)、中文和日语。

合法帐户名称的示例包括(这些名称是虚构的,但确实反映了现实世界中合法帐户名称的相似风格):Michael、sara、jose colmenares、Dimitar、Jose Rafael、Morgan、Eduardo Medina、Luis R. Mendez, Hikaru, SELENIA, Zhang Ming, Xuting Liu, Chen Zheng​​strong>.

我在 Stackoverflow 上看到了一些稍微相似的问题,这些问题询问了检测乱码文本的方法。但是这些不适合我的情况,因为合法的文本和单词实际上是有意义的,而人名通常没有。我还希望能够仅基于帐户名称而不是其他任何东西来做到这一点。

现在,我的脚本负责使用 Python 的 Fuzzy Wuzzy 包查找可疑帐户名称(名称中的相似组件)的第二个特征,并使用 50% 作为相似度阈值。脚本如下:

from fuzzywuzzy import fuzz
from fuzzywuzzy import process

import pandas as pd
import numpy as np

accounts = pd.read_csv('dataset_with_names.csv', encoding = 'ISO-8859-1', sep=None, engine='python').replace(np.nan, 'blank', regex=True)

pd.options.mode.chained_assignment = None

accounts.columns = ['name', 'email', 'akon_id', 'acct_creation_date', 'first_time_city', 'first_time_ip', 'label']

accounts['name_simplified']=accounts['name'].str.replace('[^\w\s]','')
accounts['name_simplified']=accounts['name_simplified'].str.lower()

sim_name = []

for index, row in accounts.iterrows():        
    if ' ' in row['name_simplified']:
        row['name_simplified']=row['name_simplified'].split()
        if len(row['name_simplified']) > 1:
            #print(row['name_simplified'])
            if fuzz.ratio(row['name_simplified'][0], row['name_simplified'][1]) >= 50:
                sim_name.append('True')
            else:
                sim_name.append('False')
        else:
            sim_name.append('False')
    else:
        sim_name.append('False')        

accounts['are_name_components_similar'] = sim_name 

结果对于脚本的设计目的来说是可靠的,但我还希望能够显示具有第一个特征(奇怪/随机拼写或名称由纯数字或大部分数字组成)的乱码帐户名称。到目前为止,我还没有找到解决方案。

有人可以帮忙吗?任何反馈/建议将不胜感激!

【问题讨论】:

    标签: python machine-learning classification nltk fuzzywuzzy


    【解决方案1】:

    对于第一个特征,您可以训练基于字符的 n-gram 语言模型,并将每个字符平均概率较低的所有名称视为可疑名称。

    下面是这种语言模型的一个简单粗暴的例子。它是 1-gram、2-gram 和 3-gram 语言模型的混合体,在 Brown 语料库上训练。我相信您可以找到更多相关的训练数据(例如所有演员姓名的列表)。

    from nltk.corpus import brown
    from collections import Counter
    import numpy as np
    
    text = '\n  '.join([' '.join([w for w in s]) for s in brown.sents()])
    
    unigrams = Counter(text)
    bigrams = Counter(text[i:(i+2)] for i in range(len(text)-2))
    trigrams = Counter(text[i:(i+3)] for i in range(len(text)-3))
    
    weights = [0.001, 0.01, 0.989]
    
    def strangeness(text):
        r = 0
        text = '  ' + text + '\n'
        for i in range(2, len(text)):
            char = text[i]
            context1 = text[(i-1):i]
            context2 = text[(i-2):i]
            num = unigrams[char] * weights[0] + bigrams[context1+char] * weights[1] + trigrams[context2+char] * weights[2] 
            den = sum(unigrams.values()) * weights[0] + unigrams[context1] * weights[1] + bigrams[context2] * weights[2]
            r -= np.log(num / den)
        return r / (len(text) - 2)
    

    现在您可以将这种陌生性度量应用于您的示例。

    t1 = '128, 127, h4rugz4sx383a6n64hpo, tt, t66, t65, asdfds'.split(', ')
    t2 = 'Michael, sara, jose colmenares, Dimitar, Jose Rafael, Morgan, Eduardo Medina, Luis R. Mendez, Hikaru, SELENIA, Zhang Ming, Xuting Liu, Chen Zheng'.split(', ')
    for t in t1 + t2:
        print('{:20} -> {:9.5}'.format(t, strangeness(t)))
    

    您会发现,在大多数情况下,乱七八糟的名字比普通名字更“奇怪”。例如,您可以在此处使用 3.9 的阈值。

    128                  ->    5.5528
    127                  ->    5.6572
    h4rugz4sx383a6n64hpo ->    5.9016
    tt                   ->    4.9392
    t66                  ->    6.9673
    t65                  ->    6.8501
    asdfds               ->    3.9776
    Michael              ->    3.3598
    sara                 ->    3.8171
    jose colmenares      ->    2.9539
    Dimitar              ->    3.4602
    Jose Rafael          ->    3.4604
    Morgan               ->    3.3628
    Eduardo Medina       ->    3.2586
    Luis R. Mendez       ->     3.566
    Hikaru               ->    3.8936
    SELENIA              ->    6.1829
    Zhang Ming           ->    3.4809
    Xuting Liu           ->    3.7161
    Chen Zheng           ->    3.6212
    

    当然,一个更简单的解决方案是收集所有目标语言的流行名称列表,并且根本不使用机器学习 - 只是查找。

    【讨论】:

    • 谢谢@David。这是一个很好的建议!除了使用“棕色”语料库中的单词,您认为我可以使用我已经必须训练模型的合法名称列表吗?
    • 是的,您可以这样做,尤其是在列表足够大的情况下。
    • 我们在这个函数中从 2 而不是 0 开始的原因是什么:“for i in range(2, len(text)):”?
    • @Stanleyrr 那是因为我在文本前添加了两个空格。我添加了它们以便为每个字符使用长度为 2 的上下文。
    • 事实上,我正在尝试计算 1-gram、2-gram 和 3-gram 语言模型的“微观平均值”。每个模型都乘以它的权重,对于每个模型,我将其 n-gram 的计数包含在分子中,并将相应的 (n-1)-gram 计数(其前缀)包含在分母中。当然,您可以使用更简单的模型(例如仅 3 克),但根据我的经验,这种方法效果更好。
    猜你喜欢
    • 2015-07-14
    • 2021-07-12
    • 1970-01-01
    • 2023-03-12
    • 2017-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    相关资源
    最近更新 更多