2026 · Data Science数据科学
Movie Review Sentiment — Teaching a Model to Read a Review影评情感分析:教模型读懂一篇影评
A beginner-friendly sentiment classifier for IMDB reviews, built as a teaching project. TF-IDF and logistic regression read 89.7% of unseen reviews correctly, and the model's weights show which words it trusts. Testing it on short reviews exposed a quiet bug in a common default. The standard English stop-word list deletes "not", so "not good" reads as good.一个面向初学者的 IMDB 影评情感分类器,是作为教学项目来做的。TF-IDF 加逻辑回归能正确判断 89.7% 从没见过的影评,模型的权重还能显示它信任哪些词。用短影评测试时,发现了一个常见默认设置里不易察觉的 bug:标准的英文停用词表会删掉 “not”,于是 “not good”(不好)被读成了好评。

- IMDB reviews after removing duplicates去掉重复后的 IMDB 影评数
- 49,58249,582
- Accuracy on reviews it never saw对从没见过的影评的准确率
- 89.7%89.7%
- "This movie was not good" read as positive“This movie was not good” 被判为正面的概率
- 76%76%
What it is
A model that reads an IMDB movie review and decides whether the reviewer liked the film. I built it as a teaching project, so it comes as two notebooks. One explains every step in plain language with notes for presenting it, and the other is a clean version to hand in. Both run the same analysis.
How it works
The dataset has 50,000 reviews, split evenly between positive and negative. After removing 418 duplicates and stripping leftover HTML, each review is turned into numbers with TF-IDF, which scores every word and two-word phrase by how distinctive it is. The vocabulary is fitted on the training set only, so nothing leaks from the test set. A logistic regression then learns one weight per word.
On the 9,917 reviews held out for testing, it got 89.7% right, and it was about as good on positive reviews as on negative ones.
What it learned
Because the model is linear, its weights can be read directly, and they make sense. “Great”, “excellent” and “perfect” push hardest toward positive. “Worst”, “awful”, “bad” and “boring” push hardest toward negative. It also picked up some film-critic language on its own. “Dark” and “brutal” come out slightly positive, because in reviews they are often praise.
The bug in a default
Then I tried short reviews of my own. “This movie was not good” came back 76% positive. The reason is a default most tutorials use. scikit-learn’s English stop-word list removes “not”, “no” and “never” along with “the” and “of”, so the model only ever saw “movie good”.
这是什么
一个读 IMDB 影评、判断评论者喜不喜欢这部电影的模型。我把它做成了教学项目,所以分成两个 notebook:一个用通俗的语言解释每一步,并附有讲解时用的备注;另一个是可以直接提交的简洁版本。两个跑的是同样的分析。
工作原理
数据集有 50,000 篇影评,正面和负面各占一半。去掉 418 篇重复影评、清除残留的 HTML 之后,每篇影评都用 TF-IDF 转换成数字。TF-IDF 会按每个词和每个双词短语有多大的辨识度给它打分。词表只在训练集上建立,所以测试集的信息不会泄漏进来。然后,逻辑回归为每个词学出一个权重。
在留作测试的 9,917 篇影评上,它判断对了 89.7%,而且对正面影评和负面影评的表现差不多。
它学到了什么
因为模型是线性的,它的权重可以直接读出来,而且都说得通。“Great”、“excellent” 和 “perfect” 最能把结果推向正面,“Worst”、“awful”、“bad” 和 “boring” 最能把结果推向负面。它还自己学会了一些影评人的用语:“Dark”(黑暗)和 “brutal”(残酷)的结果略偏正面,因为在影评里它们常常是夸奖。
默认设置里的 bug
后来我用自己写的短影评来测试。“This movie was not good”(这部电影不好看)得到的结果是 76% 正面。原因出在大多数教程都在用的一个默认设置上:scikit-learn 的英文停用词表会把 “not”、“no” 和 “never” 连同 “the”、“of” 一起删掉,所以模型看到的只有 “movie good”。
Keeping the negation words in fixes the first case and nudges overall accuracy up slightly, to 90.0%. It doesn’t fix the others. “Not bad at all” is still read as negative, because “bad” carries far more weight than “not bad” can undo. Word counts can’t follow how one word changes the next, and sarcasm is harder still. A review that calls a film “so bad it’s good” is a puzzle for this kind of model, which is the natural lead-in to models that read words in order.
保留否定词就能修好第一个例子,整体准确率也略有提升,到 90.0%。但其他例子还是没有修好。“Not bad at all”(一点也不差)仍然被判为负面,因为 “bad” 的权重远远超过 “not bad” 能抵消的程度。只数词频没法反映一个词怎样改变下一个词的意思,讽刺就更难了。一篇说电影 “so bad it’s good”(烂到好看)的影评,对这类模型来说是个难题,这也自然引出了按顺序读词的模型。