Views
No views yet
EleutherAI/gpt-neo-1.3B for sentiment classification (Positive, Negative, Neutral) on the tweet_eval/sentiment dataset.bitsandbytes and fine-tunes using QLoRA (PEFT), enabling efficient training and inference even on low-resource hardware.EleutherAI/gpt-neo-1.3Bnf4) via BitsAndBytesConfigpeftpefttweet_eval/sentimentPositive, Negative, Neutral["Positive", "Negative", "Neutral"] using a custom LogitsProcessor:1from transformers import LogitsProcessor
2
3class RestrictVocabLogitsProcessor(LogitsProcessor):
4 def __init__(self, allowed_token_ids):
5 self.allowed_token_ids = allowed_token_ids
6
7 def __call__(self, input_ids, scores):
8 mask = torch.full_like(scores, float("-inf"))
9 mask[:, self.allowed_token_ids] = scores[:, self.allowed_token_ids]
10 return maskpip install torch transformers peft1import torch
2from transformers import AutoTokenizer, AutoModelForCausalLM, LogitsProcessor, LogitsProcessorList
3from peft import PeftModel, PeftConfig
4
5# Load tokenizer
6tokenizer = AutoTokenizer.from_pretrained("EleutherAI/gpt-neo-1.3B")
7tokenizer.pad_token = tokenizer.eos_token # Required for generation
8
9# Load adapter config and base model
10checkpoint = "umangshikarvar/sentiment-qlora-gptneo"
11peft_config = PeftConfig.from_pretrained(checkpoint)
12
13torch_dtype = torch.float16 if torch.cuda.is_available() else torch.float32
14base_model = AutoModelForCausalLM.from_pretrained(
15 peft_config.base_model_name_or_path,
16 torch_dtype=torch_dtype
17)
18
19# Load QLoRA adapter
20model = PeftModel.from_pretrained(base_model, checkpoint)
21device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
22model.eval().to(device)
23
24# Restrict output to sentiment tokens
25class RestrictVocabLogitsProcessor(LogitsProcessor):
26 def __init__(self, allowed_token_ids):
27 self.allowed_token_ids = allowed_token_ids
28
29 def __call__(self, input_ids, scores):
30 mask = torch.full_like(scores, float("-inf"))
31 mask[:, self.allowed_token_ids] = scores[:, self.allowed_token_ids]
32 return mask
33
34sentiment_words = ["Positive", "Negative", "Neutral"]
35allowed_ids = [
36 tokenizer(word, add_special_tokens=False)["input_ids"][0]
37 for word in sentiment_words
38]
39logits_processor = LogitsProcessorList([
40 RestrictVocabLogitsProcessor(allowed_ids)
41])
42
43# Inference function
44def predict_sentiment(tweet: str) -> str:
45 prompt = f"Tweet: {tweet}\nSentiment:"
46 inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
47
48 outputs = model.generate(
49 **inputs,
50 max_new_tokens=1,
51 do_sample=False,
52 logits_processor=logits_processor
53 )
54
55 response = tokenizer.decode(outputs[0], skip_special_tokens=True)
56 prediction = response.replace(prompt, "").strip().split()[0]
57
58 if prediction.lower().startswith("pos"):
59 return "Positive"
60 elif prediction.lower().startswith("neg"):
61 return "Negative"
62 else:
63 return "Neutral"1print(predict_sentiment("I absolutely love this new feature!"))
2# Output: Positive