文章目录
前言介绍
内容介绍:建立新闻文章分类模型,使用TF-IDF和词袋模型构建特征,基于贝叶斯算法来完成分类任务。 本文仅作课程学习记录使用,若内容有误请提出指正。
处理流程:新闻数据集处理–文本分词 – 去停用词–构建文本特征–贝叶斯分类
- 构建文本特征:将文本转化成可以用数字表示的特征 ,其中两种方案:1)词袋模型特征; 2)TF-IDF特征
- 贝叶斯分类:基于贝叶斯算法来完成最终的分类任务
数据介绍:来自若干新闻站点2012年6月—7月期间国内,国际,体育,社会,娱乐等18个频道的新闻数据,提供URL和正文信息
格式说明:数据格式为
<doc>
<url>页面URL</url>
<docno>页面ID</docno>
<contenttitle>页面标题</contenttitle>
<content>页面内容</content>
</doc>
注意:content字段去除了HTML标签,保存的是新闻正文文本
数据来源:http://www.sogou.com/labs/resource/ca.php
一、新闻数据集处理
#导入模块包
import pandas as pd
import jieba
#导入数据
df_news = pd.read_table('./data/data.txt',names=['category','theme','URL','content'],encoding='utf-8')
df_news = df_news.dropna()
df_news.tail()
df_news.shape #查看数据规模
爬取的新闻数据,需要我们对文本数据进行很多预处理才能使用
字段含义:
Category:当前新闻所属的类别,一会我们要进行分别任务,这就是标签了。
Theme:新闻的主题,这个咱们先暂时不用,大家在练习的时候也可以把它当作特征。
URL:爬取的界面的链接,方便检验爬取数据是不是完整的,这个咱们暂时也不需要。
Content:新闻的内容,这些就是一篇文章了,里面的内容还是很丰富的。
二、文本分词(jibe分词器)
使用jieba分词器前,要将文章转换成list, 使用.tolist()
content = df_news.content.values.tolist() #将文章转换成list
print (content[1000]) #随便选择其中第1000个看
#结巴分词
content_S = []
for line in content:
current_segment = jieba.lcut(line) #对每一篇文章进行分词
if len(current_segment) > 1 and current_segment != '\r\n': #如果一行的单词大于一,即两个以上,并且并非换行符
content_S.append(current_segment) #保存分词的结果
#结果展示
df_content=pd.DataFrame({'content_S':content_S}) #将结果转换成表格展示
df_content.head()
三、去停用词
分词后,有很多词是不重要的,也是需要过滤的目标。可以使用停用词表过滤文件,或者根据根据词频设定停用词,出现越多的词越不重要。
停用词表是什么?
首先需要选择一个合适的停用词库,这些网上有很多现成的,但是都没那么完整,所以还需要自己添加一些。
#stopwords.txt 停用字符文件
stopwords=pd.read_csv("stopwords.txt",index_col=False,sep="\t",quoting=3,names=['stopword'], encoding='utf-8')
stopwords.head(20)#查看停用字符文件
使用停用词表过滤文件
#过滤文本:将不在停用表的单词加入到line_clean文件里
def drop_stopwords(contents,stopwords):
contents_clean = []
all_words = []
for line in contents:
line_clean = []
for word in line:
if word in stopwords:
continue
line_clean.append(word)
all_words.append(str(word))
contents_clean.append(line_clean)
return contents_clean,all_words
contents = df_content.content_S.values.tolist()
stopwords = stopwords.stopword.tolist() #修改,原代码报错:stopwords.stopword.values.tolist()
contents_clean,all_words = drop_stopwords(contents,stopwords)
#结果展示
df_content=pd.DataFrame({'contents_clean':contents_clean})
df_content.head()
四、构建文本特征
4.1)统计词频
可以用groupby()、count() 统计词频
#词频统计
counts = {}
for word in all_words:
counts[word] = counts.get(word, 0) + 1
items = list(counts.items())
items.sort(key=lambda x:x[1], reverse=True)
for i in range(10):
word, count = items[i]
print("{0:<10}{1:>5}".format(word, count))
words_count=items
4.2)词云展示
from wordcloud import WordCloud
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib
matplotlib.rcParams['figure.figsize'] = (10.0, 5.0)
wordcloud=WordCloud(font_path="./data/simhei.ttf",background_color="white",max_font_size=80)
word_frequence = {x[0]:x[1] for x in words_count[:100]}
wordcloud=wordcloud.fit_words(word_frequence)
plt.imshow(wordcloud)
4.3)TF-IDF :提取关键词
介绍链接:百度百科
通用词:如果一个词通篇出现可能就不重要,比如中国;一个单词在别的文章不出现,但是在这篇文章出现很多次,就很有可能是关键词。
import jieba.analyse #工具包
index = 2400 #随便使用一篇文章
content_S_str = "".join(content_S[index]) #把分词的结果组合在一起,形成一个句子
print (content_S_str) #打印这个句子
print (" ".join(jieba.analyse.extract_tags(content_S_str, topK=5, withWeight=False)))#选出来5个核心词
4.4)数据集标签制作
新闻的分类有很多种,汽车、财经、科技、健康、体育、教育……, 这一步需要将这些分类制作成数值型标签。
df_train=pd.DataFrame({'contents_clean':contents_clean,'label':df_news['category']})
df_train.tail()
df_train.label.unique() #查看一共有多少个标签
#下面将文字标签转换成数字
label_mapping = {"汽车": 1, "财经": 2, "科技": 3, "健康": 4, "体育":5, "教育": 6,"文化": 7,"军事": 8,"娱乐": 9,"时尚": 0}
df_train['label'] = df_train['label'].map(label_mapping) #构建一个映射方法
df_train.head()
五、建立模型
5.1)数据集切分
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(df_train['contents_clean'].values, df_train['label'].values, random_state=1)
#x_train = x_train.flatten()
x_train[0][1]
words = []
for line_index in range(len(x_train)):
try:
#x_train[line_index][word_index] = str(x_train[line_index][word_index])
words.append(' '.join(x_train[line_index]))
except:
print (line_index,word_index)
words[0]
print (len(words)) # 统计有多少个词
结果显示一共有3750个词。
5.2)使用词袋模型的特征来建模
5.2.1)制作词袋模型特征
from sklearn.feature_extraction.text import CountVectorizer
vec = CountVectorizer(analyzer='word', max_features=4000, lowercase = False) #限制条件max_features特征最大长度为4000
feature = vec.fit_transform(words)
如果不进行限制max_features,最终得到的向量长度为85093,这会使得特征长度过大,而且里面很多都是词频很低的词语,也会导致特征过于稀疏。
5.2.2)建模&观察结果
from sklearn.naive_bayes import MultinomialNB #贝叶斯模型
classifier = MultinomialNB()
classifier.fit(feature, y_train)
MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)
test_words = []
for line_index in range(len(x_test)):
try:
#
test_words.append(' '.join(x_test[line_index]))
except:
print (line_index,word_index)
test_words[0]
#模型评估
classifier.score(vec.transform(test_words), y_test)
0.804
表示该模型最后分类
5.3)使用TF-IDF特征建模
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(analyzer='word', max_features=4000, lowercase = False)
vectorizer.fit(words)
from sklearn.naive_bayes import MultinomialNB
classifier = MultinomialNB()
classifier.fit(vectorizer.transform(words), y_train)
classifier.score(vectorizer.transform(test_words), y_test)
最后结果是0.8152,比词袋模型有所提高。