# ============================================================
# SBERT TEXT REPRESENTATION
# ============================================================
from sentence_transformers import SentenceTransformer
SBERT_MODEL_NAME = "all-MiniLM-L6-v2"
sbert_model = SentenceTransformer(SBERT_MODEL_NAME)
train_texts = train_df["Combined_Text"].fillna("").astype(str).tolist()
test_texts = test_df["Combined_Text"].fillna("").astype(str).tolist()
X_train_sbert = sbert_model.encode(
train_texts,
show_progress_bar=True,
convert_to_numpy=True
)
X_test_sbert = sbert_model.encode(
test_texts,
show_progress_bar=True,
convert_to_numpy=True
)
print("SBERT dimension:", X_train_sbert.shape[1])
print("Training embeddings:", X_train_sbert.shape)
print("Test embeddings:", X_test_sbert.shape)
# ============================================================
# HYBRID FEATURE FUSION
# ============================================================
def fuse_features(sbert_features, structured_features):
return np.hstack([
sbert_features,
structured_features
])
SBERT TEXT REPRESENTATION
This cell converts the combined text feature into numerical semantic embeddings using SBERT. These embeddings will later be combined with the structured features to create the hybrid feature representation.
1. Import SBERT
from sentence_transformers import SentenceTransformer
- Imports the
SentenceTransformerclass from thesentence_transformerslibrary. - SBERT stands for Sentence-BERT.
- It converts text into dense numerical vectors called embeddings.
- These embeddings capture the semantic meaning and relationships between words/text, rather than simply representing individual words.
Viva question: Why did you use SBERT?
Answer:
“I used SBERT to convert the combined textual information into dense semantic embeddings. This allows the ML models to capture relationships between product names, companies, and countries that may not be captured by simple categorical or numerical encoding.”
2. Select the SBERT model
SBERT_MODEL_NAME = "all-MiniLM-L6-v2"
- Stores the name of the pretrained SBERT model in a variable.
-
"all-MiniLM-L6-v2"is a lightweight sentence-transformer model. - It provides a good balance between semantic representation, computational cost, and embedding size.
The important point is that you are using a pretrained model, rather than training SBERT from scratch on your PCF dataset.
Viva question: Why this particular model?
Answer:
“I selected
all-MiniLM-L6-v2because it is a relatively lightweight pretrained sentence-transformer that provides useful semantic embeddings while keeping computational requirements manageable.”
If examiner asks: Why not a larger model?
“A larger transformer could potentially provide richer representations, but it would increase computational cost. For this project, I prioritised a practical balance between semantic representation and efficiency.”
3. Load the pretrained model
sbert_model = SentenceTransformer(SBERT_MODEL_NAME)
This creates the SBERT model object.
The process is:
"all-MiniLM-L6-v2"
↓
SentenceTransformer()
↓
Pretrained SBERT model loaded
The model is now ready to convert text into embeddings.
Important viva point
You are not fitting SBERT on the PCF dataset here.
You are using an already pretrained language model to generate representations.
That is different from:
model.fit(...)
used by conventional ML models.
4. Get training text
train_texts = train_df["Combined_Text"].fillna("").astype(str).tolist()
Let's break this line into four operations.
train_df["Combined_Text"]
Selects the Combined_Text column from the training dataset.
Earlier, you created something like:
Product: Laptop | Company: Dell | Country: USA
So each row contains a combined textual representation.
.fillna("")
.fillna("")
Replaces missing text values with an empty string.
For example:
NaN
becomes:
""
This prevents missing values from causing problems during text encoding.
.astype(str)
.astype(str)
Converts every value into a string.
SBERT expects textual input, so this ensures the input has the appropriate type.
.tolist()
.tolist()
Converts the pandas Series into a Python list.
For example:
Pandas Series
↓
Python list
↓
["Product: Laptop | Company: Dell | Country: USA",
"Product: Phone | Company: Apple | Country: USA",
...]
This list is then passed to SBERT.
5. Get test text
test_texts = test_df["Combined_Text"].fillna("").astype(str).tolist()
This performs exactly the same preparation for the test dataset.
The important difference is:
train_df → train_texts
test_df → test_texts
The two datasets remain separate.
Viva question: Why do you encode train and test separately?
Answer:
“I encode the training and test observations separately so that each observation receives its embedding without mixing the datasets. The same pretrained SBERT model is used for both, ensuring that the representations are generated in a consistent way.”
6. Generate training embeddings
X_train_sbert = sbert_model.encode(
train_texts,
show_progress_bar=True,
convert_to_numpy=True
)
This is the main SBERT operation.
The model takes the training text and converts every text record into a numerical vector.
Conceptually:
Combined_Text
↓
SBERT
↓
Dense numerical embedding
For example, conceptually:
"Product: Laptop | Company: Dell | Country: USA"
↓
[0.12, -0.34, 0.56, ..., 0.08]
The actual vector contains many numerical dimensions.
7. show_progress_bar=True
show_progress_bar=True
Displays the encoding progress while SBERT processes the observations.
For example:
Encoding: 100% |████████████| ...
This does not affect the model's predictions.
It is simply useful for monitoring a potentially time-consuming operation.
Viva question: Does this parameter affect accuracy?
Answer:
“No. It only controls whether a progress bar is displayed during encoding.”
8. convert_to_numpy=True
convert_to_numpy=True
Requests the embeddings as a NumPy array.
This is important because later you use:
np.hstack(...)
to combine the SBERT features with structured features.
So the pipeline becomes:
SBERT
↓
NumPy embedding matrix
↓
np.hstack()
↓
Hybrid features
9. Generate test embeddings
X_test_sbert = sbert_model.encode(
test_texts,
show_progress_bar=True,
convert_to_numpy=True
)
The same pretrained SBERT model converts the test texts into embeddings.
Notice that you do not train or refit SBERT using the test data.
You simply apply the already loaded model.
This is important for maintaining a clean evaluation process.
Viva question: Is this data leakage?
Answer:
“No, because the SBERT model is pretrained independently and is not fitted on the PCF test data. The test text is only passed through the pretrained encoder to generate representations.”
A more cautious answer if the examiner is strict:
“The encoder itself is pretrained externally rather than learned from this dataset. I use it only as a fixed representation model and do not fine-tune it using the PCF test set.”
10. Print SBERT dimension
print("SBERT dimension:", X_train_sbert.shape[1])
X_train_sbert.shape contains:
(number of observations, number of embedding dimensions)
For example:
(800, 384)
Then:
.shape[1]
selects the second dimension:
384
So this prints the number of features generated by SBERT.
For all-MiniLM-L6-v2, the embedding dimension is typically 384.
11. Print training embedding shape
print("Training embeddings:", X_train_sbert.shape)
This shows:
(number of training observations, embedding dimensions)
For example:
Training embeddings: (800, 384)
This allows you to verify that the number of embeddings corresponds to the number of training observations.
12. Print test embedding shape
print("Test embeddings:", X_test_sbert.shape)
Similarly, this verifies the dimensions of the test embeddings.
For example:
Test embeddings: (200, 384)
The important requirement is:
number of training embeddings = number of training rows
number of test embeddings = number of test rows
HYBRID FEATURE FUSION
Now you combine the semantic text representation with the structured representation.
def fuse_features(sbert_features, structured_features):
This defines a function called fuse_features.
It accepts two inputs:
sbert_features
structured_features
sbert_features
These are the SBERT embeddings.
For example:
384 dimensions
structured_features
These are the features you previously created from:
- Year
- Product weight
- One-hot encoded categorical variables
- Country target encoding
So you have two different types of information:
SBERT
→ semantic information
Structured features
→ explicit numerical/categorical information
13. Horizontally concatenate the features
return np.hstack([
sbert_features,
structured_features
])
np.hstack() means horizontal stacking.
Suppose:
SBERT = 384 features
Structured = 10 features
Then:
384 + 10 = 394 features
The result becomes:
[ SBERT features | Structured features ]
For every observation, the two feature vectors are placed side by side.
Conceptually:
SBERT
[0.12, -0.34, 0.56, ..., 0.08]
+
Structured
[2023, 1.5, 0, 1, 0, ...]
↓
Hybrid
[0.12, -0.34, 0.56, ..., 0.08, 2023, 1.5, 0, 1, 0, ...]
Why use hybrid features?
This is one of the most important viva questions.
Your reasoning is:
Text alone
↓
captures semantic information
Structured features alone
↓
captures explicit numerical/categorical information
Both together
↓
hybrid representation
↓
potentially richer information for ML
Strong viva answer
“I used hybrid feature fusion because the two representations capture different types of information. SBERT captures semantic relationships within the combined text, while the structured features explicitly represent numerical and categorical information such as reporting year, product weight, industry, protocol, and country. By horizontally concatenating them, the downstream ML models can use both sources of information simultaneously.”
Very important distinction
Do not say:
“SBERT understands the exact carbon footprint.”
That would overclaim.
Instead say:
“SBERT provides a semantic representation of the textual information, which may contain information useful for predicting PCF.”
The PCF prediction itself is performed by your downstream ML model.
Overall pipeline for this section
Product
Company
Country
↓
Combined_Text
↓
Pretrained SBERT
↓
384-dimensional semantic embeddings
↓
┌────────────────────┐
│ Structured features│
│ Year │
│ Weight │
│ Industry │
│ Protocol │
│ Country encoding │
└────────────────────┘
↓
SBERT embeddings ──→ Feature Fusion ←── Structured features
↓
Hybrid Features
↓
ML Model
↓
PCF Prediction
Most likely examiner questions
Why SBERT instead of TF-IDF?
“TF-IDF mainly represents lexical importance based on word frequency, whereas SBERT produces dense contextual semantic embeddings. Since product and company descriptions can contain meaningful relationships beyond exact word matching, SBERT provides a richer semantic representation.”
Why combine SBERT with structured features?
“Because SBERT and structured features contain complementary information. SBERT captures semantic text information, while structured features preserve explicit numerical and categorical information.”
Why use the same SBERT model for train and test?
“To maintain a consistent feature space. The same pretrained encoder transforms both datasets, but the test data is not used to fit or fine-tune the encoder.”
What does np.hstack() do?
“It horizontally concatenates the two feature matrices, placing the SBERT and structured features side by side for each observation.”
What is the biggest limitation of this approach?
“SBERT was pretrained for general language representation, not specifically for PCF prediction. Therefore, its embeddings may not capture all domain-specific carbon-footprint relationships. The hybrid approach helps by adding explicit structured information, but it does not guarantee that every relevant PCF relationship is represented.”
Presentation wording
“In this stage, I convert the combined textual representation into semantic embeddings using the pretrained
all-MiniLM-L6-v2SBERT model. First, I prepare the training and test text by handling missing values and converting them into lists. I then pass both datasets through the same pretrained SBERT encoder and obtain numerical embeddings. I verify the dimensions of these embeddings to ensure that the transformation was successful. Finally, I define a feature-fusion function that horizontally combines the SBERT embeddings with the structured features. This creates a hybrid representation containing both semantic textual information and explicit numerical and categorical information, which is then used by the downstream machine-learning models.”
For your SBERT pipeline
- Explain how to verify row alignment
- Explain feature scaling after fusion
Top comments (0)