FLAT代碼解讀(1)-輸入

論文 FLAT: Chinese NER Using Flat-Lattice Transformer(ACL 2020)

首先介紹一下命名實(shí)體識別任務(wù)數(shù)據(jù)集的常見標(biāo)注格式:

  • BIO: B(Begin)-X 實(shí)體X的開頭紊遵;I(Inside)-X 實(shí)體X的內(nèi)部;O(Outside) 不屬于實(shí)體
  • BIOES: B(Begin)-X 實(shí)體X的開頭匀奏;I(Inside)-X 實(shí)體X的中間;O(Outside) 不屬于實(shí)體论衍;E(End)-X 實(shí)體X的結(jié)尾聚磺;S(Singleton)-the single word是實(shí)體
  • BMES:B(Begin)-X 實(shí)體X的開頭瘫寝;M(Middle)-X 實(shí)體X的中間稠炬;E(End)-X 實(shí)體X的結(jié)尾首启;S(Singleton)-the single word是實(shí)體

比如:

Michael Jeffrey Jordan was born in Brooklyn , New   York   .
B-PER   I-PER   E-PER   O   O   O  S-LOC    O B-LOC E-LOC  O

FALT整體框架圖

詞典信息加入模型被證明對中文NER任務(wù)很有效毅桃,但是結(jié)合詞典的方法通常會使輸入變成一個動態(tài)的結(jié)構(gòu)准夷,導(dǎo)致無法有效利用GPU的并行計(jì)算衫嵌。FLAT模型通過采用一個特殊的位置編碼表征輸入結(jié)構(gòu),從而不需要在運(yùn)行時動態(tài)改變結(jié)構(gòu)來表征輸入渐扮。這里推薦去看作者的講解視頻 結(jié)合詞典的中文命名實(shí)體識別

FLAT

數(shù)據(jù)處理

  1. 讀取數(shù)據(jù)集
from fastNLP.io.loader import ConllLoader

def get_bigrams(words):
    result = []
    for i, w in enumerate(words):
        if i != len(words)-1:
            result.append(words[i]+words[i+1])
        else:
            result.append(words[i]+'<end>')

    return result

train_path = os.path.join('/input/resume-ner', 'train.char.bmes')

loader = ConllLoader(['chars', 'target']) # header
train_bundle = loader.load(train_path)
datasets = dict()
datasets['train'] = train_bundle.datasets['train']
# 添加列 bigrams
datasets['train'].apply_field(get_bigrams, field_name='chars', new_field_name='bigrams')
# 添加列 seq_len
datasets['train'].add_seq_len('chars')

print(datasets['train'])

得到的輸出格式為:

train examples

chars列為樣本中的字符
target列為標(biāo)簽
bigrams列為兩兩相鄰字符組成的雙字
seq_len為chars列中字符的個數(shù)

  1. 提取vocab
from fastNLP import Vocabulary

char_vocab = Vocabulary()
bigram_vocab = Vocabulary()
label_vocab = Vocabulary()
# 根據(jù)列 field_name中的詞構(gòu)建詞典
char_vocab.from_dataset(datasets['train'], field_name='chars') # <pad> id:0, <unk> id:1, 公 id:3 ...
bigram_vocab.from_dataset(datasets['train'], field_name='bigrams') # <pad> id:0, <unk> id:1, 公司 id:2 ...                
label_vocab.from_dataset(datasets['train'], field_name='target') # <pad> id:0, <unk> id:1, O id:2, M-ORG id:3 ...

根據(jù)數(shù)據(jù)集字段中的字符構(gòu)建對應(yīng)的詞典vocab。

  1. 加載預(yù)訓(xùn)練embedding
embeddings = {}
    if char_embedding_path is not None:
        char_embedding = StaticEmbedding(char_vocab, char_embedding_path, word_dropout=0.01,
                                         min_freq=char_min_freq, only_train_min_freq=only_train_min_freq)
        embeddings['char'] = char_embedding

    if bigram_embedding_path is not None:
        bigram_embedding = StaticEmbedding(bigram_vocab, bigram_embedding_path, word_dropout=0.01,
                                           min_freq=bigram_min_freq, only_train_min_freq=only_train_min_freq)
        embeddings['bigram'] = bigram_embedding

    return datasets, vocabs, embeddings
  • char_embedding_path為預(yù)訓(xùn)練的單個字符的embedding向量察纯。
  • bigram_embedding_path為預(yù)訓(xùn)練的雙個字符的embedding向量针肥。

給定預(yù)訓(xùn)練embedding的路徑慰枕,StaticEmbdding函數(shù)根據(jù)vocab從embedding中抽取相應(yīng)的數(shù)據(jù)(只會將出現(xiàn)在vocab中的詞抽取出來,如果沒有找到博肋,則會隨機(jī)初始化一個值(但如果該word是被標(biāo)記為no_create_entry的話匪凡,則不會單獨(dú)創(chuàng)建一個值掘猿,而是會被指向unk的index))。

  1. 融入詞匯信息
w_list = load_yangjie_rich_pretrain_word_list(yangjie_rich_pretrain_word_path,
                                              _refresh=refresh_data,
                                              _cache_fp='cache/{}'.format(args.lexicon_name))

datasets,vocabs,embeddings = equip_chinese_ner_with_lexicon(datasets,vocabs,embeddings,
                                                            w_list,yangjie_rich_pretrain_word_path,
                                                            _refresh=refresh_data,_cache_fp=cache_name,
                                                            only_lexicon_in_train=args.only_lexicon_in_train,
                                                            word_char_mix_embedding_path=output_char_and_word_path,
                                                            number_normalized=args.number_normalized,
                                                            lattice_min_freq=args.lattice_min_freq,
                                                            only_train_min_freq=args.only_train_min_freq)

加載詞典數(shù)據(jù)买猖,得到w_list,詞典中的詞匯可包含兩個政勃,三個等多個字符奸远。
equip_chinese_ner_with_lexicon函數(shù)用來將詞匯信息lexicon寫入樣本中讽挟。

  • 得到詞匯相關(guān)字段
    for k, v in datasets.items():
        # partial函數(shù)將一個函數(shù)的某些參數(shù)固定住,返回一個新函數(shù)
        v.apply_field(partial(get_skip_path, w_trie=w_trie), 'chars', 'lexicons')
        v.apply_field(copy.copy, 'chars', 'raw_chars')
        v.add_seq_len('lexicons', 'lex_num')
        v.apply_field(lambda x: list(map(lambda y: y[0], x)), 'lexicons', 'lex_s')
        v.apply_field(lambda x: list(map(lambda y: y[1], x)), 'lexicons', 'lex_e')

lexicons列為樣本中匹配到的詞匯信息薛窥,如[[0, 1, '中國'],[3, 5, '天安門']]
lex_num列為樣本匹配到的詞匯的個數(shù)
lex_s列為各個匹配詞的起始索引列表眼姐,如[0, 3]
lex_e列為各個匹配詞的終止索引列表,如[1, 5]

  1. 拼接原始字符串和詞匯
    def concat(ins):
        chars = ins['chars']
        lexicons = ins['lexicons']
        result = chars + list(map(lambda x: x[2], lexicons))
        return result

    def get_pos_s(ins):
        lex_s = ins['lex_s']
        seq_len = ins['seq_len']
        pos_s = list(range(seq_len)) + lex_s
        return pos_s

    def get_pos_e(ins):
        lex_e = ins['lex_e']
        seq_len = ins['seq_len']
        pos_e = list(range(seq_len)) + lex_e
        return pos_e

    for k, v in datasets.items():
        v.apply(concat, new_field_name='lattice')
        v.set_input('lattice')
        v.apply(get_pos_s, new_field_name='pos_s')
        v.apply(get_pos_e, new_field_name='pos_e')
        v.set_input('pos_s', 'pos_e')

concat函數(shù)將詞典lexicon中匹配到的詞匯拼接到樣本末尾罢杉,得到lattice
pos_s列記為論文中的Head
pos_e列即為論文中的Tail
這三列均被設(shè)置為Input滩租。

  1. 字符轉(zhuǎn)成整數(shù)id
vocabs['char'].index_dataset(* (datasets.values()),
                                 field_name='chars', new_field_name='chars')
vocabs['bigram'].index_dataset(* (datasets.values()),
                                   field_name='bigrams', new_field_name='bigrams')
vocabs['label'].index_dataset(* (datasets.values()),
                                  field_name='target', new_field_name='target')
vocabs['lattice'].index_dataset(* (datasets.values()),
                                    field_name='lattice', new_field_name='lattice')

return datasets, vocabs, embeddings

最后通過各個vocab將datasets中的對應(yīng)字符字段轉(zhuǎn)成數(shù)字(vocab中的id)律想。Vocabulary類的主要作用就是實(shí)現(xiàn)字符和對應(yīng)id之間的互相轉(zhuǎn)換技即。

最終即得到了FLAT整體框架圖中所需要的輸入數(shù)據(jù)晌柬。

參考:
FLAT: Chinese NER Using Flat-Lattice Transformer (github.com)
論文閱讀《FLAT:Chinese NER Using Flat-Lattice Transformer》
Flat-Lattice-Transformer模型源碼測試

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末年碘,一起剝皮案震驚了整個濱河市屿衅,隨后出現(xiàn)的幾起案子涤久,更是在濱河造成了極大的恐慌,老刑警劉巖响迂,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔗彤,死亡現(xiàn)場離奇詭異然遏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)丢早,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門怨酝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來那先,“玉大人,你說我怎么就攤上這事盛险】嗑颍” “怎么了楔壤?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長递瑰。 經(jīng)常有香客問我隙畜,道長,這世上最難降的妖魔是什么慎颗? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任傲宜,我火速辦了婚禮函卒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘撇眯。我一直安慰自己叛本,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著云挟,像睡著了一般转质。 火紅的嫁衣襯著肌膚如雪休蟹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天绑榴,我揣著相機(jī)與錄音翔怎,去河邊找鬼。 笑死杨耙,一個胖子當(dāng)著我的面吹牛赤套,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播珊膜,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼容握,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了车柠?” 一聲冷哼從身側(cè)響起唯沮,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤脖旱,失蹤者是張志新(化名)和其女友劉穎堪遂,沒想到半個月后介蛉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡溶褪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鳍刷。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖尤揣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嗜愈,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布拌阴,位于F島的核電站,受9級特大地震影響纤壁,放射性物質(zhì)發(fā)生泄漏欠痴。R本人自食惡果不足惜喇辽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抽米。 院中可真熱鬧,春花似錦标捺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽戴而。三九已至,卻和暖如春扶踊,著一層夾襖步出監(jiān)牢的瞬間秧耗,已是汗流浹背分井。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铸磅,地道東北人弧械。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親抖甘。 傳聞我的和親對象是個殘疾皇子衔彻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容