无法使用Python

时间:2018-06-02 18:21:58

标签: python machine-learning classification nltk fuzzywuzzy

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

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

就我而言,有两种可能的特征可以将帐户名称显示为可疑,乱码或两者:

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

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

  3. 如果帐户名称符合上述两个条件(即' asdfs lsdfs',' 332 333'),则也应视为可疑。

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

    合法帐户名称的示例包括(这些名称已组成,但确实反映了现实世界中合法帐户名称的类似样式): Michael,sara,jose colmenares,Dimitar,Jose Rafael,Morgan,Eduardo Medina,Luis R. Mendez,Hikaru,SELENIA,张明,刘旭庭,陈铮

    我在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 
    

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

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

1 个答案:

答案 0 :(得分:2)

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

下面是这种语言模型的一个快速而肮脏的例子。它是1克,2克和3克语言模型的混合物,在布朗语料库上训练。我相信你可以找到更多相关的培训数据(例如所有演员名单)。

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[char] + weights[1] + bigrams[context1] * 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)))

你看到乱码的名字在大多数情况下比普通名字更“奇怪”。你可以在这里使用例如5.9的阈值。

128                  ->    5.9073
127                  ->    6.0044
h4rugz4sx383a6n64hpo ->    7.4261
tt                   ->    6.3916
t66                  ->    7.3553
t65                  ->    7.2584
asdfds               ->    6.1796
Michael              ->    5.6694
sara                 ->    5.5734
jose colmenares      ->    4.9489
Dimitar              ->    5.7058
Jose Rafael          ->    5.8184
Morgan               ->    5.5766
Eduardo Medina       ->    5.5703
Luis R. Mendez       ->    5.5337
Hikaru               ->     6.439
SELENIA              ->    7.1125
Zhang Ming           ->    5.1594
Xuting Liu           ->    5.5975
Chen Zheng           ->    5.3341

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