Task3 基于机器学习的文本分类 学习笔记
Author: 2tong
文本表示方法
1.One-hot
这里的One-hot与数据挖掘任务中的操作是一致的,即将每一个单词使用一个离散的向量表示。具体将每个字/词编码一个索引,然后根据索引进行赋值。
One-hot表示方法的例子如下:
句子1:我 爱 哈 尔 滨
句子2:我 喜 欢 橙 子
首先对所有句子的字进行索引,即将每个字确定一个编号:
{
'我': 1, '爱': 2, '哈': 3, '尔': 4, '滨': 5,
'喜': 6, '欢': 7, '橙': 8, '子': 9
}
在这里共包括9个字,因此每个字可以转换为一个9维度稀疏向量:
我:[1, 0, 0, 0, 0, 0, 0, 0, 0]
爱:[0, 1, 0, 0, 0, 0, 0, 0, 0]
...
海:[0, 0, 0, 0, 0, 0, 0, 0, 1]
2.Bag of Words
Bag of Words(词袋表示),也称为Count Vectors,每个文档的字/词可以使用其出现次数来进行表示。
句子1:我 爱 哈 尔 滨
句子2:我 喜 欢 橙 子
直接统计每个字出现的次数,并进行赋值:
句子1:我 爱 哈 尔 滨
转换为 [1, 1, 1, 1, 1, 0, 0, 0, 0]
句子2:我 喜 欢 橙 子
转换为 [1, 0, 0, 0, 0, 1, 1, 1, 1]
在sklearn中可以直接CountVectorizer
来实现这一步骤:
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()
vectorizer.fit_transform(corpus).toarray()
3.N-gram
N-gram与Count Vectors类似,不过加入了相邻单词组合成为新的单词,并进行计数。
如果N取值为2,则句子1和句子2就变为:
句子1:我爱 爱哈 哈尔 尔滨
句子2:我喜 喜欢 欢橙 橙子
4.TF-IDF
TF-IDF 分数由两部分组成:
- 第一部分是词语频率(Term Frequency)
- 第二部分是逆文档频率(Inverse Document Frequency)。
其中计算语料库中文档总数除以含有该词语的文档数量,然后再取对数就是逆文档频率。
TF(t)= 该词语在当前文档出现的次数 / 当前文档中词语的总数
IDF(t)= log_e(文档总数 / 出现该词语的文档总数)
基于机器学习的文本分类
不同文本表示方法
选取RidgeClassifier机器学习策略,进行不同文本表示方法的组合,通过本地构建验证集计算F1得分。
1.Count Vectors
>>> 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])
RidgeClassifier()
>>> val_pred = clf.predict(train_test[10000:])
>>> print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
0.7406241569237678
2.TF-IDF
>>> 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])
RidgeClassifier()
>>> val_pred = clf.predict(train_test[10000:])
>>> print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
0.8721598830546126
参数调整
选取TF-IDF文本表示方法、RidgeClassifer策略的组合,调整TF-IDF参数,通过本地构建验证集计算F1得分。
1.尝试调整ngram_range参数
ngram_range(min,max):是指将text分成min,min+1,min+2,…max 个不同的词组。
Test1:
### ngram_range(1,1)
>>> 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,1), max_features=3000)
>>> train_test = tfidf.fit_transform(train_df['text'])
>>> clf = RidgeClassifier()
>>> clf.fit(train_test[:10000], train_df['label'].values[:10000])
RidgeClassifier()
>>> val_pred = clf.predict(train_test[10000:])
>>> print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
0.858329649339088
Test2:
### ngram_range(1,2)
>>> 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,2), max_features=3000)
>>> train_test = tfidf.fit_transform(train_df['text'])
>>> clf = RidgeClassifier()
>>> clf.fit(train_test[:10000], train_df['label'].values[:10000])
RidgeClassifier()
>>> val_pred = clf.predict(train_test[10000:])
>>> print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
0.8719465729628795
Test3:
### ngram_range(1,5)
>>> tfidf = TfidfVectorizer(ngram_range=(1,5), max_features=3000)
>>> train_test = tfidf.fit_transform(train_df['text'])
>>> clf = RidgeClassifier()
>>> clf.fit(train_test[:10000], train_df['label'].values[:10000])
RidgeClassifier()
>>> val_pred = clf.predict(train_test[10000:])
>>> print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
0.8753002643279153
待思考:为什么ngram_range的max值增加,F1值数会更好,呈现一种什么趋势,何时出现拐点
不同机器学习策略
选取TF-IDF文本表示方法,进行不同机器学习策略的组合,通过本地构建验证集计算F1得分。
1.SVM
>>> import pandas as pd
>>> from sklearn.feature_extraction.text import TfidfVectorizer
>>> from sklearn.svm import SVC
>>> 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 = SVC()
>>> clf.fit(train_test[:10000], train_df['label'].values[:10000])
SVC()
>>> val_pred = clf.predict(train_test[10000:])
>>> print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
0.8751673004923052