Stock-Talk / train.py
aayush9's picture
Upload 27 files
16152ad verified
import pandas as pd
import torch
from torch.utils.data import TensorDataset, DataLoader, RandomSampler
from transformers import BertTokenizer, BertForSequenceClassification, AdamW, get_linear_schedule_with_warmup
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error
import os
from datetime import datetime
# Load the CSV file for training
data = pd.read_csv("Database/META_db.csv") # Provide path to your training dataset
# Drop rows with missing or empty sentiment data
data.dropna(subset=['Sentiment Polarity', 'Sentiment Confidence', 'stock_price', 'percentage_change'], inplace=True)
if data.empty:
print("No valid data found in the dataset.")
exit()
# Convert 'Sentiment Polarity' to numerical representation
data['Sentiment Polarity'] = data['Sentiment Polarity'].map({'neutral': 0, 'positive': 1, 'negative': -1})
# Convert 'Publication Date' and 'stock_date' to datetime objects
data['Publication Date'] = pd.to_datetime(data['Publication Date'])
data['stock_date'] = pd.to_datetime(data['stock_date'])
# Use only required columns
data = data[['Publication Date', 'Sentiment Polarity', 'Sentiment Confidence', 'Keywords', 'stock_date', 'stock_price', 'percentage_change']]
# Split the dataset into train and test sets
train_data, eval_data = train_test_split(data, random_state=42, test_size=0.3)
# Prepare inputs and labels
train_features = train_data[['Publication Date', 'Sentiment Polarity', 'Sentiment Confidence', 'Keywords', 'stock_date']]
train_labels = torch.tensor(train_data['percentage_change'].values, dtype=torch.float32)
eval_features = eval_data[['Publication Date', 'Sentiment Polarity', 'Sentiment Confidence', 'Keywords', 'stock_date']]
eval_labels = torch.tensor(eval_data['percentage_change'].values, dtype=torch.float32)
# Create DataLoaders
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
class CustomDataset(torch.utils.data.Dataset):
def __init__(self, features, labels, tokenizer, max_length=512):
self.features = features
self.labels = labels
self.tokenizer = tokenizer
self.max_length = max_length
def __len__(self):
return len(self.features)
def __getitem__(self, idx):
feature = self.features.iloc[idx]
text = f"Publication Date: {feature['Publication Date']}, Sentiment Polarity: {feature['Sentiment Polarity']}, Sentiment Confidence: {feature['Sentiment Confidence']}, Keywords: {feature['Keywords']}, Stock Date: {feature['stock_date']}"
inputs = self.tokenizer.encode_plus(
text,
add_special_tokens=True,
max_length=self.max_length,
padding='max_length',
return_token_type_ids=False,
truncation=True,
return_attention_mask=True,
return_tensors='pt'
)
label = self.labels[idx]
return inputs, label
train_dataset = CustomDataset(train_features, train_labels, tokenizer)
train_dataloader = DataLoader(train_dataset, shuffle=True, batch_size=20)
eval_dataset = CustomDataset(eval_features, eval_labels, tokenizer)
eval_dataloader = DataLoader(eval_dataset, batch_size=20)
# Fine-tune BERT model
model = BertForSequenceClassification.from_pretrained("bert-base-uncased", num_labels=1)
device = torch.device("cuda")
model.to(device)
optimizer = AdamW(model.parameters(), lr=2e-5, eps=1e-8)
epochs = 20
total_steps = len(train_dataloader) * epochs
scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=0, num_training_steps=total_steps)
# Inside the training loop:
for epoch in range(epochs):
model.train()
total_train_loss = 0
for step, (batch_inputs, batch_labels) in enumerate(train_dataloader):
batch_inputs = {key: val.squeeze(1).to(device) for key, val in batch_inputs.items()}
batch_labels = batch_labels.to(device)
optimizer.zero_grad()
outputs = model(**batch_inputs, labels=batch_labels)
loss = outputs.loss
total_train_loss += loss.item()
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
optimizer.step()
scheduler.step()
avg_train_loss = total_train_loss / len(train_dataloader)
print(f"Epoch {epoch+1}/{epochs}")
print(f"Average training loss: {avg_train_loss}")
# Evaluation
model.eval()
total_eval_loss = 0
predictions, true_labels = [], []
for batch_inputs, batch_labels in eval_dataloader:
batch_inputs = {key: val.squeeze(1).to(device) for key, val in batch_inputs.items()}
batch_labels = batch_labels.to(device)
with torch.no_grad():
outputs = model(**batch_inputs, labels=batch_labels)
loss = outputs.loss
logits = outputs.logits
total_eval_loss += loss.item()
predictions.extend(logits.flatten().cpu().detach().numpy())
true_labels.extend(batch_labels.cpu().detach().numpy())
avg_eval_loss = total_eval_loss / len(eval_dataloader)
print(f"Average evaluation loss: {avg_eval_loss}")
# Calculate MAE
mae = mean_absolute_error(true_labels, predictions)
print(f"Mean Absolute Error: {mae}")
# Save the trained model
output_dir = './saved_model_META/'
if not os.path.exists(output_dir):
os.makedirs(output_dir)
model.save_pretrained(output_dir)
print("Model saved successfully.")