NLP入门 - 新闻文本分类 Task3

2020-07-25  本文已影响0人  正在学习的Yuki

Task3 基于机器学习的文本分类

学习目标


文本表示方法 Part1

文本表示成计算机能够运算的数字或向量的方法一般称为词嵌入(Word Embedding)方法:将不定长的文本转换到定长的空间内。

1. One-hot
将每一个单词使用一个离散的向量表示:将每个字/词编码一个索引,然后根据索引进行赋值。
e.g.,
句子1:我 爱 北 京 天 安 门
句子2:我 喜 欢 上 海

2. Bag of Words / Count Vectors
每个文档的字/词用出现次数来表示。
句子1:我 爱 北 京 天 安 门 -> [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
句子2:我 喜 欢 上 海 -> [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]

from sklearn.feature_extraction.text import CountVectorizer
corpus = [
    'This is the first document.',
    'This document is the second document.',
    'And this is the third one.',
    'Is this the first document?',
]
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(corpus)
print(X.toarray()) # 词频结果
print(vectorizer.get_feature_names()) # 词袋中所有文本关键词

Result:

[[0 1 1 1 0 0 1 0 1]
 [0 2 0 1 0 1 1 0 1]
 [1 0 0 1 1 0 1 1 1]
 [0 1 1 1 0 0 1 0 1]]
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']

3. N-gram
与Count Vectors类似,不过加入了相邻单词组成新的单词,并进行计数。
e.g., N取值为2,就变为:
句子1:我爱 爱北 北京 京天 天安 安门
句子2:我喜 喜欢 欢上 上海

4. TF-IDF

from sklearn.feature_extraction.text import TfidfVectorizer
corpus = [
    'This is the first document.',
    'This document is the second document.',
    'And this is the third one.',
    'Is this the first document?',
]
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(corpus)
print(X.toarray())
print(vectorizer.get_feature_names())

Result:

[[0.         0.46979139 0.58028582 0.38408524 0.         0.
 0.38408524 0.         0.38408524]
[0.         0.6876236  0.         0.28108867 0.         0.53864762
 0.28108867 0.         0.28108867]
[0.51184851 0.         0.         0.26710379 0.51184851 0.
 0.26710379 0.51184851 0.26710379]
[0.         0.46979139 0.58028582 0.38408524 0.         0.
 0.38408524 0.         0.38408524]]
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']

基于机器学习的文本分类

对比不同文本表示算法的精度,通过本地构建验证集计算F1得分。

1. Count Vectors + RidgeClassifier

import pandas as pd

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score

train_df = pd.read_csv('data/train_set.csv', sep='\t', nrows=15000)

vectorizer = CountVectorizer(max_features=3000)
train_test = vectorizer.fit_transform(train_df['text'])

clf = RidgeClassifier()
clf.fit(train_test[:10000], train_df['label'].values[:10000])
val_pred = clf.predict(train_test[10000:])

print("Count Vectors + RidgeClassifier: f1_score =", end=' ')
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
# 0.74

2. TF-IDF + RidgeClassifier

import pandas as pd

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score

train_df = pd.read_csv('data/train_set.csv', sep='\t', nrows=15000)

tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
train_test = tfidf.fit_transform(train_df['text'])

clf = RidgeClassifier()
clf.fit(train_test[:10000], train_df['label'].values[:10000])
val_pred = clf.predict(train_test[10000:])

print("TF-IDF \t\t  + RidgeClassifier: f1_score =", end=' ')
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
# 0.87

Result:

Count Vectors + RidgeClassifier: f1_score = 0.7406241569237678
TF-IDF        + RidgeClassifier: f1_score = 0.8721598830546126

本章作业

  1. 尝试改变TF-IDF的参数,并验证精度
    tfidf = TfidfVectorizer(ngram_range=(1, 1), max_features=None)
for max_features in range(1000, 10000 , 1000):
    tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=max_features)
    train_test = tfidf.fit_transform(train_df['text'])

    clf = RidgeClassifier()
    clf.fit(train_test[:10000], train_df['label'].values[:10000])

    val_pred = clf.predict(train_test[10000:])
    print("max_features =",max_features,": f1_score =", end=' ')
    print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))

Result:

max_features = 1000 : f1_score = 0.8270776630718544
max_features = 2000 : f1_score = 0.8603842642428617
max_features = 3000 : f1_score = 0.8721598830546126
max_features = 4000 : f1_score = 0.8753945850878357
max_features = 5000 : f1_score = 0.8850817067811825
max_features = 6000 : f1_score = 0.8901406771892212
max_features = 7000 : f1_score = 0.8920634181410882
max_features = 8000 : f1_score = 0.8897593080180294
max_features = 9000 : f1_score = 0.89142965492415

发现max_features=7000时f1_score最高(0.8921)。

for ngram_max in range(1, 5):
    tfidf = TfidfVectorizer(ngram_range=(1,ngram_max), max_features=7000)

Result:

ngram_range=(1,1), f1_score = 0.8603325900148268
ngram_range=(1,2), f1_score = 0.8875087923712194
ngram_range=(1,3), f1_score = 0.8920634181410882
ngram_range=(1,4), f1_score = 0.891603038208734
ngram_range=(1,5), f1_score = 0.8914513820822496
  1. 尝试使用其他机器学习模型,完成训练和验证
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression(max_iter=10000)
from sklearn.svm import LinearSVC
clf = LinearSVC(max_iter=10000)

最优结果:0.8964


Refereces:

上一篇下一篇

猜你喜欢

热点阅读