2017-05-11 20 views
0

我有這個簡單的Categorizer分配相同的類別,以類似的消息

import re 


class Categorizer: 

    ''' 
    Classifies messages according to a pre-defined list of regex-es 
    If no match is found, an automatic algorithm is used to decide the category 
    ''' 

    def __init__(self, categories, message): 
     self._categories = categories 
     self._message = message 

    def _auto_detec_category(self): 
     # TODO: auto-detect category based on message (message distance/bayes classifier/...) 
     return message 

    @property 
    def category(self): 
     '''Returns the first matching category, or an automaticaly generated one if no match found''' 
     for category, regex in self._categories.items(): 
      if regex.search(self._message): 
       return category 
     return self._auto_detec_category() 


CATEGORIES = { 
    "aaa": "aaa.*AAA", 
    "bbb": "bbb.*BBB", 
} 


categories = { category: re.compile(regex) for category, regex in CATEGORIES.items() } 

MESSAGES = [ 
    "aaa 12345 AAA", 
    "aaa 66666 AAA", 
    "bbb 12345 BBB", 
    "bbb 66666 BBB", 
    "ccc 12345 CCC", 
    "ccc 66666 CCC", 
] 


for message in MESSAGES: 
    print("{} -> {}".format(Categorizer(categories, message).category, message)) 

,給了我這樣的:

aaa -> aaa 12345 AAA 
aaa -> aaa 66666 AAA 
bbb -> bbb 12345 BBB 
bbb -> bbb 66666 BBB 
ccc 12345 CCC -> ccc 12345 CCC 
ccc 66666 CCC -> ccc 66666 CCC 

我的目標是預配置的,不是模式仍然可以歸類,這樣類似的消息被賦予相同的類別。但我不確定如何定義「相似」或使用什麼實現來確保Categozier在未知消息方面做得很好。

這些消息是日誌條目,具有通用信息,但也包含一些與選擇類別無關的特定數據。

基本上,我會滿足於這樣的輸出:

aaa -> aaa 12345 AAA 
aaa -> aaa 66666 AAA 
bbb -> bbb 12345 BBB 
bbb -> bbb 66666 BBB 
auto1 -> ccc 12345 CCC 
auto1 -> ccc 66666 CCC 

當最後兩個消息都自動歸爲auto1

+0

請給出一些「類似」消息的例子,以及看起來有點類似但不屬於同一類別的消息的例子。 –

+0

@JanneKarila在回答中已經列出了這些消息:「aaa」消息彼此相似,「bbb」消息也是,「ccc」消息也是彼此不同的。我正在尋找的是一種計算消息彼此「距離」的方法,並使用閾值來決定它們何時是「相同」消息。除「度量指標提供的閾值以下」之外,沒有關於「相似」含義的定義。 – dangonfast

+0

給出這些例子,簡單的解決方案是提取每條消息的第一個單詞並單獨對其進行分類。 –

回答

1

從您的評論來看,我認爲正則表達式不是您想要的工具。

您是否嘗試過使用fuzzywuzzy庫(請參閱Docs)。它允許您比較兩個字符串的「接近度」。它並不完美,但就你而言,我會嘗試比較每個日誌條目與某些標準的「接近度」。在這裏我按照最接近的匹配進行分類。

from fuzzywuzzy import fuzz 

message = [ 
    'aaa 12345 AAA', 
    'aaa 66666 AAA', 
    'bbb 12345 BBB', 
    'bbb 66666 BBB', 
    'ccc 12345 CCC', 
    'ccc 66666 CCC', 
] 

def classify(input_str): 
    # Define standard classifications, and reset them to zero score. 
    standards = { 
     'AAA': 0, 
     'BBB': 0, 
     'CCC': 0, 
    } 

    # Score each classification according to how well is matches. 
    for key in standards: 
     standards[key] = fuzz.ratio(key, input_str) 

    # Return the classification with the highest score. 
    return max(standards, key=lambda k: standards[k]) 


for msg in messages: 
    print ('{msg}: {standard}'.format(msg=msg, standard=classify(msg)))