xbe.at

LLMs and generative AI / Fine tuning and alignment

Response:

11 min read, 18 sections

Contents
  1. Response:
  2. Introduction to Fine-tuning and Prompt Engineering
  3. Understanding Transformer Models
  4. Fine-tuning BERT for Text Classification
  5. Fine-tuning RoBERTa for Named Entity Recognition
  6. Fine-tuning DeBERTa for Question Answering
  7. Fine-tuning GPT-2 for Text Generation
  8. Introduction to Prompt Engineering
  9. Crafting Effective Prompts
  10. Few-shot Learning with Prompt Engineering
  11. Chain-of-Thought Prompting
  12. Comparing Fine-tuning and Prompt Engineering
  13. Real-life Example: Sentiment Analysis
  14. Response:
  15. Real-life Example: Sentiment Analysis
  16. Real-life Example: Text Summarization
  17. Pros and Cons of Fine-tuning vs Prompt Engineering
  18. Additional Resources

undefined

Response:

Introduction to Fine-tuning and Prompt Engineering

Fine-tuning and prompt engineering are two approaches to adapt large language models for specific tasks. Fine-tuning involves retraining the model on task-specific data, while prompt engineering focuses on crafting effective input prompts. This presentation will explore both techniques, their applications, and provide practical examples using Python.

Copyimport torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer

# Fine-tuning example
model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased")
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")

# Prompt engineering example
prompt = "Translate the following English text to French: 'Hello, world!'"
response = model.generate(**tokenizer(prompt, return_tensors="pt"))
print(tokenizer.decode(response[0]))

Understanding Transformer Models

Transformer models, such as BERT and GPT, use self-attention mechanisms to process sequential data. These models have revolutionized natural language processing tasks by capturing long-range dependencies and contextual information effectively.

Copyimport torch
import torch.nn as nn

class TransformerBlock(nn.Module):
    def __init__(self, embed_dim, num_heads):
        super().__init__()
        self.attention = nn.MultiheadAttention(embed_dim, num_heads)
        self.norm1 = nn.LayerNorm(embed_dim)
        self.norm2 = nn.LayerNorm(embed_dim)
        self.feed_forward = nn.Sequential(
            nn.Linear(embed_dim, 4 * embed_dim),
            nn.ReLU(),
            nn.Linear(4 * embed_dim, embed_dim)
        )

    def forward(self, x):
        attention_out, _ = self.attention(x, x, x)
        x = self.norm1(x + attention_out)
        ff_out = self.feed_forward(x)
        return self.norm2(x + ff_out)

# Example usage
embed_dim, num_heads = 256, 8
block = TransformerBlock(embed_dim, num_heads)
x = torch.randn(10, 32, embed_dim)  # (seq_len, batch_size, embed_dim)
output = block(x)
print(output.shape)  # torch.Size([10, 32, 256])

Fine-tuning BERT for Text Classification

Fine-tuning BERT involves retraining the pre-trained model on a specific dataset for a particular task. This process adapts the model's knowledge to the target domain while preserving its general language understanding.

Copyfrom transformers import BertForSequenceClassification, BertTokenizer
from torch.utils.data import DataLoader, TensorDataset
import torch.optim as optim

# Load pre-trained BERT model and tokenizer
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2)
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

# Prepare dataset (example)
texts = ["This movie is great!", "I didn't like the book."]
labels = [1, 0]  # 1 for positive, 0 for negative

# Tokenize and encode the dataset
encoded = tokenizer(texts, padding=True, truncation=True, return_tensors='pt')
dataset = TensorDataset(encoded['input_ids'], encoded['attention_mask'], torch.tensor(labels))
dataloader = DataLoader(dataset, batch_size=2)

# Fine-tuning loop
optimizer = optim.AdamW(model.parameters(), lr=2e-5)

for epoch in range(3):
    for batch in dataloader:
        input_ids, attention_mask, labels = batch
        outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
        loss = outputs.loss
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()

print("Fine-tuning completed")

Fine-tuning RoBERTa for Named Entity Recognition

RoBERTa, an optimized version of BERT, can be fine-tuned for tasks like Named Entity Recognition (NER). This process involves adapting the model to identify and classify named entities in text.

Copyfrom transformers import RobertaForTokenClassification, RobertaTokenizer
import torch

# Load pre-trained RoBERTa model and tokenizer
model = RobertaForTokenClassification.from_pretrained('roberta-base')
tokenizer = RobertaTokenizer.from_pretrained('roberta-base')

# Example text for NER
text = "Apple Inc. was founded by Steve Jobs in Cupertino, California."

# Tokenize the input
inputs = tokenizer(text, return_tensors="pt")

# Get predictions
with torch.no_grad():
    outputs = model(**inputs)

# Process the output
predictions = torch.argmax(outputs.logits, dim=2)
tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0])

# Map predictions to named entities (simplified example)
label_list = ["O", "B-ORG", "I-ORG", "B-PER", "I-PER", "B-LOC", "I-LOC"]
named_entities = [(token, label_list[prediction]) for token, prediction in zip(tokens, predictions[0])]

print(named_entities)

Fine-tuning DeBERTa for Question Answering

DeBERTa, an enhanced version of BERT, can be fine-tuned for complex tasks like question answering. This example demonstrates how to adapt DeBERTa to answer questions based on a given context.

Copyfrom transformers import DebertaForQuestionAnswering, DebertaTokenizer
import torch

# Load pre-trained DeBERTa model and tokenizer
model = DebertaForQuestionAnswering.from_pretrained('microsoft/deberta-base')
tokenizer = DebertaTokenizer.from_pretrained('microsoft/deberta-base')

# Example context and question
context = "The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, France. It is named after the engineer Gustave Eiffel, whose company designed and built the tower."
question = "Who is the Eiffel Tower named after?"

# Tokenize input
inputs = tokenizer(question, context, return_tensors="pt")

# Get model predictions
with torch.no_grad():
    outputs = model(**inputs)

# Process the output to get the answer
answer_start = torch.argmax(outputs.start_logits)
answer_end = torch.argmax(outputs.end_logits) + 1
answer = tokenizer.convert_tokens_to_string(tokenizer.convert_ids_to_tokens(inputs["input_ids"][0][answer_start:answer_end]))

print(f"Question: {question}")
print(f"Answer: {answer}")

Fine-tuning GPT-2 for Text Generation

GPT-2, a powerful language model, can be fine-tuned for specific text generation tasks. This example shows how to adapt GPT-2 to generate text in a particular style or domain.

Copyfrom transformers import GPT2LMHeadModel, GPT2Tokenizer, TextDataset, DataCollatorForLanguageModeling
from transformers import Trainer, TrainingArguments

# Load pre-trained GPT-2 model and tokenizer
model = GPT2LMHeadModel.from_pretrained('gpt2')
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')

# Prepare dataset (example)
train_path = "path/to/your/train.txt"
train_dataset = TextDataset(
    tokenizer=tokenizer,
    file_path=train_path,
    block_size=128)

data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer, mlm=False)

# Set up training arguments
training_args = TrainingArguments(
    output_dir="./gpt2-finetuned",
    overwrite_output_dir=True,
    num_train_epochs=3,
    per_device_train_batch_size=4,
    save_steps=10_000,
    save_total_limit=2,
)

# Create Trainer instance
trainer = Trainer(
    model=model,
    args=training_args,
    data_collator=data_collator,
    train_dataset=train_dataset,
)

# Fine-tune the model
trainer.train()

print("Fine-tuning completed")

Introduction to Prompt Engineering

Prompt engineering involves crafting effective input prompts to guide large language models towards desired outputs. This technique allows users to leverage pre-trained models for various tasks without retraining.

Copyfrom transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch

model = GPT2LMHeadModel.from_pretrained('gpt2')
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')

def generate_text(prompt, max_length=100):
    input_ids = tokenizer.encode(prompt, return_tensors='pt')
    output = model.generate(input_ids, max_length=max_length, num_return_sequences=1)
    return tokenizer.decode(output[0], skip_special_tokens=True)

# Example prompts
prompts = [
    "Translate English to French: 'Hello, how are you?'",
    "Summarize the following text: 'Artificial intelligence has made significant strides in recent years...'",
    "Write a short story about a robot learning to paint."
]

for prompt in prompts:
    print(f"Prompt: {prompt}")
    print(f"Generated text: {generate_text(prompt)}\n")

Crafting Effective Prompts

Effective prompt engineering requires understanding the model's capabilities and limitations. This slide explores techniques for creating prompts that elicit desired responses from language models.

Copyimport openai

openai.api_key = 'your-api-key'  # Replace with your actual API key

def get_completion(prompt, model="gpt-3.5-turbo"):
    messages = [{"role": "user", "content": prompt}]
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        temperature=0,
    )
    return response.choices[0].message["content"]

# Example prompts demonstrating different techniques
prompts = [
    "Explain quantum computing to a 5-year-old.",
    "Write a haiku about artificial intelligence.",
    "List 5 pros and 5 cons of social media use.",
    "Describe the taste of an apple without using the words 'sweet' or 'fruit'.",
]

for prompt in prompts:
    print(f"Prompt: {prompt}")
    print(f"Response: {get_completion(prompt)}\n")

Few-shot Learning with Prompt Engineering

Few-shot learning allows models to perform tasks with minimal examples. This technique is particularly useful when working with large language models that have broad knowledge but need guidance for specific tasks.

Copyfrom transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch

model = GPT2LMHeadModel.from_pretrained('gpt2-large')
tokenizer = GPT2Tokenizer.from_pretrained('gpt2-large')

def few_shot_learning(examples, query):
    prompt = "\n".join(examples) + "\n" + query
    input_ids = tokenizer.encode(prompt, return_tensors='pt')
    attention_mask = torch.ones(input_ids.shape, dtype=torch.long, device=input_ids.device)
    
    output = model.generate(
        input_ids,
        attention_mask=attention_mask,
        max_length=100,
        num_return_sequences=1,
        no_repeat_ngram_size=2,
        do_sample=True,
        top_k=50,
        top_p=0.95,
        temperature=0.7
    )
    
    return tokenizer.decode(output[0], skip_special_tokens=True)

# Example: Sentiment analysis
examples = [
    "Review: This movie was terrible. Sentiment: Negative",
    "Review: I loved the book, it was amazing! Sentiment: Positive",
    "Review: The restaurant was okay, nothing special. Sentiment: Neutral"
]

query = "Review: The concert was mind-blowing, I can't wait to go again! Sentiment:"
result = few_shot_learning(examples, query)
print(result)

Chain-of-Thought Prompting

Chain-of-Thought prompting is a technique that guides language models to break down complex problems into steps, improving performance on tasks requiring reasoning or multi-step processes.

Copyimport openai

openai.api_key = 'your-api-key'  # Replace with your actual API key

def chain_of_thought_prompt(question):
    prompt = f"""
    Question: {question}
    Let's approach this step-by-step:
    1) First, let's identify the key information in the question.
    2) Next, let's determine what calculation or process we need to perform.
    3) Then, we'll carry out the necessary steps.
    4) Finally, we'll state our conclusion.

    Now, let's solve the problem:
    """
    
    response = openai.Completion.create(
        engine="text-davinci-002",
        prompt=prompt,
        max_tokens=200,
        n=1,
        stop=None,
        temperature=0.7,
    )
    
    return response.choices[0].text.strip()

# Example question
question = "If a train travels at 60 mph for 2 hours, then at 30 mph for 1 hour, what is its average speed for the entire journey?"

answer = chain_of_thought_prompt(question)
print(answer)

Comparing Fine-tuning and Prompt Engineering

Fine-tuning and prompt engineering have different strengths and use cases. This slide compares the two approaches, highlighting scenarios where each method might be preferred.

Copyimport matplotlib.pyplot as plt
import numpy as np

# Data for comparison
categories = ['Customization', 'Data Requirements', 'Compute Resources', 'Flexibility', 'Deployment Complexity']
fine_tuning_scores = [9, 8, 7, 6, 5]
prompt_engineering_scores = [6, 3, 2, 9, 8]

x = np.arange(len(categories))
width = 0.35

fig, ax = plt.subplots(figsize=(12, 6))
rects1 = ax.bar(x - width/2, fine_tuning_scores, width, label='Fine-tuning', color='skyblue')
rects2 = ax.bar(x + width/2, prompt_engineering_scores, width, label='Prompt Engineering', color='lightgreen')

ax.set_ylabel('Score')
ax.set_title('Comparison of Fine-tuning vs Prompt Engineering')
ax.set_xticks(x)
ax.set_xticklabels(categories, rotation=45, ha='right')
ax.legend()

ax.bar_label(rects1, padding=3)
ax.bar_label(rects2, padding=3)

fig.tight_layout()

plt.show()

Real-life Example: Sentiment Analysis

This example demonstrates how to use both fine-tuning and prompt engineering for sentiment analysis on product reviews.

Copyfrom transformers import pipeline, AutoModelForSequenceClassification, AutoTokenizer
import torch

# Fine-tuned model approach
fine_tuned_model = AutoModelForSequenceClassification.from_pretrained("distilbert-base-uncased-finetuned-sst-2-english")
fine_tuned_tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased-finetuned-sst-2-english")
fine_tuned_classifier = pipeline("sentiment-analysis", model=fine_tuned_model, tokenizer=fine_tuned_tokenizer)

# Prompt engineering approach
gpt_model = pipeline("text-generation", model="gpt2")

def prompt_engineering_sentiment(

Response:

Real-life Example: Sentiment Analysis

This example demonstrates how to use both fine-tuning and prompt engineering for sentiment analysis on product reviews.

Copyfrom transformers import pipeline, AutoModelForSequenceClassification, AutoTokenizer

# Fine-tuned model approach
fine_tuned_model = AutoModelForSequenceClassification.from_pretrained("distilbert-base-uncased-finetuned-sst-2-english")
fine_tuned_tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased-finetuned-sst-2-english")
fine_tuned_classifier = pipeline("sentiment-analysis", model=fine_tuned_model, tokenizer=fine_tuned_tokenizer)

# Prompt engineering approach
def prompt_engineering_sentiment(review):
    prompt = f"Analyze the sentiment of the following product review: '{review}'. Is it positive or negative?"
    # This is a placeholder for a language model API call
    response = language_model_api_call(prompt)
    return "positive" if "positive" in response.lower() else "negative"

# Example usage
review = "This product exceeded my expectations. It's durable and easy to use."

fine_tuned_result = fine_tuned_classifier(review)[0]
prompt_engineering_result = prompt_engineering_sentiment(review)

print(f"Fine-tuned model result: {fine_tuned_result['label']}")
print(f"Prompt engineering result: {prompt_engineering_result}")

Real-life Example: Text Summarization

This slide showcases the application of fine-tuning and prompt engineering for text summarization, a common task in natural language processing.

Copyfrom transformers import pipeline, AutoModelForSeq2SeqLM, AutoTokenizer

# Fine-tuned model approach
fine_tuned_model = AutoModelForSeq2SeqLM.from_pretrained("t5-small")
fine_tuned_tokenizer = AutoTokenizer.from_pretrained("t5-small")
fine_tuned_summarizer = pipeline("summarization", model=fine_tuned_model, tokenizer=fine_tuned_tokenizer)

# Prompt engineering approach
def prompt_engineering_summarize(text):
    prompt = f"Summarize the following text in one sentence: '{text}'"
    # This is a placeholder for a language model API call
    response = language_model_api_call(prompt)
    return response

# Example usage
long_text = """
Climate change is one of the most pressing issues of our time. It affects weather patterns, 
sea levels, and ecosystems around the world. Scientists argue that human activities, 
particularly the burning of fossil fuels, are the main driver of these changes. 
Addressing this challenge requires global cooperation and significant changes in how we 
produce and consume energy.
"""

fine_tuned_summary = fine_tuned_summarizer(long_text, max_length=50, min_length=10, do_sample=False)[0]['summary_text']
prompt_engineering_summary = prompt_engineering_summarize(long_text)

print(f"Fine-tuned model summary: {fine_tuned_summary}")
print(f"Prompt engineering summary: {prompt_engineering_summary}")

Pros and Cons of Fine-tuning vs Prompt Engineering

This slide provides a comprehensive comparison of the advantages and disadvantages of fine-tuning and prompt engineering approaches.

Copyimport matplotlib.pyplot as plt
import numpy as np

categories = ['Performance', 'Flexibility', 'Resource Usage', 'Deployment', 'Customization']
fine_tuning = [0.8, 0.6, 0.3, 0.5, 0.9]
prompt_engineering = [0.6, 0.9, 0.8, 0.9, 0.7]

x = np.arange(len(categories))
width = 0.35

fig, ax = plt.subplots(figsize=(12, 6))
rects1 = ax.bar(x - width/2, fine_tuning, width, label='Fine-tuning', color='skyblue')
rects2 = ax.bar(x + width/2, prompt_engineering, width, label='Prompt Engineering', color='lightgreen')

ax.set_ylabel('Score')
ax.set_title('Fine-tuning vs Prompt Engineering Comparison')
ax.set_xticks(x)
ax.set_xticklabels(categories)
ax.legend()

ax.set_ylim(0, 1)
ax.set_yticks([0, 0.2, 0.4, 0.6, 0.8, 1])
ax.set_yticklabels(['0%', '20%', '40%', '60%', '80%', '100%'])

fig.tight_layout()
plt.show()

# Print textual explanation
print("Fine-tuning Pros: High performance on specific tasks, deep customization")
print("Fine-tuning Cons: Resource-intensive, less flexible for new tasks")
print("Prompt Engineering Pros: Highly flexible, easy deployment, resource-efficient")
print("Prompt Engineering Cons: May have lower performance on complex tasks")

Additional Resources

For further exploration of fine-tuning and prompt engineering techniques, consider the following resources:

  1. "Prompt Engineering Guide" by OpenAI: https://arxiv.org/abs/2309.01427
  2. "Fine-Tuning Language Models from Human Preferences" by OpenAI: https://arxiv.org/abs/1909.08593
  3. "Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer" (T5 paper): https://arxiv.org/abs/1910.10683
  4. "Language Models are Few-Shot Learners" (GPT-3 paper): https://arxiv.org/abs/2005.14165
  5. "DeBERTa: Decoding-enhanced BERT with Disentangled Attention": https://arxiv.org/abs/2006.03654

These papers provide in-depth insights into the techniques and methodologies discussed in this presentation.

More in Fine tuning and alignment

  1. Recursive Introspection for Large Language Models11 min

    RISE (Recursive IntroSpection) is a technique aimed at improving the performance and capabilities of Large Language Models (LLMs). It involves the model...

  2. Mastering AI with Fine-Tuning Large Language Models12 min

    Fine-tuning is a process of adapting a pre-trained large language model (LLM) to perform specific tasks or to specialize in a particular domain. It involves...

  3. Mastering Advanced LLM Techniques5 min

    Large Language Models (LLMs) have revolutionized natural language processing. This presentation explores advanced techniques that enhance LLM performance and...

  4. LLM Alignment Primer using Python6 min

    LLM Alignment refers to the process of ensuring that large language models behave in ways that are consistent with human values and intentions. This field...

  5. Limitations of LoRA for Pre-training Large Language Models8 min

    Why LoRA Isn't Suitable for Pre-training LLMs

  6. Knowledge Distillation in Large Language Models13 min

    Knowledge distillation is a technique used to transfer knowledge from a large, complex model (teacher) to a smaller, more efficient model (student). This...