机器学习入门 --- 贝叶斯 - 中文新闻分类任务

文本分析

停用词

语料中大量出现,但没有大的用处

Tf-idf 关键词提取

T F − I D F = 词 频 ( T F ) ∗ 逆 文 档 频 率 ( I D F ) TF-IDF = 词频(TF)*逆文档频率(IDF) TFIDF=(TF)(IDF)

假设拿到一个文章:《中国的蜜蜂养殖》

进行词频(Term Frequency,缩写为TF)统计

词 频 ( T F ) = 某 个 词 在 文 章 中 的 出 现 次 数 该 文 章 中 总 词 量 词频(TF) = \frac{某个词在文章中的出现次数}{该文章中总词量} (TF)=

统计出现次数最多的词是 “的”、“是”、“在” 这一类最常用的词(停用词)由此可见,停用词对我们做词频统计有比较大的影响,我们首先就要去掉这些停用词,去掉停用词后,再作统计,结果显示“中国”、“蜜蜂”、“养殖”这三个词的出现次数一样多,但重要性不同,因为"中国"是很常见的词,相对而言,"蜜蜂"和"养殖"不那么常见,所以本文题主应该是与"蜜蜂"和"养殖"有较大的关系

“逆文档频率”(Inverse Document Frequency,缩写为IDF)

如果某个词比较少见,但是它在这篇文章中多次出现,那么它很可能就反映了这篇文章的特性正是我们所需要的关键词

逆 文 档 频 率 ( I D F = l o g ( 语 料 库 的 文 档 总 数 包 含 该 词 的 文 档 数 + 1 ) ) 逆文档频率(IDF=log(\frac{语料库的文档总数}{包含该词的文档数+1})) (IDF=log(+1))

IDF越大,该词越重要

例子

《中国的蜜蜂养殖》:假定该文长度为1000个词,“中国”、“蜜蜂”、“养殖"各出现20次,则这三个词的"词频”(TF)都为0.02

搜索Google发现,包含"的"字的网页共有250亿张,假定这就是中文网页总数。包含"中国"的网页共有62.3亿张,包含"蜜蜂"的网页为0.484亿张,包含"养殖"的网页为0.973亿张

\包含该词的文档数(亿)IDFTF-IDF
中国62.30.6030.0121
蜜蜂0.4842.7130.0543
养殖0.9732.4100.0482

通过表格可以发现,“蜜蜂”、“养殖”的TF-IDF比较高,证明比较重要

相似度

假设句子A/B
句子A:我喜欢看电视,不喜欢看电影
句子B:我不喜欢看电视,也不喜欢看电影

分词
句子A:我/喜欢/看/电视,不/喜欢/看/电影
句子B:我/不/喜欢/看/电视,也/不/喜欢/看/电影

语料库
我,喜欢,看,电视,电影,不,也

词频
句子A:我 1,喜欢 2,看 2,电视 1,电影 1,不 1,也 0
句子B:我 1,喜欢 2,看 2,电视 1,电影 1,不 2,也 1

词频向量
句子A:[1, 2, 2, 1, 1, 1, 0]
句子B:[1, 2, 2, 1, 1, 2, 1]

计算相似度公式:

余弦相似度
c o s θ = ∑ i = 1 n ( A i ∗ B i ) ∑ i = 1 n ( A i ) 2 ∗ ∑ i = 1 n B i 2 = A ∗ B ∣ A ∣ ∗ ∣ B ∣ cos\theta = \frac{\sum_{i=1}^n(A_i*B_i)}{\sqrt{\sum_{i=1}^n(A_i)^2}*\sum_{i=1}^n{B_i}^2}=\frac{A*B}{|A|*|B|} cosθ=i=1n(Ai)2 i=1nBi2i=1n(AiBi)=ABAB

新闻数据

数据来源:搜狗实验室 - 全网新闻数据(SogouCA)

读取数据

import pandas as pd
df_news = pd.read_table('./data/val.txt',names=['category','theme','URL','content'],encoding='utf-8')
df_news = df_news.dropna()
df_news.head()

在这里插入图片描述
分词:使用结吧分词器

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类型
df_content=pd.DataFrame({'content_S':content_S})

在这里插入图片描述

# 读入停用词
stopwords=pd.read_csv("stopwords.txt",index_col=False,sep="\t",quoting=3,names=['stopword'], encoding='utf-8')

数据清洗,去掉停用词

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格式
df_content=pd.DataFrame({'contents_clean':contents_clean})

在这里插入图片描述
统计词频

import numpy
df_all_words=pd.DataFrame({'all_words':all_words})
words_count=df_all_words.groupby(by=['all_words'])['all_words'].agg({"count":numpy.size})
words_count=words_count.reset_index().sort_values(by=["count"],ascending=False)

在这里插入图片描述
使用 WordCloud,对所有词中的高词频做一个词云展示

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.head(100).values}
wordcloud=wordcloud.fit_words(word_frequence)
plt.imshow(wordcloud)

在这里插入图片描述

关键词提取

TF-IDF :提取关键词

import jieba.analyse
index = 1000
print (df_news['content'][index])
content_S_str = "".join(content_S[index])  
# jieba.analyse.extract_tags 提取关键词 topK=* 返回*个
print ("  ".join(jieba.analyse.extract_tags(content_S_str, topK=5, withWeight=False)))
阿里巴巴集团昨日宣布,将在集团管理层面设立首席数据官岗位(Chief Data Officer),阿里巴巴B2B公司CEO陆兆禧将会出任上述职务,向集团CEO马云直接汇报。>菹ぃ和6月初的首席风险官职务任命相同,首席数据官亦为阿里巴巴集团在完成与雅虎股权谈判,推进“one company”目标后,在集团决策层面新增的管理岗位。0⒗锛团昨日表示,“变成一家真正意义上的数据公司”已是战略共识。记者刘夏
阿里巴巴  集团  首席  岗位  数据

LDA :主题模型

使用 Gensim 构建 LDA 模型 Gensim官方API文档

格式要求:list of list形式,分词好的的整个语料

建模

import gensim
from gensim import corpora, models, similarities
# 做映射,相当于词袋
dictionary = corpora.Dictionary(contents_clean)
corpus = [dictionary.doc2bow(sentence) for sentence in contents_clean]
# 建模
lda = gensim.models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20) #类似Kmeans自己指定K值

查看主题词提取结果

for topic in lda.print_topics(num_topics=20, num_words=5):
    print (topic[1])
0.005*"万" + 0.004*"号" + 0.003*"热血" + 0.003*"同学" + 0.003*"防守"
0.023*"a" + 0.022*"e" + 0.016*"i" + 0.016*"o" + 0.015*"n"
0.006*"老公" + 0.005*"饰演" + 0.005*"说" + 0.005*"两人" + 0.004*"中"
0.008*"中" + 0.008*"男人" + 0.006*"女人" + 0.005*"说" + 0.003*"D"
0.012*"电影" + 0.011*"导演" + 0.008*"中" + 0.005*"影片" + 0.005*"主演"
0.006*"中" + 0.005*"西班牙" + 0.003*"航母" + 0.003*"葡萄牙" + 0.003*"前锋"
0.006*"比赛" + 0.006*"中" + 0.006*"皮肤" + 0.003*"含有" + 0.003*"蛋白质"
0.010*"说" + 0.007*"中" + 0.007*"中国" + 0.004*"学校" + 0.003*"舞台"
0.007*"中" + 0.004*"说" + 0.004*"吃" + 0.004*"食物" + 0.003*"M"
0.007*"M" + 0.007*"L" + 0.007*"S" + 0.004*"T" + 0.004*"G"
0.009*"官兵" + 0.005*"部队" + 0.004*"武警" + 0.004*"说" + 0.004*"工作"
0.020*"男人" + 0.008*"女人" + 0.008*"该剧" + 0.006*"剧中" + 0.006*"剧"
0.008*"万" + 0.007*"号" + 0.005*"转" + 0.003*"V" + 0.003*"e"
0.010*"球队" + 0.010*"比赛" + 0.009*"选手" + 0.008*"中" + 0.007*"中国"
0.029*"节目" + 0.013*"主持人" + 0.012*"卫视" + 0.007*"粉丝" + 0.007*"主持"
0.006*"中" + 0.005*"中国" + 0.004*"万" + 0.003*"市场" + 0.003*"公司"
0.008*"中" + 0.005*"恋情" + 0.004*"分手" + 0.004*"说" + 0.004*"学生"
0.005*"观众" + 0.005*"中" + 0.005*"说" + 0.004*"婚礼" + 0.004*"於"
0.005*"S" + 0.004*"I" + 0.004*"中" + 0.003*"e" + 0.003*"女主角"
0.007*"考生" + 0.007*"李小璐" + 0.006*"中" + 0.005*"剧组" + 0.003*"C"

中文新闻分类任务

因为在数据集中,category相当于我们的 label,但它是中文的,需要将其改为数字形式,最后用贝叶斯分类器进行新闻分类操作

# 整合训练数据
df_train=pd.DataFrame({'contents_clean':contents_clean,'label':df_news['category']})

在这里插入图片描述
首先拿到 label 表中的标签

df_train.label.unique()
array(['汽车', '财经', '科技', '健康', '体育', '教育', '文化', '军事', '娱乐', '时尚'],
      dtype=object)

对标签做映射

# label替换
label_mapping = {"汽车": 1, "财经": 2, "科技": 3, "健康": 4, "体育":5, "教育": 6,"文化": 7,"军事": 8,"娱乐": 9,"时尚": 0}
df_train['label'] = df_train['label'].map(label_mapping)
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)

因为后面将数据转化为向量的需求,我们需要提前将文章转换成 str 格式,转化时需要用 sklearn 的 CountVectorizer
这里先用一个例子看一下 CountVectorizer 是怎么使用的:

  • 例1:使用默认 ngram_range=(1, 1) 进行向量化处理
from sklearn.feature_extraction.text import CountVectorizer
# 语料库demo
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(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]
  • 例2:设置 ngram_range=(1,4) 进行向量化处理
from sklearn.feature_extraction.text import CountVectorizer
# 语料库demo
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]

例1在做分词向量时,是每个词都分开,但是还有一种方法是对分词进行组合,将向量维度做的更复杂

参数说明:ngram_range = (1, 4) 表示选取1到4个词做为组合方式: 词向量组合为: ‘dog’, ‘cat’, ‘fish’, ‘dog cat’, ‘cat fish’, ‘dog cat fish’ 构成词频标签

通过这两个例子,我们可以看到,语料库的格式是一个 list 结构,每个元素是str结构,并且用逗号隔开,里面的分词以空格方式间隔,所以我们的数据集也要转换成这样一种格式

#转换成 str 格式
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]
'中新网 上海 日电 于俊 父亲节 网络 吃 一顿 电影 快餐 微 电影 爸 对不起 我爱你 定于 本月 父亲节 当天 各大 视频 网站 首映 葜 谱 鞣 剑 保慈 障蚣 钦 呓 樯 埽 ⒌ 缬 埃 ǎ 停 椋 悖 颍 铩 妫 椋 恚 称 微型 电影 新 媒体 平台 播放 状态 短时 休闲 状态 观看 完整 策划 系统 制作 体系 支持 显示 较完整 故事情节 电影 微 超短 放映 微 周期 制作 天 数周 微 规模 投资 人民币 几千 数万元 每部 内容 融合 幽默 搞怪 时尚 潮流 人文 言情 公益 教育 商业 定制 主题 单独 成篇 系列 成剧 唇 开播 微 电影 爸 对不起 我爱你 讲述 一对 父子 观念 缺少 沟通 导致 关系 父亲 传统 固执 钟情 传统 生活 方式 儿子 新派 音乐 达 习惯 晚出 早 生活 性格 张扬 叛逆 两种 截然不同 生活 方式 理念 差异 一场 父子 间 拉开序幕 子 失手 打破 父亲 心爱 物品 父亲 赶出 家门 剧情 演绎 父亲节 妹妹 哥哥 化解 父亲 这场 矛盾 映逋坏 嚼 斫 狻 ⒍ 粤 ⒌ 桨容 争执 退让 传统 尴尬 父子 尴尬 情 男人 表达 心中 那份 感恩 一杯 滤挂 咖啡 父亲节 变得 温馨 镁 缬 缮 虾 N 逄 煳 幕 传播 迪欧 咖啡 联合 出品 出品人 希望 观摩 扪心自问 父亲节 父亲 记得 父亲 生日 哪一天 父亲 爱喝 跨出 家门 那一刻 感觉 一颗 颤动 心 操劳 天下 儿女 父亲节 大声 喊出 父亲 家人 爱 完'

处理完训练集,再对测试集进行相同的操作

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,word_index)

检查处理结果

test_words[0]
'国家 公务员 考试 申论 应用文 类 试题 实质 一道 集 概括 分析 提出 解决问题 一体 综合性 试题 说 一道 客观 凝练 申发 论述 文章 题目 分析 历年 国考 申论 真题 公文 类 试题 类型 多样 包括 公文 类 事务性 文书 类 题材 从题 干 作答 材料 内容 整合 分析 无需 太 创造性 发挥 纵观 历年 申论 真题 作答 应用文 类 试题 文种 格式 作出 特别 重在 内容 考查 行文 格式 考生 平常心 面对 应用文 类 试题 准确 把握 作答 领会 内在 含义 把握 题材 主旨 材料 结构 轻松 应对 应用文 类 试题 R 弧 ⒆ 钒 盐 展文 写作 原则 T 材料 中来 应用文 类 试题 材料 总体 把握 客观 考生 材料 中来 材料 中 把握 材料 准确 理解 题材 主旨 T 政府 角度 作答 应用文 类 试题 更应 注重 政府 角度 观点 政府 角度 出发 原则 表述 观点 提出 解决 之策 考生 作答 站 政府 人员 角度 看待 提出 解决问题 T 文体 结构 形式 考查 重点 文体 结构 大部分 评分 关键点 解答 方法 薄 ⒆ ス 丶 词 明 方向 作答 题目 题干 作答 作答 方向 作答 角度 关键 向导 考生 仔细阅读 题干 作答 抓住 关键词 作答 方向 相关 要点 整理 作答 思路 年国考 地市级 真 题为 例 潦惺姓 府 宣传 推进 近海 水域 污染 整治 工作 请 给定 资料 市政府 工作人员 身份 草拟 一份 宣传 纲要 R 求 保对 宣传 内容 要点 提纲挈领 陈述 玻 体现 政府 精神 全市 各界 关心 支持 污染 整治 工作 通俗易懂 超过 字 肮 丶 词 近海 水域 污染 整治 工作 市政府 工作人员 身份 宣传 纲要 提纲挈领 陈述 体现 政府 精神 全市 各界 关心 支持 污染 整治 工作 通俗易懂 提示 归结 作答 要点 包括 污染 情况 原因 解决 对策 作答 思路 情况 原因 对策 意义 逻辑 顺序 安排 文章 结构 病 ⒋ 缶殖 龇 ⅲ 明 结构 解答 应用文 类 试题 考生 材料 整体 出发 大局 出发 高屋建瓴 把握 材料 主题 思想 事件 起因 解决 对策 阅读文章 构建 文章 结构 直至 快速 解答 场 ⒗ 硭 乘悸 罚明 逻辑 应用文 类 试题 严密 逻辑思维 情况 原因 对策 意义 考生 作答 先 弄清楚 解答 思路 统筹安排 脉络 清晰 逻辑 表达 内容 表述 础 把握 明 详略 考生 仔细阅读 分析 揣摩 应用文 类 试题 内容 答题 时要 详略 得当 主次 分明 安排 内容 增加 文章 层次感 阅卷 老师 阅卷 时能 明白 清晰 一目了然 玻埃 保蹦旯 考 考试 申论 试卷 分为 省级 地市级 两套 试卷 能力 大有 省级 申论 试题 考生 宏观 角度看 注重 深度 广度 考生 深谋远虑 地市级 试题 考生 微观 视角 观察 侧重 考查 解决 能力 考生 贯彻执行 作答 区别对待'

确认无误后,开始进行下一步,将语料库的分词转化为向量,这里有两种方法:CountVectorizer 构造Ngram词袋模型TfidfVectorizer 构造 tf-idf 词袋模型

CountVectorizer() 函数

CountVectorizer()函数,在默认参数下,只考虑每个单词出现的频率;然后构成一个特征矩阵,每一行表示一个训练文本的词频统计结果(也可以通过 ngram_range 参数调整词组,构建更复杂的矩阵)。其思想是,先根据所有训练文本,不考虑其出现顺序,只将训练文本中每个出现过的词汇单独视为一列特征,构成一个词汇表,该方法又称为词袋法(Bag of Words)

TfidfVectorizer() 函数

TfidfVectorizer() 函数,基于tf-idf算法,计算方法在开头有讲

  • 方法1:使用 CountVectorizer 构造Ngram词袋模型
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)

进行测试

classifier.score(vec.transform(test_words), y_test)

最终贝叶斯分类器的结果是0.804

  • 方法2:使用 TfidfVectorizer 构造 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

天池大赛是国内知名的数据科学竞赛平台,零基础入门NLP - 新闻文本分类是其中的一项比赛任务。这个任务的目标是利用机器学习和自然语言处理的方法,对给定的新闻文本进行分类,即根据新闻内容判断其所属的类别。这个任务对于初学者来说是一个很好的入门项目。 在解决这个问题的过程中,我们需要首先对提供的训练数据进行探索性数据分析,了解数据的分布,词频以及类别的平衡情况。然后,我们可以进行文本预处理,包括分词、去除停用词、词干化等。接下来,可以构建特征表示,可以使用TF-IDF、Word2Vec或者其他词嵌入模型来提取文本的向量表示。在构建特征表示后,可以选择合适的机器学习算法,如朴素贝叶斯、支持向量机、深度学习等,来训练分类模型。 在进行模型训练之前,可以将数据集分为训练集和验证集,用于模型的评估和调优。我们可以使用交叉验证,调整模型的超参数,选择表现最好的模型。在模型训练完成后,可以使用测试集对模型进行评估,计算准确率、召回率和F1值等指标。最后,我们可以利用模型对给定的未知新闻文本进行分类预测。 在解决这个问题的过程中,还可以进行一些方法的优化和改进。比如,可以使用集成学习的方法,如随机森林、XGBoost或者LightGBM等,结合多个分类器的结果来提高整体的分类准确率。此外,可以尝试使用预训练的模型,如BERT等,来获得更好的特征表示。此外,还可以尝试使用深度学习网络,如卷积神经网络或者循环神经网络,来提取文本的高级语义特征。 总之,零基础入门NLP - 新闻文本分类是一个很好的机会,可以学习和应用自然语言处理的知识和技术。通过解决这个问题,我们可以深入了解文本分类的基本概念和方法,提升自己在数据科学领域的能力和竞争力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值