Python数据科学实战:从文本分析到建模预测的完整流程解析
[id_1647214475[id_1645630818]

上周的推文让我们掌握了文本分析的基本思路。这次推文主要是学习怎样利用 Python 来实践这些思路。
实战
1. 数据准备
数据样例如下, 数据总量为7.7万+:
本节用一个实战例子展示文本分析的最简易流程。首先将原始数据中的“评分”设定为因变量。把“评价内容”当作自变量,接着依据评价内容提取 TF-IDF 特征。之后,凭借评价内容的特征进行建模,以预测整体评分。
import jieba #导入分词模块
import pandas as pd # 导入Pandas模块
# 1. 导入数据
comments_df = pd.read_excel("https://github.com/xiangyuchang/xiangyuchang.github.io/blob/master/BearData/comment_nm.xlsx" 这个链接后面带有 "?raw=true",它指向一个 Excel 文件。) #读入数据
print('数据的维度是:', comments_df.shape)
comments_df.head() #查看数据的前5行
# 2. 清洗数据, 删除空的数据
def clean_sents(txt):
txt = str(txt) if txt is not None else ""
if len(txt) == 0:
return None
else:
return txt
comments_df2["评价内容"] = comments_df2["评价内容"].apply(clean_sents)
comments_df2 是一个数据框,它是从 comments_df2 中筛选出满足 comments_df2 中某一条件的行所得到的。具体来说,是筛选出 comments_df2 中满足 comments_df2 内部某个条件的行。"评价内容"] != "nan"]
len(comments_df2)
# 运行结果
# 58117
以上仅为最基础的数据清洗工作,即删除缺失值,在此不再详细说明。经过过滤后,样本的数量为 5.8 万多条,相比之前减少了 2.2 万多条。
2. 分词
文本分析的第一步是分词。常用中文包是jieba: .
函数说明
再次声明,本书的学习曲线是平滑的。它只是对最重要的函数进行调用和说明。在实际使用中,如果这些函数不够用,你需要自行翻阅对应的官方文档。成熟的开源库通常都有完善的文档,你可以做到即学即用。
运行代码
引入停用词文本,需在以下网址进行下载:https://github.com/zhiyiZeng/cluebearpython/blob/master/chapter8/data/stopwords.txt
stopwords_file = "stopwords.txt"
with打开(os.path.join(path, stopwords_file)),"r", encoding="utf8") as f:
stopwords_list 等于将 word 去除两端空格后所组成的列表。for word in f.read()]
def filter_stopwords(txt):
"""过滤停用词"""
sent = jieba.lcut(txt)
words = []
for word in sent:
if(word in stopwords_list):
continue
else:
将 word 添加到 words 列表中。
return words
comments_df2["评价内容"] = comments_df2["评价容"].apply(filter_stopwords)
comments_df2.head()
本例代码首先导入停用词库,接着使用 Pandas 的 apply()方法对每条评论进行分词操作,分词完成之后,针对每个单词去判断它是否在停用词库当中,如果存在就进行过滤。最后再将过滤后的分词结果返回。最终的结果呈现如下。
3. 统计词频
在进行 feature 提取之前,建议先绘制一个词云。这也是探索性分析的一部分,通过绘制词云能够对数据的整体情况有一个印象。
函数说明
运行代码
# 3. 切分训练集和验证集和测试集
在 sklearn.model_selection 中导入 train_test_split 函数。
val_y 也是从 comments_df2 中拆分出来的一部分。"评价内容"], comments_df2["评分"], test_size=0.3)
val_X 与 val_y 进行 train_test_split 操作,测试集大小为 0.5,得到 val_X 和 val_y 的测试集部分,分别记为 test_X 和 test_y。即 val_X, test_X, val_y, test_y = train_test_split(val_X, val_y, test_size=0.5)。
# 4. 统计词频
from nltk import FreqDist
# 把所有词和对应的词频放在一个list里
all_words = []
for comment in comments_df2["评价内容"]:
all_words.extend(comment)
len(all_words)
fdisk = FreqDist(all_words)
TOP_COMMON_WORDS = 1000
fdisk 中的 most_common_words 经过 most_common(TOP_COMMON_WORDS)的处理后得到了 most_common_words
most_common_words[:10]
最终得到的结果是只截取前 10 条数据,其中第一列是词,第二列是对应的词频。
4. 词云
词云是把词呈现在有一定形状的图片上。并且会依据词的词频大小,生成不同尺寸的词。如此一来,就可以很直观地分辨出不同词的词频大小关系。需要注意的是,词云是对文本类型数据进行的探索性分析,只是为了能直观地反映词频大小关系,并非精确度量。所以,不能把词云的结果完全当作分析的依据。不过,词云依然具有很高的探索性数据分析价值。对于画词云的工具,推荐使用 wordcloud()。
函数说明
from wordcloud import WordCloud
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
# 词云形状
mask 等于通过 np.array 函数将通过 Image.open 函数打开的位于 os.path.join(path, 路径下的图像转换为数组。"火锅图片.png")))
wc 等于 WordCloud,其字体路径为 os.path.join(path,"simkai.ttf"),
背景颜色为"white",
contour_width=3,
contour_color='steelblue',
mask=mask,
width=1000,
height=1000)
使用频率字典 dict(most_common_words) 来生成 wc 的内容
fig = plt.figure(figsize=(10, 10))
plt.imshow(wc)
# 取消坐标轴
plt.axis("off")
# 保存图片
plt 把图像保存到 os.path.join(path, 这个路径中。"火锅词云.png"), dpi=1000)
# 展示图片
plt.show()
最后用 matplotlib 展示图片并保存。
注意:
这里的 PIL 包指的是 pillow。安装时依然是`pip install pillow`。引入时包名是 PIL。这是因为旧版的 pillow 已不再被官方维护,之后有其他开发者重新进行了维护。为了区分,才出现了这样的情况。使用时记住这一小变化就可以了。
plt.savefig()需要在 plt.show()之前进行。如果不这样做,就会保存为空图片。这是因为 plt.show()会清空画布中的对象。
最终运行结果:
5. 提取feature
下面进行最关键的一步,即提起TF-IDF特征。
函数说明
运行代码:
from nltk.text import TextCollection
tfidf_generator 是由 TextCollection 函数处理 train_X.values.tolist()得到的
def extract_tfidf这些是语言相关的内容,包括文本、目标、文本集合以及常见词汇。:
"""
提取文本的tf-idf.
texts: 输入的文本.
targets: 对应的评价.
预先初始化了一个 TextCollection 。
输入的前 N 个词被当作特征来进行计算。
"""
# 得到行向量的维度
n_sample = len(texts)
# 得到列向量的维度
n_feat 的长度等于 common_words 的长度。
# 初始化X矩阵, X为最后要输出的TF-IDF矩阵
X 被初始化为一个大小为 [n_sample, n_feat] 的全零数组。
y = np.zeros(n_sample)
for i, text in enumerate(texts):
if i % 5000 == 0:
print("已经完成{}个样本的特征提取.".format(i))
每一行都对应一个文档,需要计算这个文档中词的 tf-idf 值。如果某个词在文档中没有出现,那么它的 tf-idf 值就为 0。
feature_vector = []
for word in common_words:
if word in text:
tf_idf 是通过 text_collection 来计算 word 在 text 中的 tf_idf 值。
else:
tf_idf = 0.0
将 tf_idf 添加到 feature_vector 中。
X 的第 i 行等于一个由 feature_vector 构成的 NumPy 数组
y 的第 i 个元素等于 targets 的第 i 行
return X, y
从 train_X 和 train_y 中提取 tfidf,使用 tfidf_generator 以及 dict(most_common_words).keys(),得到 cleaned_train_X 和 cleaned_train_y
然后,将处理后的结果分别赋值给 cleaned_val_X 和 cleaned_val_y。
上述代码逻辑是:对于需要处理的训练集和验证集的 X,要分别对其每一行(也就是每一个文档)进行操作。先匹配总词数,接着计算每一行中每一个词的 tf - idf,最后将结果输出。
6. 用sklearn进行训练
最后,就可以把提取出来的 TF-IDF 扔到模型当中去进行训练。至于需要使用什么样的模型,这要根据具体的需求来决定,这里就不再详细说明了,读者可以自己去尝试。下面的这个例子,展示了使用 SVM 来进行训练的代码。
from sklearn import svm
clf = svm.SVC()
clf 对 cleaned_train_X 和 cleaned_train_y 进行拟合操作。
clf 对 cleaned_train_X 和 cleaned_train_y 进行评分。
调用 clf 的 score 方法,传入 cleaned_val_X 和 cleaned_val_y 作为参数。
总结
在“准备”部分,我们运用一个小例子,让大家能快速知晓什么是“文本处理”。接着我们发现,“文本处理”的本质与“数字处理”本质是相同的。这使得我们能够迅速消除对“文本处理”的恐惧。在进阶阶段,我们针对“准备”部分中的“分词”以及“特征提取”的存在意义和类型进行了探讨。在实战阶段,我们使用实际的数据来带领大家完成文本处理的流程,让文本处理的各个环节都畅通无阻,如同打通了任督六脉一般。
在具体项目中,会碰到诸多不同的问题,仅靠这些知识是远远不够的。然而,相信本部分的内容能够让各位同学从对“文本处理”的恐惧中摆脱出来,这也符合了本系列带大家入门的最初想法。
往期精彩回顾
下载本系列相关数据