美文网首页机器学习与数据挖掘自然语言处理(NLP)
中文新闻分类,逻辑回归大战朴素贝叶斯

中文新闻分类,逻辑回归大战朴素贝叶斯

作者: 松鼠的读书笔记 | 来源:发表于2019-02-26 17:55 被阅读69次

1 问题背景

我们有一堆新闻文本数据,包含“新闻类别”、“新闻内容”两列,希望建立一个模型,来预测新闻内容属于哪个类别。

这是一个文本分类问题,朴素贝叶斯和逻辑回归可以说是文本分类最常用的Baseline模型,今天小树带大家来看看,朴素贝叶斯和逻辑回归效果如何以及它们两个究竟谁更厉害。

操作环境:jupyter notebook + python3
预备知识:中文分词、tf-idf、朴素贝叶斯模型、逻辑回归模型

2 加载相关包

import numpy as np
import pandas as pd
import random
from sklearn.svm import SVC
from sklearn import preprocessing, decomposition, model_selection, metrics, pipeline
from sklearn.model_selection import GridSearchCV
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.decomposition import TruncatedSVD
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import MultinomialNB

3 加载数据并进行数据预处理

(1)加载数据

# load data
data = [[i.split("\t")[0],i.split("\t")[1]] for i in open(u"data/cnews.train.txt","r", encoding="utf-8")]
# 打乱数据
random.shuffle(data)
data[1]
output

(2)分词,标签转换,求tf-idf

# 对新闻内容进行分词
import jieba
jieba.enable_parallel() #并行分词开启
terms = [" ".join([j for j in jieba.cut(i[1])]) 
         for i in data[:1000]]

#接下来用scikit-learn中的LabelEncoder将文本标签(Text Label)转化为数字(Integer)
lbl_enc = preprocessing.LabelEncoder()
y = lbl_enc.fit_transform([i[0] for i in data[:1000]])

from sklearn.feature_extraction.text import TfidfVectorizer
# 初始化TFidf对象,去停用词,加2元语言模型
tfv = TfidfVectorizer(min_df=3,  max_features=None, strip_accents='unicode', analyzer='word',token_pattern=r'\w{1,}', ngram_range=(1, 2), use_idf=1,smooth_idf=1,sublinear_tf=1, stop_words = 'english')

tfv.fit(terms)
X_all = tfv.transform(terms)

(3)观察label分布,划分数据集

len_train = 600
X_train = X_all[:len_train] 
y_train = y[:len_train]
X_test = X_all[len_train:]
y_test = y[len_train:]

print('X_train shape: ', X.shape)
print('y_train shape: ', y_train.shape)
print('X_test shape: ', X_test.shape)
print('y_test shape: ', y_test.shape)

# 观察label的分布: 共有10个类别,类别均衡
label_data = pd.DataFrame({'label':y})
print('\nDistribution of all label:\n', label_data.label.value_counts())
output

从上面的数据可以得到两点结论:

  • 我们的特征有29812个,而训练样本只有600个,特征维度远远大于训练样本数量,因此特征空间是非常稀疏的。
  • 从label的分布来看,各个类别是平衡的。

4 定义评估标准

这是一个典型的多分类问题,采用常用的multi-class log loss进行评估。

def multiclass_logloss(actual, predicted, eps=1e-15):
    """
    对数损失度量(Logarithmic Loss  Metric)的多分类版本。
    :param actual: 包含actual target classes的数组
    :param predicted: 分类预测结果矩阵, 每个类别都有一个概率
    """
    # Convert 'actual' to a binary array if it's not already:
    if len(actual.shape) == 1:
        actual2 = np.zeros((actual.shape[0], predicted.shape[1]))
        for i, val in enumerate(actual):
            actual2[i, val] = 1
        actual = actual2

    clip = np.clip(predicted, eps, 1 - eps)
    rows = actual.shape[0]
    vsota = np.sum(actual * np.log(clip))
    return -1.0 / rows * vsota

好了,万事俱备,开始激动人心的建模时刻!

5 朴素贝叶斯 vs 逻辑回归

step 1 建立一个朴素贝叶斯的baseline模型

clf_nb = MultinomialNB()   # 多项式朴素贝叶斯
clf_nb.fit(X_train, y_train)
predictions = clf_nb.predict_proba(X_test)

print ("logloss: %0.3f " % multiclass_logloss(y_test, predictions))

logloss: 1.111

朴素贝叶斯在测试集上的logloss为1.111, 效果不太好,没关系,我们把这个作为baseline。

step 2 建立一个逻辑回归模型来对比看看

clf_lr = LogisticRegression(C=1.0,solver='lbfgs',multi_class='multinomial')
clf_lr.fit(X_train, y_train)
predictions = clf_lr.predict_proba(X_test)

print ("logloss: %0.3f " % multiclass_logloss(y_test, predictions))

logloss: 1.223

看起来似乎逻辑回归比朴素贝叶斯效果还差喔。

step 3 我们来调参吧

# 创建评分函数
mll_scorer = metrics.make_scorer(multiclass_logloss, greater_is_better=False, needs_proba=True)

(1)朴素贝叶斯调参

nb_model = MultinomialNB()

# 创建pipeline 
clf = pipeline.Pipeline([('nb', nb_model)])

# 搜索参数设置
param_grid = {'nb__alpha': [0.001, 0.01, 0.1, 1, 10, 100]}

# 网格搜索模型(Grid Search Model)初始化
model = GridSearchCV(estimator=clf, param_grid=param_grid, scoring=mll_scorer,
                                 verbose=10, n_jobs=-1, iid=True, refit=True, cv=6)

# fit网格搜索模型
model.fit(X_train, y_train)
print("Best score: %0.3f" % model.best_score_)
print("Best parameters set:")
best_parameters = model.best_estimator_.get_params()
for param_name in sorted(param_grid.keys()):
    print("\t%s: %r" % (param_name, best_parameters[param_name]))

Best parameters set: nb__alpha: 0.1

我们发现alpha = 0.1时,模型效果最好,用这个参数重新跑跑看

# 使用最优参数建模
clf_nb = MultinomialNB(alpha=0.1)
clf_nb.fit(X_train, y_train)
predictions = clf_nb.predict_proba(X_test)

print ("logloss: %0.3f " % multiclass_logloss(y_test, predictions))

logloss: 0.243

朴素贝叶斯调参后logloss 从1.111 直接降到了0.243,惊不惊喜,意不意外!只是简单的调参就收获了如此大的性能提升,而且0.243这个表现说明朴素贝叶斯的效果还是杠杠的哟。

下面来看看逻辑回归调参之后能否反超朴素贝叶斯!

(2)逻辑回归调参

lr_model = LogisticRegression(solver='lbfgs',multi_class='multinomial')

# 创建pipeline 
clf = pipeline.Pipeline([('lr', lr_model)])

# 搜索参数设置
param_grid = {'lr__C': [0.1, 1.0, 10]}

# 网格搜索模型(Grid Search Model)初始化
model = GridSearchCV(estimator=clf, param_grid=param_grid, scoring=mll_scorer,
                                 verbose=10, n_jobs=-1, iid=True, refit=True, cv=6)

# fit网格搜索模型
model.fit(X_train, y_train)
print("Best score: %0.3f" % model.best_score_)
print("Best parameters set:")
best_parameters = model.best_estimator_.get_params()
for param_name in sorted(param_grid.keys()):
    print("\t%s: %r" % (param_name, best_parameters[param_name]))

Best parameters set: lr__C: 10

用这个最优参数重新训练模型:

clf_lr = LogisticRegression(C=10, solver='lbfgs',multi_class='multinomial')
clf_lr.fit(X_train, y_train)
predictions = clf_lr.predict_proba(X_test)

print ("logloss: %0.3f " % multiclass_logloss(y_test, predictions))

logloss: 0.546

调参后逻辑回归的表现也变好了很多,但是跟朴素贝叶斯比,还是相去甚远,看起来好像还是朴素贝叶斯更厉害嘛!逻辑回归还有翻盘的机会吗?

前面提到,我们的数据是训练样本很少,而特征维度非常高,这种情形下,很容易发生过拟合!!!!

那怎么办?我有一个大胆的想法...

我们重新调逻辑回归的(L2)正则化系数,加大加大,人有多大胆,地有多大产!!!

lr_model = LogisticRegression(solver='lbfgs',multi_class='multinomial')

# 创建pipeline 
clf = pipeline.Pipeline([('lr', lr_model)])

# 搜索参数设置
param_grid = {'lr__C': [1000,10000,100000,1000000, 10000000, 100000000]}

# 网格搜索模型(Grid Search Model)初始化
model = GridSearchCV(estimator=clf, param_grid=param_grid, scoring=mll_scorer,
                                 verbose=10, n_jobs=-1, iid=True, refit=True, cv=6)

# fit网格搜索模型
model.fit(X_train, y_train)
print("Best score: %0.3f" % model.best_score_)
print("Best parameters set:")
best_parameters = model.best_estimator_.get_params()
for param_name in sorted(param_grid.keys()):
    print("\t%s: %r" % (param_name, best_parameters[param_name]))

Best parameters set: lr__C: 1000000

小树这辈子就没见过这么大的正则化系数...看看它是不是虚张声势先!

clf_lr = LogisticRegression(C=1000000, solver='lbfgs',multi_class='multinomial')
clf_lr.fit(X_train, y_train)
predictions = clf_lr.predict_proba(X_test)

print ("logloss: %0.3f " % multiclass_logloss(y_test, predictions))

logloss: 0.125

佩服三连.jpg !!!好了,贝叶斯你跪下叫爸爸吧!!!

。。。。。。

贝叶斯表示不服,这过拟合上天了,全靠惩罚系数,能不能来点正常的套路?!

那降维打击了解一下?

#使用SVD(奇异值分解)进行降维,components设为180,对于SVM来说,SVD的components的合适调整区间一般为120~200 
svd = decomposition.TruncatedSVD(n_components=180)
svd.fit(X_train)
xtrain_svd = svd.transform(X_train)
xtest_svd = svd.transform(X_test)

#对从SVD获得的数据进行缩放
scl = preprocessing.StandardScaler()
scl.fit(xtrain_svd)
xtrain_svd_scl = scl.transform(xtrain_svd)
xtest_svd_scl = scl.transform(xtest_svd)

# 看看降维后LR的效果
clf_lr = LogisticRegression(C=100, solver='lbfgs',multi_class='multinomial')
clf_lr.fit(xtrain_svd_scl, y_train)
predictions = clf_lr.predict_proba(xtest_svd_scl)

print ("logloss: %0.3f " % multiclass_logloss(y_test, predictions))

logloss: 0.144

贝叶斯,卒。至此,逻辑回归大获全胜!


参考资料:

[1] 网易云课堂AI工程师(自然语言处理)-文本分类
[2] 【NLP文本分类】各种文本分类算法集锦,从入门到精通

相关文章

  • 中文新闻分类,逻辑回归大战朴素贝叶斯

    1 问题背景 我们有一堆新闻文本数据,包含“新闻类别”、“新闻内容”两列,希望建立一个模型,来预测新闻内容属于哪个...

  • 深度学习知识点汇总-机器学习基础(6)

    2.6 逻辑回归与朴素贝叶斯有什么区别? 逻辑回归是判别模型, 朴素贝叶斯是生成模型。 朴素贝叶斯属于贝叶斯,逻辑...

  • 数据挖掘-分类

    分类--逻辑回归,朴素贝叶斯,决策树,随机森林,GDBT,XGBoost 分类评估--正确率,精度,召回率,F1值...

  • 朴素贝叶斯法

    朴素贝叶斯法 朴素贝叶斯法的学习与分类 朴素贝叶斯法的参数估计 朴素贝叶斯实现 高斯朴素贝叶斯实现 使用 skle...

  • Logistic Regression vs Naive Bay

    相同 逻辑回归和朴素贝叶斯都是对条件概率进行建模,使得最终的分类结果有很好的解释性。 不同 具体流程 逻辑回归:假...

  • 轻松带你搞懂朴素贝叶斯分类算法

    贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。而朴素朴素贝叶斯分类是贝叶斯分类...

  • 机器学习算法朴素贝叶斯分类

    贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。而朴素朴素贝叶斯分类是贝叶斯分类...

  • 监督学习之概率模型

    贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。而朴素朴素贝叶斯分类是贝叶斯分类...

  • 朴素贝叶斯

    朴素贝叶斯 用处:朴素贝叶斯主要解决的是而分类的问题。 为什么叫朴素贝叶斯: 因为贝叶斯分类只做最原始,最简单的假...

  • 朴素贝叶斯法(NaiveBayes)

    朴素贝叶斯法(Naive Bayes) 朴素贝叶斯法是基于贝叶斯定力和特征条件独立假设的分类方法。 朴素贝叶斯法实...

网友评论

    本文标题:中文新闻分类,逻辑回归大战朴素贝叶斯

    本文链接:https://www.haomeiwen.com/subject/uulwyqtx.html