HADI MOUMENI

AdversAttack

Everyone keeps pitching AI that reads the news and trades on it, so I wanted to see how sturdy that mapping from words to a number actually is. I trained a sentiment classifier on financial headlines, then attacked it. The result is a little unsettling. A one-character typo, “rose” to “ruse”, the kind you read straight past, flips a headline the model is 93% sure is positive into a negative call. Every example is generated by the code, nothing is faked. The famous version of this (“stock rises” becoming “stock falls”) is actually impossible with one character, and it isn’t even an attack, since swapping rises for falls is a real change in meaning a good model should catch. The interesting version is the opposite: a change that keeps the meaning intact and still flips the label.

Highlights

  • A single-character typo flips a 93%-confident positive headline to negative. Across the held-out set, about 18% of confident-positive headlines flip on one character and 48% within two.
  • The attack is FGSM adapted to text. FGSM is a continuous, image-style method, so I use its discrete descendant HotFlip: score every single edit by the loss gradient, then verify the best few with an exact forward pass. The gradient ranked the winning edit first out of 3,385 candidates.
  • It was never really about typos. Swapping one word for a calendar month, which carries no sentiment, flips it just as well. The model’s most negative-weighted tokens are things like the digits 3, 11, 17 and the word “by”, artifacts of how the training data was phrased, not bad news.
  • Not everything is fragile. Headlines that stack several sentiment cues shrug off two edits. The weakness concentrates where a single token carries the whole verdict, which in short headlines is most of the time.
  • Everything is from scratch in NumPy: the TF-IDF features, the softmax classifier trained by hand, and the attack. No PyTorch, and no scikit-learn for the parts that matter.

Tech Stack

  • Python, NumPy - Everything, written from scratch
  • TF-IDF (word + character n-grams) - Hand-rolled feature extractor
  • Softmax regression + Adam - The classifier, trained by hand
  • FGSM / HotFlip - Gradient-guided single-edit attack
  • Financial PhraseBank - Dataset (Malo et al., 2014)
  • Vercel - Hosts the write-up

Notes

  • The whole thing is one honest reframing. “Rises to falls with one character” is impossible, and not an attack anyway. A meaning-preserving typo that still flips the label is both possible and far more damning, so that is what I went after.
  • The model hitting 76.5% held-out on three classes is a faithful baseline for this benchmark, not a tuned number. I’d rather it stay representative than look impressive, because a fragile weak model proves nothing. A fragile accurate one is the point.
  • The surprising part was reading the weights. The model’s idea of “bad news” leans partly on stray digits and quotation marks. It learned the accent of its training set, not sentiment, and an accent is easy to imitate or corrupt.
  • The data is licensed non-commercial, so the repo never ships it. It downloads on first run and stays git-ignored.
  • I want to point the same recipe at a transformer next. There the edits stop being typos and turn into fluent synonyms, which are harder to notice, not easier.

Check it out: AdversAttack