【博主使用的python版本:3.6.8】
本次沒有額外的資料下載
ort tensorflow as tf import pandas as pd import time import numpy as np import matplotlib.pyplot as plt from tensorflow.keras.layers import Embedding, MultiHeadAttention, Dense, Input, Dropout, LayerNormalization from transformers import DistilBertTokenizerFast #, TFDistilBertModel from transformers import TFDistilBertForTokenClassification from tqdm import tqdm_notebook as tqdm
在順序到序列任務中,資料的相對順序對其含義非常重要。當你訓練順序神經網路(如RNN)時,你按順序將輸入輸入到網路中。有關資料順序的資訊會自動輸入到模型中。但是,在訓練轉換器網路時,會一次性將資料全部輸入到模型中。雖然這大大減少了訓練時間,但沒有關於資料順序的資訊。這就是位置編碼有用的地方 - 您可以專門編碼輸入的位置,並使用以下正弦和餘弦公式將它們傳遞到網路中:
正弦和餘弦方程的值足夠小(介於 -1 和 1 之間),因此當您將位置編碼新增到單詞嵌入時,單詞嵌入不會明顯失真。位置編碼和單詞嵌入的總和最終是輸入到模型中的內容。結合使用這兩個方程有助於變壓器網路關注輸入資料的相對位置。請注意,雖然在講座中,Andrew 使用垂直向量,但在此作業中,所有向量都是水平的。所有矩陣乘法都應相應調整。
通過計算正弦和餘弦方程的內項,獲取用於計算位置編碼的可能角度:
實現函數 get_angles() 來計算正弦和餘弦位置編碼的可能角度
def get_angles(pos, i, d): """ 獲取位置編碼的角度 Arguments: pos -- 包含位置的列向量[[0], [1], ...,[N-1]] i -- 包含維度跨度的行向量 [[0, 1, 2, ..., M-1]] d(integer) -- 編碼大小 Returns: angles -- (pos, d) 陣列 """ angles = pos/ (np.power(10000, (2 * (i//2)) / np.float32(d))) return angles
我們測試一下:
def get_angles_test(target): position = 4 d_model = 16 pos_m = np.arange(position)[:, np.newaxis] dims = np.arange(d_model)[np.newaxis, :] result = target(pos_m, dims, d_model) assert type(result) == np.ndarray, "你必須返回一系列陣列集合" assert result.shape == (position, d_model), f"防止錯誤我們希望: ({position}, {d_model})" assert np.sum(result[0, :]) == 0 assert np.isclose(np.sum(result[:, 0]), position * (position - 1) / 2) even_cols = result[:, 0::2] odd_cols = result[:, 1::2] assert np.all(even_cols == odd_cols), "奇數列和偶數列的子矩陣必須相等" limit = (position - 1) / np.power(10000,14.0/16.0) assert np.isclose(result[position - 1, d_model -1], limit ), f"組後的值必須是 {limit}" print("\033[92mAll tests passed") get_angles_test(get_angles) # 例如 position = 4 d_model = 8 pos_m = np.arange(position)[:, np.newaxis] dims = np.arange(d_model)[np.newaxis, :] get_angles(pos_m, dims, d_model)