BertConfig, BertForQuestionAnswering, BertTokenizer


1.BertConfig

類 BertConfigBertForQuestionAnswering

BERT 模型的配置類,BERT 的超參配置都在這里。其參數(藍色)和方法(黃色)總覽如下:

參數
vocab_size:詞匯表大小。
hidden_size=768:encoder 層和 pooler 層大小。這實際上就是 embedding_size,BERT 干的事情就是不停地優化 embedding。。。
num_hidden_layers=12:encoder 中隱層個數。
num_attention_heads=12:每個 attention 層的 head 個數。
intermediate_size=3072:中間層大小。
hidden_act="gelu":隱層激活函數。
hidden_dropout_prob=0.1:所有全連接層的 dropout 概率,包括 embedding 和 pooler。
attention_probs_dropout_prob=0.1:attention 層的 dropout 概率。
max_position_embeddings=512:最大序列長度。
type_vocab_size=16:token_type_ids 的詞匯表大小。
initializer_range=0.02:初始化所有權重時的標准差。
方法
from_dict(cls, json_object):從一個字典來構建配置。
from_json_file(cls, json_file):從一個 json 文件來構建配置。
to_dict(self):將配置保存為字典。
to_json_string(self):將配置保存為 json 字符串。

原文鏈接:https://blog.csdn.net/u010099080/article/details/106915111

2.BertForQuestionAnswering

Pytorch下載好transformers后,點擊進入源代碼:

def requires_backends(obj, backends): if not isinstance(backends, (list, tuple)): backends = [backends] name = obj.__name__ if hasattr(obj, "__name__") else obj.__class__.__name__
    if not all(BACKENDS_MAPPING[backend][0]() for backend in backends): raise ImportError("".join([BACKENDS_MAPPING[backend][1].format(name) for backend in backends]))

3.BertTokenizer

  BERT 源碼中 tokenization.py 就是預處理進行分詞的程序,主要有兩個分詞器:BasicTokenizer 和 WordpieceTokenizer,另外一個 FullTokenizer 是這兩個的結合:先進行 BasicTokenizer 得到一個分得比較粗的 token 列表,然后再對每個 token 進行一次 WordpieceTokenizer,得到最終的分詞結果。

BasicTokenizer
  BasicTokenizer(以下簡稱 BT)是一個初步的分詞器。對於一個待分詞字符串,流程大致就是轉成 unicode -> 去除各種奇怪字符 -> 處理中文 -> 空格分詞 -> 去除多余字符和標點分詞 -> 再次空格分詞,結束。

WordpieceTokenizer
  按照從左到右的順序,將一個詞拆分成多個子詞,每個子詞盡可能長。 greedy longest-match-first algorithm,貪婪最長優先匹配算法。

例如:比如"loved",“loving”,"loves"這三個單詞。其實本身的語義都是“愛”的意思,但是如果我們以單詞為單位,那它們就算不一樣的詞,在英語中不同后綴的詞非常的多,就會使得詞表變的很大,訓練速度變慢,訓練的效果也不是太好。

BPE算法通過訓練,能夠把上面的3個單詞拆分成"lov",“ed”,“ing”,"es"幾部分,這樣可以把詞的本身的意思和時態分開,有效的減少了詞表的數量。

以下摘自源代碼:

class WordpieceTokenizer(object): """Runs WordPiece tokenization."""

    def __init__(self, vocab, unk_token, max_input_chars_per_word=100): self.vocab = vocab self.unk_token = unk_token self.max_input_chars_per_word = max_input_chars_per_word def tokenize(self, text): """ Tokenizes a piece of text into its word pieces. This uses a greedy longest-match-first algorithm to perform tokenization using the given vocabulary. For example, :obj:`input = "unaffable"` wil return as output :obj:`["un", "##aff", "##able"]`. Args: text: A single token or whitespace separated tokens. This should have already been passed through `BasicTokenizer`. Returns: A list of wordpiece tokens. """ output_tokens = [] for token in whitespace_tokenize(text): chars = list(token) if len(chars) > self.max_input_chars_per_word: output_tokens.append(self.unk_token) continue is_bad = False start = 0 sub_tokens = [] while start < len(chars): end = len(chars) cur_substr = None while start < end: substr = "".join(chars[start:end]) if start > 0: substr = "##" + substr if substr in self.vocab: cur_substr = substr break end -= 1
                if cur_substr is None: is_bad = True break sub_tokens.append(cur_substr) start = end if is_bad: output_tokens.append(self.unk_token) else: output_tokens.extend(sub_tokens) return output_tokens

再來看BertTokenizer類下的method。

    def _tokenize(self, text): split_tokens = [] if self.do_basic_tokenize: for token in self.basic_tokenizer.tokenize(text, never_split=self.all_special_tokens): # If the token is part of the never_split set
                if token in self.basic_tokenizer.never_split: split_tokens.append(token) else: split_tokens += self.wordpiece_tokenizer.tokenize(token) else: split_tokens = self.wordpiece_tokenizer.tokenize(text) return split_tokens

部分摘自:
https://blog.csdn.net/u010099080/article/details/102587954


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM