This model is a single-head Transformer trained for binary text classification.
Its computational footprint is intentionally lightweight:
PARAMETERS
~1ā5 M
typical small Transformer
MEMORY (RAM)
~50ā200 MB
model weights + TF runtime
HARDWARE
CPU only
GPU not required at inference
MAX SEQ LEN
80 tokens
O(n²) attention applies
ā¹ļø Self-attention complexity scales as O(n²·d) where n = sequence length and d = embedding dimension.
At n=80 this is negligible ā the dominant cost is the first inference call due to TF graph compilation
(TensorFlow's XLA warm-up). Subsequent calls are significantly faster.
š2 Ā· Latency
Latency is the total wall-clock time from receiving user input to returning the
result ā it includes tokenization, padding, model forward-pass, and HTML rendering.
1st REQUEST (cold)
500 ms ā 3 s
TF graph compilation
WARM REQUESTS
20 ā 80 ms
CPU inference, typical
WITH GPU
< 10 ms
if CUDA is available
ā¹ļø Network latency (Gradio UI ā Python backend) adds ~5ā15 ms on localhost.
On Hugging Face Spaces or remote servers, add 50ā150 ms round-trip depending on geography.
ā”3 Ā· Inference Time
Inference time measures only the model.predict() call ā
the neural network forward pass itself. This is the pure compute cost and excludes
tokenization, Gradio overhead, and network round-trips. Each run shows the live
measured value above in the result card.
BATCH SIZE
1 sample
single-text inference
TYPICAL RANGE
5 ā 50 ms
warm, CPU, seq=80
VARIABILITY
±10ā30%
OS scheduling, cache state
ā¹ļø First-call inference is slower because TensorFlow traces and compiles the computation graph
(XLA/JIT). After the first call the compiled graph is cached in memory, making all
subsequent inferences significantly faster and more consistent.
ā ļø4 Ā· When Predictions May Vary or Be Unreliable
š
MIXED SENTIMENT
Text containing both positive and negative signals (e.g., "ą¦Ŗą¦£ą§ą¦Æą¦ą¦æ ą¦øą§ą¦Øą§ą¦¦ą¦° ą¦ą¦æą¦Øą§ą¦¤ą§ দাম ą¦¬ą§ą¦¶ą¦æ") confuses the
binary classifier. Confidence will hover near 50 % and may flip with small edits.
š¤
OOV / RARE VOCABULARY
Words not seen during training are mapped to an unknown token <UNK>.
Heavy use of slang, dialect, transliteration, or technical jargon will degrade accuracy.
š
CODE-SWITCHING (BANGLISH)
Mixing Bangla script with English words or Roman-script Bangla causes many tokens to be
OOV, making predictions unreliable. Use pure Unicode Bangla for best results.
š
VERY SHORT OR VERY LONG TEXT
Single-word inputs lack context. Texts exceeding 80 tokens are silently truncated ā
sentiment expressed only in the trailing portion will be ignored entirely.
š
SARCASM & IRONY
The model has no pragmatic understanding. Ironic phrases like "ą¦¹ą§ą¦Æą¦¾ą¦, ঠসাধারণ ą¦øą¦¾ą¦°ą§ą¦ą¦æą¦ø!" (sarcastic)
are likely classified as Positive because the surface tokens are positive.
š
DOMAIN SHIFT
If the training data consisted mainly of product reviews, the model may perform poorly
on political commentary, news text, or social media posts with different linguistic patterns.
š²
DROPOUT AT INFERENCE (if training=True)
Dropout layers are disabled during inference (training=False),
so results are deterministic. If you call the model with training=True,
outputs will differ randomly on each run.
"""
# ============================================================
# GRADIO UI
# ============================================================
with gr.Blocks(css=css, title="Bangla Sentiment Analyzer") as demo:
with gr.Column(elem_id="bsa-wrap"):
gr.HTML(HERO)
with gr.Column(elem_id="bsa-card"):
gr.HTML(SEC_INPUT)
text_input = gr.Textbox(
lines=4,
placeholder="ą¦ą¦ą¦¾ą¦Øą§ ą¦ą¦Ŗą¦Øą¦¾ą¦° ą¦¬ą¦¾ą¦ą¦²ą¦¾ ą¦°ą¦æą¦ą¦æą¦ বা ą¦®ą¦Øą§ą¦¤ą¦¬ą§ą¦Æ ą¦²ą¦æą¦ą§ą¦Ø...",
label="", show_label=False,
)
with gr.Row(elem_classes="bsa-btnrow"):
submit_btn = gr.Button("š Analyze Sentiment", variant="primary", scale=3)
clear_btn = gr.Button("ā Clear", variant="secondary", scale=1)
gr.HTML(SEC_RESULT)
with gr.Column(elem_classes="bsa-result"):
output_html = gr.HTML(value=EMPTY_RESULT)
gr.HTML(DIVIDER)
gr.HTML(EX_LABEL)
# āā EXAMPLE BUTTONS āā
with gr.Row(elem_classes="ex-btn-row"):
ex1 = gr.Button(EXAMPLES[0], elem_classes="ex-btn")
ex2 = gr.Button(EXAMPLES[1], elem_classes="ex-btn")
with gr.Row(elem_classes="ex-btn-row"):
ex3 = gr.Button(EXAMPLES[2], elem_classes="ex-btn")
ex4 = gr.Button(EXAMPLES[3], elem_classes="ex-btn")
with gr.Row(elem_classes="ex-btn-row"):
ex5 = gr.Button(EXAMPLES[4], elem_classes="ex-btn")
# āā Static info panel (always visible below the main card) āā
gr.HTML(INFO_PANEL)
gr.HTML(FOOTER)
# āā Main events āā
submit_btn.click(fn=predict_sentiment, inputs=text_input, outputs=output_html)
text_input.submit(fn=predict_sentiment, inputs=text_input, outputs=output_html)
clear_btn.click(fn=lambda: ("", EMPTY_RESULT), inputs=None, outputs=[text_input, output_html])
# āā Example button events āā
ex1.click(fn=lambda: EXAMPLES[0], inputs=None, outputs=text_input)
ex2.click(fn=lambda: EXAMPLES[1], inputs=None, outputs=text_input)
ex3.click(fn=lambda: EXAMPLES[2], inputs=None, outputs=text_input)
ex4.click(fn=lambda: EXAMPLES[3], inputs=None, outputs=text_input)
ex5.click(fn=lambda: EXAMPLES[4], inputs=None, outputs=text_input)
if __name__ == "__main__":
demo.launch(share=True)