jieba源碼研讀筆記(十一) - 詞性標注之POSTokenizer初探

jieba源碼研讀筆記(十一) - 詞性標注之POSTokenizer初探

前言

前篇看了posseg/__init__.py檔的大架構,這裡將繼續介紹檔案中的POSTokenizer這個類別。
本篇僅介紹POSTokenizer類別初始化及載入字典的部份,核心函數及其wrapper將會在後續的文章裡介紹。

POSTokenizer類別

初始化

class POSTokenizer(object):

    def __init__(self, tokenizer=None):
        # 它需要借用jieba.Tokenizer的get_dict_file, get_DAG, calc等函數
        # 所以這裡才會定義了tokenizer這個屬性
        self.tokenizer = tokenizer or jieba.Tokenizer()
        # 這一句怎麼同時出現在__init__()及initialize()?
        self.load_word_tag(self.tokenizer.get_dict_file())

    def __repr__(self):
        return '<POSTokenizer tokenizer=%r>' % self.tokenizer

    def __getattr__(self, name):
        if name in ('cut_for_search', 'lcut_for_search', 'tokenize'):
            # may be possible?
            raise NotImplementedError
        # POSTokenizer並未實作cut_for_search, lcut_for_search, tokenize
        # 其餘的功能如cut, lcut等有被POSTokenizer覆寫,所以可以使用
        return getattr(self.tokenizer, name)

    def initialize(self, dictionary=None):
        self.tokenizer.initialize(dictionary)
        # 這一句怎麼同時出現在__init__()及initialize()?
        self.load_word_tag(self.tokenizer.get_dict_file())

載入字典

class POSTokenizer(object):
    # ...
    def load_word_tag(self, f):
        #這個函數接受一個開啟的file object當作輸入,然後將它的內容讀到一個dict內
        #從jieba/dict.txt中載入word_tag_tab
        self.word_tag_tab = {} #一個把詞彙對應到詞性的字典
        f_name = resolve_filename(f)
        for lineno, line in enumerate(f, 1):
            try:
                line = line.strip().decode("utf-8")
                if not line:
                    continue
                word, _, tag = line.split(" ")
                self.word_tag_tab[word] = tag
            except Exception:
                raise ValueError(
                    'invalid POS dictionary entry in %s at Line %s: %s' % (f_name, lineno, line))
        f.close()
        
    def makesure_userdict_loaded(self):
        #在使用者有用add_word增加新詞時self.tokenizer.user_word_tag_tab才會不為空
        if self.tokenizer.user_word_tag_tab:
            #參考https://www.programiz.com/python-programming/methods/dictionary/update
            #字典1.update(字典2):如果字典2的key不在字典1中,則把該key加入字典1;
            #如果字典2的key己經存在字典1中,則更新字典1中該key的值
            self.word_tag_tab.update(self.tokenizer.user_word_tag_tab)
            self.tokenizer.user_word_tag_tab = {}

dict.txt中的內容:

AT&T 3 nz
B超 3 n
c# 3 nz
C# 3 nz
c++ 3 nz
C++ 3 nz
T恤 4 n
A座 3 n
A股 3 n

可以看出字典中的三個欄位分別是詞彙本身,詞頻以及它的詞性。
load_word_tag這個函數讀取dict.txt,用以建立word_tag_tab這個dict,把詞彙本身對應到詞性去。
如果使用者有自定義詞彙,那麼makesure_userdict_loaded函數會將它們加入word_tag_tab

詞性標注核心函數

這裡定義的幾個函數實現了POSTokenizer的核心功能,在後續的章節裡將會一一介紹。

class POSTokenizer(object):
    # ...
    def __cut(self, sentence):
        ...

    def __cut_detail(self, sentence):
        ...

    def __cut_DAG_NO_HMM(self, sentence):
        ...

    def __cut_DAG(self, sentence):
        ...

詞性標注函數wrapper

這裡定義了詞性標注函數的wrapper,一樣留在後續的章節裡介紹。

class POSTokenizer(object):
    # ...
    def __cut_internal(self, sentence, HMM=True):
        ...

    def _lcut_internal(self, sentence):
        return list(self.__cut_internal(sentence))

    def _lcut_internal_no_hmm(self, sentence):
        return list(self.__cut_internal(sentence, False))

    def cut(self, sentence, HMM=True):
        for w in self.__cut_internal(sentence, HMM=HMM):
            yield w

    def lcut(self, *args, **kwargs):
        return list(self.cut(*args, **kwargs))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我们来介绍一下如何使用 NLTK 和 jieba 进行中英文分词和词性标注。 首先,我们需要安装 NLTK 和 jieba。可以在命令行中使用以下命令安装: NLTK:`pip install nltk` jieba:`pip install jieba` 接下来,我们可以使用 NLTK 中的 `pos_tag()` 函数和 jieba 中的 `posseg` 模块来分别进行英文和中文的词性标注。 对于英文,我们可以使用 NLTK 中的 `pos_tag()` 函数,示例代码如下: ```python import nltk nltk.download('punkt') nltk.download('averaged_perceptron_tagger') text = "This is a sample English sentence." tokens = nltk.word_tokenize(text) pos_tags = nltk.pos_tag(tokens) print(pos_tags) ``` 输出结果: ``` [('This', 'DT'), ('is', 'VBZ'), ('a', 'DT'), ('sample', 'JJ'), ('English', 'JJ'), ('sentence', 'NN'), ('.', '.')] ``` 其中,`pos_tag()` 函数的输入是一个被分词后的单词列表,返回值是一个元组列表,每个元组包含单词和对应的词性标注。 对于中文,我们可以使用 jieba 中的 `posseg` 模块,示例代码如下: ```python import jieba.posseg as pseg text = "这是一个样例中文句子。" words = pseg.cut(text) for word, flag in words: print(word, flag) ``` 输出结果: ``` 这 r 是 v 一个 m 样例 n 中文 nz 句子 n 。 x ``` 其中,`pseg.cut()` 函数的输入是一个中文句子,返回值是一个生成器,每次迭代产生一个元组,包含分词和对应的词性标注。 需要注意的是,中文分词和词性标注的准确性受到语料库的影响。可以使用已有的语料库,也可以根据自己的需求创建和使用语料库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值