问题背景:
公众平台的公众号每天都会发布大量文章,通过群发图文的形式向用户每天推送内容。由于公众号面向的用户群体、专注的领域不同,图文内容也差异很大。一些公众号主要发布时事政治内容,而另外一些公众号主要发布游戏的视频与周边等。识别公众号的内容对公众平台的运营与新场景应用发挥重要作用,其中对公众号文本的挖掘能力是一个基础能力。本次题目选择时尚类公众号的文章,关注化妆个护领域,要求根据给出的文章内容(已分词)识别出该文章是否向用户推荐化妆个护相关的商品。
知识背景:
(一)、文本预处理
1.数据清洗:对于爬虫爬取的HTML原始文本,需要进行数据清洗过滤掉标签文本。
2.分词(只针对中文文本):对于中文文本数据,比如一条中文的句子,词语词之间是连续的,而数据分析的最小单位粒度我们希望是词语,所以我们需要进行分词工作,这样就给下一步的工作做准备。
3.词性标注(可选):词性标注POS的目的是为了让句子在后面的处理中融入更多的有用的语言信息。不过对于一些文本处理任务,这一步不是必须的。
4.去停用词:停用词stopword是指那些对文本特征没有任何贡献作用的词语,例如一些语气助词和一些标点符号。在一些文本也能针对性的去掉一些词,如形容词
(二)、构造文本特征
将文本符号转换成或者表示成能让学习模型能够处理的数据类型,也就是将文本符号串转变为数字,更确切的说是向量阵列:矩阵。一般使用的方法有词袋(count,tf-idf)和词向量(word2vec,glove)。
(三)、特征选择
在文本挖掘与文本分类的有关问题中,常采用特征选择方法。原因是文本的特征一般都是单词(term),具有语义信息,使用特征选择找出的k维子集,仍然是单词作为特征,保留了语义信息,而特征提取则找k维新空间,将会丧失了语义信息。常用方法有DF(Document Frequency),MI(Mutual Information),IG(Information Gain),CHI(Chi-square,也就是卡方),WLLR(Weighted Log Likelihood Ration)等。
(四)、学习模型训练
将文本表示为广义特征数据结构以后,将特征放入学习模型,然后用于测试数据集的预测,得到结果。本次作业使用决策树模型进行文本分类。
模型评估,评价指标通常由准确率,AUC和F1。
AUC:ROC全称是“受试者工作特征”(Receiver Operating Characteristic)。ROC曲线的面积就是AUC(Area Under the Curve)。AUC用于衡量“二分类问题”机器学习算法性能(泛化能力)。
F1:F1分数可以看作是模型准确率和召回率的一种加权平均,它的最大值是1,最小值是0。
(五)词袋模型原理
Bag-of-words模型是信息检索领域常用的文档表示方法。
在信息检索中,BOW模型假定对于一个文档,忽略它的单词顺序和语法、句法等要素,将其仅仅看作是若干个词汇的集合,文档中每个单词的出现都是独立的,不依赖于其它单词是否出现。(是不关顺序的)
Wikipedia[1]上给出了如下例子:
John likes to watch movies.
Mary likes too.John also likes to watch football games.
根据上述两句话中出现的单词, 我们能构建出一个字典 (dictionary):
{"John": 1, "likes": 2, "to": 3, "watch": 4, "movies": 5, "also": 6, "football": 7, "games": 8, "Mary": 9, "too": 10}
该字典中包含10个单词, 每个单词有唯一索引, 注意它们的顺序和出现在句子中的顺序没有关联. 根据这个字典, 我们能将上述两句话重新表达为下述两个向量:
[1, 2, 1, 1, 1, 0, 0, 0, 1, 1]
[1, 1, 1, 1, 0, 1, 1, 1, 0, 0]
这两个向量共包含10个元素, 其中第i个元素表示字典中第i个单词在句子中出现的次数. 因此BoW模型可认为是一种统计直方图 (histogram). 在文本检索和处理应用中, 可以通过该模型很方便的计算词频.但是从上面我们也能够看出,在构造文档向量的过程中可以看到,我们并没有表达单词在原来句子中出现的次序
适用场景:
现在想象在一个巨大的文档集合D,里面一共有M个文档,而文档里面的所有单词提取出来后,一起构成一个包含N个单词的词典,利用Bag-of-words模型,每个文档都可以被表示成为一个N维向量。变为N维向量之后,很多问题就变得非常好解了,计算机非常擅长于处理数值向量,我们可以通过余弦来求两个文档之间的相似度,也可以将这个向量作为特征向量送入分类器进行主题分类等一系列功能中去。
(6)决策树原理
分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点和有向边组成。结点有两种类型:内部节点和叶节点,内部节点表示一个特征或属性,叶节点表示一个类。分类的时候,从根节点开始,对实例的某一个特征进行测试,根据测试结果,将实例分配到其子结点;此时,每一个子结点对应着该特征的一个取值。如此递归向下移动,直至达到叶结点,最后将实例分配到叶结点的类中。通俗点说就是一个if-then的过程。常见的决策树有ID3、C4.5、CART等。
处理过程:
由于文本已经过已经过分词处理,所以接下来的工作就比较简单。思路如下:把文本用词袋模型表示出来,经过特征选择,降低每个文本向量的维度,然后通过训练集(train.tsv)训练出一个决策树模型,对测试集(test.tsv)进行分类。
结果:
改进之处:
可以看到,利用python中sklearn的决策树进行分类,准确只有大概72%,不是特别的高。如果想提高准确率,可以从以下几个方面入手:
1、增加训练集的数据量。决策树是一种有监督学习,训练集的数据量越大,得到的模型就越完善,进行分类时就越准确。
2、构造文本特征的时候,利用TF-IDF(词频-逆文档频率)值作为权重,这样得到的词袋模型就更加准确,我使用的利用TF(词频)作为权重,这样势必会受到一些词频高,但与文章主题内容不相关的词语影响,在决策树进行训练时会产生错误的划分。
3、使用更完善的决策树,如GDBT、xgboost决策树。xgboost决策树是n颗cart决策树互相作用得到的一种决策树模型。
源代码:
# -*- coding: utf-8 -*-import pandas as pdimport os,sysimport numpy as npimport jiebafrom sklearn.externals import joblibfrom sklearn.feature_extraction.text import CountVectorizerfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn import treetrain ="trian.tsv"train_df = pd.read_csv(r"train.tsv", sep="\t")test_df = pd.read_csv(r'test2.tsv', sep="\t")train_df_X = train_df.content.values.tolist() # to listtrain_df_y = train_df.label.values.tolist()test_df_X = test_df.content.values.tolist()test_df_y = test_df.label.values.tolist()def preprocess_text(content_lists, sentences, label_lists):for i in range(0, len(content_lists)):line = content_lists[i]label = label_lists[i]try:segs = line.split("|")segs = [v for v in segs if not str(v).isdigit()] # 去数字segs = list(filter(lambda x: x.strip(), segs)) # 去左右空格segs = list(filter(lambda x: len(x) > 1, segs)) # 长度为1的字符sentences.append((" ".join(segs), label))except Exception:print(line)continue# 生成训练数据sentences_train = []preprocess_text(train_df_X, sentences_train, train_df_y)# 生成测试数据sentences_test = []preprocess_text(test_df_X, sentences_test, test_df_y)x_train, y_train = zip(*sentences_train)x_test, y_test = zip(*sentences_test)vec = CountVectorizer(analyzer='word', # tokenise by character ngramsmax_features=3500, )vec.fit(x_train)vec.fit(x_test)clf = tree.DecisionTreeClassifier(criterion="entropy", min_samples_split=4)clf = clf.fit(vec.transform(x_train), y_train)os.chdir("E:\\Users\\Administrator\\PycharmProjects\\untitled1\\model_save")joblib.dump(clf,'model_save/train_mode1.m')#保存决策树模型,下次直接调用即可clf=joblib.load('model_save/train_mode1.m')#调用决策树模型print(clf.score(vec.transform(x_test), y_test))#输出准确率
如果觉得《利用决策树对微信公众号文本进行分类》对你有帮助,请点赞、收藏,并留下你的观点哦!