新闻分类入门笔记
导入相关库
import pandas as pd
import jieba #用于分词
import re #正则表达式库
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer #用于生成词向量
from sklearn.model_selection import train_test_split #划分训练集和测试集
from sklearn.naive_bayes import MultinomialNB #用于导入多项式朴素贝叶斯分类器
自定义函数
'''
函数说明:用于加载停用词表
Parameter:
path - 停用词的路径
Return:
stopwords - 停用词列表
Author:
mx
Modify:
2019-10-15 20:02:04
'''
def loadStopwors(path):
stopwrds = []
with open(path, 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
stopwrds.append(line.strip())
return stopwrds
'''
函数说明: 去除停用词
Parameter:
data - 填入要去除停用词的数据(list to list类型或者series类型)如:['a,b,c', 'd,e,f']
stopwords - 停用词列表
Return:
rwrds - 去除停用词后的data
Author:
mx
Modify:
2019-10-15 20:03:04
'''
def removeStopwords(data, stopwords):
r = r'[\u4e00-\u9fa5]+' # 表示包含所有中文的正则表达式
rwrds = []
for line in data:
wrd = []
for w in line:
if w not in stopwords and re.match(r,w): # 取出所有非停用词和非中文
wrd.append(w)
rwrds.append(wrd)
return rwrds
'''
函数说明: 将list to list类型数据转化为带空格的list类型,如将['a,b,c', 'd,e,f']转化为['a b c', 'd e f']
Parameter:
ls - 要转化的list to list类型数据,如['a,b,c', 'd,e,f']
Return:
rls - 转化完的带空格的list类型,如['a b c', 'd e f']
Author:
mx
Modify:
2019-10-15 20:09:29
'''
def ls2blankls(ls):
rls = []
for line in ls:
rls.append(' '.join(line))
return rls
文本预处理
df_ori = pd.read_csv('news_data.txt', sep = '\t', header = 0,
names = ['label', 'title', 'content'], encoding = 'utf-8')
# 读入要处理的数据,其中sep表示分隔符,header=0 是去除第一行中文标签
# 数据来源于处理过后的搜狗新闻数据,当然你可以自己下载数据进行处理,地址如下
# https://www.sogou.com/labs/resource/ca.php
df_ori.head() # 查看前五行数据
label | title | content | |
---|---|---|---|
0 | 汽车 | 新辉腾 4.2 V8 4座加长Individual版2011款 最新报价 | 经销商 电话 试驾/订车U憬杭州滨江区江陵路1780号4008-112233转5864#保常... |
1 | 汽车 | 918 Spyder概念车 | 呼叫热线 4008-100-300 服务邮箱 kf@peopledaily.com.cn |
2 | 汽车 | 日内瓦亮相 MINI性能版/概念车-1.6T引擎 | MINI品牌在二月曾经公布了最新的MINI新概念车Clubvan效果图,不过现在在日内瓦车展... |
3 | 汽车 | 清仓大甩卖一汽夏利N5威志V2低至3.39万 | 清仓大甩卖!一汽夏利N5、威志V2低至3.39万=日,启新中国一汽强势推出一汽夏利N5、威志... |
4 | 汽车 | 大众敞篷家族新成员 高尔夫敞篷版实拍 | 在今年3月的日内瓦车展上,我们见到了高尔夫家族的新成员,高尔夫敞篷版,这款全新敞篷车受到了众... |
# df_ori.describe() #查看数据描述信息(对有数字的列特别有用,可查看数据分布情况,均值,方差...),按需使用
# df_ori.info() #查看数据信息,和上面差不多,按需使用
# df_ori.isnull().sum() #查看数据缺失情况,按需使用
# df_ori.duplicated().sum() #查看数据重复情况,按需使用
# df_ori[(df_ori.duplicated())] #查看重复数据
df_ori.drop_duplicates(inplace=True) #去除重复数据,inplace=True表示改变源数据,默认为False,则不改变源数据
# df_ori.fillna(df_ori.label.mean()) #处理缺失值,可以选择先前.fillna('ffill')向后'bfill',均值填充,
# 当然也可以直接drop。同样有
# inplace参数。(由于上面没有发现缺失值,故不处理缺失值)
df_ori.index = range(df_ori.shape[0]) # 更新索引,因为删除列之后索引会发生变化,所以需更新索引
df_ori.content.shape #看看数据清洗后还剩下多少数据
(4949,)
中文分词
words = [] # 开始中文分词
for line in df_ori.content:
w = jieba.lcut(line)
words.append(w)
Building prefix dict from the default dictionary ...
Loading model from cache /tmp/jieba.cache
Loading model cost 1.077 seconds.
Prefix dict has been built succesfully.
?words
# 可以查看分词后的情况
stopwords = loadStopwors('stopwords.txt') # 加载停用词
rmwords = removeStopwords(words, stopwords) # 去除停用词
df_clean = pd.DataFrame({'content': rmwords, 'label': df_ori.label}) #构建清洗完的df
df_clean.head()
content | label | |
---|---|---|
0 | [经销商, 电话, 试驾, 订车, 憬, 杭州, 滨江区, 江陵, 路, 号, 转, 保常,... | 汽车 |
1 | [呼叫, 热线, 服务, 邮箱] | 汽车 |
2 | [品牌, 二月, 公布, 最新, 新, 概念车, 效果图, 日内瓦, 车展, 品牌, 带来,... | 汽车 |
3 | [清仓, 甩卖, 夏利, 威志, 低至, 万, 启新, 中国, 强势, 推出, 夏利, 威志... | 汽车 |
4 | [日内瓦, 车展, 见到, 高尔夫, 家族, 新, 成员, 高尔夫, 敞篷版, 款, 全新,... | 汽车 |
for i in range(len(df_clean.content)): # 去除回车和只有一个词的行
if len(df_clean.content[i])<2:
df_clean.drop(i,inplace=True)
df_clean.index = range(df_clean.shape[0]) # 重置索引
# content_ls = df_clean.content.tolist() # 将series类型转为list to list类型,因为后面函数接受的是list to list类型
df_clean.content = ls2blankls(df_clean.content) # 将逗号分隔的series转化的数据转化为空格分隔的series
df_clean.head() #看看转化的情况
content | label | |
---|---|---|
0 | 经销商 电话 试驾 订车 憬 杭州 滨江区 江陵 路 号 转 保常 叮 万 阒 菔 邪 自魄... | 汽车 |
1 | 呼叫 热线 服务 邮箱 | 汽车 |
2 | 品牌 二月 公布 最新 新 概念车 效果图 日内瓦 车展 品牌 带来 全新 版 概念车 性能... | 汽车 |
3 | 清仓 甩卖 夏利 威志 低至 万 启新 中国 强势 推出 夏利 威志 清仓 甩卖 活动 冲击... | 汽车 |
4 | 日内瓦 车展 见到 高尔夫 家族 新 成员 高尔夫 敞篷版 款 全新 敞篷车 众多 高尔夫 ... | 汽车 |
构建词向量空间
train_x,test_x,train_y,test_y = train_test_split(df_clean.content,
df_clean.label, test_size = 0.3, random_state = 1)
# 划分训练集和测试集,test_size 表示测试集占比,random_state表示随机数种子
#构造词向量生成器,这里比较了两种分类器
#其中lowcase表示是否要转化为小写,默认是True
# 处理中文时不需要转化,故设为False
# max_feature表示向量基的个数,以词频在前3000的词作为基向量
ctVec = CountVectorizer(encoding= 'utf-8',lowercase= False,
max_features= 3000, analyzer= 'word',)
tfidfVec = TfidfVectorizer()
ctVec.fit(train_x) # 开始转换向量,注意这里只接受列表格式和series格式,并且内部元素为分好词的字符串
tfidfVec.fit(train_x)
TfidfVectorizer(analyzer='word', binary=False, decode_error='strict',
dtype=<class 'numpy.float64'>, encoding='utf-8',
input='content', lowercase=True, max_df=1.0, max_features=None,
min_df=1, ngram_range=(1, 1), norm='l2', preprocessor=None,
smooth_idf=True, stop_words=None, strip_accents=None,
sublinear_tf=False, token_pattern='(?u)\\b\\w\\w+\\b',
tokenizer=None, use_idf=True, vocabulary=None)
# ctVec.get_feature_names()[:100] # 可以查看作为词向量基的词语
模型训练
ctVecclf = MultinomialNB() #选择多项式朴素贝叶斯分类器
ctVecclf.fit(ctVec.transform(train_x), train_y) # 训练数据,注意x是转为向量的x
tfidfVecclf = MultinomialNB()
tfidfVecclf.fit(tfidfVec.transform(train_x), train_y)
MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)
模型评估
print('ctVecclf 的精确度为:{:.4f}'.format(ctVecclf.score(ctVec.transform(test_y), test_y)))
print('tfidfVecclf 的精确度为:{:.4f}'.format(tfidfVecclf.score(tfidfVec.transform(test_x), test_y)))
ctVecclf 的精确度为:0.8960
tfidfVecclf 的精确度为:0.8190
参考资料
https://www.cnblogs.com/datou-swag/articles/10060532.html
https://zhuanlan.zhihu.com/p/30022645
https://www.cnblogs.com/xiaochi/p/10957729.html
http://kreader.cnki.net/Kreader/CatalogViewPage.aspx?dbCode=cdmd&filename=1019114111.nh&tablename=CMFD201902&compose=&first=1&uid=WEEvREcwSlJHSldRa1Fhb09jT0lPd2ZpejlLdnZ2ajJiOGp5T3hEZXo2MD0=$9A4hF_YAuvQ5obgVAqNKPCYcEjKensW4IQMovwHtwkF4VYPoHbKxJw!!
https://www.cnblogs.com/happyfei/p/9498322.html#_label3_0_0_0
https://blog.csdn.net/shener_m/article/details/81047669
思维导图地址:http://naotu.baidu.com/file/509974a4de616d21f58e1be39ee00ba0?token=291de8a34f27a187