Logo

Text Representation Techniques in NLP (Including Arabic Data)

12 min read
Lesson slides
1 / 15

Text Representation Techniques in NLP (Including Arabic Data)

Turning text into numbers: one-hot encoding, bag-of-words, TF-IDF, and word embeddings

Introduction

Machine learning models cannot process raw text data directly; they require numeric inputs. This is where text representation techniques come into play. Below, we explore various methods to transform textual data into numerical feature spaces.


Preparation


texts = [
    "The quick brown fox jumps over the lazy dog",
    "Natural language processing is a subfield of artificial intelligence",
    "Machine learning enables computers to learn from data without explicit programming",
    "Deep learning is a branch of machine learning focused on neural networks",
    "Word embeddings capture semantic relationships between words in a text corpus"
]
 
test_txt = "Machine learning is awesome"
 
# Build Vocabulary
vocab = sorted(set(word for sentence in texts for word in sentence.split()))

One-Hot-Encoding

One-Hot Encoding is technique to represent text numerically.

What is One-Hot Encoding?

  • Each unique word is represented as a vector of size equal to the vocabulary.
  • Only one position in the vector is set to 1, and the rest are 0.

import numpy as np
word_to_index = {word: idx for idx, word in enumerate(vocab)}
def one_hot_encode(word):
    """Convert a single English word into a one-hot encoded vector."""
    one_hot_vector = np.zeros(len(vocab))
    if word in word_to_index:
        one_hot_vector[word_to_index[word]] = 1  # Set index position to 1
    return one_hot_vector
 
# Example: Encode individual words
example_words = test_txt.split()
one_hot_vectors = {word: one_hot_encode(word) for word in example_words}
 
# Print One-Hot Encodings
for word, vector in one_hot_vectors.items():
    print(f"{word}: {vector}")
Machine: [0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
learning: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
is: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
awesome: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder
 
encoder = OneHotEncoder(sparse_output=False,handle_unknown='ignore')
vocab_np = np.array(vocab).reshape(-1, 1)
encoder.fit(vocab_np)
test_txt_words = np.array(test_txt.lower().split()).reshape(-1, 1)
encoded_words = encoder.transform(test_txt_words)
for word, vector in zip(test_txt_words.flatten(), encoded_words):
    print(f"{word}: {vector}")
machine: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
learning: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
is: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
awesome: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

Binary Encoding - Simplest version of BoW


What is Binary Encoding?

Binary Encoding is a simple way of representing text numerically. The key idea is:

  • Construct a vocabulary from all unique words in the dataset.
  • Create a vector for each document, where each position corresponds to a word from the vocabulary.
  • If a word is present in a document, mark 1; otherwise, mark 0.
 
def binary_transform(text):
    """Convert text into a binary vector."""
    output = np.zeros(len(vocab))
    words = set(text.split())  # Tokenize the input
    for i, v in enumerate(vocab):
        output[i] = v in words  # Set 1 if the word exists
    return output
 
print(binary_transform(test_txt))
[0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.
 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
 
vec = CountVectorizer(binary=True)
vec.fit(texts)
 
df = pd.DataFrame(vec.transform(texts).toarray(), columns=sorted(vec.vocabulary_.keys()))
print(df)
   artificial  between  branch  brown  capture  computers  corpus  data  deep  \
0           0        0       0      1        0          0       0     0     0   
1           1        0       0      0        0          0       0     0     0   
2           0        0       0      0        0          1       0     1     0   
3           0        0       1      0        0          0       0     0     1   
4           0        1       0      0        1          0       1     0     0   
 
   dog  ...  quick  relationships  semantic  subfield  text  the  to  without  \
0    1  ...      1              0         0         0     0    1   0        0   
1    0  ...      0              0         0         1     0    0   0        0   
2    0  ...      0              0         0         0     0    0   1        1   
3    0  ...      0              0         0         0     0    0   0        0   
4    0  ...      0              1         1         0     1    0   0        0   
 
   word  words  
0     0      0  
1     0      0  
2     0      0  
3     0      0  
4     1      1  
 
[5 rows x 43 columns]
print(sorted(vec.vocabulary_.keys()))
print(vec.transform([test_txt]).toarray())
['artificial', 'between', 'branch', 'brown', 'capture', 'computers', 'corpus', 'data', 'deep', 'dog', 'embeddings', 'enables', 'explicit', 'focused', 'fox', 'from', 'in', 'intelligence', 'is', 'jumps', 'language', 'lazy', 'learn', 'learning', 'machine', 'natural', 'networks', 'neural', 'of', 'on', 'over', 'processing', 'programming', 'quick', 'relationships', 'semantic', 'subfield', 'text', 'the', 'to', 'without', 'word', 'words']
[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 0 0]]
df = pd.DataFrame(vec.transform([test_txt]).toarray(), columns=sorted(vec.vocabulary_.keys()))
print(df)
   artificial  between  branch  brown  capture  computers  corpus  data  deep  \
0           0        0       0      0        0          0       0     0     0   
 
   dog  ...  quick  relationships  semantic  subfield  text  the  to  without  \
0    0  ...      0              0         0         0     0    0   0        0   
 
   word  words  
0     0      0  
 
[1 rows x 43 columns]

Bag of words


What is Bag of Words?

Bag of Words (BoW) is similar to Binary Encoding but records how many times a word appears in a document instead of just presence (1 or 0).

from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
 
vec = CountVectorizer()
vec.fit(texts)
 
df = pd.DataFrame(vec.transform(texts).toarray(), columns=sorted(vec.vocabulary_.keys()))
print(df)
   artificial  between  branch  brown  capture  computers  corpus  data  deep  \
0           0        0       0      1        0          0       0     0     0   
1           1        0       0      0        0          0       0     0     0   
2           0        0       0      0        0          1       0     1     0   
3           0        0       1      0        0          0       0     0     1   
4           0        1       0      0        1          0       1     0     0   
 
   dog  ...  quick  relationships  semantic  subfield  text  the  to  without  \
0    1  ...      1              0         0         0     0    2   0        0   
1    0  ...      0              0         0         1     0    0   0        0   
2    0  ...      0              0         0         0     0    0   1        1   
3    0  ...      0              0         0         0     0    0   0        0   
4    0  ...      0              1         1         0     1    0   0        0   
 
   word  words  
0     0      0  
1     0      0  
2     0      0  
3     0      0  
4     1      1  
 
[5 rows x 43 columns]

TF-IDF(Term Frequency - Inverse Document Frequency) - Weighted BoW


Why Use TF-IDF?

  • Reduces the weight of common words while increasing importance of rare but meaningful words.
  • Helps in tasks like text classification and search engines.
from sklearn.feature_extraction.text import TfidfVectorizer
 
vec = TfidfVectorizer()
vec.fit(texts)
 
df = pd.DataFrame(vec.transform(texts).toarray(), columns=sorted(vec.vocabulary_.keys()))
print(df)
   artificial   between    branch     brown   capture  computers    corpus  \
0     0.00000  0.000000  0.000000  0.301511  0.000000   0.000000  0.000000   
1     0.37007  0.000000  0.000000  0.000000  0.000000   0.000000  0.000000   
2     0.00000  0.000000  0.000000  0.000000  0.000000   0.311561  0.000000   
3     0.00000  0.000000  0.307781  0.000000  0.000000   0.000000  0.000000   
4     0.00000  0.316228  0.000000  0.000000  0.316228   0.000000  0.316228   
 
       data      deep       dog  ...     quick  relationships  semantic  \
0  0.000000  0.000000  0.301511  ...  0.301511       0.000000  0.000000   
1  0.000000  0.000000  0.000000  ...  0.000000       0.000000  0.000000   
2  0.311561  0.000000  0.000000  ...  0.000000       0.000000  0.000000   
3  0.000000  0.307781  0.000000  ...  0.000000       0.000000  0.000000   
4  0.000000  0.000000  0.000000  ...  0.000000       0.316228  0.316228   
 
   subfield      text       the        to   without      word     words  
0   0.00000  0.000000  0.603023  0.000000  0.000000  0.000000  0.000000  
1   0.37007  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  
2   0.00000  0.000000  0.000000  0.311561  0.311561  0.000000  0.000000  
3   0.00000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  
4   0.00000  0.316228  0.000000  0.000000  0.000000  0.316228  0.316228  
 
[5 rows x 43 columns]
df = pd.DataFrame(vec.transform([test_txt]).toarray(), columns=sorted(vec.vocabulary_.keys()))
print(df)
   artificial  between  branch  brown  capture  computers  corpus  data  deep  \
0         0.0      0.0     0.0    0.0      0.0        0.0     0.0   0.0   0.0   
 
   dog  ...  quick  relationships  semantic  subfield  text  the   to  \
0  0.0  ...    0.0            0.0       0.0       0.0   0.0  0.0  0.0   
 
   without  word  words  
0      0.0   0.0    0.0  
 
[1 rows x 43 columns]

Embeddings


Personality Embeddings: What Are You Like?

Read : https://jalammar.github.io/illustrated-word2vec/

“I give you the desert chameleon, whose ability to blend itself into the background tells you all you need to know about the roots of ecology and the foundations of a personal identity.”
~ Children of Dune

Understanding Personality Traits

On a scale of 0 to 100, how introverted or extraverted are you? (Where 0 is the most introverted and 100 is the most extraverted). Have you ever taken a personality test like MBTI or, even better, the Big Five Personality Traits test?

If not, these tests ask a series of questions and then score you on a number of axes, introversion/extraversion being one of them.

Example Personality Test Result

The Big Five Personality Traits test can provide deep insights into personality and has been shown to predict academic, personal, and professional success. Here’s an example of how it might look:

Openness: 72/100
Conscientiousness: 85/100
Extraversion: 38/100
Agreeableness: 65/100
Neuroticism: 47/100

Visualizing Personality Scores

Imagine I’ve scored 38/100 on the introversion/extraversion scale. We can visualize this as:

To make it more useful for mathematical operations, let’s normalize the range from -1 to 1:

Adding More Dimensions

How well do you feel you know a person based on just one piece of information? Not much! People are complex. Let’s add another trait score to represent personality in two dimensions:

Instead of just points, we can represent personality as vectors. Why? Because vectors allow us to measure similarity mathematically!

Comparing Two People’s Personalities

Imagine I need to be replaced by someone with a similar personality. Below, we compare two other individuals:

Which person is more similar to me?

A common method to measure similarity in vector space is cosine similarity:

If cosine similarity is close to 1, the vectors point in the same direction, meaning they are more similar.

  • Person #1 is more similar because their vector points in the same general direction as mine.
  • Person #2 is less similar because their vector is in a different quadrant.

Scaling to More Dimensions

Two dimensions aren’t enough to fully capture human personality. Decades of psychology research suggest that personality can be best described with five major traits (The Big Five), along with many sub-traits.

The problem? We can’t draw neat little arrows for five dimensions! But in machine learning, we often deal with high-dimensional spaces. Luckily, cosine similarity still works for any number of dimensions!

Key Takeaways

At the end of this section, we should remember two key ideas:

  1. We can represent people (and things) as vectors of numbers – which is great for machines!
  2. We can easily calculate how similar these vectors are to each other using cosine similarity.


Word Embeddings


Word2Vec (Trained on Context-Based Prediction)

  • CBOW (Continuous Bag of Words): Predicts a word from its context.
  • Skip-Gram: Predicts context words from a single word.

import gensim
 
word2vec_model = gensim.models.KeyedVectors.load_word2vec_format(
    "GoogleNews-vectors-negative300.bin", binary=True
)
 
print("Word2Vec (King):", word2vec_model["king"][:10])  # First 10 values
Word2Vec (King): [ 0.12597656  0.02978516  0.00860596  0.13964844 -0.02563477 -0.03613281
  0.11181641 -0.19824219  0.05126953  0.36328125]
print("Word2Vec (Queen):", word2vec_model["Queen"][:10])  # First 10 values
Word2Vec (Queen): [-0.22070312 -0.17480469 -0.10498047  0.2578125   0.16210938 -0.13085938
 -0.16699219  0.07373047 -0.07226562  0.02404785]

GloVe (Trained on Word Co-Occurrence Statistics)

  • Unlike Word2Vec, GloVe is based on matrix factorization of a word-word co-occurrence matrix.
  • Captures global word relationships.

import numpy as np
 
# Load GloVe embeddings
glove_embeddings = {}
with open("glove.6B.100d.txt", "r", encoding="utf-8") as f:
    for line in f:
        values = line.split()
        word = values[0]
        vector = np.asarray(values[1:], dtype="float32")
        glove_embeddings[word] = vector
 
print("GloVe 'king':", glove_embeddings["king"][:10])  # Show first 10 values
GloVe 'king': [-0.32307 -0.87616  0.21977  0.25268  0.22976  0.7388  -0.37954 -0.35307
 -0.84369 -1.1113 ]