唐宇迪《python数据分析与机器学习实战》学习笔记
16Python文本数据分析:新闻分类任务 (贝叶斯算法应用实例)
**
**
数据如下图:content为主体内容,
1.1 停用词:在语料中大量出现又没啥大用,会干扰统计分析,因此去掉。(例如:一个、一切、¥、#等),网上搜索停用词表,匹配过滤。
1.2 Tf-idf:关键词提取 :
这里修改一下:词频=(某个词在文章出现次数)/(文章总的词汇量)
1.3 相似度
1.4 总结大致流程:语料—清洗(停用词)—分词—构造向量(词频转为向量;词转为向量word2vector、Gensim;整篇文章转为向量不切实)
**
1.1 数据采集及导入
**
首先安装jieba模块,本来打开cmd中输入: pip install jieba 就行,但是我这里报错:Could not find a version that satisfies the requirement skimage (from versions: ) ,这是网络原因,需要使用国内豆瓣的镜像加速。
这里改为: pip install jieba -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com 成功安装。
接着导入库:
import pandas as pd
import jieba
数据的话使用搜狗实验室的数据,数据源:http://www.sogou.com/labs/resource/ca.php,需要提取里面的数据。
这里直接用现成数据。
df_news = pd.read_table('./data/val.txt',names=['category','theme','URL','content'],encoding='utf-8')
df_news = df_news.dropna()
df_news.head()
1.2 转换为list
content = df_news.content.values.tolist()
#结巴分词器,需要把数据的列拿出来再转换list
content[1000]
‘阿里巴巴集团昨日宣布,将在集团管理层面设立首席数据官岗位(Chief\u3000Data\u3000Officer),阿里巴巴B2B公司CEO陆兆禧将会出任上述职务,向集团CEO马云直接汇报。>菹ぃ和6月初的首席风险官职务任命相同,首席数据官亦为阿里巴巴集团在完成与雅虎股权谈判,推进“one\u3000company”目标后,在集团决策层面新增的管理岗位。0⒗锛团昨日表示,“变成一家真正意义上的数据公司”已是战略共识。记者刘夏’
1.3 分词:使用结巴分词器
content_S = [] #存待会分词后的结果
for line in content: #遍历二维list
current_segment = jieba.lcut(line) #把这句话分词
if len(current_segment) > 1 and current_segment != '\r\n':
#确实有分词,而且不包含换行符
content_S.append(current_segment)
content_S[1000]
df_content = pd.DataFrame({'content_S':content_S})
df_content.head()
stopwords = pd.read_csv('stopwords.txt',index_col = False,sep='\t',
quoting=3,names=['stopword'],encoding ='utf-8')
stopwords.head(10)
#定义筛选函数
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.values.tolist()
contents_clean, all_words = drop_stopwords(contents, stopwords)
df_content=pd.DataFrame({'contents_clean':contents_clean}) #每一列的分词
df_content.head()
保留下来的都是主体,这里还有些字母也可以去掉,函数里面定义就行。
看一下,目前去掉停用次后所有出现过得词:
df_all_words=pd.DataFrame({'all_words':all_words})
df_all_words.head()
#统计出现次数
import numpy #通过groupby把相同的分成一堆堆,再用函数统计每堆大小
words_count=df_all_words.groupby(by=['all_words'])['all_words'].agg({"count":numpy.size})##分组大小
print(words_count.head())
#给索引
words_count=words_count.reset_index()
print(words_count.head())
#算完乱序,进行排序
words_count=words_count.sort_values(by=["count"],ascending=False)
print(words_count.head())
1.7 生成词云
wordcloub模块安装:这里我遇到和上面安装相似的问题,所以还是用镜像:pip install wordcloub -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['figure.figsize'] = (10.0, 5.0)
#选择字体、背景颜色、字体最大值
wordcloud=WordCloud(font_path="./data/simhei.ttf",background_color="white",max_font_size=80)
#这里画前100个词
word_frequence = {x[0]:x[1] for x in words_count.head(100).values}
wordcloud=wordcloud.fit_words(word_frequence)
plt.imshow(wordcloud)
plt.show()
import jieba.analyse
index = 2000
print(df_news['content'][index])#打印原始的作对比
print('————————————————')
# 'A'.join(B) 以A作为分隔符,将B中所有的元素合并成一个新的字符串
content_S_str = "".join(content_S[index]) #把分词结果拿出来
print(" ".join(jieba.analyse.extract_tags(content_S_str,topK =5,withWeight=False)))
#关键词提取:传入数据、返回5个关键词、
6月24日,是梅西25岁的生日。《世界体育报》特地为梅西提前做了个专题,梅西手持一件印有他姓氏和25号号码的巴塞罗那球衣,跳蚤提前许下了生日愿望。!拔颐窍氯季的目标,和之前永远相同,那就是踢出漂亮的足球,并且赢得尽可能多的冠军奖杯。”梅西许愿,“如果能再次赢得西甲和欧冠冠军的话,那会非常美妙,我们将会努力再给球迷带来一次双冠王的喜悦。下赛季我的儿子将会出生,对于我来说,这将是一个特殊的赛季。我希望,下赛季对于巴萨而言也会是一个特殊的赛季。”6杂诎腿,梅西永远感激于心:“我永远感激巴萨为我所做的一切,我的病曾经需要巨额治疗资金,巴萨照顾好了我生活的方方面面,巴萨给了我踢足球的机会。这太美妙了,因为巴萨让我梦想成真。”<唇25岁的梅西,一共为巴萨出场329次,跳蚤打进253球,并且已经连续拿到了3个金球奖杯。在团队荣誉方面,梅西代表巴萨和阿根廷国青队拿到了21个冠军头衔。在个人荣誉方面,梅西也拿到了13个奖项,其中包括3个金球奖、1个世界足球先生奖项,2个欧洲金靴奖、2个西甲金靴奖、4个欧冠金靴和1个世青赛金靴。除了世界杯和美洲杯外,梅西拿到了能拿的一切荣誉。在25岁的年龄段上,梅西的成就已经超越了贝利、克鲁伊夫、马拉多纳和迪斯蒂法诺这四大球王。#玻邓甑谋蠢虽然拿到了世界杯冠军,但总奖杯数仅为18个,比梅西少3个。在个人荣誉方面,贝利在国家队只拿了1959年美洲杯金靴。贝利的绝大多数个人荣誉,都是他在巴西国内联赛或者州内部联赛的金靴。25岁的克鲁伊夫拿到了8个冠军和2个个人奖项,25岁的马拉多纳拿到了5个冠军和6个个人奖项,25岁的迪斯蒂法诺拿到了4个冠军和2个个人奖项。无论比团队荣誉还是个人奖项,梅西都是这一年龄段的史上最佳。
————————————————
梅西 巴萨 拿到 奖项 冠军
格式要求:list of list(一篇文章分词后为一个list,多个文章就是list of list) ,分好词的整个语料
安装gensim,我还是用的镜像:pip install gensim -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com ,流程网站:https://blog.csdn.net/sinat_26917383/article/details/79357700#1__27
#导入库
from gensim import corpora,models,similarities
import gensim
#做映射,相当于词带
dictionary = corpora.Dictionary(contents_clean) #做字典,例如:今天映射0、明天2、、、、
corpus = [dictionary.doc2bow (sentence) for sentence in contents_clean]
lda = gensim.models.ldamodel.LdaModel(corpus=corpus,id2word = dictionary,
num_topics=20)
#传语料、传映射字典、得到20个主题(无监督过程,需要一点经验)
lda.print_topic(1,topn=5) #第一类主题的前五个关键词
‘0.014*“电影” + 0.010*“a” + 0.010*“观众” + 0.009*“导演” + 0.007*“中”’
输出20个主题的关键词及其权重:
for topic in lda.print_topics(num_topics=20, num_words=5):
print (topic[1]) #topic[0]为0-20索引
0.010*“中国” + 0.010*“文化” + 0.006*“P” + 0.006*“中” + 0.004*“演出”
0.014*“电影” + 0.010*“a” + 0.010*“观众” + 0.009*“导演” + 0.007*“中”
0.005*“万” + 0.004*“号” + 0.003*“捷克” + 0.003*“中” + 0.003*“面包”
0.008*“中” + 0.004*“发展” + 0.004*“中国” + 0.004*“说” + 0.004*“比赛”
0.012*“说” + 0.007*“孩子” + 0.006*“中” + 0.005*“粉丝” + 0.004*“女儿”
0.009*“e” + 0.007*“女人” + 0.007*“男人” + 0.007*“中” + 0.005*“o”
0.009*“官兵” + 0.006*“部队” + 0.004*“工作” + 0.004*“中” + 0.003*“说”
0.005*“赛季” + 0.005*“中国” + 0.004*“中” + 0.003*“航母” + 0.003*“联赛”
0.031*“e” + 0.026*“o” + 0.025*“i” + 0.023*“a” + 0.023*“n”
0.007*“中” + 0.006*“创作” + 0.005*“饰演” + 0.004*“V” + 0.004*“a”
0.012*“中” + 0.012*“球队” + 0.011*“节目” + 0.010*“选手” + 0.008*“比赛”
0.008*“S” + 0.007*“中” + 0.006*“M” + 0.006*“V” + 0.005*“T”
0.004*“朱丹” + 0.003*“中” + 0.003*“官兵” + 0.003*“学校” + 0.003*“小学”
0.008*“饰演” + 0.008*“中” + 0.006*“中国” + 0.004*“男人” + 0.004*“於”
0.007*“卫视” + 0.006*“中” + 0.005*“万” + 0.005*“比赛” + 0.004*“考生”
0.004*“中国” + 0.004*“中” + 0.003*“S” + 0.003*“菲律宾” + 0.002*“万元”
0.008*“中” + 0.004*“中国” + 0.004*“说” + 0.004*“吃” + 0.004*“美国”
0.004*“吃” + 0.003*“中” + 0.003*“基金” + 0.003*“续约” + 0.002*“端午”
0.005*“万” + 0.005*“a” + 0.004*“号” + 0.004*“e” + 0.004*“N”
0.004*“中” + 0.004*“万” + 0.003*“公司” + 0.003*“S” + 0.003*“中国”
4.1 构造数据
df_train = pd.DataFrame({'contents_clean':contents_clean,'label':df_news['category']})
print(df_train.tail())
print(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) #扩展:map(函数,序列..)接受函数并作用于序列
df_train.head()
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)
print(x_train[0])
print('——————————————————————')
#为了满足向量转换器输入格式而操作,之后有举例方便理解
words = []
for line_index in range(len(x_train)): #一个个转换
try:
words.append(' '.join(x_train[line_index])) #list转string并用空格分开
#Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串
except:
print (line_index)
print(words[0])
print (len(words))
[‘中新网’, ‘上海’, ‘日电’, ‘于俊’, ‘父亲节’, ‘网络’, ‘吃’, ‘一顿’, ‘电影’, ‘快餐’, ‘微’, ‘电影’, ‘爸’, ‘对不起’, ‘我爱你’, ‘定于’, ‘本月’, ‘父亲节’, ‘当天’, ‘各大’, ‘视频’, ‘网站’, ‘首映’, ‘葜’, ‘谱’, ‘鞣’, ‘剑’, ‘保慈’, ‘障蚣’, ‘钦’, ‘呓’, ‘樯’, ‘埽’, ‘⒌’, ‘缬’, ‘埃’, ‘ǎ’, ‘停’, ‘椋’, ‘悖’, ‘颍’, ‘铩’, ‘妫’, ‘椋’, ‘恚’, ‘称’, ‘微型’, ‘电影’, ‘新’, ‘媒体’, ‘平台’, ‘播放’, ‘状态’, ‘短时’, ‘休闲’, ‘状态’, ‘观看’, ‘完整’, ‘策划’, ‘系统’, ‘制作’, ‘体系’, ‘支持’, ‘显示’, ‘较完整’, ‘故事情节’, ‘电影’, ‘微’, ‘超短’, ‘放映’, ‘微’, ‘周期’, ‘制作’, ‘天’, ‘数周’, ‘微’, ‘规模’, ‘投资’, ‘人民币’, ‘几千’, ‘数万元’, ‘每部’, ‘内容’, ‘融合’, ‘幽默’, ‘搞怪’, ‘时尚’, ‘潮流’, ‘人文’, ‘言情’, ‘公益’, ‘教育’, ‘商业’, ‘定制’, ‘主题’, ‘单独’, ‘成篇’, ‘系列’, ‘成剧’, ‘唇’, ‘开播’, ‘微’, ‘电影’, ‘爸’, ‘对不起’, ‘我爱你’, ‘讲述’, ‘一对’, ‘父子’, ‘观念’, ‘缺少’, ‘沟通’, ‘导致’, ‘关系’, ‘父亲’, ‘传统’, ‘固执’, ‘钟情’, ‘传统’, ‘生活’, ‘方式’, ‘儿子’, ‘新派’, ‘音乐’, ‘达’, ‘习惯’, ‘晚出’, ‘早’, ‘生活’, ‘性格’, ‘张扬’, ‘叛逆’, ‘两种’, ‘截然不同’, ‘生活’, ‘方式’, ‘理念’, ‘差异’, ‘一场’, ‘父子’, ‘间’, ‘拉开序幕’, ‘子’, ‘失手’, ‘打破’, ‘父亲’, ‘心爱’, ‘物品’, ‘父亲’, ‘赶出’, ‘家门’, ‘剧情’, ‘演绎’, ‘父亲节’, ‘妹妹’, ‘哥哥’, ‘化解’, ‘父亲’, ‘这场’, ‘矛盾’, ‘映逋坏’, ‘嚼’, ‘斫’, ‘狻’, ‘⒍’, ‘粤’, ‘⒌’, ‘桨容’, ‘争执’, ‘退让’, ‘传统’, ‘尴尬’, ‘父子’, ‘尴尬’, ‘情’, ‘男人’, ‘表达’, ‘心中’, ‘那份’, ‘感恩’, ‘一杯’, ‘滤挂’, ‘咖啡’, ‘父亲节’, ‘变得’, ‘温馨’, ‘镁’, ‘缬’, ‘缮’, ‘虾’, ‘N’, ‘逄’, ‘煳’, ‘幕’, ‘传播’, ‘迪欧’, ‘咖啡’, ‘联合’, ‘出品’, ‘出品人’, ‘希望’, ‘观摩’, ‘扪心自问’, ‘父亲节’, ‘父亲’, ‘记得’, ‘父亲’, ‘生日’, ‘哪一天’, ‘父亲’, ‘爱喝’, ‘跨出’, ‘家门’, ‘那一刻’, ‘感觉’, ‘一颗’, ‘颤动’, ‘心’, ‘操劳’, ‘天下’, ‘儿女’, ‘父亲节’, ‘大声’, ‘喊出’, ‘父亲’, ‘家人’, ‘爱’, ‘完’]
———————————————————————————
中新网 上海 日电 于俊 父亲节 网络 吃 一顿 电影 快餐 微 电影 爸 对不起 我爱你 定于 本月 父亲节 当天 各大 视频 网站 首映 葜 谱 鞣 剑 保慈 障蚣 钦 呓 樯 埽 ⒌ 缬 埃 ǎ 停 椋 悖 颍 铩 妫 椋 恚 称 微型 电影 新 媒体 平台 播放 状态 短时 休闲 状态 观看 完整 策划 系统 制作 体系 支持 显示 较完整 故事情节 电影 微 超短 放映 微 周期 制作 天 数周 微 规模 投资 人民币 几千 数万元 每部 内容 融合 幽默 搞怪 时尚 潮流 人文 言情 公益 教育 商业 定制 主题 单独 成篇 系列 成剧 唇 开播 微 电影 爸 对不起 我爱你 讲述 一对 父子 观念 缺少 沟通 导致 关系 父亲 传统 固执 钟情 传统 生活 方式 儿子 新派 音乐 达 习惯 晚出 早 生活 性格 张扬 叛逆 两种 截然不同 生活 方式 理念 差异 一场 父子 间 拉开序幕 子 失手 打破 父亲 心爱 物品 父亲 赶出 家门 剧情 演绎 父亲节 妹妹 哥哥 化解 父亲 这场 矛盾 映逋坏 嚼 斫 狻 ⒍ 粤 ⒌ 桨容 争执 退让 传统 尴尬 父子 尴尬 情 男人 表达 心中 那份 感恩 一杯 滤挂 咖啡 父亲节 变得 温馨 镁 缬 缮 虾 N 逄 煳 幕 传播 迪欧 咖啡 联合 出品 出品人 希望 观摩 扪心自问 父亲节 父亲 记得 父亲 生日 哪一天 父亲 爱喝 跨出 家门 那一刻 感觉 一颗 颤动 心 操劳 天下 儿女 父亲节 大声 喊出 父亲 家人 爱 完
3750
为理解向量转换器而举例:
from sklearn.feature_extraction.text import CountVectorizer #把词/句子转化为向量
#假装这里有四篇短文
texts = ["dog cat fish","dog cat cat","fish bird","bird"] #向量转换器的输入格式!!!
cv = CountVectorizer() #向量构造器
cv_fit = cv.fit_transform(texts)
print(cv.get_feature_names())
print(cv_fit.toarray())
print('————————')
print(cv_fit.toarray().sum(axis=0))
[‘bird’, ‘cat’, ‘dog’, ‘fish’]
[[0 1 1 1]
[0 2 1 0]
[1 0 0 1]
[1 0 0 0]]
————————
[2 3 2 2]
from sklearn.feature_extraction.text import CountVectorizer
texts = ["dog cat fish","dog cat cat","fish bird","bird"]
cv = CountVectorizer(ngram_range=(1,4))
cv_fit = cv.fit_transform(texts)
print(cv.get_feature_names())
print(cv_fit.toarray())
print(cv_fit.toarray().sum(axis=0))
[‘bird’, ‘cat’, ‘cat cat’, ‘cat fish’, ‘dog’, ‘dog cat’, ‘dog cat cat’, ‘dog cat fish’, ‘fish’, ‘fish bird’]
[[0 1 0 1 1 1 0 1 1 0]
[0 2 1 0 1 1 1 0 0 0]
[1 0 0 0 0 0 0 0 1 1]
[1 0 0 0 0 0 0 0 0 0]]
[2 3 1 1 2 2 1 1 2 1]
4.3 贝叶斯模型
#训练模型建立
from sklearn.feature_extraction.text import CountVectorizer
vec = CountVectorizer(analyzer='word', max_features=4000, lowercase = False)
vec.fit(words)
from sklearn.naive_bayes import MultinomialNB
classifier = MultinomialNB()
classifier.fit(vec.transform(words), y_train)
#进行测试
test_words = []
for line_index in range(len(x_test)):
try:
#x_train[line_index][word_index] = str(x_train[line_index][word_index])
test_words.append(' '.join(x_test[line_index]))
except:
print (line_index)
print('test_words[0]',test_words[0])
print('——————————————‘)
print('test_words_sorce',classifier.score(vec.transform(test_words), y_test))
test_words[0] 国家 公务员 考试 申论 应用文 类 试题 实质 一道 集 概括 分析 提出 解决问题 一体 综合性 试题 说 一道 客观 凝练 申发 论述 文章 题目 分析 历年 国考 申论 真题 公文 类 试题 类型 多样 包括 公文 类 事务性 文书 类 题材 从题 干 作答 材料 内容 整合 分析 无需 太 创造性 发挥 纵观 历年 申论 真题 作答 应用文 类 试题 文种 格式 作出 特别 重在 内容 考查 行文 格式 考生 平常心 面对 应用文 类 试题 准确 把握 作答 领会 内在 含义 把握 题材 主旨 材料 结构 轻松 应对 应用文 类 试题 R 弧 ⒆ 钒 盐 展文 写作 原则 T 材料 中来 应用文 类 试题 材料 总体 把握 客观 考生 材料 中来 材料 中 把握 材料 准确 理解 题材 主旨 T 政府 角度 作答 应用文 类 试题 更应 注重 政府 角度 观点 政府 角度 出发 原则 表述 观点 提出 解决 之策 考生 作答 站 政府 人员 角度 看待 提出 解决问题 T 文体 结构 形式 考查 重点 文体 结构 大部分 评分 关键点 解答 方法 薄 ⒆ ス 丶 词 明 方向 作答 题目 题干 作答 作答 方向 作答 角度 关键 向导 考生 仔细阅读 题干 作答 抓住 关键词 作答 方向 相关 要点 整理 作答 思路 年国考 地市级 真 题为 例 潦惺姓 府 宣传 推进 近海 水域 污染 整治 工作 请 给定 资料 市政府 工作人员 身份 草拟 一份 宣传 纲要 R 求 保对 宣传 内容 要点 提纲挈领 陈述 玻 体现 政府 精神 全市 各界 关心 支持 污染 整治 工作 通俗易懂 超过 字 肮 丶 词 近海 水域 污染 整治 工作 市政府 工作人员 身份 宣传 纲要 提纲挈领 陈述 体现 政府 精神 全市 各界 关心 支持 污染 整治 工作 通俗易懂 提示 归结 作答 要点 包括 污染 情况 原因 解决 对策 作答 思路 情况 原因 对策 意义 逻辑 顺序 安排 文章 结构 病 ⒋ 缶殖 龇 ⅲ 明 结构 解答 应用文 类 试题 考生 材料 整体 出发 大局 出发 高屋建瓴 把握 材料 主题 思想 事件 起因 解决 对策 阅读文章 构建 文章 结构 直至 快速 解答 场 ⒗ 硭 乘悸 罚明 逻辑 应用文 类 试题 严密 逻辑思维 情况 原因 对策 意义 考生 作答 先 弄清楚 解答 思路 统筹安排 脉络 清晰 逻辑 表达 内容 表述 础 把握 明 详略 考生 仔细阅读 分析 揣摩 应用文 类 试题 内容 答题 时要 详略 得当 主次 分明 安排 内容 增加 文章 层次感 阅卷 老师 阅卷 时能 明白 清晰 一目了然 玻埃 保蹦旯 考 考试 申论 试卷 分为 省级 地市级 两套 试卷 能力 大有 省级 申论 试题 考生 宏观 角度看 注重 深度 广度 考生 深谋远虑 地市级 试题 考生 微观 视角 观察 侧重 考查 解决 能力 考生 贯彻执行 作答 区别对待
——————————————————
test_words_sorce 0.804
4.4 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)
print(classifier.score(vectorizer.transform(test_words), y_test))
0.8152