Kaggle的该题目是NLP入门的经典案列,本文也是出于这样的目的来学习NLP常用技术,主要参考Overview。
数据预处理
训练数据中包含了电影的评论内容和情感标签,评论内容是英文的,里面有可能包含各种特殊字符,也有可能是网页内容。测试数据只包含了评论内容,要求预测该评论对应的情感标签。评论内容是自然语言,需要先对评论做预处理,包括去除Html标签、去除特殊字符、分词、去除停用词等。
1 | def review_to_words(raw_review): |
特征表示
现在我们已经把一条评论转换为word列表,但是模型训练时候需要是数值类型的,所以需要对评论进行特征表示。一种简单的想法是使用One-Hot编码。将评论转换为一个向量,向量长度为所有出现过的word的个数,如果某个word在该评论中出现过,则设置向量的该位置为1,这样就将一条评论转换为一个向量。
但是这种方法有个问题是向量长度可能会非常长,一种优化是只提取出现次数最多的n个word作为向量下标,向量的值在该条评论中该Word的出现次数,sklearn中CountVectorizer就是做了这样的事情。 1
2
3
4
5
6
7#5000的含义向量最大长度为5000,选取次数最多的5000个单词作为向量下标
vectorizer = CountVectorizer(analyzer = "word", tokenizer = None, preprocessor = None, stop_words = None, max_features = 5000)
train_data_features = vectorizer.fit_transform(clean_train_reviews)
train_data_features = pd.DataFrame(train_data_features.toarray())
t_data_features = vectorizer.transform(clean_test_reviews)
test_data_features = test_data_features.toarray()
模型训练
这里简单的使用随机森林进行训练预测,得到0.84的精度。 1
2
3
4
5forest = RandomForestClassifier(n_estimators = 100)
forest = forest.fit( train_data_features, train["sentiment"] )
result = forest.predict(test_data_features)
output = pd.DataFrame( data={"id":test["id"], "sentiment":result} )
output.to_csv( "submission.csv", index=False, quoting=3 )
特征表示优化
除了上面的CountVectorizer可以做NLP编码,sklean还提供了TfidfVectorizer来做NLP编码。它同样会选取出现次数最多的n个word做为向量下标,但是向量的值为每个Word的TF-IDF。 1
2
3
4
5
6torizer = TfidfVectorizer(analyzer = "word", tokenizer = None, preprocessor = None, stop_words = None, max_features = 5000)
train_data_features = vectorizer.fit_transform(clean_train_reviews)
train_data_features = pd.DataFrame(train_data_features.toarray())
test_data_features = vectorizer.transform(clean_test_reviews)
test_data_features = test_data_features.toarray()