rishigupta04's picture
Update src/inference/predictor.py
8483306 verified
Raw
History Blame Contribute Delete
6.98 kB
import json
import logging
from pathlib import Path
import joblib
import numpy as np
import torch
from transformers import (
AutoTokenizer,
AutoModelForSequenceClassification
)
# =====================================================
# LOGGING
# =====================================================
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
# =====================================================
# PATHS
# =====================================================
ARTIFACT_DIR = Path("src")
MODEL_DIR = ARTIFACT_DIR / "models"
FEATURE_DIR = ARTIFACT_DIR / "features"
#
# MODEL_PATH = (
# HF_MODEL_ID
# )
#
# MODEL_CONFIG_PATH = (
# MODEL_DIR /
# "model_config.json"
# )
#
# TOKENIZER_PATH = (
# FEATURE_DIR /
# "tokenizer"
# )
HF_MODEL_ID = (
"rishigupta04/yt-comments-sentiment-analyzer"
)
tokenizer = AutoTokenizer.from_pretrained(
HF_MODEL_ID
)
model = AutoModelForSequenceClassification.from_pretrained(
HF_MODEL_ID
)
LABEL_ENCODER_PATH = (
FEATURE_DIR /
"label_encoder.pkl"
)
# =====================================================
# DEVICE
# =====================================================
DEVICE = (
"cuda"
if torch.cuda.is_available()
else "cpu"
)
# =====================================================
# PREPROCESSOR
# =====================================================
class TextPreprocessor:
def preprocess(
self,
text
):
if text is None:
return ""
return str(text).strip()
# =====================================================
# PREDICTOR
# =====================================================
class SentimentPredictor:
def __init__(self):
logger.info(
f"Using Device: {DEVICE}"
)
self.device = DEVICE
self.preprocessor = (
TextPreprocessor()
)
logger.info(
"Loading tokenizer..."
)
self.tokenizer = (
AutoTokenizer
.from_pretrained(
HF_MODEL_ID
)
)
logger.info(
"Loading label encoder..."
)
self.label_encoder = (
joblib.load(
LABEL_ENCODER_PATH
)
)
self.config = {
"model_name":
HF_MODEL_ID
}
logger.info(
"Loading model..."
)
self.model = (
AutoModelForSequenceClassification
.from_pretrained(
HF_MODEL_ID
)
)
self.model = (
AutoModelForSequenceClassification
.from_pretrained(
HF_MODEL_ID
)
)
self.model.to(
self.device
)
self.model.eval()
logger.info(
"Model Loaded Successfully"
)
# =================================================
# SINGLE PREDICTION
# =================================================
@torch.no_grad()
def predict(
self,
text
):
text = (
self.preprocessor
.preprocess(text)
)
encoded = self.tokenizer(
text,
truncation=True,
padding=True,
max_length=192,
return_tensors="pt"
)
input_ids = (
encoded["input_ids"]
.to(self.device)
)
attention_mask = (
encoded["attention_mask"]
.to(self.device)
)
outputs = self.model(
input_ids=input_ids,
attention_mask=
attention_mask
)
probs = torch.softmax(
outputs.logits,
dim=1
)
pred_idx = (
torch.argmax(
probs,
dim=1
)
.item()
)
confidence = (
probs.max()
.item()
)
sentiment = (
self.label_encoder
.inverse_transform(
[pred_idx]
)[0]
)
return {
"sentiment":
sentiment,
"confidence":
round(
confidence,
4
)
}
# =================================================
# BATCH PREDICTION
# =================================================
@torch.no_grad()
def predict_batch(
self,
texts,
batch_size=64
):
results = []
for i in range(
0,
len(texts),
batch_size
):
batch = texts[
i:i+batch_size
]
batch = [
self.preprocessor
.preprocess(t)
for t in batch
]
encoded = self.tokenizer(
batch,
truncation=True,
padding=True,
max_length=192,
return_tensors="pt"
)
input_ids = (
encoded["input_ids"]
.to(self.device)
)
attention_mask = (
encoded["attention_mask"]
.to(self.device)
)
outputs = self.model(
input_ids=input_ids,
attention_mask=
attention_mask
)
probs = torch.softmax(
outputs.logits,
dim=1
)
preds = torch.argmax(
probs,
dim=1
)
probs = (
probs.cpu()
.numpy()
)
preds = (
preds.cpu()
.numpy()
)
sentiments = (
self.label_encoder
.inverse_transform(
preds
)
)
for sentiment, prob in zip(
sentiments,
probs
):
results.append({
"sentiment":
sentiment,
"confidence":
float(
np.max(
prob
)
)
})
return results