成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

從零實現大模型-GPT2任務微調 原創

發布于 2024-7-2 11:26
瀏覽
0收藏

??從零實現大模型-BERT預訓練??

??從零實現大模型-BERT微調??

我們在BERT微調那篇文章中提到,許多NLP任務(如情感分析和問答)都依賴于上下文理解能力。而像BERT這種雙向模型具有較強的上下文理解能力,因此非常適合用于任務微調,即針對某個具體任務進行微調。

??從零實現大模型-GPT2預訓練??

??從零實現大模型-GPT2指令微調??

??從零實現大模型-GPT2 RLHF??

而像GPT這種自回歸模型,在預訓練完成后會進行一個指令微調過程,用于跟隨人類指令,然后通過指令去完成不同的任務(翻譯,總結)。

那GPT能否像BERT那樣,直接微調用于完成某個具體任務呢?雖然BERT更適合,但GPT確實也可以。

今天我們就基于之前的GPT2預訓練模型,使用一個垃圾郵件數據集,來微調一個郵件分類模型。

1.垃圾郵件識別

傳統ML方法

當然,也可以通過傳統的機器學習方法實現垃圾郵件分類,例如,貝葉斯分類,或者基于統計學,事先設定一些敏感詞匯,如果郵件中出現了這些敏感詞匯,就認為是垃圾郵件。

Embedding

但傳統機器學習方法依賴人類經驗,既然我們正在寫大模型的文章,就得入鄉隨俗。

我們通過Embedding實現文本分類,具體來說就是計算郵件內容的Embedding,然后計算“spam”和“none spam”的Embedding,最后通過計算余弦相似度來判斷郵件類型。

從零實現大模型-GPT2任務微調-AI.x社區

指令微調模型

其實,還有比計算Embedding更簡單的方法,如果大模型已經經過預訓練、指令微調以及RLHF過程,那么就可以直接利用這種指令跟隨能力來實現垃圾郵件分類。

例如,我們構造下面的prompt輸入給chatGPT。

"Is the following text 'spam'? Answer with 'yes' or 'no':"
    " 'You are a winner you have been specially"
    " selected to receive $1000 cash or a $2000 award.'"

以下是GPT4-o給出的答案,不僅準確識別出了垃圾郵件,還遵循了人類指令輸出了“yes”。

從零實現大模型-GPT2任務微調-AI.x社區

如果只使用預訓練模型,沒有經過指令微調,前面我們也測試過,模型雖然有輸出,但輸出只是簡單的拷貝輸入。

輸入:
Is the following text 'spam'? Answer with 'yes' or 'no': 'You are a winner you have been specially selected to receive $1000 cash or a $2000 award.'
輸出:
The following text 'spam'? Answer with 'yes' or 'no': 'You are a winner

2.任務微調

本文完整代碼如下,建議結合代碼閱讀文本。

https://github.com/AIDajiangtang/LLM-from-scratch/blob/main/GPT2_fine-tune_spam_classifier_from_scratch.ipynb

在通過Embedding實現文本分類時,Embedding是通過調用openAI的API得到的,其實,這個Embedding也可以看作是GPT模型輸出隱狀態的一部分。

除了用Embedding計算余弦相似度來實現文分類外,還可以基于隱狀態實現一個分類模型,也就是在模型的輸出端加一個分類頭。

從零實現大模型-GPT2任務微調-AI.x社區

準備數據

訓練數據來自公開的垃圾郵件數據集,包括文本和標簽兩列,標簽列中spam代表是垃圾郵件。

從零實現大模型-GPT2任務微調-AI.x社區

因為數據集中垃圾郵件數量少于正常郵件,所以要平衡正負樣本數量。

# Examine class distributions
print(df["Label"].value_counts())

Label
ham     4825
spam     747
Name: count, dtype: int64


def create_balanced_dataset(df):
    num_spam = df[df["Label"] == "spam"].shape[0]
    ham_subset = df[df["Label"] == "ham"].sample(num_spam, random_state=123)
    balanced_df = pd.concat([ham_subset, df[df["Label"] == "spam"]])
    return balanced_df


balanced_df = create_balanced_dataset(df)
print(balanced_df["Label"].value_counts())

Label
ham     747
spam    747
Name: count, dtype: int64


接下來劃分訓練集,驗證機和測試集。

接下來是tokenization,padding或者截斷到最大長度。

最后構造Dataloader。

加載預訓練模型

加載gpt2預訓練模型。

CHOOSE_MODEL = "gpt2-small (124M)"
INPUT_PROMPT = "Every effort moves"
BASE_CONFIG = {
    "vocab_size": 50257,     # Vocabulary size
    "context_length": 1024,  # Context length
    "drop_rate": 0.0,        # Dropout rate
    "qkv_bias": True         # Query-key-value bias
}
model_configs = {
    "gpt2-small (124M)": {"emb_dim": 768, "n_layers": 12, "n_heads": 12},
    "gpt2-medium (355M)": {"emb_dim": 1024, "n_layers": 24, "n_heads": 16},
    "gpt2-large (774M)": {"emb_dim": 1280, "n_layers": 36, "n_heads": 20},
    "gpt2-xl (1558M)": {"emb_dim": 1600, "n_layers": 48, "n_heads": 25},
}
BASE_CONFIG.update(model_configs[CHOOSE_MODEL])


assert train_dataset.max_length <= BASE_CONFIG["context_length"], (
    f"Dataset length {train_dataset.max_length} exceeds model's context "
    f"length {BASE_CONFIG['context_length']}. Reinitialize data sets with "
    f"`max_length={BASE_CONFIG['context_length']}`"
)


from gpt_download import download_and_load_gpt2


model_size = CHOOSE_MODEL.split(" ")[-1].lstrip("(").rstrip(")")
settings, params = download_and_load_gpt2(model_size=model_size, models_dir="gpt2")


model = GPTModel(BASE_CONFIG)
load_weights_into_gpt(model, params)
model.eval()

再微調過程中,可以凍結大部分預訓練模型參數。

# Freeze all model layers first
for param in model.parameters():
  param.requires_grad = False

添加分類頭

在預訓練模型的輸出端加一個二分類分類頭。

# Add a classification head
torch.manual_seed(123)
num_classes = 2
model.out_head = torch.nn.Linear(
    in_features=BASE_CONFIG["emb_dim"], # 768
    out_features=num_classes,           # 2 (spam or not spam)
)


構造損失函數

因為是二分類,所以構造一個交叉熵損失函數。

def calculate_loss_batch(input_batch, target_batch, model, device):
  input_batch, target_batch = input_batch.to(device), target_batch.to(device)
  logits = model(input_batch)[:, -1, :] # Grab logits of last output token only!
  loss = torch.nn.functional.cross_entropy(logits, target_batch)
  return loss


然后開始訓練,訓練過程與指令微調過程基本一致。

import time


start_time = time.time()
torch.manual_seed(123)


# Create optimizer
optimizer = torch.optim.AdamW(model.parameters(), lr=5e-5, weight_decay=0.1)


# Set training epochs
num_epochs = 5


# Train the model
train_losses, val_losses, train_accs, val_accs, examples_seen = train_classifier(
    model=model,
    train_loader=train_loader,
    val_loader=val_loader,
    optimizer=optimizer,
    device=device,
    num_epochs=num_epochs,
    eval_freq=50,
    eval_iter=5,
    tokenizer=tokenizer,
)


end_time = time.time()
execution_time_minutes = (end_time - start_time) / 60
print(f"Training completed in {execution_time_minutes:.2f} minutes.")


本文轉載自公眾號人工智能大講堂 

原文鏈接:??https://mp.weixin.qq.com/s/n1h9JeCxV3Kq_yj0-_RS5A??



?著作權歸作者所有,如需轉載,請注明出處,否則將追究法律責任
標簽
收藏
回復
舉報
回復
相關推薦
主站蜘蛛池模板: 在线观看黄色电影 | 插插插干干干 | 国产精品成人一区二区三区夜夜夜 | 综合二区| 99视频在线免费观看 | 欧美一级在线观看 | 91不卡在线 | 亚洲国产精品久久久 | 四虎永久免费地址 | 国产精品视频在线播放 | 免费一区二区 | 国产精品久久久久久久岛一牛影视 | 久久久国产精品 | 天堂成人国产精品一区 | 国产aa | 国产欧美一区二区三区国产幕精品 | 国产视频一二三区 | 一级黄色毛片免费 | 日韩a在线| 欧美日韩亚洲国产综合 | 国产一级久久久久 | 中文字幕日韩在线观看 | 国产久视频 | 性做久久久久久免费观看欧美 | 精品亚洲91| 精品综合久久久 | 日本午夜在线视频 | 亚洲国产精品成人无久久精品 | 黄网站涩免费蜜桃网站 | 亚洲免费久久久 | 午夜视频大全 | 欧美在线激情 | 永久www成人看片 | 日韩一区二区免费视频 | 欧美无乱码久久久免费午夜一区 | 天天操夜夜操 | 午夜国产一级 | 人人干人人干人人 | 羞羞视频在线网站观看 | 中文字幕av免费 | 国产一区二区视频免费在线观看 |