NLP入门之新闻文本分类竞赛——task3

NLP入门之新闻文本分类竞赛——task3

文本数字化——向量空间模型

1.什么是One-Hot编码?

​ One-Hot编码,又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效。One-Hot编码是分类变量作为二进制向量的表示。这首先要求将分类值映射到整数值。然后,每个整数值被表示为二进制向量,除了整数的索引之外,它都是零值,它被标记为1。

#### One-Hot表示方法示例如下
"""
    句⼦1:我 爱 北 京 天 安 ⻔
    句⼦2:我 喜 欢 上 海
    {
     '我': 1, '爱': 2, '北': 3, '京': 4, '天': 5,
     '安': 6, '⻔': 7, '喜': 8, '欢': 9, '上': 10, '海': 11
    }
    我:[1, 0, 0, 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, 0, 0, 0, 0, 1]
"""

2.Bag of Words模型

​ Bag-of-words模型是信息检索领域常用的文档表示方法。在信息检索中,BOW模型假定对于一个文档,忽略它的单词顺序和语法、句法等要素,将其仅仅看作是若干个词汇的集合,文档中每个单词的出现都是独立的,不依赖于其它单词是否出现。也就是说,文档中任意一个位置出现的任何单词,都不受该文档语意影响而独立选择的 。BOW模型有很多缺点,首先它没有考虑单词之间的顺序,其次它无法反应出一个句子的关键词 。

#### Bag of Words表示方法示例如下
"""
    句⼦1:我 爱 北 京 天 安 ⻔
    转换为 [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
    句⼦2:我 喜 欢 上 海
    转换为 [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]
"""
#### Bag of Words 在sklearn示例如下
from sklearn.feature_extraction.text import CountVectorizer
corpus = [
    "John likes to watch movies, Mary likes movies too",
    "John also likes to watch football games",
]
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(corpus)
print(vectorizer.get_feature_names())
print(X.toarray())
"""
    输出结果:
    ['also', 'football', 'games', 'john', 'likes', 'mary', 'movies', 'to', 'too', 'watch']
    [[0 0 0 1 2 1 2 1 1 1]
     [1 1 1 1 1 0 0 1 0 1]]
"""

3.N-gram

N-gram与Count Vectors类似,不过加入了相邻单词组合成为新的单词,并进行计数,如果N取值为2,则句子1和句子2就变为:

1. 句⼦1:我爱 爱北 北京 京天 天安 安⻔ 
2. 句⼦2:我喜 喜欢 欢上 上海

N-gram具体原理介绍博客:https://blog.csdn.net/songbinxu/article/details/80209197

3.TF-IDF

TF-IDF看名字也知道包括两部分TF和IDF,TF(Term Frequency,词频)的公式为:
T F ( t ) = 该 词 语 在 当 前 ⽂ 档 出 现 的 次 数 / 当 前 ⽂ 档 中 词 语 的 总 数 TF(t)= 该词语在当前⽂档出现的次数 / 当前⽂档中词语的总数 TF(t)=/
而IDF(inverse document frequency,逆文本频率)的公式为:
I D F ( t ) = l o g e ( ⽂ 档 总 数 / 出 现 该 词 语 的 ⽂ 档 总 数 ) IDF(t)= log_e(⽂档总数 / 出现该词语的⽂档总数) IDF(t)=loge/
其中,分母之所以加1是为了防止分母为0。所以,TF-IDF的公式为:

T F − I D F ( t ) = T F ( t ) ∗ I D F ( t ) TF−IDF(t)=TF(t)∗IDF(t) TFIDF(t)=TF(t)IDF(t)

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(vectorizer.get_feature_names())
print(X.toarray())
"""
    ['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
    [[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]]	
"""

传统机器学习实现文本分类

1.贝叶斯模型实现

贝叶斯定理:
P ( A ∣ B ) = P ( B ∣ A ) ∗ P ( A ) / P ( B ) P(A|B) = P(B|A)*P(A)/P(B) P(AB)=P(BA)P(A)/P(B)
假设B1,B2…Bn彼此独立,则有:
P ( B 1 ∗ B 2 ∗ … ∗ B n ∣ A ) = P ( B 1 ∣ A ) ∗ P ( B 2 ∣ A ) ∗ … ∗ P ( B n ∣ A ) P(B1*B2*…*Bn|A) = P(B1|A)*P(B2|A)*…*P(Bn|A) P(B1B2BnA)=P(B1A)P(B2A)P(BnA)
要计算每个词语在不同类别下出现的概率,有以下几个步骤:

  1. 选择训练数据,标记类别
  2. 把所有训练数据进行分词,并且组成成一个包含所有词语的词袋集合
  3. 把每个训练数据转换成词袋集合长度的向量
  4. 利用每个类别的下训练数据,计算词袋集合中每个词语的概率

2.支持向量机(SVM)

支持向量机(Support Vector Machine, SVM)是一类按监督学习(supervised learning) 方式对数据进行二元分类的广义线性分类器(generalized linear classifier),可用于分类或回归挑战,其决策边界是对学习样本求解的最大边距超平面(maximum-margin hyperplane)。然而,它主要用于分类问题。SVM算法最初是为二值分类问题设计的,当处理多类问题时,就需要构造合适的多类分类器。目前,构造SVM多类分类器的方法主要有两类:一类是直接法,直接在目标函数上进行修改,将多个分类面的参数求解合并到一个最优化问题中,通过求解该最优化问题“一次性”实现多类分类。这种方法看似简单,但其计算复杂度比较高,实现起来比较困难,只适合用于小型问题中;另一类是间接法,主要是通过组合多个二分类器来实现多分类器的构造,常见的方法有one-against-one和one-against-all两种。

a.一对多法(one-versus-rest,简称1-v-r SVMs)。训练时依次把某个类别的样本归为一类,其他剩余的样本归为另一类,这样k个类别的样本就构造出了k个SVM。分类时将未知样本分类为具有最大分类函数值的那类。

b.一对一法(one-versus-one,简称1-v-1 SVMs)。其做法是在任意两类样本之间设计一个SVM,因此k个类别的样本就需要设计k(k-1)/2个SVM。当对一个未知样本进行分类时,最后得票最多的类别即为该未知样本的类别。Libsvm中的多类分类就是根据这个方法实现的。

一个关于SVM原理介绍博客:https://blog.csdn.net/v_july_v/article/details/7624837**

三 机器学习+向量空间模型实现文本分类

1.代码实现

import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import MultinomialNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.multiclass import OneVsRestClassifier
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import f1_score

train_df = pd.read_csv('../dataset/train_set.csv', sep='\t', nrows=15000)  # nrows设置显示获取数据数目
# 通过Bag of Words 转化词向量
vectorizer = CountVectorizer(max_features=3000)
bow_train_data= vectorizer.fit_transform(train_df['text'])

# 通过TF-IDF转化词向量
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
tf_train_data = tfidf.fit_transform(train_df['text'])

# 可选Bag of Words和TF-IDF
#train = bow_train_data[:10000]
#test = bow_train_data[10000:]
train = tf_train_data[:10000]
test = tf_train_data[10000:]
train_label = train_df['label'].values[:10000]
test_label = train_df['label'].values[10000:]

# 岭回归算法
rid_model = RidgeClassifier()

# 朴素贝叶斯算法
nb_model = MultinomialNB(alpha=0.01)

# 支持向量机算法
svm_model = OneVsRestClassifier(SVC(kernel='linear',probability=True, C=1.2))
"""
#参数 “kernel”、“gamma”和“C”对性能影响较大
sklearn.svm.SVC(C=1.0, kernel='rbf', degree=3, gamma=0.0, coef0=0.0, shrinking=True, probability=False,tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, random_state=None)
"""
# K近邻算法
knn_model = KNeighborsClassifier(n_neighbors=8)

def model(clf_model, model_name, train, train_label, test, test_label):
    clf_model.fit(train, train_label)
    predict_results = clf_model.predict(test)
    print(model_name + "score: " + str(f1_score(test_label, predict_results, average='macro')))

# 岭回归算法 + tfidf
model(rid_model, " rid_model", train, train_label, test, test_label)
# 朴素贝叶斯算法 + tfidf
model(nb_model, " nb_model", train, train_label, test, test_label)
# 支持向量机算法 + tfidf
model(svm_model, " svm_model", train, train_label, test, test_label)
# K近邻算法
model(knn_model, " knn_model", train, train_label, test, test_label)
"""
tfidf + 相关机器学习算法输出结果(Bag of Words较低):
 rid_modelscore: 0.8721598830546126
 nb_modelscore: 0.8323669201262175
 svm_modelscore: 0.8799660794185611
 knn_modelscore: 0.8158583357841626
"""

结果分析:根据f1_score的值可以看出使用tfidf+岭回归/SVM较高。

3.TF-IDF参数调节

train_df = pd.read_csv('../dataset/train_set.csv', sep='\t', nrows=15000)  # nrows设置显示获取数据数目
# tfidf 调参
max_features_lsit = [1000, 2000, 3000, 4000, 5000, 6000]  # 设置max_features
for ngram_range in range(1, 4):
    # ngram_range 参数设置1-4
    for max_feature in max_features_lsit:
        tfidf = TfidfVectorizer(ngram_range=(1, ngram_range), max_features=max_feature)
        train_test = tfidf.fit_transform(train_df['text'])
        rid_model = RidgeClassifier()
        rid_model.fit(train_test[:10000], train_df['label'].values[:10000])
        predict_results = rid_model.predict(train_test[10000:])
        print(ngram_range, max_feature, f1_score(train_df['label'].values[10000:], predict_results, average='macro'))
"""
输出结果:
1 1000 0.835944644945302
1 2000 0.8612273690592904
1 3000 0.8588110190969614
1 4000 0.8601916764212559
1 5000 0.8603325900148268
1 6000 0.8603325900148268

2 1000 0.8288900927279318
2 2000 0.8584782097110735
2 3000 0.8726280447745621
2 4000 0.8794233135546486
2 5000 0.8864473704687724
2 6000 0.8877841442863286

3 1000 0.8270776630718544
3 2000 0.8605269056047407
3 3000 0.8721598830546126
3 4000 0.8753274805998447
3 5000 0.8850817067811825
3 6000 0.8901406771892212
"""
"""
3 8000 0.8900057135245728
4 7000 0.8914344232297767
4 8000 0.8929861900360884
5 7000 0.8914513820822496
5 8000 0.8918029951044769
"""

结果分析:通过修改设置max_features,ngram_range参数,可以发现随着两个值的增大f1_score一般是在增大,大约增大到0.89趋势接近平缓。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值