Skip to content

Commit dbc6f39

Browse files
committed
improved readme
1 parent c134832 commit dbc6f39

File tree

4 files changed

+33
-4
lines changed

4 files changed

+33
-4
lines changed

README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,15 @@ The model is a Logistic Regression classifier, trained using GridSearchCV to fin
6464
## Evaluation and Explainability
6565
To evaluate the model, we generate a classification graph, showcasing precision, recall and F1-score per class. We also save a confusion matrix (true vs predicted labels). Both are saved as .png images under the `/metrics` directory. Our model presented the following results:
6666

67-
**Classification Report**
67+
### Classification Report
6868
![Model's Classification Report](metrics/classification_report.png)
6969

70-
**Confusion Matrix**
70+
The blue (precision), orange (recall) and green (f1-score) bars show the metrics for each class. We can see that the model is overall more precise when detecting positive reviews, but shows solid scores on both cases.
71+
72+
### Confusion Matrix
7173
![Model's Confusion Matrix](metrics/classification_report.png)
7274

75+
As we see from the confusion matrix, the model's most frequent mistake is confusing negative reviews as positive. Aside from training and using other models, this could also be a result of an unbalanced dataset - one that has more positive reviews than negative ones.
7376

7477
For explainability, we want to know why a review was classified as positive or negative. We use two complementary tools:
7578

@@ -78,9 +81,29 @@ LIME works on individual predictions. For a given review, it identifies the top
7881

7982
![Model's LIME Report](explainability/lime.png)
8083

84+
This graph shows which words weighted the model the most towards a specific prediction. Green words weight towards a positive review and red ones, towards a negative review.
8185

8286
### SHAP (SHapley Additive exPlanations)
8387
SHAP provides a more general view. Instead of only explaining one prediction, it highlights the most influential words across many reviews. The `explainability.py` file loads the trained Logistic Regression model and the TF–IDF pipeline and samples reviews, generating LIME and SHAP visualizations in the `/explainability` folder.
8488

85-
8689
![Model's SHAP Report](explainability/shap.png)
90+
91+
This is an SHAP Summary Plot. The Y-axis shows the most important words/features, sorted by overall importance, while the X-axis shows their SHAP value (impact on the model’s output).
92+
93+
Red means the feature increased the chance of predicting “positive”, and blue means the feature pushed towards “negative”.Their position from left to right define how strong the impact was.
94+
95+
## Summary
96+
In this project, we built a sentiment analysis model using Olist’s Brazilian E-Commerce Public Dataset. Our objective was to automatically classify customer reviews as positive or negative and to further interpret the model’s decisions using explainability tools.
97+
98+
The final model is a Logistic Regression classifier, trained on TF–IDF features and optimized with GridSearchCV. The training/test split was 80/20, and the model was optimized for F1-score.
99+
100+
### Results:
101+
- **Accuracy**: ~88%
102+
- **F1-score**: 0.82 (negative), 0.91 (positive)
103+
- **Precision/Recall**: the model is more reliable at detecting positive reviews, but still achieves solid results for negative ones.
104+
105+
### Explainability:
106+
107+
**LIME** demonstrated how individual words influence single predictions. **SHAP** provided a global perspective, ranking the most influential words across the dataset.
108+
109+
Overall, the project achieved its dual goal: building a performant model for sentiment classification and making its predictions transparent and interpretable.

explainability.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ def run_shap_example(df, model, vectorizer, sample_size=100):
3939
shap_values = explainer(X_transformed)
4040

4141
# Run SHAP on the first review and get results
42-
shap.plots.bar(shap_values[0], max_display=10, show=False)
42+
shap.summary_plot(
43+
shap_values,
44+
X_transformed,
45+
feature_names=vectorizer.get_feature_names_out(),
46+
show=False
47+
)
48+
4349
plt.savefig("explainability/shap.png", dpi=300, bbox_inches="tight")
4450
plt.close()
4551

explainability/lime.png

409 Bytes
Loading

explainability/shap.png

5.75 KB
Loading

0 commit comments

Comments
 (0)