??????很典型的多个特征维度的新闻种类分类,包含了例如文本信息如何转换成数字特征 ,如何设置停用词 ,如何去掉符号转大小 ,如何解决内存不足 等等许多问题的解决。包括使用各种分类方法测试最终选择最优的模型。 ??????可以私信提供完整代码工程及其数据集!!!
一、选题背景
??????在智能设备的高度普及和互联网技术的高速发展的同时,信息爆炸已经成为了一个越来越棘手的问题,各类文本信息呈爆炸式增长。新闻文本作为一种重要的数据承载形式有着重要的地位,如何在巨大的信息源中准确、快速的获取到有价值的信息成为人们的迫切需要。新闻文本分类是文本分类研究的一个细分领域,是信息检索、推荐系统等应用领域中必不可少的部分,分类的目标是为每一个新闻文本分配对应标签,标签代表了该新闻期望的分类类型。分类后的新闻文本具有多种用途,如根据不同分类推荐不同广告信息;对候选新闻进行过滤,进而提高推荐系统的准确率;在信息检索中依据类别信息制定不同的检索策略等。新闻已经成为广大网民用户获取各类资讯的重要信息来源,担当了重要的信息传播媒介角色。因此,新闻分类平台具有较大的意义和实用价值。
??????新闻分类问题属于自然语言处理(NLP- Natural Language Processing)领域中的分类问题,是NLP中一个比较经典的问题。通俗来讲就是给定一篇文档,通过算法将文档分为n个类别中的某一类或者多类,相似任务有垃圾邮件识别、情感分析等。一般以已标注好的分类数据为基础,搭建并训练分类模型,利用得到的分类模型来解决分类问题,对未标注的文本数据进行预测,从而产生最终的分类结果。文本分类的处理流程大致分为文本预处理、文本特征提取、分类模型构建等,常用的分类算法包括以传统机器学习方法为主的分类算法,如朴素贝叶斯方法、基于决策树的方法等,以及以神经网络为基础的算法,如卷积网络CNN、循环神经网络 RNN 等。
??????本论文在常用分类方法和文本分类流程研究的基础上,选取随机梯度下降(SGD)分类和卷积神经网络算法搭建分类模型,不断提高测试样本的准确率,使用Python语言搭建了一个具有分类功能的新闻分类系统。
二、分类算法的介绍
??????分类问题是有监督学习的一个核心问题。通过对训练集的学习得到一个分类模型或者对应的决策函数(即分类器),以准确率等指标作为模型的衡量标准。通过分类器对新的输入进行输出类别的预测,即分类。当分类的类别为多个时,为多分类问题,本论文对应的分类任务为多分类问题。
??????常用的文本分类算法主要是以机器学习方法为主的各类有监督及无监督算法,下面针对常用的几个分类算法进行简单介绍。
??????朴素贝叶斯分类(Native Bayes)法是一种生成式模型。他的基本思想是基于贝叶斯定理和特征的条件独立性假设,使用极大似然估计或者贝叶斯估计来得到先验概率P(Y)和条件概率P(X|Y),从而学习出两者的联合概率分布P(X,Y),根据贝叶斯定理求出后验概率最大的类别。贝叶斯定理如下: ??????其中P(Y)与 P(X|Y)已知,条件概率P(X|Y)中X具有多个特征分量,导致其参数数量较多,朴素贝叶斯法对实际计算中需要对其进行条件独立性假设,使每个属性对分类的作用相互独立,从而减少参数数量以及简化模型的训练过程。
??????决策树是一种比较常用的分类和回归算法,是一种具有较高可读性的树形模型。决策树的建立过程可以看作基于文本特征对样本进行分类的过程,每个叶结点对应一个类别,非叶节点代表划分属性。建立决策树模型的关键问题在于划分属性的选择,常用的划分属性选择方法有信息增益、基尼指数等。如决策树ID3算法根据信息增益来进行划分属性选择,C4.5根据信息增益比进行划分,CART分类回归树则是根据基尼指数来进行划分。
??????卷积神经网络(CNN)是一种由卷积和池化操作构成的前馈神经网络,主要用来处理具有网格结构的数据,最早主要应用于图像处理和语音识别领域。CNN出色的特征提取功能,使其在自然语言处理领域也得到了广泛应用,如文本分类、情感分析等问题。卷积网络在处理文本分类任务时,需要将句子或文档按行展开,每行对应一个词的词向量表示,从而将文本表示为一个二维网络结构。
三、模型搭建
3.1 随机梯度下降(SGD)的介绍
??????随机梯度下降(SGD)是一个既有效又简单的方法作用于在诸如(线性)支持向量机和 Logistic回归等凸损失函数下的线性分类器的学习。
??????并且SGD 已经很成功的应用在了大规模下和稀疏机器学习问题上,主要是用于进行文本分类和自然语言处理。对给定一个稀疏的数据,(Sklearn)中的分类器能够很容易的扩展为能够处理超过105个训练样本和超过105个特征的问题。
??????SGD算法是从样本中随机抽出一组,训练后按梯度更新一次,然后再抽取一组,再更新一次,在样本量及其大的情况下,可能不用训练完所有的样本就可以获得一个损失值在可接受范围之内的模型了。随机是指每次迭代过程中,样本都要被随机打乱,有效减小样本之间造成的参数更新抵消问题。该算法通过sklearn中的SGDClassifier实现的,选择的损失函数为Logistic损失函数。
3.2 多层感知器(MLP)介绍
??????多层感知器(MLP),也称为多层神经网络,其结构为:输入层——隐含层(1或n层)——输出层,MLP神经网络不同层之间是全连接;最底层是输入层,中间是隐藏层,最后是输出层。最简单的MLP只有一层隐藏层hidden layer如下图所示:
以3层MLP为例: ??????其中:w为权重矩阵,表示神经元之间的连接强度;b为偏置矩阵,偏置的设置是为了正确分类样本;下标表示层数;函数f是激活函数,起非线性映射的作用,其可将神经元的输出幅度限制在一定范围内,常用的sigmoid函数或者tanh函数。
??????输入层:如一个n维向量X;隐藏层:输出;输出层:隐藏层到输出层可以看成是一个多类别的逻辑回归,表示隐藏层的输出。因此,MLP所有的参数就是各个层之间的连接权重以及偏置,多层感知机的训练学习目的就是确定最佳的参数,具体模型搭建如下图所示: ??????其中:隐含层采用的激活函数是ReLU,并且在隐含层中使用Dropout()函数,将某些神经元设置为0(抑制)。输出层使用softmax()的激活函数。
3.3 具体实现
??????首先,通过构建停用词表,使用正则表达式对字符串进行去除停用词和去除标点符号预处理。正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑,在python中是通过re模块实现的。
??????通过re.sub()函数,将新闻内容中的标点符号替换为空格。re.sub()函数含有5个参数,其中,pattern表示正则中的模式字符串;repl表示要替换的字符串(即匹配到pattern后替换为repl);string表示要被处理的原始数据,预处理结果如下图所示:
其次,将新闻类别标签数值化,结果如下图所示: ??????CountVectorize是属于常见的特征数值计算类,是一个文本特征提取方法。对于每一个训练文本,它只考虑每种词汇在该训练文本中出现的频率。CountVectorizer会将文本中的词语转换为词频矩阵,它通过fit_transform函数计算各个词语出现的次数。CountVectorizer类的参数很多,本文设置的参数是:ngram_range、max_features。其中,ngram_range表示词组切分的长度范围;max_features表示对所有关键词的term frequency进行降序排序,只取前max_features个作为关键词集。
四、结果及说明
??????通过多项式朴素贝叶斯(MultinomialNB)对News_Category_Dataset_train新闻进行分类,得到的准确率为74.6%左右。通过搭建MLP模型,对新闻进行分类,得到准确率为78%左右,同时,通过随机梯度下降分类器对新闻进行分类,得到准确率为79%左右,具体结果如下图所示:
图 MLP结果 图 MultinomialNB和SGD结果
五、设计中遇到的困难
5.1未解决的困难:
- 在预处理方面做了很多尝试,想要去掉某些特征字段,但是效果都不是很理想,预处理后查看特征可以很明显的看出来模型分类中要素占比最多的字段是网站链接其次是作者。尝试去掉这两个字段,希望能从标题和主旨字段提取有效信息进行分类,但是效果都不尽人意。个人认为主要的原因是单词数量过少,如果有全篇文本分析效果应该会更好。
- 准确率稳定在79%,对于这个结果并不是很满意,尝试了几乎所有的分类模型,不断调参但都很难有所提升,感觉关键原因还是在预处理方面。
- 在尝试cnn rnn MLP模型,最常见的错误就是内存不足,只能不断减少训练的样本数量或者减少特征,但对准确率都会有所影响。
附录-代码
import json
import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer,TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.model_selection import train_test_split
import jieba.analyse
from sklearn.linear_model import SGDClassifier
with open('stopwords.txt', 'rb') as fp:
stopword = fp.read().decode('utf-8')
stpwrdlst = stopword.splitlines()
tmp = []
tmp_new_feature=[]
tmp_new_label=[]
for line in open("News_Category_Dataset_train.json",'r'):
tmp.append(json.loads(line))
tmp_new=[]
dict={}
for i in tmp:
a=''.join(list(i.values())[0:1])
dict[a]=dict.get(a, 0)
if int(dict[a]) < 2000:
dict[a]=dict[a]+1
tmp_new.append(i)
else:
pass
print(np.shape(tmp_new))
import re
for i in tmp_new:
aa=list(i.values())[1:]
dd=' '.join(list(aa))
r = '[’!"#$%&\'()*+,:;<=>?@[\\]^_`{|}~\n。!,]+'
line = re.sub(r, ' ', dd)
lower=line.lower()
new=ting_yong_ci(lower)
tmp_new_feature.append(new)
print(np.array(tmp_new_feature))
for i in tmp_new:
tmp_new_label.append(list(i.values())[0:1])
x = []
label = []
j = 0
for i in tmp_new_label:
if i not in x:
x.append(i)
i = j
label.append(i)
j = j+1
else:
pos = x.index(i)
i = pos
label.append(i)
print(x)
cv=CountVectorizer(stop_words=None,ngram_range=(1,2))
cv_fit=cv.fit_transform(tmp_new_feature)
X_train, X_test, y_train, y_test = train_test_split(cv_fit, label, test_size=0.33, random_state=0)
print(cv.get_feature_names())
print(np.shape(cv.get_feature_names()))
print(cv.vocabulary_)
print(cv.stop_words_)
from sklearn.naive_bayes import MultinomialNB
clf1 = MultinomialNB(alpha=0.001)
clf1.fit(X_train,y_train)
y_predicet = clf1.predict(X_test)
score=clf1.score(X_test,y_test)
print('----------------------------------------')
print('多项式朴素贝叶斯:',score)
print('----------------------------------------')
clf = SGDClassifier(loss = 'log')
clf.fit(X_train,y_train)
y_predicet = clf.predict(X_test)
score=clf.score(X_test,y_test)
print('随机梯度下降分类器:',score)
print('----------------------------------------')
cv=CountVectorizer(ngram_range=(1,2),max_features=10000)
cv_fit=cv.fit_transform(tmp_new_feature)
cv_fit=cv_fit.toarray()
print(np.shape(cv_fit))
X_train, X_test, y_train, y_test = train_test_split(cv_fit, label, test_size=0.2, random_state=0)
model = models.Sequential()
model.add(Dense(128, activation='relu', input_dim=10000))
model.add(Dropout(0.4))
model.add(Dense(41, activation='softmax'))
model.compile(loss='sparse_categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
model.fit(X_train, y_train,
epochs=10,
batch_size=128)
score = model.evaluate(X_test, y_test)
print(score)
|