遷移學(xué)習(xí)-Question

1. 講下BERT。

  • 雙向二階段預(yù)訓(xùn)練模型-word-piece狰域。


  • Special Token:[CLS]媳拴、[SEP]
  • BERT_Base(12 layers)兆览、BERT_Large(24 layers)屈溉。
  • Pre-training:Task #1: Masked LMTask #2: Next Sentence Prediction
  • Special Token:start and end tokens (<s>, <e>)抬探、delimiter token ($)子巾。

  • Fine-tuning:Two Sentence ClassificationSingle Sentence Classification小压、Question Answering线梗、Single Sentence Tagging

2. 能否實現(xiàn)下Word Piece?忘記步驟了怠益,換成實現(xiàn)一下從若干文件中生成一個詞典缠导,即word2idx和idx2word。BPE算法溉痢。

WordPiece算法可以看作是BPE的變種僻造。不同點在于,WordPiece基于概率生成新的subword而不是下一最高頻字節(jié)對孩饼。

算法:

  1. 準(zhǔn)備足夠大的訓(xùn)練語料
  2. 確定期望的subword詞表大小
  3. 將單詞拆分成字符序列
  4. 基于第3步數(shù)據(jù)訓(xùn)練語言模型
  5. 從所有可能的subword單元中選擇加入語言模型后能最大程度地增加訓(xùn)練數(shù)據(jù)概率的單元作為新的單元
  6. 重復(fù)第5步直到達到第2步設(shè)定的subword詞表大小或概率增量低于某一閾值
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:
          input = "unaffable"
          output = ["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

Byte Pair Encoding:

def bpe(self, token):
        if token in self.cache:
            return self.cache[token]
        word = tuple(token)
        pairs = get_pairs(word)

        if not pairs:
            return token

        while True:
            bigram = min(pairs, key=lambda pair: self.bpe_ranks.get(pair, float("inf")))
            if bigram not in self.bpe_ranks:
                break
            first, second = bigram
            new_word = []
            i = 0
            while i < len(word):
                try:
                    j = word.index(first, i)
                except ValueError:
                    new_word.extend(word[i:])
                    break
                else:
                    new_word.extend(word[i:j])
                    i = j

                if word[i] == first and i < len(word) - 1 and word[i + 1] == second:
                    new_word.append(first + second)
                    i += 2
                else:
                    new_word.append(word[i])
                    i += 1
            new_word = tuple(new_word)
            word = new_word
            if len(word) == 1:
                break
            else:
                pairs = get_pairs(word)
        word = " ".join(word)
        self.cache[token] = word
        return word

    def _tokenize(self, text):
        """ Tokenize a string. """
        bpe_tokens = []
        for token in re.findall(self.pat, text):
            token = "".join(
                self.byte_encoder[b] for b in token.encode("utf-8")
            )  # Maps all our bytes to unicode strings, avoiding controle tokens of the BPE (spaces in our case)
            bpe_tokens.extend(bpe_token for bpe_token in self.bpe(token).split(" "))
        return bpe_tokens
# '想要有直升機\n想要和你飛到宇宙去\n想要和你融化在一起\n融化在宇宙里\n我每天每天每'

# 這個數(shù)據(jù)集有6萬多個字符髓削。為了打印方便,我們把換行符替換成空格镀娶,然后僅使用前1萬個字符來訓(xùn)練模型立膛。
corpus_chars = corpus_chars.replace('\n', ' ').replace('\r', ' ')
corpus_chars = corpus_chars[0:10000]

idx_to_char = list(set(corpus_chars))
char_to_idx = dict([(char, i) for i, char in enumerate(idx_to_char)])
vocab_size = len(char_to_idx)
vocab_size # 1027

3. 講下bert,講著講著面試官打斷了我梯码,說你幫我估算下一層bert大概有多少參數(shù)量宝泵。

講下BERT:如問題1。

# BertEmbeddings:
self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id) 
self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size)
self.token_type_embeddings = nn.Embedding(config.type_vocab_size, config.hidden_size)

# BertAttention(BertSelfAttention+ BertSelfOutput):
#### BertSelfAttention
self.query = nn.Linear(config.hidden_size, self.all_head_size)
self.key = nn.Linear(config.hidden_size, self.all_head_size)
self.value = nn.Linear(config.hidden_size, self.all_head_size)
self.dropout = nn.Dropout(config.attention_probs_dropout_prob)
#### BertSelfOutput
self.dense = nn.Linear(config.hidden_size, config.hidden_size)
self.LayerNorm = BertLayerNorm(config.hidden_size, eps=config.layer_norm_eps)
self.dropout = nn.Dropout(config.hidden_dropout_prob)

# BertIntermediate
self.dense = nn.Linear(config.hidden_size, config.intermediate_size)

# BertOutput
self.dense = nn.Linear(config.intermediate_size, config.hidden_size)
self.LayerNorm = BertLayerNorm(config.hidden_size, eps=config.layer_norm_eps)
self.dropout = nn.Dropout(config.hidden_dropout_prob)

# BertPooler
self.dense = nn.Linear(config.hidden_size, config.hidden_size)

4. bert里add&norm是什么以及作用轩娶。

  • add:Residual connection(殘差連接)儿奶,主要是為了避免模型較深時,在進行反向傳播時鳄抒,梯度消失等問題闯捎。
  • norm:Layer Normalization(層歸一化)椰弊,為了解決網(wǎng)絡(luò)中數(shù)據(jù)分布變化大,學(xué)習(xí)過程慢的問題瓤鼻。

5. 了不了解bert的擴展模型秉版,roberta,SpanBERT茬祷,XLM清焕,albert;介紹幾個除了bert之外的模型祭犯。

roberta:


SpanBERT:

XLM:

albert:





transformer-xl(extra-long)

Transformer

Transformer-XL (extra-long)

State Reuse for Segment-Level Recurrence

Incoherent Positional Encoding

Relative Positional Encoding

Segment-Level Recurrence in Inference

Contributions

xlnet:

Permutation Language Model

Permutation Language Model

Formulation Reparameterizing

Two-Stream Self-Attention

Two-Stream Self-Attention

Contributions

6. bert源碼里mask部分在哪個模塊耐朴;bert如何mask。

Multi-Head Attention:(BertSelfAttention)

class BertSelfAttention(nn.Module):
    def __init__(self, config):
        super().__init__()
        if config.hidden_size % config.num_attention_heads != 0 and not hasattr(config, "embedding_size"):
            raise ValueError(
                "The hidden size (%d) is not a multiple of the number of attention "
                "heads (%d)" % (config.hidden_size, config.num_attention_heads)
            )

        self.num_attention_heads = config.num_attention_heads
        self.attention_head_size = int(config.hidden_size / config.num_attention_heads)
        self.all_head_size = self.num_attention_heads * self.attention_head_size

        self.query = nn.Linear(config.hidden_size, self.all_head_size)
        self.key = nn.Linear(config.hidden_size, self.all_head_size)
        self.value = nn.Linear(config.hidden_size, self.all_head_size)

        self.dropout = nn.Dropout(config.attention_probs_dropout_prob)

    def transpose_for_scores(self, x):
        new_x_shape = x.size()[:-1] + (self.num_attention_heads, self.attention_head_size)
        x = x.view(*new_x_shape)
        return x.permute(0, 2, 1, 3)

    def forward(
        self,
        hidden_states,
        attention_mask=None,
        head_mask=None,
        encoder_hidden_states=None,
        encoder_attention_mask=None,
        output_attentions=False,
    ):
        mixed_query_layer = self.query(hidden_states)

        # If this is instantiated as a cross-attention module, the keys
        # and values come from an encoder; the attention mask needs to be
        # such that the encoder's padding tokens are not attended to.
        if encoder_hidden_states is not None:
            mixed_key_layer = self.key(encoder_hidden_states)
            mixed_value_layer = self.value(encoder_hidden_states)
            attention_mask = encoder_attention_mask
        else:
            mixed_key_layer = self.key(hidden_states)
            mixed_value_layer = self.value(hidden_states)

        query_layer = self.transpose_for_scores(mixed_query_layer)
        key_layer = self.transpose_for_scores(mixed_key_layer)
        value_layer = self.transpose_for_scores(mixed_value_layer)

        # Take the dot product between "query" and "key" to get the raw attention scores.
        attention_scores = torch.matmul(query_layer, key_layer.transpose(-1, -2))
        attention_scores = attention_scores / math.sqrt(self.attention_head_size)
        if attention_mask is not None:
            # Apply the attention mask is (precomputed for all layers in BertModel forward() function)
            attention_scores = attention_scores + attention_mask

        # Normalize the attention scores to probabilities.
        attention_probs = nn.Softmax(dim=-1)(attention_scores)

        # This is actually dropping out entire tokens to attend to, which might
        # seem a bit unusual, but is taken from the original Transformer paper.
        attention_probs = self.dropout(attention_probs)

        # Mask heads if we want to
        if head_mask is not None:
            attention_probs = attention_probs * head_mask

        context_layer = torch.matmul(attention_probs, value_layer)

        context_layer = context_layer.permute(0, 2, 1, 3).contiguous()
        new_context_layer_shape = context_layer.size()[:-2] + (self.all_head_size,)
        context_layer = context_layer.view(*new_context_layer_shape)

        outputs = (context_layer, attention_probs) if output_attentions else (context_layer,)
        return outputs

7. 估計一下bert的參數(shù)量盹憎。

估算下bert的參數(shù)量:如問題3。

  • BERT_{BASE}: L=12, H=768, A=12, Total Parameters=110M铐刘。
  • BERT_{LARGE}: L=24, H=1024, A=16, Total Parameters=340M陪每。

8. roberta和bert在預(yù)訓(xùn)練時的不同。

RoBERTa
  • Static vs. Dynamic Masking
  • Model Input Format and Next Sentence Prediction

9. 介紹下roberta镰吵,為什么選用wwm檩禾。

同上:
Whole Word Masking (wwm),暫翻譯為全詞Mask或整詞Mask疤祭,是谷歌在2019年5月31日發(fā)布的一項BERT的升級版本盼产,主要更改了原預(yù)訓(xùn)練階段的訓(xùn)練樣本生成策略。 簡單來說勺馆,原有基于WordPiece的分詞方式會把一個完整的詞切分成若干個子詞戏售,在生成訓(xùn)練樣本時,這些被分開的子詞會隨機被mask草穆。 在全詞Mask中灌灾,如果一個完整的詞的部分WordPiece子詞被mask,則同屬該詞的其他部分也會被mask悲柱,即全詞Mask锋喜。

需要注意的是,這里的mask指的是廣義的mask(替換成[MASK]豌鸡;保持原詞匯嘿般;隨機替換成另外一個詞),并非只局限于單詞替換成[MASK]標(biāo)簽的情況涯冠。 更詳細的說明及樣例請參考:#4

同理炉奴,由于谷歌官方發(fā)布的BERT-base, Chinese中,中文是以為粒度進行切分蛇更,沒有考慮到傳統(tǒng)NLP中的中文分詞(CWS)盆佣。 我們將全詞Mask的方法應(yīng)用在了中文中往堡,使用了中文維基百科(包括簡體和繁體)進行訓(xùn)練,并且使用了哈工大LTP作為分詞工具共耍,即對組成同一個的漢字全部進行Mask虑灰。

下述文本展示了全詞Mask的生成樣例。 注意:為了方便理解痹兜,下述例子中只考慮替換成[MASK]標(biāo)簽的情況穆咐。

10. BERT、GPT字旭、ELMO之間的區(qū)別(模型結(jié)構(gòu)对湃、訓(xùn)練方式)。

  • BERT-雙向兩階段預(yù)訓(xùn)練模型:Pre-training(MLM遗淳、NSP)+Fine-Tuning(...)
  • GPT-單向兩階段預(yù)訓(xùn)練模型:Pre-training(LM)+Fine-Tuning(...)
  • ELMO-兩個方向預(yù)訓(xùn)練模型:Pre-training(兩個單向LM)+supervised NLP tasks(使用LSTM各層表征)

11. BERT為什么只用Transformer的Encoder而不用Decoder拍柒。

BERT在Pre-training過程中使用的Masked Language Model(AE),聯(lián)合上下文信息預(yù)測被[MASK]掉的標(biāo)記屈暗。而Decoder采用的一種單向的語言模型(LM)拆讯。所以BERT使用Encoder,而不是用Decoder养叛。

12. xlnet和bert有啥不同种呐。自回歸&&自編碼的知識,其中解釋了xlnet排列語言模型以及雙流attention弃甥。

bert:自回歸爽室;xlnet:自回歸&&自編碼。


Auto-Regressive (AR)

Auto-Encoding (AE)

Auto-Encoding (AE)

Permutation Language Model

Permutation Language Model

Two-Stream Self-Attention

Two-Stream Self-Attention

13. albert了解嗎淆攻?embedding層矩陣分解+參數(shù)共享+SOP+工程細節(jié)阔墩。

ALBERT: A Lite BERT

ALBERT: A Lite BERT

ALBERT: A Lite BERT

GLUE Results

Concluding Remarks
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瓶珊,隨后出現(xiàn)的幾起案子戈擒,更是在濱河造成了極大的恐慌,老刑警劉巖艰毒,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件筐高,死亡現(xiàn)場離奇詭異,居然都是意外死亡丑瞧,警方通過查閱死者的電腦和手機柑土,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绊汹,“玉大人稽屏,你說我怎么就攤上這事∥鞴裕” “怎么了狐榔?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵坛增,是天一觀的道長。 經(jīng)常有香客問我薄腻,道長收捣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任庵楷,我火速辦了婚禮罢艾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尽纽。我一直安慰自己咐蚯,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布弄贿。 她就那樣靜靜地躺著春锋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪差凹。 梳的紋絲不亂的頭發(fā)上期奔,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音直奋,去河邊找鬼。 笑死施禾,一個胖子當(dāng)著我的面吹牛脚线,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弥搞,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼邮绿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了攀例?” 一聲冷哼從身側(cè)響起船逮,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎粤铭,沒想到半個月后挖胃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡梆惯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年酱鸭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垛吗。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡凹髓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怯屉,到底是詐尸還是另有隱情蔚舀,我是刑警寧澤饵沧,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站赌躺,受9級特大地震影響狼牺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寿谴,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一锁右、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧讶泰,春花似錦咏瑟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至狼犯,卻和暖如春余寥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背悯森。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工宋舷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓢姻。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓祝蝠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親幻碱。 傳聞我的和親對象是個殘疾皇子绎狭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

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