特种设备舆情数据分析
- 作者:[ccmajor]
- 日期:2020/11
项目描述
基于应用python进行自然语言处理分析-舆情文本1,应用朴素贝叶斯naive_bayes方法进行分类预测,用于舆情文本规范化分类。
数据字典
- EquType:特种设备类型
- Words:处理后的特种设备舆情文本/语料库
项目任务
- 3.1 语料库查看
- 3.2 数据预处理
- 3.3 建模
- 3.4 模型评估
数据预处理
# 引入必要的包
import csv
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import time
%matplotlib notebook
# 解决matplotlib显示中文问题
# 仅适用于Windows
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# MacOS请参考 http://wenda.chinahadoop.cn/question/5304 修改字体配置
# 指定数据集路径
dataset_path = '.\data'
datafile_yuqing3 = os.path.join(dataset_path, 'yuqing3.csv')
# 加载数据
raw_data = pd.read_csv(datafile_yuqing3)
#raw_data.head()
#raw_data
# 手工提取EquType、Words,按照特种设备目录统一特种设备类型,作为语料库
#Corpus_TF8.txt
#Corpus_TF8.csv
# 补充舆情数量少得类别
#Corpus_bc.txt
#Corpus_bc.csv
# 读取语料库
datafile_corpus = os.path.join(dataset_path, 'Corpus_TF8_wuqita.csv')
# 加载数据
corpus_raw_data = pd.read_csv(datafile_corpus)
corpus_raw_data
EquType | Words | |
---|---|---|
0 | 压力容器 | 广西 柳州市 融水县 广场 附近 烧烤店 厨房 煤气罐 起火 救援 人员 立即 赶赴现场 扑... |
1 | 电梯 | 安徽省 滁州市 九九 广场 一位 老人 被困 电梯 接警 民警 迅速 赶往 现场 电梯 维修... |
2 | 压力容器 | 湖南省 永州市 冷水滩区 珊瑚 路 早餐 店 液化气 瓶 发生爆炸 现场 浓烟滚滚 具体 人... |
3 | 压力容器 | 辽宁省 朝阳市 龙城区 西 大营子镇 东梁 居民 家中 液化气罐 着火 救援 人员 立即 赶... |
4 | 电梯 | 福建省 福州市 鳌祥 佳园 小区 被困 电梯 近 小时 电梯 紧急 按钮 无人 回应 被困 ... |
... | ... | ... |
6979 | 压力管道 | 今天 点份许 疑似 煤气管道 泄漏 爆炸 隐患 河南 北路 海宁路 天潼路 部分 路段 全面... |
6980 | 压力容器 | 国道 邯郸市 肥乡 区辛安镇 路段 临街 门市 前 一辆 装载 汽油 罐车 不知 何故 突然... |
6981 | 压力容器 | 昨日 广深高速 广州 深圳 方向 麻涌 出口处 一辆 装载 吨 煤焦油 油罐车 转弯 速度 ... |
6982 | 压力管道 | 郑州市 文博 东路 发生 地下 暖气 管道 爆裂 事件 水蒸气 瞬间 笼罩 马路 正当 一组... |
6983 | 压力管道 | 河南 平顶山 汝州 工厂 发生 疑似 天然气 爆炸 事故现场 视频 显示 事故现场 一片狼藉... |
6984 rows × 2 columns
## 读取补充语料库
#datafile_corpus_bc = os.path.join(dataset_path, 'Corpus_bc.csv')
## 加载数据
#corpus_raw_data_bc = pd.read_csv(datafile_corpus_bc)
#corpus_raw_data_bc
#查看预料库
print('舆情数量:')
print('锅炉:',list(corpus_raw_data.EquType).count('锅炉'))
print('压力容器:',list(corpus_raw_data.EquType).count('压力容器'))
print('压力管道:',list(corpus_raw_data.EquType).count('压力管道'))
print('电梯:',list(corpus_raw_data.EquType).count('电梯'))
print('起重机械:',list(corpus_raw_data.EquType).count('起重机械'))
print('客运索道:',list(corpus_raw_data.EquType).count('客运索道'))
print('大型游乐设施:',list(corpus_raw_data.EquType).count('大型游乐设施'))
print('场(厂)内专用机动车辆:',list(corpus_raw_data.EquType).count('场(厂)内专用机动车辆'))
print('其他:',list(corpus_raw_data.EquType).count('其他'))
舆情数量:
锅炉: 51
压力容器: 2747
压力管道: 220
电梯: 3129
起重机械: 693
客运索道: 10
大型游乐设施: 90
场(厂)内专用机动车辆: 44
其他: 0
##查看补充预料库
#print('舆情数量:')
#print('锅炉:',list(corpus_raw_data_bc.EquType).count('锅炉'))
#print('压力容器:',list(corpus_raw_data_bc.EquType).count('压力容器'))
#print('压力管道:',list(corpus_raw_data_bc.EquType).count('压力管道'))
#print('电梯:',list(corpus_raw_data_bc.EquType).count('电梯'))
#print('起重机械:',list(corpus_raw_data_bc.EquType).count('起重机械'))
#print('客运索道:',list(corpus_raw_data_bc.EquType).count('客运索道'))
#print('大型游乐设施:',list(corpus_raw_data_bc.EquType).count('大型游乐设施'))
#print('场(厂)内专用机动车辆:',list(corpus_raw_data_bc.EquType).count('场(厂)内专用机动车辆'))
#print('其他:',list(corpus_raw_data_bc.EquType).count('其他'))
corpus_cln_data = corpus_raw_data.dropna().copy()
corpus_cln_data
#corpus_cln_data.tail(2)
EquType | Words | |
---|---|---|
0 | 压力容器 | 广西 柳州市 融水县 广场 附近 烧烤店 厨房 煤气罐 起火 救援 人员 立即 赶赴现场 扑... |
1 | 电梯 | 安徽省 滁州市 九九 广场 一位 老人 被困 电梯 接警 民警 迅速 赶往 现场 电梯 维修... |
2 | 压力容器 | 湖南省 永州市 冷水滩区 珊瑚 路 早餐 店 液化气 瓶 发生爆炸 现场 浓烟滚滚 具体 人... |
3 | 压力容器 | 辽宁省 朝阳市 龙城区 西 大营子镇 东梁 居民 家中 液化气罐 着火 救援 人员 立即 赶... |
4 | 电梯 | 福建省 福州市 鳌祥 佳园 小区 被困 电梯 近 小时 电梯 紧急 按钮 无人 回应 被困 ... |
... | ... | ... |
6979 | 压力管道 | 今天 点份许 疑似 煤气管道 泄漏 爆炸 隐患 河南 北路 海宁路 天潼路 部分 路段 全面... |
6980 | 压力容器 | 国道 邯郸市 肥乡 区辛安镇 路段 临街 门市 前 一辆 装载 汽油 罐车 不知 何故 突然... |
6981 | 压力容器 | 昨日 广深高速 广州 深圳 方向 麻涌 出口处 一辆 装载 吨 煤焦油 油罐车 转弯 速度 ... |
6982 | 压力管道 | 郑州市 文博 东路 发生 地下 暖气 管道 爆裂 事件 水蒸气 瞬间 笼罩 马路 正当 一组... |
6983 | 压力管道 | 河南 平顶山 汝州 工厂 发生 疑似 天然气 爆炸 事故现场 视频 显示 事故现场 一片狼藉... |
6983 rows × 2 columns
#查看清洗后的预料库
print('舆情数量:')
print('锅炉:',list(corpus_cln_data.EquType).count('锅炉'))
print('压力容器:',list(corpus_cln_data.EquType).count('压力容器'))
print('压力管道:',list(corpus_cln_data.EquType).count('压力管道'))
print('电梯:',list(corpus_cln_data.EquType).count('电梯'))
print('起重机械:',list(corpus_cln_data.EquType).count('起重机械'))
print('客运索道:',list(corpus_cln_data.EquType).count('客运索道'))
print('大型游乐设施:',list(corpus_cln_data.EquType).count('大型游乐设施'))
print('场(厂)内专用机动车辆:',list(corpus_cln_data.EquType).count('场(厂)内专用机动车辆'))
print('其他:',list(corpus_cln_data.EquType).count('其他'))
舆情数量:
锅炉: 51
压力容器: 2746
压力管道: 220
电梯: 3129
起重机械: 693
客运索道: 10
大型游乐设施: 90
场(厂)内专用机动车辆: 44
其他: 0
#corpus_cln_data.EquType.unique()
label_mapping = {"锅炉": 1, "压力容器": 2, "压力管道": 3, "电梯": 4, "起重机械":5, "客运索道": 6,"大型游乐设施": 7,"场(厂)内专用机动车辆": 8,"其他": 9}
corpus_cln_data['EquType'] = corpus_cln_data['EquType'].map(label_mapping)
corpus_cln_data.head()
EquType | Words | |
---|---|---|
0 | 2 | 广西 柳州市 融水县 广场 附近 烧烤店 厨房 煤气罐 起火 救援 人员 立即 赶赴现场 扑... |
1 | 4 | 安徽省 滁州市 九九 广场 一位 老人 被困 电梯 接警 民警 迅速 赶往 现场 电梯 维修... |
2 | 2 | 湖南省 永州市 冷水滩区 珊瑚 路 早餐 店 液化气 瓶 发生爆炸 现场 浓烟滚滚 具体 人... |
3 | 2 | 辽宁省 朝阳市 龙城区 西 大营子镇 东梁 居民 家中 液化气罐 着火 救援 人员 立即 赶... |
4 | 4 | 福建省 福州市 鳌祥 佳园 小区 被困 电梯 近 小时 电梯 紧急 按钮 无人 回应 被困 ... |
list(corpus_cln_data.EquType).count('电梯')
0
创建训练、测试集
# 创建训练、测试集
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(corpus_cln_data['Words'].values, corpus_cln_data['EquType'].values, random_state=1)
print (len(x_train))
print (len(x_test))
#print(x_train)
#print(x_train[0])
#x_train = x_train.flatten()
words = [] #为训练集创建list对象
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])) #x_train转为list对象
except:
print (line_index)
print(words[0])
print (len(words))
5237
1746
网 友 昨 日 发 来 消 息 偃 师 游 园 旁 大 型 吊 车 倾 斜 现 场 视 频 显 示 吊 车 吊 臂 地 面 平 行 网 友 现 场 事 故 造 成 人 员 伤 亡 天 太 热 提 醒 各 行 各 业 小 伙 伴
5237
print(type(corpus_cln_data))
print(type(x_train))
<class 'pandas.core.frame.DataFrame'>
<class 'numpy.ndarray'>
test_words = [] #创建测试集的list对象
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])
test_words[1:2]
['晚 上 点 山 东 省 德 州 市 新 华 路 西 首 供 热 管 道 发 生 泄 漏 德 州 市 主 城 区 三 分 之 二 供 热 影 响 德 州 市 热 力 公 司 管 道 进 行 抢 修 早 上 点 管 道 漏 点 已 经 成 功 封 堵']
## MultinomialNB朴素贝叶斯手册用法
#rng = np.random.RandomState(1)
#X = rng.randint(5, size=(6, 100))
#y = np.array([1, 2, 3, 4, 5, 6])
#from sklearn.naive_bayes import MultinomialNB
#clf = MultinomialNB()
#clf.fit(X, y)
#MultinomialNB()
#print(clf.predict(X[2:3]))
y_test
array([2, 3, 4, ..., 2, 2, 4], dtype=int64)
数据建模
#构建词袋
#CountVectorizer:将文本中的词语转换为词频矩阵,只考虑词频
from sklearn.feature_extraction.text import CountVectorizer
#max_features:对所有关键词的term frequency进行降序排序,取前max_features个作为关键词集
vec = CountVectorizer(analyzer='char', max_features=3000, lowercase = False)
vec.fit(words)
#构建贝叶斯模型
from sklearn.naive_bayes import MultinomialNB #MultinomialNB:Naive Bayes classifier for multinomial models
classifier = MultinomialNB()
classifier.fit(vec.transform(words), y_train)
MultinomialNB()
模型评估
#############################################################################
#模型评估
#vec.transform:Convert a collection of text documents to a matrix of token counts
#classifier.score:Return the mean accuracy on the given test data and labels.
#score:Return the mean accuracy on the given test data and labels.
print('test_words_sorce_all:',classifier.score(vec.transform(test_words), y_test)) #评估预测正确率平均值
test_words_sorce_all: 0.9501718213058419
###测试
#基于测试集的预测
classifier_pred = classifier.predict(vec.transform(test_words))
#构建混淆矩阵
cm = pd.crosstab(classifier_pred,y_test)
#绘制混淆矩阵图
sns.heatmap(cm,annot = True,cmap ='GnBu',fmt ='d')
#去除x轴和y轴标签
plt.xlabel('')
plt.ylabel('')
#显示图形
plt.show()
<IPython.core.display.Javascript object>
#模型的预测准确率
from sklearn import metrics
print('模型的准确率为:\n',metrics.accuracy_score(y_test,classifier_pred))
print('模型的评估报告:\n',metrics.classification_report(y_test,classifier_pred))
模型的准确率为:
0.9501718213058419
模型的评估报告:
precision recall f1-score support
1 1.00 0.15 0.27 13
2 0.94 0.98 0.96 682
3 0.83 0.64 0.72 61
4 0.98 0.99 0.99 772
5 0.88 0.92 0.90 184
6 0.00 0.00 0.00 3
7 0.82 0.67 0.74 21
8 0.00 0.00 0.00 10
accuracy 0.95 1746
macro avg 0.68 0.54 0.57 1746
weighted avg 0.94 0.95 0.94 1746
D:\Python\Anaconda3\envs\python383\lib\site-packages\sklearn\metrics\_classification.py:1221: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
_warn_prf(average, modifier, msg_start, len(result))
##计算正例的预测概率,用于生成roc曲线的数据, 好像主要用于二分类
#y_score = classifier.predict_proba(x_test)[:,1]
#fpr,tpr,threshold=metrics.roc_curve(y_test.map(("锅炉": 1, "压力容器": 2, "压力管道": 3, "电梯": 4, "起重机械":5, "客运索道": 6,"大型游乐设施": 7,"场(厂)内专用机动车辆": 8,"其他": 9),y_score))
##计算auc的值
#roc_auc=metrics.auc(fpr,tpr)
##绘制面积图
#plt.stackplot(fpr,tpr,color='steelblue',alpha = 0.5,edgecolor ='black')
##添加边际线
#pit.plot(fpr,tpr,color='black',lw=l)
##添加对角线
#plt.plot([0,1],[0,1],color ='red',linestyle = '--')
##添加文本信息
#plt.text(0.5,0.3,'roc curve(area = %0.2f)' % roc_auc)
##添加x轴与y轴标签
#plt.xlabel('l-specificity')
#plt.ylabel('sensitivity')
##显示图形
#plt.show()
模型保存
# 使用pickle保存模型
import pickle
with open('pickle_classifier.pkl', 'wb') as fid:
pickle.dump(classifier, fid,2)
# 使用joblib保存模型
import joblib
# 保存
joblib.dump(classifier,'joblib_classifier.pkl')
['joblib_classifier.pkl']
#单项预测
#vec_test_word = vec.transform((test_words[0:1]))
vec_test_word = vec.transform(['辽宁省 朝阳市 龙城区 西 大营子镇 东梁 居民 家中 液化气罐 着火 救援 人员 立即 赶赴现场 液化气罐 迅速 转移 屋外 安全 地带 进行 冷却 降温 大火 进行 扑救 防止 火势 蔓延 液化气罐 冷却 后用 湿 棉被 焖 灭 成功 处置 险情'])
#print(test_words[0:1])
#print(vec_test_word)
print(vec_test_word.shape)
print(classifier.predict(vec_test_word))
(1, 3000)
[2]
# 测试打包和解包是否影响模型准确率
new_classifier = joblib.load('joblib_classifier.pkl')
vec_test_word = vec.transform(['辽宁省 朝阳市 龙城区 西 大营子镇 东梁 居民 家中 液化气罐 着火 救援 人员 立即 赶赴现场 液化气罐 迅速 转移 屋外 安全 地带 进行 冷却 降温 大火 进行 扑救 防止 火势 蔓延 液化气罐 冷却 后用 湿 棉被 焖 灭 成功 处置 险情'])
print(vec_test_word.shape)
print(classifier.predict(vec_test_word))
(1, 3000)
[2]