نویسنده(های): احسان
در ابتدا منتشر شد به سمت هوش مصنوعی.
در این مقاله، فرآیند تنظیم دقیق مدلهای زبان برای طبقهبندی متن را بررسی میکنیم. ما این کار را در سه سطح انجام خواهیم داد: اول، با افزودن دستی یک سر طبقه بندی در PyTorch* و آموزش مدل به طوری که بتوانید روند کامل را ببینید. دوم، با استفاده از کتابخانه Transformers* Hugging Face برای ساده کردن فرآیند. و سوم، با استفاده از PyTorch Lightning* و شتاب دهنده ها برای بهینه سازی عملکرد تمرین. در پایان این راهنما، درک کاملی از جریان کار تنظیم دقیق خواهید داشت.
مقدمه
ایده پشت استفاده از تنظیم دقیق در پردازش زبان طبیعی (NLP) از Computer Vision (CV) قرض گرفته شد. مدل های CV ابتدا بر روی آموزش داده شدند بزرگ مجموعه داده ها مانند ImageNet تا ویژگی های اولیه تصاویر مانند لبه ها یا رنگ ها را به آنها آموزش دهد. اینها از پیش آموزش دیده مدل های آن زمان بود به خوبی تنظیم شده است در یک کار پایین دستی مانند طبقه بندی پرندگان با نسبتاً کوچک تعداد نمونه های برچسب گذاری شده
مدلهای تنظیمشده معمولاً به دقت بالاتری نسبت به مدلهای تحت نظارت که از ابتدا روی همان مقدار داده برچسبگذاری شده آموزش داده شدهاند، دست مییابند.
علیرغم محبوبیت و موفقیت یادگیری انتقالی در CV، برای سالها مشخص نبود که فرآیند پیشآموزشی مشابه برای NLP چیست. در نتیجه، برنامههای NLP برای دستیابی به عملکرد بالا به مقادیر زیادی از دادههای برچسبدار نیاز داشتند.
تنظیم دقیق چه تفاوتی با پیش تمرین دارد؟
با پیش آموزش، مدل های زبان کسب الف عمومی درک زبان ها در طول این فرآیند، آنها الگوهای زبان را یاد می گیرند اما معمولاً قادر به پیروی از دستورالعمل ها یا پاسخ به سؤالات نیستند. در مورد مدلهای GPT، این یادگیری تحت نظارت خود شامل پیشبینی کلمه بعدی (یک جهته) بر اساس دادههای آموزشی آنها است که اغلب صفحات وب هستند. در مورد برت (بازنمودهای رمزگذار دوطرفه از ترانسفورماتورها)، یادگیری شامل پیش بینی کلمات به طور تصادفی پوشانده شده (دو جهته) و پیش بینی ترتیب جمله است. اما چگونه می توانیم مدل های زبان را برای داده های خود یا وظایف خود تطبیق دهیم؟
تنظیم دقیق به آموزش یک مدل از پیش آموزش دیده ادامه می دهد تا عملکرد آن را افزایش دهد خاص وظایف به عنوان مثال، از طریق “تنظیم دقیق دستورالعمل” می توانید به یک مدل آموزش دهید که بیشتر شبیه یک چت بات رفتار کند. این فرآیند برای تخصصی کردن یک مدل با هدف عمومی مانند OpenAI* GPT-4 در برنامهای مانند ChatGPT* یا GitHub* Copilot است. با تنظیم دقیق مدل زبان خود، می توانید قابلیت اطمینان، عملکرد و حریم خصوصی مدل خود را افزایش دهید و در عین حال هزینه های استنتاج مرتبط را در مقایسه با خدمات مبتنی بر اشتراک کاهش دهید، به خصوص اگر حجم زیادی از داده یا درخواست های مکرر دارید.
تنظیم دقیق یک مدل زبان برای طبقه بندی متن
پیش پردازش و آماده سازی DataLoader
اگر با پیش پردازش داده ها راحت هستید، از این بخش صرفنظر کنید. در کل فرض میکنیم که دادههای برچسبگذاریشده خود را در فایلهای Train، اعتبارسنجی و آزمایشی csv هر کدام با یک متن و یک ستون برچسب ذخیره کردهایم. برای آموزش، برچسب ها باید عددی باشند، بنابراین اگر اینطور نیست، شما
می توانید از فرهنگ لغت label_to_id مانند {"negative": 0, "positive": 1}
و یک نقشه برداری برای به دست آوردن فرمت مورد نظر انجام دهید.
برای مشخص بودن، از BERT به عنوان مدل پایه استفاده می کنیم و تعداد برچسب های طبقه بندی را روی 4 قرار می دهیم. DistilBERT که اندازه مدل BERT را تا 40 درصد کاهش می دهد، استنتاج سرعت را تا 60 درصد کاهش می دهد در حالی که 97 درصد از قابلیت های درک زبان BERT را حفظ می کند.
نگاهی سریع به BERT
BERT در سال 2018 توسط گوگل معرفی شد و از آن زمان انقلابی در زمینه NLP ایجاد کرده است. برخلاف مدلهای سنتی که متن را به روشی یکجهت پردازش میکنند، BERT برای درک متن یک کلمه در یک جمله با نگاه کردن به اطراف چپ و راست آن طراحی شده است. این رویکرد دو طرفه به BERT اجازه می دهد تا تفاوت های ظریف زبان را به طور موثرتری دریافت کند.
ویژگی های کلیدی BERT
- پیش آموزش: BERT بر روی مجموعه عظیمی از متن از قبل آموزش داده شده است،
از جمله کل ویکی پدیا و BookCorpus. پیش تمرین
شامل دو کار است: مدل سازی زبان ماسک شده (MLM) و بعدی
پیش بینی جمله (NSP). - معماری: BERT_BASE دارای 12 لایه (بلوک های ترانسفورماتور)، 768 است
واحدهای پنهان و 12 سر توجه، در مجموع 110 میلیون
پارامترها
شما می توانید این آموزش را اجرا کنید Intel® Tiber™ AI Cloud، با استفاده از یک نمونه پردازنده Intel® Xeon®. این پلتفرم منابع محاسباتی فراوانی را برای اجرای روان کد ما فراهم می کند.
import osimport torch
from torch.utils.data import DataLoader, Dataset
from transformers import AutoTokenizer
import pandas as pd
# Parameters
model_ckpt = "bert-base-uncased"
num_labels = 4
batch_size = 16
num_workers = 6
# Load the tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_ckpt)
# Custom Dataset class
class TextDataset(Dataset):
def __init__(self, dataframe, tokenizer, max_length=512):
self.data = dataframe
self.tokenizer = tokenizer
self.max_length = max_length
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
row = self.data.iloc[idx]
text = row["text"] # Replace "text" with your actual column name for text
label = row["label"] # Replace "label" with your actual column name for labels
# Tokenize the input text
encoding = self.tokenizer(
text,
max_length=self.max_length,
padding="max_length",
truncation=True,
return_tensors="pt",
)
return {
"input_ids": encoding["input_ids"].squeeze(0), # Remove batch dimension with squeeze
"attention_mask": encoding["attention_mask"].squeeze(0),
"label": torch.tensor(label, dtype=torch.long),
}
os.environ["TOKENIZERS_PARALLELISM"] = "false"
# Load csv files
train_df = pd.read_csv("train.csv")
val_df = pd.read_csv("val.csv")
test_df = pd.read_csv("test.csv")
# Create Dataset objects
train_dataset = TextDataset(train_df, tokenizer)
val_dataset = TextDataset(val_df, tokenizer)
test_dataset = TextDataset(test_df, tokenizer)
# Create DataLoaders
train_loader = DataLoader(
train_dataset, batch_size=batch_size, shuffle=True, num_workers=num_workers
)
val_loader = DataLoader(val_dataset, batch_size=batch_size, num_workers=num_workers)
test_loader = DataLoader(test_dataset, batch_size=batch_size, num_workers=num_workers)
نشانه طبقه بندی [CLS]
این [CLS]
نشانه معمولاً در ابتدای توالی ورودی در مدلهای مبتنی بر ترانسفورماتور مانند BERT و انواع آن اضافه میشود. در طول تنظیم دقیق، مدل یاد می گیرد که اطلاعات معناداری را به آن اختصاص دهد [CLS]
نشانه، که زمینه توالی ورودی را جمع می کند. این آخرین حالت پنهان مربوط به [CLS]
سپس توکن به عنوان نمایشی از کل ورودی استفاده می شود، که می تواند از طریق یک لایه طبقه بندی کننده برای کارهای پایین دستی مانند تحلیل احساسات، دسته بندی موضوع یا هر وظیفه ای که نیاز به تصمیم گیری بر اساس کل توالی دارد. این مکانیسم به مدل اجازه می دهد تا بر درک کلی متن و ویژگی های خاص کار برای پیش بینی های دقیق تمرکز کند.
بر خلاف مدلهای سنتی که ممکن است به تعبیههای استاتیک متکی باشند (مانند word2vec)، ترانسفورماتورها تولید میکنند تعبیه های متنی، به طوری که معنای یک توکن به توکن های اطراف آن بستگی دارد. این [CLS]
نشانه، با عبور از لایه ها، به طور فزاینده ای از معنای کل دنباله آگاه می شود، که آن را به یک نمایش خلاصه خوب برای وظایف پایین دستی تبدیل می کند. برای برخی از وظایف، به ویژه آنهایی که نیاز به درک دقیق تری دارند، ممکن است استراتژی های دیگری به کار گرفته شود. به عنوان مثال، برای طبقه بندی اسناد، که در آن هر کلمه به طور مساوی کمک می کند، برخی از مدل ها استفاده می کنند به معنای جمع کردن بیش از همه جاسازی های نشانه
سطح 1: PyTorch
در این قسمت به صورت دستی یک هد طبقه بندی را به مدل پایه اضافه می کنیم و تنظیمات دقیق را انجام می دهیم. ما با استفاده از AutoModel
کلاسی که توکن ها (یا بهتر بگوییم رمزگذاری نشانه ها) را به جاسازی تبدیل می کند و سپس آنها را از طریق پشته رمزگذار تغذیه می کند تا حالت های پنهان. در حالی که AutoModel
برای درک ایده پشت کاری که انجام می دهیم مفید است، برای تنظیم دقیق طبقه بندی متن، بهتر است با آن کار کنیدAutoModelForSequenceClassification
در عوض، همانطور که در زیر بحث می کنیم.
import torch
from torch import nn
from transformers import AutoModel# Load the base model with AutoModel and add a classifier
class CustomModel(nn.Module):
def __init__(self, model_ckpt, num_labels):
super(CustomModel, self).__init__()
self.model = AutoModel.from_pretrained(model_ckpt) # Base transformer model
self.classifier = nn.Linear(
self.model.config.hidden_size, num_labels
) # Classification head. The 1st parameter equals 768 for BERT as discussed above
def forward(self, input_ids, attention_mask):
# Forward pass through the transformer model
outputs = self.model(input_ids=input_ids, attention_mask=attention_mask)
# Use the [CLS] token (0-th token in the sequence) for classification
cls_output = outputs.last_hidden_state[
:, 0, :
] # Shape: (batch_size, hidden_size)
# Pass through the classifier head
logits = self.classifier(cls_output)
return logits
# Initialize the model
model = CustomModel(model_ckpt, num_labels)
# Loss function and optimizer
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=5e-5)
# Training function
def train(model, optimizer, train_loader, loss_fn):
model.train()
total_loss = 0
for batch in train_loader:
optimizer.zero_grad()
# Unpack the batch data
input_ids = batch["input_ids"]
attention_mask = batch["attention_mask"]
label = batch["label"]
# Forward pass
output = model(input_ids, attention_mask)
# Compute loss
loss = loss_fn(output, label)
loss.backward()
# Update the model parameters
optimizer.step()
total_loss += loss.item()
print(f"Train loss: {total_loss / len(train_loader):.2f}")
import torch
def evaluate(model, test_loader, loss_fn):
model.eval() # Set model to evaluation mode
total_loss = 0
total_acc = 0
total_samples = 0
with torch.no_grad(): # No gradient computation needed during evaluation
for batch in test_loader:
input_ids = batch["input_ids"]
attention_mask = batch["attention_mask"]
labels = batch["label"]
# Forward pass
output = model(input_ids, attention_mask)
# Compute loss
loss = loss_fn(output, labels)
total_loss += loss.item()
# Compute accuracy
predictions = torch.argmax(output, dim=1)
total_acc += torch.sum(predictions == labels).item()
total_samples += labels.size(0)
# Calculate average loss and accuracy
avg_loss = total_loss / len(test_loader)
avg_acc = total_acc / total_samples * 100
print(f"Test loss: {avg_loss:.2f}, Test acc: {avg_acc:.2f}%")
در نهایت، میتوانیم مدل را آموزش، ارزیابی و ذخیره کنیم.
num_epochs = 3for epoch in range(num_epochs):
train(model, optimizer, train_loader, loss_fn)
evaluate(model, test_loader, loss_fn)
torch.save(model.state_dict(), "./fine-tuned-model.pt")
سطح 2: ترانسفورماتورهای صورت در آغوش گرفتن
در حال حاضر، ما از راحتی استفاده می کنیم AutoModelForSequenceClassification
کلاسی که سر طبقه بندی را به صورت خودکار به مدل پایه اضافه می کند. این را با کاری که ما با آن انجام دادیم مقایسه کنید AutoModel
کلاس در بخش قبل!
همچنین توجه داشته باشید که کلاس Trainer از Hugging Face’s Transformers
کتابخانه به طور مستقیم می تواند رسیدگی کند Dataset
اشیاء بدون نیاز به الفDataLoader
، زیرا به طور خودکار دسته بندی و جابجایی را انجام می دهد
شما
from transformers import AutoModelForSequenceClassification, Trainer, TrainingArgumentsmodel = AutoModelForSequenceClassification.from_pretrained(
model_ckpt, num_labels=num_labels
)
training_args = TrainingArguments(
output_dir="./results",
num_train_epochs=3,
warmup_steps=500,
weight_decay=0.01,
logging_dir="./logs",
logging_steps=10, # Log every 10 steps
evaluation_strategy="steps",
save_steps=500, # Save model checkpoint every 500 steps
load_best_model_at_end=True, # Load the best model at the end of training
metric_for_best_model="accuracy",
)
# Train the model
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=test_dataset,
)
trainer.train()
trainer.evaluate(test_dataset)
سطح 3: PyTorch Lightning
رعد و برق به تعبیر آن است مستندات، ” یادگیری عمیق چارچوبی با «باتریهای گنجانده شده» برای محققان حرفهای هوش مصنوعی و یادگیری ماشینی مهندسانی که نیاز به حداکثر انعطاف پذیری دارند در حالی که عملکرد فوق العاده شارژ در مقیاس دارند.
همانطور که خواهیم دید، با کمی کد سازمانی اضافی، لایتنینگ Trainer
موارد زیر را خودکار می کند:
- تکرار دوره ای و دسته ای
optimizer.step()
،loss.backward()
،optimizer.zero_grad()
تماس می گیرد- فراخوانی از
model.eval()
، فعال و غیرفعال کردن درجه ها در طول
ارزیابی - ذخیره و بارگذاری ایست بازرسی
- ورود به سیستم
- شتاب دهنده، چندپردازنده گرافیکی، و TPU پشتیبانی (شماره
.to(device)
تماس لازم است.) - آموزش با دقت ترکیبی
میتوانید با پردازندههای Intel Gaudi، تمرینهای بیشتری را تسریع کنید، که به شما امکان میدهد کارهای بیشتری انجام دهید یادگیری عمیق آموزش با هزینه کمتر می توانید یک نمونه Intel Gaudi را به صورت رایگان امتحان کنید Intel® Tiber™ AI Cloud.
import torchmetrics
import lightning as L
from lightning.pytorch.callbacks import ModelCheckpoint
from lightning.pytorch.loggers import TensorBoardLogger
from transformers import AutoModelForSequenceClassification# A LightningModule is a torch.nn.Module with added functionality.
# It wraps around a regular PyTorch model.
class LightningModel(L.LightningModule):
def __init__(self, model, learning_rate=5e-5):
super().__init__()
self.learning_rate = learning_rate
self.model = model
self.val_acc = torchmetrics.Accuracy(task="multiclass", num_classes=num_labels)
self.test_acc = torchmetrics.Accuracy(task="multiclass", num_classes=num_labels)
def forward(self, input_ids, attention_mask, labels):
return self.model(input_ids, attention_mask=attention_mask, labels=labels)
def _shared_step(self, batch, batch_idx):
outputs = self(
batch["input_ids"],
attention_mask=batch["attention_mask"],
labels=batch["label"],
)
return outputs
def training_step(self, batch, batch_idx):
outputs = self._shared_step(batch, batch_idx)
self.log("train_loss", outputs["loss"])
return outputs["loss"]
def validation_step(self, batch, batch_idx):
outputs = self._shared_step(batch, batch_idx)
self.log("val_loss", outputs["loss"], prog_bar=True)
logits = outputs["logits"]
self.val_acc(logits, batch["label"])
self.log("val_acc", self.val_acc, prog_bar=True)
def test_step(self, batch, batch_idx):
outputs = self._shared_step(batch, batch_idx)
logits = outputs["logits"]
self.test_acc(logits, batch["label"])
self.log("accuracy", self.test_acc, prog_bar=True)
def configure_optimizers(self):
optimizer = torch.optim.Adam(self.parameters(), lr=self.learning_rate)
return optimizer
model = AutoModelForSequenceClassification.from_pretrained(
model_ckpt, num_labels=num_labels
)
lightning_model = LightningModel(model)
callbacks = [
ModelCheckpoint(save_top_k=1, mode="max", monitor="val_acc") # Save top 1 model
]
logger = TensorBoardLogger(save_dir="./logs", name="fine-tuned-model")
trainer = L.Trainer(
max_epochs=3,
callbacks=callbacks,
accelerator="hpu",
precision="bf16-mixed", # By default, HPU training uses 32-bit precision. To enable mixed precision, set the precision flag.
devices="auto",
logger=logger,
log_every_n_steps=10,
)
trainer.fit(lightning_model, train_dataloaders=train_loader, val_dataloaders=val_loader)
trainer.test(lightning_model, train_loader, ckpt_path="best")
trainer.test(lightning_model, val_loader, ckpt_path="best")
trainer.test(lightning_model, test_loader, ckpt_path="best")
در حالی که کلاس Transformers Trainer از آموزش توزیع شده پشتیبانی میکند، اما در مورد ویژگیهای پیشرفته مانند تماسهای سفارشی، ورود به سیستم، و مقیاسبندی بدون درز در چندین GPU یا گره، سطح یکپارچگی و انعطافپذیری مشابه Lightning را ارائه نمیدهد.
مشاوره عملی
اکنون که با فرآیند تنظیم دقیق آشنا شدید، ممکن است
تعجب می کنم که چگونه می توانید آن را برای کار خاص خود اعمال کنید. در اینجا تعدادی است
توصیه عملی:
- داده های واقعی را برای کار خود جمع آوری کنید یا داده های مصنوعی تولید کنید. برای مثال ببینید تولید داده های مصنوعی با مدل های زبان: راهنمای عملی.
- یک مدل نسبتا کوچک را دقیق تنظیم کنید.
- مدل زبان خود را در مجموعه آزمون خود ارزیابی کنید، و اگر برای کار شما در دسترس است، روی یک معیار ارزیابی کنید.
- اندازه مجموعه داده آموزشی، اندازه مدل پایه و در صورت لزوم پیچیدگی کار را افزایش دهید.
به خاطر داشته باشید که تنظیم دقیق استاندارد یا متعارف زبان
مدل هایی که در این نوشته توضیح داده شده است می توانند گران باشند. به جای
با بهروزرسانی تمام وزنها و سوگیریها، فقط آخرین مورد را میتوانیم بهروزرسانی کنیم
لایه به صورت زیر
# Freeze all layers
for param in model.parameters():
param.requires_grad = False# Unfreeze last layer
for param in model.pre_classifier.parameters():
param.requires_grad = True
for param in model.classifier.parameters():
param.requires_grad = True
در مقالههای آینده، در مورد تکنیکهای تنظیم دقیقتر کارآمدتر بحث خواهیم کرد، پس با ما همراه باشید!
برای اطلاعات بیشتر در مورد نحوه توسعه هوش مصنوعی، به سایت مراجعه کنید توسعه هوش مصنوعی Intel®
منابع.
قدردانی ها
نویسنده از جک اریکسون برای ارائه بازخورد دقیق در مورد پیش نویس قبلی این اثر تشکر می کند.
مطالعه پیشنهادی
*اسامی و برندهای دیگر ممکن است به عنوان دارایی دیگران ادعا شود.
منتشر شده از طریق به سمت هوش مصنوعی