Spaces:
Sleeping
Sleeping
Update src/webApp.py
Browse files- src/webApp.py +14 -7
src/webApp.py
CHANGED
|
@@ -240,7 +240,6 @@ def shap_bar_chart(shap_values, feature_names):
|
|
| 240 |
textposition="outside"
|
| 241 |
))
|
| 242 |
fig.update_layout(
|
| 243 |
-
fig.update_layout(
|
| 244 |
title="Feature Impact (SHAP)",
|
| 245 |
xaxis_title="SHAP Impact (positive = pushes toward Suspicious)",
|
| 246 |
yaxis_title="",
|
|
@@ -390,10 +389,14 @@ def interpret_shap_features(shap_df):
|
|
| 390 |
strength = "strongly" if abs(impact) > 0.05 else "slightly"
|
| 391 |
|
| 392 |
if feature == "review_frequency":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 393 |
interpretations.append(
|
| 394 |
-
f"
|
| 395 |
-
"Higher reviewer volume increases suspicion as it mirrors the high frequency "
|
| 396 |
-
"posting patterns seen in coordinated fake review campaigns."
|
| 397 |
)
|
| 398 |
elif feature == "unverified_ratio":
|
| 399 |
interpretations.append(
|
|
@@ -402,10 +405,14 @@ def interpret_shap_features(shap_df):
|
|
| 402 |
"behaviour where the reviewer may not have actually bought the product."
|
| 403 |
)
|
| 404 |
elif feature == "extreme_rating_ratio":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 405 |
interpretations.append(
|
| 406 |
-
f"
|
| 407 |
-
"Extreme ratings (1 or 5 stars) are a weak signal, they appear in both "
|
| 408 |
-
"genuine and suspicious reviews, so the model gives this moderate weight."
|
| 409 |
)
|
| 410 |
elif feature == "very_short_review":
|
| 411 |
interpretations.append(
|
|
|
|
| 240 |
textposition="outside"
|
| 241 |
))
|
| 242 |
fig.update_layout(
|
|
|
|
| 243 |
title="Feature Impact (SHAP)",
|
| 244 |
xaxis_title="SHAP Impact (positive = pushes toward Suspicious)",
|
| 245 |
yaxis_title="",
|
|
|
|
| 389 |
strength = "strongly" if abs(impact) > 0.05 else "slightly"
|
| 390 |
|
| 391 |
if feature == "review_frequency":
|
| 392 |
+
if impact > 0:
|
| 393 |
+
explanation = "Higher reviewer volume increases suspicion as it mirrors the high frequency posting patterns seen in coordinated fake review campaigns."
|
| 394 |
+
elif abs(impact) < 0.001:
|
| 395 |
+
explanation = "Reviewer volume had no meaningful impact on this prediction."
|
| 396 |
+
else:
|
| 397 |
+
explanation = "Lower reviewer volume reduces suspicion as this reviewer has not posted at high enough volume to suggest coordinated or incentivised reviewing behaviour."
|
| 398 |
interpretations.append(
|
| 399 |
+
f"- **{feature}** ({abs(impact):.4f}): {strength} {direction}. {explanation}"
|
|
|
|
|
|
|
| 400 |
)
|
| 401 |
elif feature == "unverified_ratio":
|
| 402 |
interpretations.append(
|
|
|
|
| 405 |
"behaviour where the reviewer may not have actually bought the product."
|
| 406 |
)
|
| 407 |
elif feature == "extreme_rating_ratio":
|
| 408 |
+
if impact > 0:
|
| 409 |
+
explanation = "An extreme rating was given. Extreme ratings (1 or 5 stars) appear more frequently in suspicious reviews, though they are equally common in genuine enthusiastic reviews. The model treats this as a mild signal rather than a strong flag."
|
| 410 |
+
elif abs(impact) < 0.001:
|
| 411 |
+
explanation = "Extreme rating had no meaningful impact on this prediction."
|
| 412 |
+
else:
|
| 413 |
+
explanation = "A non-extreme rating was given. Mid-range ratings are less commonly associated with suspicious behaviour and this pushed the model away from flagging this review."
|
| 414 |
interpretations.append(
|
| 415 |
+
f"- **{feature}** ({abs(impact):.4f}): {strength} {direction}. {explanation}"
|
|
|
|
|
|
|
| 416 |
)
|
| 417 |
elif feature == "very_short_review":
|
| 418 |
interpretations.append(
|