1. 程式人生 > 其它 >RGAT-ABSA資料處理過程

RGAT-ABSA資料處理過程

1.如果訓練資料採用的編碼方式是Bert,則通過BertTokenizer.from_pretrained(args.bert_model_dir)來載入預訓練模型和訓練的引數。

2.載入train_dataset訓練資料,test_dataset測試資料,word_vocab資料的詞表,dep_tag_vocab依存關係詞表還有dep_tag_vocab單詞詞性詞表。

資料形式:

train_dataset,test_dataset的形式:

sentence_ids 句子中單詞對應的詞表id
aspect_ids 方面詞對應詞表中的索引
dep_tag_ids 依存關係對應依存關係詞表中的索引
dep_dir_ids 依存關係方向 1表示以方面詞為起點的依存關係 2表示以方面詞為終止位置的依存關係
pos_class 單詞的詞性
text_len 句子中單詞的個數,句子的長度
aspect_len 方面詞的個數
sentiment 方面詞對應的極性
deprel_ids 真實的依存關係對應依存關係詞表的索引
dephead 依存關係頭位置
aspect_position  方面詞在句子中位置,如果對應位置是方面詞則為1,否則為0
if bert:如果採用bert編碼方式,就不需要sentence_ids和aspect_ids了,用以下的列表代替,它們是根據bert模型自帶的詞表獲取的單詞索引
    input_ids
    word_indexer
    input_aspect_ids
    aspect_indexer
or:如果是pure_bert那麼就把句子和方面進行拼接,來進行訓練和預測
    input_cat_ids
    segment_ids

word_vocab  dep_tag_vocab dep_tag_vocab它們的形式相同,都是以下的形式

{'itos': ['[PAD]', '[UNK]', 'the', ',', 'was', '.', 'but', 'to'], 'stoi': defaultdict(<function _default_unk_index at 0x0000029DBC50AA60>, {'[PAD]': 0, '[UNK]': 1, 'the': 2, ',': 3, 'was': 4, '.': 5, 'but': 6, 'to': 7}), 'len': 8}

word_vocab形式,itos是詞按照出現次數從多到少進行排序,stoi是itos中的每個詞對應的索引
 {'itos': itos, 'stoi': stoi, 'len': len(itos)}

資料構造過程:

train_dataset和test_dataset的構造過程:

(1)將原始的xml資料解析成json的形式得到input_data資料

tags是句子中每個單詞的詞性,predicted_dependencies是每個單詞所連線的依存關係,predicted_heads是依存關係的頭,終止位置就是當前單詞的位置,dependencies就是依存關係以及依存關係的起止位置,from_to就是方面詞的起止位置。

{"sentence": "But the staff was so horrible to us.", 
"tokens": ["But", "the", "staff", "was", "so", "horrible", "to", "us", "."],
"tags": ["CC", "DT", "NN", "VBD", "RB", "JJ", "IN", "PRP", "."],
"predicted_dependencies": ["cc", "det", "nsubj", "cop", "advmod", "root", "prep", "pobj", "punct"],
"predicted_heads": [6, 3, 6, 6, 6, 0, 6, 7, 6],
"dependencies": [["cc", 6, 1], ["det", 3, 2], ["nsubj", 6, 3], ["cop", 6, 4], ["advmod", 6, 5],
["root", 0, 6], ["prep", 6, 7], ["pobj", 7, 8], ["punct", 6, 9]],
"aspect_sentiment": [["staff", "negative"]], "from_to": [[2, 3]]}

(2)對於輸入的資料,每個句子可能有多個方面詞,我們要將它處理成每次一個句子只對應一個方面詞,並且對依賴樹進行裁剪,讓方面詞作為root,保留與方面詞直接相連的詞之間的依存關係,其他關係進行去除,取而代之的是新建的n_con關係,當與方面詞之間沒有直接的依賴關係並且與方面詞之間的距離大於4,直接不構建關係。利用get_rolled_and_unrolled_data(input_data, args):這一函式進行處理。

構建新的依賴樹的過程:迴圈遍歷一個句子的依存關係,如果依存關係的起始位置是方面詞,依存關係的終止位置如果滿足條件(不在方面詞的範圍之內,並且位置不是0,而且dep_idx裡面沒有這一位置)就把這一依存關係加入到dep_tag這一
列表中,並且將1新增到dep_dir中,代表這一依存關係是以方面詞為起始位置的。並且把依存關係的終止位置(不是方面詞的位置)新增到dep_idx中。
如果依存關係的終止位置是方面詞,並且依存關係的起始位置滿足條件(不在方面詞的範圍之內,並且位置不是0,而且dep_idx裡面沒有這一位置),就把這一依存關係加入到dep_tag這一列表中,把2新增到dep_dir中,代表這一依存關係是以
方面詞為終止位置的,並且把依存關係的起始位置新增到dep_idx這一列表中。這時只構建了與方面詞直接相連的依存關係,下面就要捨棄不與方面詞直接相連的依存關係,取而代之的是新的依存關係n_con.
還有一些詞沒有與方面詞建立依存關係,這是就用n_con替代,遍歷dep_idx,如果dep_idx裡面的值是依存關係的起始位置,並且依存關係的終止位置不是根,不是方面詞也不在dep_idx中,就把加入到dep_idx列表中,並把1加入到dep_dir中,
代表這一新的依存關係是以方面詞為起始位置的,這一關係的名稱為ncon_2,因為這一依存關係與方面詞連線的另一頭是通過與方面詞直接相連的詞找到的,在進行迴圈時,是通過上一輪新增如dep_idx的值找到的,這是依存關係的名稱就是
ncon_3,因為迴圈的次數通過
max_hop控制,迴圈完成之後還是會有沒有與方面詞建立依存關係的詞,這些詞就建立一種特殊的非連結關係,non-connect填充到dep_tag中,用0填充到dep_dir.將這些詞的位置填充到dep_idx中。

將dep_idx中的值進行排序,讓依存關係和句子的詞相對應,dep_tag中第一個位置的依存關係就是第一個詞的依存關係,第二個位置的依存關係就是第二個詞的依存關係。
最終獲取的修建的依賴樹的依存關係如下:

 

首先將句子中的所有大寫字母轉成小寫字母,獲取方面詞的起止位置,構造新的依賴樹,構造依賴樹的函式如下:

args.add_non_connect 是否構建新的n_con依存關係
args.max_hop這一新的依存關係方面詞與其他詞之間的距離限制
dep_tag, dep_idx, dep_dir = reshape_dependency_tree_new(frm, to, e['dependencies'],
multi_hop=args.multi_hop, add_non_connect=args.add_non_connect, tokens=e['tokens'], max_hop=args.max_hop)
# dep_tag是修剪之後的依賴樹的依存關係
dep_tag = []
# dep_idx是依賴樹中以方面詞為起始位置,dep_idx為終止位置的依存關係
dep_idx = []
# 代表依存關係的方向,1代表以方面詞為起始位置,2代表以方面詞為終止位置
dep_dir = []

構建新的依賴樹的過程:迴圈遍歷一個句子的依存關係,如果依存關係的起始位置是方面詞,依存關係的終止位置如果滿足條件(不在方面詞的範圍之內,並且位置不是0,而且dep_idx裡面沒有這一位置)就把這一依存關係加入到dep_tag這一
列表中,並且將1新增到dep_dir中,代表這一依存關係是以方面詞為起始位置的。並且把依存關係的終止位置(不是方面詞的位置)新增到dep_idx中。
如果依存關係的終止位置是方面詞,並且依存關係的起始位置滿足條件(不在方面詞的範圍之內,並且位置不是0,而且dep_idx裡面沒有這一位置),就把這一依存關係加入到dep_tag這一列表中,把2新增到dep_dir中,代表這一依存關係是以
方面詞為終止位置的,並且把依存關係的起始位置新增到dep_idx這一列表中。這時只構建了與方面詞直接相連的依存關係,下面就要捨棄不與方面詞直接相連的依存關係,取而代之的是新的依存關係n_con.
還有一些詞沒有與方面詞建立依存關係,這是就用n_con替代,遍歷dep_idx,如果dep_idx裡面的值是依存關係的起始位置,並且依存關係的終止位置不是根,不是方面詞也不在dep_idx中,就把加入到dep_idx列表中,並把1加入到dep_dir中,
代表這一新的依存關係是以方面詞為起始位置的,這一關係的名稱為ncon_2,因為這一依存關係與方面詞連線的另一頭是通過與方面詞直接相連的詞找到的,在進行迴圈時,是通過上一輪新增如dep_idx的值找到的,這是依存關係的名稱就是
ncon_3,因為迴圈的次數通過
max_hop控制,迴圈完成之後還是會有沒有與方面詞建立依存關係的詞,這些詞就建立一種特殊的非連結關係,non-connect填充到dep_tag中,用0填充到dep_dir.將這些詞的位置填充到dep_idx中。

將dep_idx中的值進行排序,讓依存關係和句子的詞相對應,dep_tag中第一個位置的依存關係就是第一個詞的依存關係,第二個位置的依存關係就是第二個詞的依存關係。
最終獲取的修建的依賴樹的依存關係如下:








[{'sentence': ['but', 'the', 'staff', 'was', 'so', 'horrible', 'to', 'us', '.'], 'tags': ['CC', 'DT', 'NN', 'VBD', 'RB', 'JJ', 'IN', 'PRP', '.'],
'pos_class': ['CC', 'DT', 'NN', 'VBD', 'RB', 'JJ', 'IN', 'PRP', '.'], 'aspect': ['staff'], 'sentiment': 0,
'predicted_dependencies': ['cc', 'det', 'nsubj', 'cop', 'advmod', 'root', 'prep', 'pobj', 'punct'],
'predicted_heads': [6, 3, 6, 6, 6, 0, 6, 7, 6], 'from': 2, 'to': 3, 'dep_tag': ['ncon_2', 'det', '<pad>', 'ncon_2', 'ncon_2', 'nsubj', 'ncon_2', 'ncon_3', '<pad>'],
'dep_idx': [0, 1, 2, 3, 4, 5, 6, 7, 8], 'dep_dir': [1, 1, 0, 1, 1, 2, 1, 1, 0],
'dependencies': [['cc', 6, 1], ['det', 3, 2], ['nsubj', 6, 3], ['cop', 6, 4], ['advmod', 6, 5], ['root', 0, 6], ['prep', 6, 7], ['pobj', 7, 8], ['punct', 6, 9]]}]

(3)根據被修剪的依賴樹和依存關係構建單詞向量,單詞和依存關係以及單詞詞性的詞表,比按照出現次數從多到少進行排序,並儲存為pkl檔案

word_vecs, word_vocab, dep_tag_vocab, pos_tag_vocab = load_and_cache_vocabs(
        train_all_unrolled+test_all_unrolled, args)
構建資料的詞表,word_vocab形式,itos是詞按照出現次數從多到少進行排序,stoi是itos中的每個詞對應的索引 {'itos': itos, 'stoi': stoi, 'len': len(itos)},將統計的詞表資料序列化,填寫進入
cached_word_vocab_file,最終儲存的檔案的格式時pkl檔案。
獲取詞向量 word_vecs,如果是glove詞向量,看單詞是否在glove詞典中,如果在就獲取詞向量,如果是<pad>就建立一個300維的全為0的張量,不滿足以上兩個條件,就從一個均勻分佈中隨機取樣。如果編碼方式不是glove,word_vocab
和word_vecs都返回空。
dep_tag_vocab和pos_tag_vocab與word_vocab是相同的構造方式
(4)我們建立了詞表,依存關係表和詞性表,計算機進行處理的時候要將它們轉換成數字進行計算。
獲取資料中句子和方面詞的索引,如果是glove或者elmo的編碼方式,就根據之前我們從資料集
中統計的詞表獲取索引,如果是bert編碼,就根據bert自帶的詞表獲取索引,如果是bert型別,就句子和方面詞分開進行訓練,如果是pure_Bert就要將句子和方面詞進行拼接訓練。
Return from getitem:
        sentence_ids
        aspect_ids
        dep_tag_ids
        dep_dir_ids
        pos_class
        text_len
        aspect_len
        sentiment
        deprel
        dephead
        aspect_position
        if bert:
            input_ids
            word_indexer
            input_aspect_ids
            aspect_indexer
        or:
            input_cat_ids
            segment_ids