hi, gpt
Hello! How can I help you today? If you have any questions or topics you'd like to discuss, feel free to ask.
I have to work on an English news article category classification AI project. From now on, I will explain the project I have to do
Great! I'd be happy to help you with your English news article category classification AI project. Please go ahead and explain the project in detail, including the objectives, any specific requirements, and the data you have available. This will help me provide you with the best guidance and suggestions.
The data is divided into three files. 1. Training data : train.csv 2. Test data : test.csv 3. Submission file : sample_submission.csv The train.csv file consists of 3 columns of id, text, and label and the test.csv file consists of 2 columns of id and text. The sample_submission.csv file consists of id and label columns. Label consists of a total of 8, and the text column consists of news article data.
It seems like you're working on a supervised text classification project where you have a dataset of news articles with their respective categories. Here's an outline of the steps you can follow to approach this project:
Data exploration and preprocessing: Start by loading the train.csv and test.csv files using a library like pandas. Analyze the distribution of categories in the train.csv file, and perform necessary text preprocessing steps like tokenization, lowercasing, and removing stop words and special characters. You can use libraries like NLTK or spaCy for text preprocessing.
Feature extraction: Convert the text data into a numerical representation that can be used as input for a machine learning model. Common methods include Bag of Words, Term Frequency-Inverse Document Frequency (TF-IDF), and word embeddings like Word2Vec or GloVe.
Model selection: Choose a machine learning model suitable for text classification. Popular choices include Logistic Regression, Multinomial Naive Bayes, Support Vector Machines, and more advanced models like Random Forests, Gradient Boosting Machines, and deep learning models such as Convolutional Neural Networks (CNN) and Recurrent Neural Networks (RNN).
Model training and validation: Split the train.csv data into training and validation sets, and train your chosen model on the training data. You can use libraries like scikit-learn or TensorFlow/Keras for this step. Monitor the model's performance on the validation set to ensure it's not overfitting and to fine-tune hyperparameters.
Model evaluation: Once your model is trained, evaluate its performance on the test.csv data. Calculate relevant metrics like accuracy, precision, recall, and F1-score to assess the performance of your model.
Submission: Generate predictions on the test.csv data using your trained model, and create a submission file in the format of sample_submission.csv. Make sure the submission file contains the id and label columns, where the label column consists of the predicted categories for each news article in the test.csv data.
Model improvement: If needed, iterate on the model by trying different feature extraction methods, models, or hyperparameters to improve performance.
Remember that using deep learning models like CNNs or RNNs might require GPU resources for efficient training. Additionally, you can explore pre-trained models like BERT, which have shown great results in text classification tasks. For BERT, you can use the Hugging Face Transformers library to fine-tune the model on your dataset.
Based on the above, Write python code to train and infer a model to classify labels using the pretrained roberta large model When writing code, Split the data into a training set and a validation set using train_test_split() or some other method. and in the training process, measure the macro-f1 socre for each epoch using the validation dataset, and saves the model when the f1 socre is maximal. and set the number of epochs to 10 and set the batch_size to 8 and use tqdm in the for loop so that I can see the progress. and enter the weight for each class in the weight factor of Cross Entropy loss.
To use the pre-trained RoBERTa-large model for your classification task, you'll need the Hugging Face Transformers library. First, ensure it is installed by running:
bashCopy codepip install transformers
Then, you can use the following Python code to train and infer a model using the RoBERTa-large model:
pythonCopy codeimport pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score
from transformers import RobertaTokenizer, RobertaForSequenceClassification, AdamW, get_linear_schedule_with_warmup
import torch
from torch.utils.data import DataLoader, Dataset
from tqdm.auto import tqdm
class NewsDataset(Dataset):
def __init__(self, data, tokenizer, max_length):
self.data = data
self.tokenizer = tokenizer
self.max_length = max_length
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
text = self.data.iloc[idx]["text"]
label = self.data.iloc[idx]["label"]
encoding = self.tokenizer.encode_plus(
text,
add_special_tokens=True,
max_length=self.max_length,
padding="max_length",
truncation=True,
return_attention_mask=True,
return_tensors="pt",
)
return {
"input_ids": encoding["input_ids"].flatten(),
"attention_mask": encoding["attention_mask"].flatten(),
"label": torch.tensor(label, dtype=torch.long),
}
def train_epoch(model, data_loader, optimizer, scheduler, device):
model = model.train()
losses = []
for batch in tqdm(data_loader):
input_ids = batch["input_ids"].to(device)
attention_mask = batch["attention_mask"].to(device)
labels = batch["label"].to(device)
model.zero_grad()
outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
loss = outputs.loss
losses.append(loss.item())
loss.backward()
optimizer.step()
scheduler.step()
return np.mean(losses)
def evaluate(model, data_loader, device):
model = model.eval()
labels_all = []
predictions_all = []
with torch.no_grad():
for batch in tqdm(data_loader):
input_ids = batch["input_ids"].to(device)
attention_mask = batch["attention_mask"].to(device)
labels = batch["label"].to(device)
outputs = model(input_ids, attention_mask=attention_mask)
logits = outputs.logits
_, preds = torch.max(logits, dim=1)
labels_all.extend(labels.cpu().numpy())
predictions_all.extend(preds.cpu().numpy())
f1_macro = f1_score(labels_all, predictions_all, average='macro')
return f1_macro
device = "cuda" if torch.cuda.is_available() else "cpu"
tokenizer = RobertaTokenizer.from_pretrained("roberta-large")
model = RobertaForSequenceClassification.from_pretrained("roberta-large", num_labels=8).to(device)
optimizer = AdamW(model.parameters(), lr=2e-5)
num_epochs = 10
batch_size = 8
train_data = pd.read_csv("train.csv")
train_data, val_data = train_test_split(train_data, test_size=0.1, stratify=train_data["label"], random_state=42)
train_dataset = NewsDataset(train_data, tokenizer, max_length=512)
val_dataset = NewsDataset(val_data, tokenizer, max_length=512)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)
total_steps = len(train_loader) *
keep talking
Sure, let's continue with the code from where we left off:
pythonCopy codetotal_steps = len(train_loader) * num_epochs
scheduler = get_linear_schedule_with_warmup(
optimizer,
num_warmup_steps=0,
num_training_steps=total_steps,
)
# Set class weights for the CrossEntropyLoss
class_weights = torch.tensor([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], dtype=torch.float32).to(device)
loss_function = torch.nn.CrossEntropyLoss(weight=class_weights)
best_f1_macro = 0
for epoch in range(num_epochs):
print(f"Epoch {epoch + 1}/{num_epochs}")
print("-" * 10)
train_loss = train_epoch(model, train_loader, optimizer, scheduler, device)
print(f"Train loss: {train_loss}")
val_f1_macro = evaluate(model, val_loader, device)
print(f"Validation F1 Macro: {val_f1_macro}")
if val_f1_macro > best_f1_macro:
print("F1 Macro score improved. Saving the model.")
best_f1_macro = val_f1_macro
torch.save(model.state_dict(), "best_roberta_large_model.bin")
print("Training completed.")
In this code snippet, we continue with the training process. First, we set up the scheduler for the learning rate with a linear warmup. Then, we set the class weights for the CrossEntropyLoss function. You can adjust these weights based on the distribution of the labels in your dataset.
After that, we start the training loop. For each epoch, we train the model using the train_epoch
function and evaluate the model using the evaluate
function. If the macro F1 score on the validation dataset improves, we save the model.
Finally, after training for 10 epochs, the training process is completed. You can then use the saved model for inference on the test dataset.
can you write inference code?
Certainly! Here's the code for inference on the test dataset using the trained RoBERTa-large model:
pythonCopy codedef predict(model, data_loader, device):
model = model.eval()
predictions = []
with torch.no_grad():
for batch in tqdm(data_loader):
input_ids = batch["input_ids"].to(device)
attention_mask = batch["attention_mask"].to(device)
outputs = model(input_ids, attention_mask=attention_mask)
logits = outputs.logits
_, preds = torch.max(logits, dim=1)
predictions.extend(preds.cpu().numpy())
return predictions
# Load the best model
model.load_state_dict(torch.load("best_roberta_large_model.bin"))
# Load and preprocess the test dataset
test_data = pd.read_csv("test.csv")
test_dataset = NewsDataset(test_data, tokenizer, max_length=512)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
# Make predictions on the test dataset
predictions = predict(model, test_loader, device)
# Create submission DataFrame and save it as a CSV file
submission = pd.DataFrame({"id": test_data["id"], "label": predictions})
submission.to_csv("sample_submission.csv", index=False)
print("Inference completed. The sample_submission.csv file has been generated.")
In this code snippet, we first load the best model saved during the training phase. We then load and preprocess the test dataset using the NewsDataset
class and create a DataLoader for it.
Next, we use the predict
function to make predictions on the test dataset. After obtaining the predictions, we create a submission DataFrame with the required format and save it as a CSV file.
With the generated "sample_submission.csv" file, you can now submit your results for evaluation.
Newdataset class doesn't fit test_data. Create a new class for test_data.
You're right, the NewsDataset
class expects a label to be present in the dataset. We can create a new class specifically for the test data that does not require labels. Here's the updated code snippet:
pythonCopy codeclass TestNewsDataset(Dataset):
def __init__(self, data, tokenizer, max_length):
self.data = data
self.tokenizer = tokenizer
self.max_length = max_length
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
text = self.data.iloc[idx]["text"]
encoding = self.tokenizer.encode_plus(
text,
add_special_tokens=True,
max_length=self.max_length,
padding="max_length",
truncation=True,
return_attention_mask=True,
return_tensors="pt",
)
return {
"input_ids": encoding["input_ids"].flatten(),
"attention_mask": encoding["attention_mask"].flatten(),
}
# Load and preprocess the test dataset
test_data = pd.read_csv("test.csv")
test_dataset = TestNewsDataset(test_data, tokenizer, max_length=512)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
The TestNewsDataset
class is almost identical to the NewsDataset
class, but it does not include the label in the returned dictionary. Now, you can use this class for the test data without any issues.
How about using focalloss instead of crossentropyloss in this code?
You can use the Focal Loss instead of CrossEntropyLoss for your classification task. Focal Loss is designed to address the class imbalance problem by down-weighting the loss contribution from easy examples and focusing on the hard examples. You'll need to implement the Focal Loss function in PyTorch:
pythonCopy codeimport torch.nn.functional as F
class FocalLoss(torch.nn.Module):
def __init__(self, alpha=1, gamma=2, reduction="mean"):
super(FocalLoss, self).__init__()
self.alpha = alpha
self.gamma = gamma
self.reduction = reduction
def forward(self, inputs, targets):
BCE_loss = F.cross_entropy(inputs, targets, reduction="none")
pt = torch.exp(-BCE_loss)
F_loss = self.alpha * (1 - pt) ** self.gamma * BCE_loss
if self.reduction == "mean":
return torch.mean(F_loss)
elif self.reduction == "sum":
return torch.sum(F_loss)
else:
return F_loss
Now, you can replace the CrossEntropyLoss with the FocalLoss in the training loop:
pythonCopy code# Instantiate the FocalLoss
loss_function = FocalLoss(alpha=1.0, gamma=2.0, reduction="mean").to(device)
def train_epoch(model, data_loader, optimizer, scheduler, device, loss_function):
model = model.train()
losses = []
for batch in tqdm(data_loader):
input_ids = batch["input_ids"].to(device)
attention_mask = batch["attention_mask"].to(device)
labels = batch["label"].to(device)
model.zero_grad()
outputs = model(input_ids, attention_mask=attention_mask)
logits = outputs.logits
loss = loss_function(logits, labels)
losses.append(loss.item())
loss.backward()
optimizer.step()
scheduler.step()
return np.mean(losses)
In this code snippet, we've created the FocalLoss
class and instantiated it. Then, we modified the train_epoch
function to use the Focal Loss instead of CrossEntropyLoss. The rest of the code remains the same.
Feel free to adjust the alpha
and gamma
parameters in the FocalLoss to optimize its performance for your specific task.
Could you modify evaluate function to match the changes?
Certainly! Here's the modified evaluate
function that incorporates the FocalLoss:
pythonCopy codedef evaluate(model, data_loader, device, loss_function):
model = model.eval()
labels_all = []
predictions_all = []
losses = []
with torch.no_grad():
for batch in tqdm(data_loader):
input_ids = batch["input_ids"].to(device)
attention_mask = batch["attention_mask"].to(device)
labels = batch["label"].to(device)
outputs = model(input_ids, attention_mask=attention_mask)
logits = outputs.logits
loss = loss_function(logits, labels)
losses.append(loss.item())
_, preds = torch.max(logits, dim=1)
labels_all.extend(labels.cpu().numpy())
predictions_all.extend(preds.cpu().numpy())
loss_mean = np.mean(losses)
f1_macro = f1_score(labels_all, predictions_all, average='macro')
return loss_mean, f1_macro
In this modified version of the evaluate
function, we've added the loss_function
as an argument. We also compute the loss for each batch in the validation data and calculate the mean loss for the entire validation dataset.
Now, the evaluate
function returns both the mean validation loss and the macro F1 score. You can use this information during the training process to monitor the model's performance:
pythonCopy codefor epoch in range(num_epochs):
print(f"Epoch {epoch + 1}/{num_epochs}")
print("-" * 10)
train_loss = train_epoch(model, train_loader, optimizer, scheduler, device, loss_function)
print(f"Train loss: {train_loss}")
val_loss, val_f1_macro = evaluate(model, val_loader, device, loss_function)
print(f"Validation Loss: {val_loss}")
print(f"Validation F1 Macro: {val_f1_macro}")
if val_f1_macro > best_f1_macro:
print("F1 Macro score improved. Saving the model.")
best_f1_macro = val_f1_macro
torch.save(model.state_dict(), "best_roberta_large_model.bin")
This will give you an overview of how the FocalLoss affects the model's performance on the validation dataset during training.
train_data has a data imbalance problem. can you do data augmentation using EDA(Easy Data Augmentation) or some other method?
To address the data imbalance problem, you can perform data augmentation using Easy Data Augmentation (EDA). EDA includes four simple techniques:
- Synonym replacement
- Random insertion
- Random swap
- Random deletion
First, you need to install the nltk
library for synonym replacement:
bashCopy codepip install nltk
Here's a Python implementation of EDA:
pythonCopy codeimport random
import nltk
from nltk.corpus import wordnet as wn
nltk.download('wordnet')
nltk.download('averaged_perceptron_tagger')
def synonym_replacement(words, n):
new_words = words.copy()
random_word_list = list(set([word for word in words if word]))
random.shuffle(random_word_list)
num_replaced = 0
for random_word in random_word_list:
synonyms = get_synonyms(random_word)
if len(synonyms) >= 1:
synonym = random.choice(list(synonyms))
new_words = [synonym if word == random_word else word for word in new_words]
num_replaced += 1
if num_replaced >= n:
break
return new_words
def get_synonyms(word):
synonyms = set()
for syn in wn.synsets(word):
for lemma in syn.lemmas():
synonym = lemma.name().replace("_", " ").replace("-", " ").lower()
synonym = "".join([char for char in synonym if char in ' qwertyuiopasdfghjklzxcvbnm'])
synonyms.add(synonym)
if word in synonyms:
synonyms.remove(word)
return list(synonyms)
def random_insertion(words, n):
new_words = words.copy()
for _ in range(n):
add_word(new_words)
return new_words
def add_word(new_words):
synonyms = []
counter = 0
while len(synonyms) < 1:
random_word = new_words[random.randint(0, len(new_words) - 1)]
synonyms = get_synonyms(random_word)
counter += 1
if counter >= 10:
return
random_synonym = synonyms[0]
random_idx = random.randint(0, len(new_words) - 1)
new_words.insert(random_idx, random_synonym)
def random_deletion(words, p):
if len(words) == 1:
return words
remaining = list(filter(lambda x: random.uniform(0, 1) > p, words))
if len(remaining) == 0:
return [random.choice(words)]
else:
return remaining
def random_swap(words):
new_words = words.copy()
for _ in range(int(len(words))):
idx1, idx2 = random.sample(range(0, len(words)), 2)
new_words[idx1], new_words[idx2] = new_words[idx2], new_words[idx1]
return new_words
def eda(sentence, alpha_sr=0.1, alpha_ri=0.1, alpha_rs=0.1, p_rd=0.1, num_aug=9):
words = nltk.word_tokenize(sentence)
num_words = len(words)
num_sr = max(1, int(alpha_sr * num_words))
num_ri = max(1, int(alpha_ri * num_words))
num_rs = max(1, int(alpha_rs * num_words))
augmented_sentences = []
for _ in range(num_aug):
a_words = words.copy()
a_words = synonym_replacement(a_words, num_sr)
a_words = random_insertion(a_words,
keep talking
Sure, let's continue with the EDA implementation:
pythonCopy code a_words = random_insertion(a_words, num_ri)
a_words = random_swap(a_words, num_rs)
a_words = random_deletion(a_words, p_rd)
augmented_sentences.append(' '.join(a_words))
return augmented_sentences
def augment_data(df, num_aug=9):
augmented_data = []
for _, row in df.iterrows():
original_text = row["text"]
label = row["label"]
augmented_texts = eda(original_text, num_aug=num_aug)
for aug_text in augmented_texts:
augmented_data.append({"text": aug_text, "label": label})
return pd.DataFrame(augmented_data)
In this code snippet, we continue with the EDA implementation by completing the eda
function and defining a new function called augment_data
. The eda
function generates augmented sentences for a given input sentence. The augment_data
function takes a DataFrame as input and generates a new DataFrame with augmented text data.
Now you can use the augment_data
function to augment your training dataset:
pythonCopy codetrain_data = pd.read_csv("train.csv")
# Augment the training data
augmented_train_data = augment_data(train_data)
train_data = train_data.append(augmented_train_data, ignore_index=True)
# Shuffle the training data
train_data = train_data.sample(frac=1).reset_index(drop=True)
By augmenting the training data, you can increase the number of samples for the underrepresented classes and improve the model's performance on those classes. You can adjust the num_aug
parameter to control the number of augmented samples generated for each input sample.
in this code, gives the following error --------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[3], line 6 3 train_data = pd.read_csv("train.csv") 5 # Augment the training data ----> 6 augmented_train_data = augment_data(train_data) 7 train_data = train_data.append(augmented_train_data, ignore_index=True) 9 # Shuffle the training data Cell In[2], line 95, in augment_data(df, num_aug) 93 original_text = row["text"] 94 label = row["label"] ---> 95 augmented_texts = eda(original_text, num_aug=num_aug) 96 for aug_text in augmented_texts: 97 augmented_data.append({"text": aug_text, "label": label}) Cell In[2], line 84, in eda(sentence, alpha_sr, alpha_ri, alpha_rs, p_rd, num_aug) 82 a_words = synonym_replacement(a_words, num_sr) 83 a_words = random_insertion(a_words, num_ri) ---> 84 a_words = random_swap(a_words, num_rs) 85 a_words = random_deletion(a_words, p_rd) 86 augmented_sentences.append(' '.join(a_words)) TypeError: random_swap() takes 1 positional argument but 2 were given Could you fix the code so that there is no error?
Apologies for the oversight. The random_swap
function should only have one parameter. I'll correct this in the code snippet below:
pythonCopy codedef random_swap(words, n):
new_words = words.copy()
for _ in range(n):
idx1, idx2 = random.sample(range(0, len(words)), 2)
new_words[idx1], new_words[idx2] = new_words[idx2], new_words[idx1]
return new_words
def eda(sentence, alpha_sr=0.1, alpha_ri=0.1, alpha_rs=0.1, p_rd=0.1, num_aug=9):
words = nltk.word_tokenize(sentence)
num_words = len(words)
num_sr = max(1, int(alpha_sr * num_words))
num_ri = max(1, int(alpha_ri * num_words))
num_rs = max(1, int(alpha_rs * num_words))
augmented_sentences = []
for _ in range(num_aug):
a_words = words.copy()
a_words = synonym_replacement(a_words, num_sr)
a_words = random_insertion(a_words, num_ri)
a_words = random_swap(a_words, num_rs)
a_words = random_deletion(a_words, p_rd)
augmented_sentences.append(' '.join(a_words))
return augmented_sentences
The only change made was to add the n
parameter to the random_swap
function. This change ensures the proper number of swaps are performed based on the specified alpha_rs
value.
With this update, the code should work without any errors.
Can you augment the data by label so that the number of data for each label exceeds 5000?
To augment the data by label so that the number of data for each label exceeds 5000, you can modify the augment_data
function as follows:
pythonCopy codedef augment_data(df, target_count=5000):
augmented_data = []
label_counts = df['label'].value_counts()
for label, count in label_counts.items():
label_df = df[df['label'] == label]
num_aug_per_sample = max(1, int((target_count - count) / count))
for _, row in label_df.iterrows():
original_text = row["text"]
augmented_texts = eda(original_text, num_aug=num_aug_per_sample)
for aug_text in augmented_texts:
augmented_data.append({"text": aug_text, "label": label})
if len(augmented_data) + count >= target_count:
break
if len(augmented_data) + count >= target_count:
break
return pd.DataFrame(augmented_data)
In this modified version of the augment_data
function, we first calculate the label counts in the input DataFrame. Then, for each label, we calculate how many augmented samples per original sample we need to generate (num_aug_per_sample
) in order to reach the target_count
. We use this value as the num_aug
parameter when calling the eda
function.
Now, you can use the updated augment_data
function to augment your training dataset:
pythonCopy codetrain_data = pd.read_csv("train.csv")
# Augment the training data
augmented_train_data = augment_data(train_data, target_count=5000)
train_data = train_data.append(augmented_train_data, ignore_index=True)
# Shuffle the training data
train_data = train_data.sample(frac=1).reset_index(drop=True)
By using this approach, you ensure that there will be at least 5000 samples for each label in the augmented dataset.
in this code, gives the following warning. The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead. train_data = train_data.append(augmented_train_data, ignore_index=True) Could you modify the code?
Certainly! You can use pd.concat()
to replace the deprecated append
method. Here's the updated code snippet:
pythonCopy codetrain_data = pd.read_csv("train.csv")
# Augment the training data
augmented_train_data = augment_data(train_data, target_count=5000)
train_data = pd.concat([train_data, augmented_train_data], ignore_index=True)
# Shuffle the training data
train_data = train_data.sample(frac=1).reset_index(drop=True)
Now, the pd.concat()
function is used to combine the original and augmented training data. This should eliminate the warning you were encountering.
Could you modify the augment_data function to have more than 5000 data by augmenting it based on the label with less than 5000 data?
Certainly! You can modify the augment_data
function to augment only the labels with fewer than 5000 samples. Here's the updated function:
pythonCopy codedef augment_data(df, target_count=5000):
augmented_data = []
label_counts = df['label'].value_counts()
for label, count in label_counts.items():
if count < target_count:
label_df = df[df['label'] == label]
num_aug_per_sample = max(1, int((target_count - count) / count))
for _, row in label_df.iterrows():
original_text = row["text"]
augmented_texts = eda(original_text, num_aug=num_aug_per_sample)
for aug_text in augmented_texts:
augmented_data.append({"text": aug_text, "label": label})
if len(augmented_data) + count >= target_count:
break
if len(augmented_data) + count >= target_count:
break
return pd.DataFrame(augmented_data)
In this version of the augment_data
function, we only augment the labels with fewer than 5000 samples. If the label count is already equal to or greater than the target_count
, the function skips the augmentation process for that label.
Now, you can use the updated augment_data
function to augment your training dataset:
pythonCopy codetrain_data = pd.read_csv("train.csv")
# Augment the training data
augmented_train_data = augment_data(train_data, target_count=5000)
train_data = pd.concat([train_data, augmented_train_data], ignore_index=True)
# Shuffle the training data
train_data = train_data.sample(frac=1).reset_index(drop=True)
By using this approach, you ensure that there will be at least 5000 samples for each label in the augmented dataset, while not over-augmenting labels that already meet the target count.
Could you modify the augment_data function so that the number of data for each label exceeds 5000 by augmenting based on the label with less than 5000 data?
Apologies for the confusion in my previous response. I have now modified the augment_data
function to ensure that the number of samples for each label exceeds 5000 by augmenting only the labels with less than 5000 samples:
pythonCopy codedef augment_data(df, target_count=5000):
augmented_data = []
label_counts = df['label'].value_counts()
for label, count in label_counts.items():
label_df = df[df['label'] == label]
if count < target_count:
num_aug_required = target_count - count
num_aug_per_sample = max(1, int(num_aug_required / count))
else:
continue
augmented_count = 0
for _, row in label_df.iterrows():
original_text = row["text"]
augmented_texts = eda(original_text, num_aug=num_aug_per_sample)
for aug_text in augmented_texts:
augmented_data.append({"text": aug_text, "label": label})
augmented_count += 1
if augmented_count >= num_aug_required:
break
if augmented_count >= num_aug_required:
break
return pd.DataFrame(augmented_data)
In this version of the augment_data
function, we calculate the number of augmented samples required (num_aug_required
) for each label that has fewer than 5000 samples. We then augment these labels accordingly, ensuring that there are at least 5000 samples for each label in the resulting dataset.
Now, you can use the updated augment_data
function to augment your training dataset:
pythonCopy codetrain_data = pd.read_csv("train.csv")
# Augment the training data
augmented_train_data = augment_data(train_data, target_count=5000)
train_data = pd.concat([train_data, augmented_train_data], ignore_index=True)
# Shuffle the training data
train_data = train_data.sample(frac=1).reset_index(drop=True)
This approach guarantees that the number of samples for each label exceeds 5000 in the augmented dataset.