关键词/词组->分类识别系统 设计+实现

来源:互联网 发布:蓝科型材优化注册码 编辑:程序博客网 时间:2024/06/07 09:15

设计

给出一篇文章,判断其属于某一个分类
格式如下,{}中表示是一组词

>>> 广告事前
贵公司
{
办证
电话
}

>>> 广告事后
{
网站
代购
}
开发票

构思:

1.单个关键词,实际应用中一个单关键词最多属于一个分类,先做一下倒排

censor_single_keyword={
    "贵公司":1,
    "开发票":2,
}

配合多关键词查找(比如Aho-Corasick State Machine),很easy

2.
    a. 给每一个组分配id

    1:{
    办证
    电话
    },
    2:{
    网站
    代购
    }

    b.

    记录    类别id - 分组id
    用array

    c.  
    记录    分组id - id的中内容长度
    用array
    'B' unsigned char int 1

    d.
    词做倒排
    词  <-> 分类id列表

    e.
    多关键词查找 统计出出现的词的set
   
    f.
    新建一个字典
    每一个出现词 分类id count+=1
    for xx in 这个字典
        if count == 分组id 中 id的中内容长度
    确认是这个分类(这里只考虑属于一个分类)
------------------------
实现
~/algorithm/censor/lib/multi_pattern_search $ cat keyword2group.py

~/algorithm/censor $ cat lib/multi_pattern_search/keyword2group.py
#coding:utf-8
from array import array
from collections import defaultdict
from multi_pattern_search import MultiPatternSearch


class CensorKeyword(object):
    def __init__(self):
        pass

    def _reload(self):
        self.group_name_list = []
        self.single_keyword_to_cat_id = {}
        self.group_keyword = []
        self.group_keyword_to_group_id = {}
        self.group_id_to_cat_id = array('I')
        self.group_keyword_length = array('B')
        self.single_search = MultiPatternSearch()
        self.group_search = MultiPatternSearch()

    def _init_search(self):
        for i in self.single_keyword_to_cat_id.keys():
            self.single_search.add_keyword(i)
        group_keyword_set = set()
        for i in self.group_keyword:
            for k in i:
                group_keyword_set.add(k)
        for i in group_keyword_set:
            self.group_search.add_keyword(i)

    def _keyword_to_group_id(self):
        #词做倒排
        group_keyword_to_group_id = self.group_keyword_to_group_id
        for pos, group_keyword_list in enumerate(self.group_keyword):
            for keyword in group_keyword_list:
                if keyword not in group_keyword_to_group_id:
                    group_keyword_to_group_id[keyword] = array('I')
                group_keyword_to_group_id[keyword].append(pos)

    def load_txt(self, txt):
        self._reload()
        SINGE_KEYWORD = 0
        GROUP_KEYWORD = 1
        txt = txt.split("/n")
        state = SINGE_KEYWORD
        group_keyword = set()
        #处理文本
        for line in txt:
            line = line.strip()
            if not line:
                continue
            if line.startswith(">>>"):
                cat_id = len(self.group_name_list)
                group_name_list = line[3:].strip()
                self.group_name_list.append(group_name_list)
                state = SINGE_KEYWORD
            elif len(line) == 1:
                if line == '{':
                    state = GROUP_KEYWORD
                elif line == "}":
                    state = SINGE_KEYWORD
                    if group_keyword:
                        group_keyword = tuple(group_keyword)
                        self.group_keyword.append(group_keyword)
                        self.group_id_to_cat_id.append(cat_id)
                        self.group_keyword_length.append(len(group_keyword))
                        group_keyword = set()
            elif state == SINGE_KEYWORD:
                self.single_keyword_to_cat_id[line] = cat_id
            elif state == GROUP_KEYWORD:
                group_keyword.add(line)

        self._keyword_to_group_id()
        self._init_search()

    def which_group_id(self, text):
        total_group = len(self.group_name_list)
        group = total_group

        single_search = self.single_search.count(text)
        all_keys =        single_search.keys()
        if single_search:
            for key in single_search.keys():
                cat_id = self.single_keyword_to_cat_id[key]
                if cat_id < group:
                    group = cat_id

        group_search = self.group_search.count(text)
        all_keys.extend(group_search.keys())
        group_count = defaultdict(int)
        for k in group_search.keys():
            group_id_list = self.group_keyword_to_group_id[k]
            for i in group_id_list:
                group_count[i]+=1

        for k, v in group_count.iteritems():
            if self.group_keyword_length[k] <= v:
                #返回最小的那个 事情比事后优先级高
                cat_id = self.group_id_to_cat_id[k]
                if cat_id < group:
                    group = cat_id
        if group < total_group:
            return group, all_keys

    def which_group_name(self, text):
        pos = self.which_group_id(text)
        if pos is not None:
            pos , keywords = pos
            keywords = " ".join(keywords)
            return self.group_name_list[pos], keywords


if __name__ == "__main__":
    test_input = """
>>> 广告事前
    贵公司
{
    办证
    电话
}
{
    是
    网站
    促销
}


>>> 敏感文章事前


>>> 广告事后
    开发票
{
    网站
    代购
}
    的


>>> 敏感文章事后

"""
    censor_keyword = CensorKeyword()
    censor_keyword.load_txt(test_input)
    censor_keyword.load_txt(test_input)
    censor_keyword.load_txt(test_input)
    test = """
牛奶@咖啡3月21日专场演出(免票)
牛奶@咖啡3月21日专场演出(免票)
活动介绍
牛奶@咖啡自从巡演回来后一直没有在北京作专场演出,如果你对最近每次的小型演出还不过瘾,就到我们的这次专场上听个够吧!“一起不孤单!”

让更多的人来一起倾听牛奶@咖啡的歌声吧!如果你还不知道他们,去下面的网址了解一下吧!http://www.douban.com/group/milkcoffee/

牛奶@咖啡3月21日周六下午1点半SOHO尚都专场,免票无需报名

地点:SOHO尚都西塔一层钢琴舞台(地铁一号线永安里站B口出倒126路公交芳草地站下车即是)
咨询电话:老徐:13801108173
活动网址:http://www.douban.com/event/10533960/
同时还有市集可以逛:http://www.douban.com/event/10503500/
    """

    #print " ".join(censor_keyword.which_group_name("贵公司"))
    #print " ".join(censor_keyword.which_group_name("代购网站的"))
    print " ".join(censor_keyword.which_group_name(test))

原创粉丝点击