Hugging Face is an open-source and platform provider of machine learning technologies. You can use install their package to access some interesting pre-built models to use them directly or to fine-tune (retrain it on your dataset leveraging the prior knowledge coming with the first training), then host your trained models on the platform, so that you may use them later on other devices and apps.
Please, go to the website and sign-in to access all the features of the platform.
Read more about Text classification with Hugging Face
The Hugging face models are Deep Learning based, so will need a lot of computational GPU power to train them. Please use Colab to do it, or your other GPU cloud provider, or a local machine having NVIDIA GPU.
Find below a simple example, with just 10 epochs of fine-tuning`.
Read more about the fine-tuning concept : here
!pip install datasets
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/ Requirement already satisfied: datasets in /usr/local/lib/python3.10/dist-packages (2.12.0) Requirement already satisfied: numpy>=1.17 in /usr/local/lib/python3.10/dist-packages (from datasets) (1.22.4) Requirement already satisfied: pyarrow>=8.0.0 in /usr/local/lib/python3.10/dist-packages (from datasets) (9.0.0) Requirement already satisfied: dill<0.3.7,>=0.3.0 in /usr/local/lib/python3.10/dist-packages (from datasets) (0.3.6) Requirement already satisfied: pandas in /usr/local/lib/python3.10/dist-packages (from datasets) (1.5.3) Requirement already satisfied: requests>=2.19.0 in /usr/local/lib/python3.10/dist-packages (from datasets) (2.27.1) Requirement already satisfied: tqdm>=4.62.1 in /usr/local/lib/python3.10/dist-packages (from datasets) (4.65.0) Requirement already satisfied: xxhash in /usr/local/lib/python3.10/dist-packages (from datasets) (3.2.0) Requirement already satisfied: multiprocess in /usr/local/lib/python3.10/dist-packages (from datasets) (0.70.14) Requirement already satisfied: fsspec[http]>=2021.11.1 in /usr/local/lib/python3.10/dist-packages (from datasets) (2023.4.0) Requirement already satisfied: aiohttp in /usr/local/lib/python3.10/dist-packages (from datasets) (3.8.4) Requirement already satisfied: huggingface-hub<1.0.0,>=0.11.0 in /usr/local/lib/python3.10/dist-packages (from datasets) (0.15.1) Requirement already satisfied: packaging in /usr/local/lib/python3.10/dist-packages (from datasets) (23.1) Requirement already satisfied: responses<0.19 in /usr/local/lib/python3.10/dist-packages (from datasets) (0.18.0) Requirement already satisfied: pyyaml>=5.1 in /usr/local/lib/python3.10/dist-packages (from datasets) (6.0) Requirement already satisfied: attrs>=17.3.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp->datasets) (23.1.0) Requirement already satisfied: charset-normalizer<4.0,>=2.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp->datasets) (2.0.12) Requirement already satisfied: multidict<7.0,>=4.5 in /usr/local/lib/python3.10/dist-packages (from aiohttp->datasets) (6.0.4) Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in /usr/local/lib/python3.10/dist-packages (from aiohttp->datasets) (4.0.2) Requirement already satisfied: yarl<2.0,>=1.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp->datasets) (1.9.2) Requirement already satisfied: frozenlist>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from aiohttp->datasets) (1.3.3) Requirement already satisfied: aiosignal>=1.1.2 in /usr/local/lib/python3.10/dist-packages (from aiohttp->datasets) (1.3.1) Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0.0,>=0.11.0->datasets) (3.12.0) Requirement already satisfied: typing-extensions>=3.7.4.3 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0.0,>=0.11.0->datasets) (4.5.0) Requirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests>=2.19.0->datasets) (1.26.15) Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests>=2.19.0->datasets) (2022.12.7) Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests>=2.19.0->datasets) (3.4) Requirement already satisfied: python-dateutil>=2.8.1 in /usr/local/lib/python3.10/dist-packages (from pandas->datasets) (2.8.2) Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas->datasets) (2022.7.1) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.8.1->pandas->datasets) (1.16.0)
!pip install transformers
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/ Requirement already satisfied: transformers in /usr/local/lib/python3.10/dist-packages (4.29.2) Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from transformers) (3.12.0) Requirement already satisfied: huggingface-hub<1.0,>=0.14.1 in /usr/local/lib/python3.10/dist-packages (from transformers) (0.15.1) Requirement already satisfied: numpy>=1.17 in /usr/local/lib/python3.10/dist-packages (from transformers) (1.22.4) Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from transformers) (23.1) Requirement already satisfied: pyyaml>=5.1 in /usr/local/lib/python3.10/dist-packages (from transformers) (6.0) Requirement already satisfied: regex!=2019.12.17 in /usr/local/lib/python3.10/dist-packages (from transformers) (2022.10.31) Requirement already satisfied: requests in /usr/local/lib/python3.10/dist-packages (from transformers) (2.27.1) Requirement already satisfied: tokenizers!=0.11.3,<0.14,>=0.11.1 in /usr/local/lib/python3.10/dist-packages (from transformers) (0.13.3) Requirement already satisfied: tqdm>=4.27 in /usr/local/lib/python3.10/dist-packages (from transformers) (4.65.0) Requirement already satisfied: fsspec in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.14.1->transformers) (2023.4.0) Requirement already satisfied: typing-extensions>=3.7.4.3 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.14.1->transformers) (4.5.0) Requirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests->transformers) (1.26.15) Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests->transformers) (2022.12.7) Requirement already satisfied: charset-normalizer~=2.0.0 in /usr/local/lib/python3.10/dist-packages (from requests->transformers) (2.0.12) Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests->transformers) (3.4)
!pip install --upgrade accelerate
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/ Requirement already satisfied: accelerate in /usr/local/lib/python3.10/dist-packages (0.19.0) Requirement already satisfied: numpy>=1.17 in /usr/local/lib/python3.10/dist-packages (from accelerate) (1.22.4) Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from accelerate) (23.1) Requirement already satisfied: psutil in /usr/local/lib/python3.10/dist-packages (from accelerate) (5.9.5) Requirement already satisfied: pyyaml in /usr/local/lib/python3.10/dist-packages (from accelerate) (6.0) Requirement already satisfied: torch>=1.6.0 in /usr/local/lib/python3.10/dist-packages (from accelerate) (2.0.1+cu118) Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from torch>=1.6.0->accelerate) (3.12.0) Requirement already satisfied: typing-extensions in /usr/local/lib/python3.10/dist-packages (from torch>=1.6.0->accelerate) (4.5.0) Requirement already satisfied: sympy in /usr/local/lib/python3.10/dist-packages (from torch>=1.6.0->accelerate) (1.11.1) Requirement already satisfied: networkx in /usr/local/lib/python3.10/dist-packages (from torch>=1.6.0->accelerate) (3.1) Requirement already satisfied: jinja2 in /usr/local/lib/python3.10/dist-packages (from torch>=1.6.0->accelerate) (3.1.2) Requirement already satisfied: triton==2.0.0 in /usr/local/lib/python3.10/dist-packages (from torch>=1.6.0->accelerate) (2.0.0) Requirement already satisfied: cmake in /usr/local/lib/python3.10/dist-packages (from triton==2.0.0->torch>=1.6.0->accelerate) (3.25.2) Requirement already satisfied: lit in /usr/local/lib/python3.10/dist-packages (from triton==2.0.0->torch>=1.6.0->accelerate) (16.0.5) Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from jinja2->torch>=1.6.0->accelerate) (2.1.2) Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy->torch>=1.6.0->accelerate) (1.3.0)
!pip install sentencepiece
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/ Requirement already satisfied: sentencepiece in /usr/local/lib/python3.10/dist-packages (0.1.99)
import huggingface_hub
import os
import numpy as np
import pandas as pd
from datasets import load_dataset
from sklearn.model_selection import train_test_split
from transformers import AutoModelForSequenceClassification
from transformers import TFAutoModelForSequenceClassification
from transformers import AutoTokenizer, AutoConfig
from transformers import TrainingArguments, Trainer, DataCollatorWithPadding
from sklearn.metrics import mean_squared_error
huggingface_hub.notebook_login()
# Now you are logged in to the Hugging Face Hub
VBox(children=(HTML(value='<center> <img\nsrc=https://huggingface.co/front/assets/huggingface_logo-noborder.sv…
# Disabe W&B
os.environ["WANDB_DISABLED"] = "true"
# Load the dataset from a GitHub link
url = "https://raw.githubusercontent.com/Azubi-Africa/Career_Accelerator_P5-NLP/master/zindi_challenge/data/Train.csv"
df = pd.read_csv(url)
# A way to eliminate rows containing NaN values
df = df[~df.isna().any(axis=1)]
# Split the train data => {train, eval}
train, eval = train_test_split(df, test_size=0.2, random_state=42, stratify=df['label'])
train.head()
tweet_id | safe_text | label | agreement | |
---|---|---|---|---|
9305 | YMRMEDME | Mickey's Measles has gone international <url> | 0.0 | 1.000000 |
3907 | 5GV8NEZS | S1256 [NEW] Extends exemption from charitable ... | 0.0 | 1.000000 |
795 | EI10PS46 | <user> your ignorance on vaccines isn't just ... | 1.0 | 0.666667 |
5793 | OM26E6DG | Pakistan partly suspends polio vaccination pro... | 0.0 | 1.000000 |
3431 | NBBY86FX | In other news I've gone up like 1000 mmr | 0.0 | 1.000000 |
train.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 7999 entries, 9305 to 1387 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 tweet_id 7999 non-null object 1 safe_text 7999 non-null object 2 label 7999 non-null float64 3 agreement 7999 non-null float64 dtypes: float64(2), object(2) memory usage: 312.5+ KB
eval.head()
tweet_id | safe_text | label | agreement | |
---|---|---|---|---|
6571 | R7JPIFN7 | Children's Museum of Houston to Offer Free Vac... | 1.0 | 1.000000 |
1754 | 2DD250VN | <user> no. I was properly immunized prior to t... | 1.0 | 1.000000 |
3325 | ESEVBTFN | <user> thx for posting vaccinations are impera... | 1.0 | 1.000000 |
1485 | S17ZU0LC | This Baby Is Exactly Why Everyone Needs To Vac... | 1.0 | 0.666667 |
4175 | IIN5D33V | Meeting tonight, 8:30pm in room 322 of the stu... | 1.0 | 1.000000 |
eval.label.unique()
array([ 1., -1., 0.])
print(f"new dataframe shapes: train is {train.shape}, eval is {eval.shape}")
new dataframe shapes: train is (7999, 4), eval is (2000, 4)
from datasets import DatasetDict, Dataset
train_dataset = Dataset.from_pandas(train[['tweet_id', 'safe_text', 'label', 'agreement']])
eval_dataset = Dataset.from_pandas(eval[['tweet_id', 'safe_text', 'label', 'agreement']])
dataset = DatasetDict({'train': train_dataset, 'eval': eval_dataset})
dataset = dataset.remove_columns('__index_level_0__')
dataset
DatasetDict({ train: Dataset({ features: ['tweet_id', 'safe_text', 'label', 'agreement'], num_rows: 7999 }) eval: Dataset({ features: ['tweet_id', 'safe_text', 'label', 'agreement'], num_rows: 2000 }) })
# Preprocess text (username and link placeholders)
def preprocess(text):
new_text = []
for t in text.split(" "):
t = '@user' if t.startswith('@') and len(t) > 1 else t
t = 'http' if t.startswith('http') else t
new_text.append(t)
return " ".join(new_text)
checkpoint = "cardiffnlp/twitter-xlm-roberta-base-sentiment"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
# config = AutoConfig.from_pretrained(MODEL)
def transform_labels(label):
label = label['label']
num = 0
if label == -1: #'Negative'
num = 0
elif label == 0: #'Neutral'
num = 1
elif label == 1: #'Positive'
num = 2
return {'labels': num}
def tokenize_data(example):
return tokenizer(example['safe_text'], padding='max_length')
# Change the tweets to tokens that the models can exploit
dataset = dataset.map(tokenize_data, batched=True)
# Transform labels and remove the useless columns
remove_columns = ['tweet_id', 'label', 'safe_text', 'agreement']
dataset = dataset.map(transform_labels, remove_columns=remove_columns)
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
Map: 0%| | 0/7999 [00:00<?, ? examples/s]
Asking to pad to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no padding.
Map: 0%| | 0/2000 [00:00<?, ? examples/s]
Map: 0%| | 0/7999 [00:00<?, ? examples/s]
Map: 0%| | 0/2000 [00:00<?, ? examples/s]
dataset
DatasetDict({ train: Dataset({ features: ['input_ids', 'attention_mask', 'labels'], num_rows: 7999 }) eval: Dataset({ features: ['input_ids', 'attention_mask', 'labels'], num_rows: 2000 }) })
# Configure the trianing parameters like `num_train_epochs`:
# the number of time the model will repeat the training loop over the dataset
training_args = TrainingArguments("test_trainer",
num_train_epochs=10,
load_best_model_at_end=True,
save_strategy='epoch',
evaluation_strategy='epoch',
logging_strategy='epoch',
logging_steps=100,
per_device_train_batch_size=8,
)
Using the `WANDB_DISABLED` environment variable is deprecated and will be removed in v5. Use the --report_to flag to control the integrations used for logging result (for instance --report_to none).
# Loading a pretrain model while specifying the number of labels in our dataset for fine-tuning
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=3)
train_dataset = dataset['train'].shuffle(seed=10)
eval_dataset = dataset['eval'].shuffle(seed=10)
def compute_metrics(eval_pred):
logits, labels = eval_pred
predictions = np.argmax(logits, axis=-1)
return {"rmse": mean_squared_error(labels, predictions, squared=False)}
trainer = Trainer(
model,
training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
data_collator=data_collator,
tokenizer=tokenizer,
compute_metrics=compute_metrics,
)
trainer.train()
/usr/local/lib/python3.10/dist-packages/transformers/optimization.py:407: FutureWarning: This implementation of AdamW is deprecated and will be removed in a future version. Use the PyTorch implementation torch.optim.AdamW instead, or set `no_deprecation_warning=True` to disable this warning warnings.warn( You're using a XLMRobertaTokenizerFast tokenizer. Please note that with a fast tokenizer, using the `__call__` method is faster than using a method to encode the text followed by a call to the `pad` method to get a padded encoding.
Epoch | Training Loss | Validation Loss | Rmse |
---|---|---|---|
1 | 0.728900 | 0.692720 | 0.736546 |
2 | 0.576800 | 0.672787 | 0.650385 |
3 | 0.456600 | 0.883064 | 0.630079 |
4 | 0.355400 | 0.931305 | 0.651153 |
5 | 0.273600 | 1.030852 | 0.629682 |
6 | 0.187300 | 1.398479 | 0.667832 |
7 | 0.115500 | 1.517482 | 0.640312 |
8 | 0.080300 | 1.693804 | 0.635610 |
9 | 0.051700 | 1.781752 | 0.646142 |
10 | 0.035100 | 1.872524 | 0.646916 |
Epoch | Training Loss | Validation Loss | Rmse |
---|---|---|---|
1 | 0.728900 | 0.692720 | 0.736546 |
2 | 0.576800 | 0.672787 | 0.650385 |
3 | 0.456600 | 0.883064 | 0.630079 |
4 | 0.355400 | 0.931305 | 0.651153 |
5 | 0.273600 | 1.030852 | 0.629682 |
6 | 0.187300 | 1.398479 | 0.667832 |
7 | 0.115500 | 1.517482 | 0.640312 |
8 | 0.080300 | 1.693804 | 0.635610 |
9 | 0.051700 | 1.781752 | 0.646142 |
10 | 0.035100 | 1.872524 | 0.646916 |
TrainOutput(global_step=10000, training_loss=0.2861065677642822, metrics={'train_runtime': 1771.8633, 'train_samples_per_second': 45.145, 'train_steps_per_second': 5.644, 'total_flos': 1705660480665036.0, 'train_loss': 0.2861065677642822, 'epoch': 10.0})
Don't worry the above issue, it is a KeyboardInterrupt
that means I stopped the training to avoid taking a long time to finish.
# Launch the final evaluation
trainer.evaluate()
{'eval_loss': 0.6727872490882874, 'eval_rmse': 0.650384501660364, 'eval_runtime': 5.5238, 'eval_samples_per_second': 362.072, 'eval_steps_per_second': 45.259, 'epoch': 10.0}
Some checkpoints of the model are automatically saved locally in test_trainer/
during the training.
You may also upload the model on the Hugging Face Platform... Read more
# Push the model and tokenizer to Hugging Face
# Push model and tokenizer to HugginFace
model.push_to_hub("ikoghoemmanuell/finetuned_sentiment_modell")
tokenizer.push_to_hub("ikoghoemmanuell/finetuned_sentiment_modell")
Upload 1 LFS files: 0%| | 0/1 [00:00<?, ?it/s]
pytorch_model.bin: 0%| | 0.00/1.11G [00:00<?, ?B/s]
tokenizer.json: 0%| | 0.00/17.1M [00:00<?, ?B/s]
Upload 2 LFS files: 0%| | 0/2 [00:00<?, ?it/s]
sentencepiece.bpe.model: 0%| | 0.00/5.07M [00:00<?, ?B/s]
CommitInfo(commit_url='https://huggingface.co/ikoghoemmanuell/finetuned_sentiment_modell/commit/545fe3500337a22fd72d9bc9aa54396e026e699c', commit_message='Upload tokenizer', commit_description='', oid='545fe3500337a22fd72d9bc9aa54396e026e699c', pr_url=None, pr_revision=None, pr_num=None)