| import torch
|
| import torch.nn as nn
|
| from torch.utils.data import DataLoader
|
| from transformers import BertTokenizer
|
| import torch.optim as optim
|
| from sklearn.metrics import accuracy_score
|
| from tqdm import tqdm
|
|
|
| from data.imdb_data import IMDBDataset
|
| from model.sentiment_model import SentimentAnalysisModel
|
|
|
|
|
| def evaluate(model, dataloader, device):
|
| model.eval()
|
| preds, labels = [], []
|
|
|
| with torch.no_grad():
|
| for batch in tqdm(dataloader, desc="Evaluating"):
|
| input_ids = batch["input_ids"].to(device)
|
| attention_mask = batch["attention_mask"].to(device)
|
| batch_labels = batch["labels"].to(device)
|
|
|
| outputs = model(input_ids, attention_mask)
|
| predictions = torch.argmax(outputs, dim=1)
|
|
|
| preds.extend(predictions.cpu().tolist())
|
| labels.extend(batch_labels.cpu().tolist())
|
|
|
| acc = accuracy_score(labels, preds)
|
| print(f"Validation Accuracy: {acc:.4f}")
|
| return acc
|
|
|
|
|
| def train():
|
|
|
| model_name = "bert-base-uncased"
|
| batch_size = 8
|
| max_length = 256
|
| lr = 2e-5
|
| epochs = 3
|
|
|
|
|
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| print("Using device:", device)
|
|
|
| tokenizer = BertTokenizer.from_pretrained(model_name)
|
|
|
| train_dataset = IMDBDataset("train", tokenizer, max_length)
|
| test_dataset = IMDBDataset("test", tokenizer, max_length)
|
|
|
| train_loader = DataLoader(
|
| train_dataset,
|
| batch_size=batch_size,
|
| shuffle=True,
|
| num_workers=4,
|
| pin_memory=True
|
| )
|
|
|
| test_loader = DataLoader(
|
| test_dataset,
|
| batch_size=batch_size,
|
| shuffle=False,
|
| num_workers=4,
|
| pin_memory=True
|
| )
|
|
|
| model = SentimentAnalysisModel(model_name).to(device)
|
| print("Model device:", next(model.parameters()).device)
|
|
|
| optimizer = optim.AdamW(model.parameters(), lr=lr)
|
| criterion = nn.CrossEntropyLoss()
|
|
|
|
|
| for epoch in range(epochs):
|
| model.train()
|
| total_loss = 0
|
|
|
| loop = tqdm(train_loader, desc=f"Epoch {epoch + 1}/{epochs}")
|
| for step, batch in enumerate(loop):
|
| input_ids = batch["input_ids"].to(device)
|
| attention_mask = batch["attention_mask"].to(device)
|
| labels = batch["labels"].to(device)
|
|
|
| optimizer.zero_grad()
|
| outputs = model(input_ids, attention_mask)
|
| loss = criterion(outputs, labels)
|
|
|
| loss.backward()
|
| optimizer.step()
|
|
|
| total_loss += loss.item()
|
| loop.set_postfix(loss=loss.item())
|
|
|
| avg_loss = total_loss / len(train_loader)
|
| print(f"\nEpoch {epoch + 1} Training Loss: {avg_loss:.4f}")
|
|
|
| evaluate(model, test_loader, device)
|
|
|
|
|
| torch.save(model.state_dict(), "bert_imdb_sentiment.pth")
|
| print("Model saved.")
|
|
|
|
|
| if __name__ == "__main__":
|
| train()
|
|
|