日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

BERT-Pytorch demo初探

發布時間:2023/11/28 生活经验 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BERT-Pytorch demo初探 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

https://zhuanlan.zhihu.com/p/50773178

概述

本文基于?pytorch-pretrained-BERT(huggingface)版本的復現,探究如下幾個問題:

  1. pytorch-pretrained-BERT的基本框架和使用
  2. 如何利用BERT將句子轉為詞向量
  3. 如何使用BERT訓練模型(針對SQuAD數據集的問答模型,篇幅問題,可能下篇再寫)

因為已經有很多文章對BERT的結構和效果做了詳盡的介紹,所以對于模型的效果和結構就不在這里贅述了。

基本框架和使用

環境

首先,利用pip安裝包:

1    pip install pytorch-pretrained-bert

這種安裝方法可能會導致一個編碼問題,具體細節可以參考這里。作者已經把這個錯誤改了過來,但是沒有發布新的版本(當前版本為0.1.2),因此需要我們先從github上下載源碼,然后安裝:

1    pip install [--editable] .

結構

Google提供了6種預訓練的模型,具體細節如下:

  • bert-base-uncased: 12-layer, 768-hidden, 12-heads, 110M parameters
  • bert-large-uncased: 24-layer, 1024-hidden, 16-heads, 340M parameters
  • bert-base-cased: 12-layer, 768-hidden, 12-heads , 110M parameters
  • bert-base-multilingual: 102 languages, 12-layer, 768-hidden, 12-heads, 110M parameters
  • bert-base-chinese: Chinese Simplified and Traditional, 12-layer, 768-hidden, 12-heads, 110M parameters

作者對于每個預訓練的模型都提供了6個model類和3個tokenizer類供我們使用。具體的模型簡介和參數可以參照這里README中pytorch model和Tokenizer部分。

1    tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
2    model = BertModel.from_pretrained('bert-base-uncased')

初始化

上面就是對model和tokenizer進行初始化的代碼,“BertTokenizer”和“BertModel”可以替換為自己需要的模型和分詞器,后面函數的參數對應6中預訓練的模型。由于是預訓練的模型,所以肯定是要下模型和詞表的,作者把資源放到了亞馬遜的云上,鏈接寫在了一個環境變量里,如果第一次使用,要提前下載,下載后的文件存放在cache文件夾:~/.pytorch_pretrained_bert/下。

1    PRETRAINED_MODEL_ARCHIVE_MAP = {
2        'bert-base-uncased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased.tar.gz",
3        'bert-large-uncased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased.tar.gz",
4        'bert-base-cased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-cased.tar.gz",
5        'bert-base-multilingual': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual.tar.gz",
6        'bert-base-chinese': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-chinese.tar.gz",
7    }

不知道其他人下載情況如何,反正在我這邊利用requeset去下就很慢,所以肯定是想提前下好,然后放過去的。這是我踩的一個大坑。在Folx上下好模型后,我欣喜的關掉了那個賊慢的python程序(雖然顯示已經下了一半了),一波美滋滋的拷貝之后,發現并沒有卵用,它并沒有識別我下好的文件,又重新開始request了。只能先讓它慢悠悠的下著,看看下下來的東西是啥,然后去讀讀源碼。

后來發現大概的流程是這樣的,它會把文件先下到一個tmp文件夾中,然后復制到cache文件夾下。(但我已經把資源放到里面了啊,并無卵用!)在讀代碼的同時,tokenizer的東西下好了,經過代碼和文件的雙重驗證:它會把鏈接名和一堆爛七八糟的tag加起來做MD5,然后作為文件名,過程很復雜,看不太懂。

經過再一次深入的閱讀,我發現了它大概的流程:它會先判斷?from_pretrained?函數的參數,如果是上文中?PRETRAINED_MODEL_ARCHIVE_MAP?已有的,就會去cache里找;如果不是,就會判斷它是不是一個路徑,會在這個路徑下找需要的文件,一個config文件和一個bin文件,正好和我們下載的文件對應。

 1    """2    Params:3    pretrained_model_name: either:4    - a str with the name of a pre-trained model to load selected in the list of:5    . `bert-base-uncased`6    . `bert-large-uncased`7    . `bert-base-cased`8    . `bert-base-multilingual`9    . `bert-base-chinese`
10    - a path or url to a pretrained model archive containing:
11    . `bert_config.json` a configuration file for the model
12    . `pytorch_model.bin` a PyTorch dump of a BertForPreTraining instance
13    *inputs, **kwargs: additional input for the specific Bert class
14    (ex: num_labels for BertForSequenceClassification)
15    """
16

接下來的操作就簡單了,直接貼代碼:

1    UNCASED='./bert-base-uncased' # your path for model and vocab 
2    VOCAB='bert-base-uncased-vocab.txt'
3    tokenizer=BertTokenizer.from_pretrained(os.path.join(UNCASED,VOCAB))
4    model = BertModel.from_pretrained(UNCASED)

需要注意的是,Tokenizer需要的是詞表,我們看到的model需要的是文件,詞表的鏈接如下:

1    PRETRAINED_VOCAB_ARCHIVE_MAP = {
2        'bert-base-uncased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt",
3        'bert-large-uncased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-vocab.txt",
4        'bert-base-cased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-cased-vocab.txt",
5        'bert-base-multilingual': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-vocab.txt",
6        'bert-base-chinese': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-chinese-vocab.txt",
7    }

利用BERT獲取詞向量

作者其實在README中的?Usage給出了將句子轉為詞向量的demo,但是有點簡略。同時,作者在extract_features.py中提供了詳細的使用方法,接下來的內容就是對這里面的代碼進行解讀了。

因為Usage中的注釋已經很詳細了,所以接下來重點關注兩個點:

  1. 如何批量處理(將文件中的句子轉為詞向量)
  2. 獲得的詞向量結構如何,是模型的哪個部分的輸出

批量處理

1    layer_indexes = [int(x) for x in args.layers.split(",")]
2    tokenizer = BertTokenizer.from_pretrained(args.bert_model)
3    examples = read_examples(args.input_file)
4    features = convert_examples_to_features(
5        examples=examples, seq_length=args.max_seq_length, tokenizer=tokenizer)
6    unique_id_to_feature = {}
7    for feature in features:
8        unique_id_to_feature[feature.unique_id] = feature
9    model = BertModel.from_pretrained(args.bert_model)

其實處理的流程很簡單,就是讀入文件,然后將其轉為需要的格式(InputFeatures類),然后利用模型進行處理。重點在于文件讀取的函數中:

 1    def read_examples(input_file):2        """Read a list of `InputExample`s from an input file."""3        examples = []4        unique_id = 05        with open(input_file, "r") as reader:6            while True:7                line = convert_to_unicode(reader.readline())8                if not line:9                    break
10                line = line.strip()
11                text_a = None
12                text_b = None
13                m = re.match(r"^(.*) \|\|\| (.*)$", line)
14                if m is None:
15                    text_a = line
16                else:
17                    text_a = m.group(1)
18                    text_b = m.group(2)
19                examples.append(
20                    InputExample(unique_id=unique_id, text_a=text_a, text_b=text_b))
21                unique_id += 1
22        return examples

最關鍵的部分就是13行的那個正則表達式,模型中對于文本會分成兩部分,part A 和 part B。在這個函數中,將兩個部分的文本以“ ||| ” 分割(注意前后有空格),所以文件中的每一行應該是“I love you ||| Hello world”這樣。

詞向量結構

 1    all_encoder_layers, _ = model(input_ids, token_type_ids=None, attention_mask=input_mask)2    all_encoder_layers = all_encoder_layers34    for b, example_index in enumerate(example_indices):5        feature = features[example_index.item()]6        unique_id = int(feature.unique_id)7        # feature = unique_id_to_feature[unique_id]8        output_json = collections.OrderedDict()9        output_json["linex_index"] = unique_id
10        all_out_features = []
11        for (i, token) in enumerate(feature.tokens):
12            all_layers = []
13            for (j, layer_index) in enumerate(layer_indexes):
14                layer_output = all_encoder_layers[int(layer_index)].detach().cpu().numpy()
15                layer_output = layer_output[b]
16                layers = collections.OrderedDict()
17                layers["index"] = layer_index
18                layers["values"] = [
19                    round(x.item(), 6) for x in layer_output[i]
20                ]
21                all_layers.append(layers)
22                out_features = collections.OrderedDict()
23                out_features["token"] = token
24                out_features["layers"] = all_layers
25                all_out_features.append(out_features)
26                output_json["features"] = all_out_features
27                writer.write(json.dumps(output_json) + "\n")

19行得到的是一個list,長度為網絡的層數,每個元素是[batch,sequence,embedding]的向量。

對于每個序列,序列中每個向量的token,分別獲取它相應層(由參數arg.layers控制,本文中是最后四層)的編碼。最后對于每個序列中的每個token會獲取到[layer,dimension]大小的向量作為features。

?

總結

以上是生活随笔為你收集整理的BERT-Pytorch demo初探的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。