🤵♂️ 个人主页:@艾派森的个人主页
✍🏻作者简介:Python学习者
🐋 希望大家多多支持,我们一起进步!😄
如果文章对你有帮助的话,
欢迎评论 💬点赞👍🏻 收藏 📂加关注+
喜欢大数据分析项目的小伙伴,希望可以多多支持该系列的其他文章
大数据分析案例-基于随机森林算法预测人类预期寿命 |
大数据分析案例-基于随机森林算法的商品评价情感分析 |
大数据分析案例-用RFM模型对客户价值分析(聚类) |
大数据分析案例-对电信客户流失分析预警预测 |
大数据分析案例-基于随机森林模型对北京房价进行预测 |
大数据分析案例-基于RFM模型对电商客户价值分析 |
大数据分析案例-基于逻辑回归算法构建垃圾邮件分类器模型 |
大数据分析案例-基于决策树算法构建员工离职预测模型 |
大数据分析案例-基于KNN算法对茅台股票进行预测 |
大数据分析案例-基于多元线性回归算法构建广告投放收益模型 |
大数据分案例-基于随机森林算法构建返乡人群预测模型 |
大数据分析案例-基于决策树算法构建金融反欺诈分类模型 |
目录
1.项目背景
2.项目简介
2.1项目说明
2.2数据说明
2.3技术工具
3.算法原理
4.项目实施步骤
4.1理解数据
4.2数据清洗
4.3探索性数据分析
4.3.1分析谣言和非谣言数据比例
4.3.2分析谣言帖子的评论数和点赞数分布
4.3.3分析非谣言帖子的评论数和点赞数分布
4.3.4分析变量之间的相关系数
4.4特征工程
4.5模型构建
4.6模型评估
4.7模型预测
5.实验总结
源代码
1.项目背景
随着互联网技术的发展和应用的普及,互联网中的信息量正以指数级别的速度飞速地增长,已经成为了一个巨大的信息库。也正因如此大量不可靠的信息可以快速地在人群中传播。而社交媒体上的谣言泛滥可能会导致社会混乱,进而影响人们正常的生活秩序。特别是在面临突发公共事件时,广泛传播的谣言可能会具有极大的破坏性。谣言检测是自然语言处理中文本分类的子任务。谣言检测的主要目的是识别没有丝毫结构规则可言的新闻文本,判断其是否为假新闻(谣言)。
近年来,在线社交网络迅速兴起,以微博为代表的新兴社交媒体依靠惊人的传播速度和广度深刻地影响着人们的生活。在微博平台上用户是主体,微博的内容是信息传播的重要载体。但是,近年来微博平台上的垃圾用户和谣言问题日益严峻,不仅影响平台数据的可用性和安全性,还会造成平台发展不健康以及用户使用体验差等问题。因此,设计有效的方法检测垃圾用户和谣言具有重要的现实意义。
本项目的研究目的是从海量微博帖子文本信息中,挖掘其中的蕴含的特征,并提出一种新的谣言检测的方法,以微博上的帖子为数据,对其进行建模,找出分类的关键特征,并以机器学习模型进行分类预测,判断其是否为谣言。
2.项目简介
2.1项目说明
本项目通过使用机器学习等算法对微博中谣言和非谣言数据进行分析建模,构造谣言检测模型,针对恶意的谣言进行精准识别,有效解决谣言引发诸多的不安定因素,并对经济和社会产生巨大的影响。
2.2数据说明
数据来源于微博社区管理中心的处理的谣言帖子,共有3387条帖子信息,具体变量字段如下:
变量名 | 含义 |
ID | 帖子的唯一编码 |
text | 帖子内容 |
评论数 | 帖子下面的评论数 |
点赞数 | 帖子的点赞 |
label | 是否为谣言,1表示谣言,0表示非谣言 |
2.3技术工具
Python版本:3.9
代码编辑器:jupyter notebook
3.算法原理
(1)算法简介
朴素贝叶斯法是基于贝叶斯定理与特征条件独立性假设的分类方法。对于给定的训练集,首先基于特征条件独立假设学习输入输出的联合概率分布(朴素贝叶斯法这种通过学习得到模型的机制,显然属于生成模型);然后基于此模型,对给定的输入 x,利用贝叶斯定理求出后验概率最大的输出 y。
(2)朴素贝叶斯分类器的公式
假设某个体有n项特征(Feature),分别为F1、F2、…、Fn。现有m个类别(Category),分别为C1、C2、…、Cm。贝叶斯分类器就是计算出概率最大的那个分类,也就是求下面这个算式的最大值:
P(C|F1F2...Fn) = P(F1F2...Fn|C)P(C)/P(F1F2...Fn)
由于P(F1F2…Fn) 对于所有的类别都是相同的,可以省略,问题就变成了求
P(F1F2...Fn|C)P(C)的最大值。朴素贝叶斯分类器则是更进一步,假设所有特征都彼此独立,因此
P(F1F2...Fn|C)P(C) = P(F1|C)P(F2|C) ... P(Fn|C)P(C)
上式等号右边的每一项,都可以从统计资料中得到,由此就可以计算出每个类别对应的概率,从而找出最大概率的那个类。虽然“所有特征彼此独立”这个假设,在现实中不太可能成立,但是它可以大大简化计算,而且有研究表明对分类结果的准确性影响不大。
(3)朴素贝叶斯常用的三个模型
高斯模型:处理特征是连续型变量的情况
多项式模型:最常见,要求特征是离散数据
伯努利模型:要求特征是离散的,且为布尔类型,即true和false,或者1和0
(4) 朴素贝叶斯法的评价
朴素贝叶斯法的优点:朴素贝叶斯算法假设了数据集属性之间是相互独立的,因此算法的逻辑性十分简单,并且算法较为稳定,当数据呈现不同的特点时,朴素贝叶斯的分类性能不会有太大的差异。换句话说就是朴素贝叶斯算法的健壮性比较好,对于不同类型的数据集不会呈现出太大的差异性。当数据集属性之间的关系相对比较独立时,朴素贝叶斯分类算法会有较好的效果。
朴素贝叶斯法的缺点:属性独立性的条件同时也是朴素贝叶斯分类器的不足之处。数据集属性的独立性在很多情况下是很难满足的,因为数据集的属性之间往往都存在着相互关联,如果在分类过程中出现这种问题,会导致分类的效果大大降低。
4.项目实施步骤
4.1理解数据
首先使用pandas加载谣言数据集并查看前五行
查看数据大小
从结果可看出原始数据共有3387条,5列
查看数据基本信息
从结果可看出各变量的数据类型
查看数据描述性统计
从结果看出这些变量的均值、方差、最大最小、四分位数等信息。
4.2数据清洗
查看原始数据是否存在缺失值
从结果可看出各个变量不存在缺失值,故不需要进行缺失值处理
查看原始数据是否存在重复值
从结果看出原始数据不存在重复值,故不需要进行重复值处理
4.3探索性数据分析
4.3.1分析谣言和非谣言数据比例
从结果看出,谣言和非谣言数据比例相差不大,数据比较均衡。
4.3.2分析谣言帖子的评论数和点赞数分布
从图可以看出,谣言帖子的评论数主要集中在0-250以内,点赞数主要集中在0-100以内。
4.3.3分析非谣言帖子的评论数和点赞数分布
从图可以看出,非谣言帖子的评论数主要集中在0-500以内,点赞数主要集中在0-1000以内。
对比两者可大致看出,谣言的帖子评论数和点赞数均明显少于非谣言的帖子,两者还是有较大的差距。
4.3.4分析变量之间的相关系数
从相关系数热力图可看出,评论数和点赞数为正相关关系,但与label均为弱负相关关系。
4.4特征工程
首先需要对文本数据进行处理,包括去除无用字符、分词、去停用词等操作
接着对上面处理后的文本数据进行词向量化,将其转化为计算机能识别的数据,接着对数据进行拆分,拆分为训练集和测试集,其中测试集比例为0.2。
4.5模型构建
构建随机森林模型并查模型准确率
构建朴素贝叶斯模型并查看模型准确率
构建SVM支持向量机模型并查看模型准确率
构建xgboost模型并查看模型准确率
通过四个模型的对比,我们发现朴素贝叶斯算法模型的准确率最高,故选取其作为最后的算法模型。
4.6模型评估
模型评估这里,我们主要选取了模型混淆矩阵、分类报告、ROC曲线作为评估指标。
从混淆矩阵可看出,模型在预测非谣言数据时分类正确个数为309,错误个数为48;在预测谣言数据是分类正确个数为281,错误个数为40。分类报告可以看出模型在0和1分类上的精确率、召回率、f1值等信息。ROC曲线可看出曲线靠近左上方,模型效果较好。
4.7模型预测
使用模型进行预测,发现十个中有九个正确,模型效果还不错。
5.实验总结
本次实验通过对谣言数据进行分析建模,我们得出了以下结论:
1.谣言帖子的评论数和点赞数显著小于非谣言帖子。
2.评论数和点赞数为正相关关系,但与label标签均为负相关关系。
3.四个模型中,朴素贝叶斯算法模型效果最好,准确率为0.87。
心得与体会:
通过这次Python项目实战,我学到了许多新的知识,这是一个让我把书本上的理论知识运用于实践中的好机会。原先,学的时候感叹学的资料太难懂,此刻想来,有些其实并不难,关键在于理解。
在这次实战中还锻炼了我其他方面的潜力,提高了我的综合素质。首先,它锻炼了我做项目的潜力,提高了独立思考问题、自我动手操作的潜力,在工作的过程中,复习了以前学习过的知识,并掌握了一些应用知识的技巧等
在此次实战中,我还学会了下面几点工作学习心态:
1)继续学习,不断提升理论涵养。在信息时代,学习是不断地汲取新信息,获得事业进步的动力。作为一名青年学子更就应把学习作为持续工作用心性的重要途径。走上工作岗位后,我会用心响应单位号召,结合工作实际,不断学习理论、业务知识和社会知识,用先进的理论武装头脑,用精良的业务知识提升潜力,以广博的社会知识拓展视野。
2)努力实践,自觉进行主角转化。只有将理论付诸于实践才能实现理论自身的价值,也只有将理论付诸于实践才能使理论得以检验。同样,一个人的价值也是透过实践活动来实现的,也只有透过实践才能锻炼人的品质,彰显人的意志。
3)提高工作用心性和主动性。实习,是开端也是结束。展此刻自我面前的是一片任自我驰骋的沃土,也分明感受到了沉甸甸的职责。在今后的工作和生活中,我将继续学习,深入实践,不断提升自我,努力创造业绩,继续创造更多的价值。
这次Python实战不仅仅使我学到了知识,丰富了经验。也帮忙我缩小了实践和理论的差距。在未来的工作中我会把学到的理论知识和实践经验不断的应用到实际工作中,为实现理想而努力。
源代码
import pandas as pd
import matplotlib.pylab as plt
import seaborn as sns
sns.set(font="SimHei")
plt.rcParams['font.sans-serif'] = ['SimHei'] #解决中文显示
plt.rcParams['axes.unicode_minus'] = False #解决符号无法显示
import warnings
warnings.filterwarnings('ignore')
data = pd.read_csv('谣言和非谣言数据.csv')
data.head()
data.shape
data.info()
data.describe()
# 查看各变量缺失值情况
data.isnull().sum()
# 使用any()检测数据是否存在重复值,False表明不存在重复值,True表示存在重复值
any(data.duplicated())
# 分析数据中谣言和非谣言的比例
sns.countplot(data=data,x='label')
plt.xticks([0,1],['非谣言','谣言'])
plt.title('谣言与非谣言的比例')
plt.show()
# 分析谣言帖子的评论数和点赞数分布
plt.figure(figsize=(16,16))
plt.subplot(2,1,1)
sns.boxplot(data=data[data['label']==1],x='评论数')
plt.title('谣言帖子的评论数分布情况')
plt.subplot(2,1,2)
sns.boxplot(data=data[data['label']==1],x='点赞数')
plt.title('谣言帖子的点赞数分布情况')
plt.show()
# 分析非谣言帖子的评论数和点赞数分布
plt.figure(figsize=(16,16))
plt.subplot(2,1,1)
sns.boxplot(data=data[data['label']==0],x='评论数')
plt.title('非谣言帖子的评论数分布情况')
plt.subplot(2,1,2)
sns.boxplot(data=data[data['label']==0],x='点赞数')
plt.title('非谣言帖子的点赞数分布情况')
plt.show()
# 分析各个特征之间的相关系数
fig = plt.figure(figsize=(6,6))
sns.heatmap(data.corr(),vmax=1,annot=True,linewidths=0.5,cbar=False,cmap='YlGnBu',annot_kws={'fontsize':14})
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.title('各个因素之间的相关系数',fontsize=16)
plt.show()
import re
import jieba
def chinese_word_cut(mytext):
# 文本预处理 :去除一些无用的字符只提取出中文出来
new_data = re.findall('[\u4e00-\u9fa5]+', mytext, re.S)
new_data = " ".join(new_data)
# 文本分词
seg_list_exact = jieba.cut(new_data)
result_list = []
with open('停用词库.txt', encoding='utf-8') as f: # 可根据需要打开停用词库,然后加上不想显示的词语
con = f.readlines()
stop_words = set()
for i in con:
i = i.replace("\n", "") # 去掉读取每一行数据的\n
stop_words.add(i)
for word in seg_list_exact:
if word not in stop_words and len(word) > 1:
result_list.append(word)
return " ".join(result_list)
data["text_cutted"] = data.text.apply(chinese_word_cut)
data.head()
# 文本向量化
from sklearn.feature_extraction.text import CountVectorizer
tf_vectorizer = CountVectorizer()
X = tf_vectorizer.fit_transform(data['text_cutted'])
y = data['label']
# 划分数据集
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X, y,test_size=0.2)
# 构建随机森林模型
from sklearn.ensemble import RandomForestClassifier
rfc = RandomForestClassifier()
rfc.fit(x_train,y_train)
print('模型准确率:',rfc.score(x_test,y_test))
# 构建朴素贝叶斯算法模型
from sklearn.naive_bayes import GaussianNB
gnb = GaussianNB()
gnb.fit(x_train.toarray(),y_train)
print('模型准确率:',gnb.score(x_test.toarray(),y_test))
# 构造svm支持向量机模型
from sklearn.svm import SVC
svc = SVC()
svc.fit(x_train,y_train)
print('模型准确率:',svc.score(x_test,y_test))
# 构造xgboost算法模型
from xgboost import XGBClassifier
xgb = XGBClassifier()
xgb.fit(x_train,y_train)
print('模型准确率:',xgb.score(x_test,y_test))
# 因为朴素贝叶斯模型准确率最高,故选用朴素贝叶斯模型作为最终的模型
from sklearn.metrics import confusion_matrix,classification_report,auc,roc_curve
# 模型评估
y_pred = gnb.predict(x_test.toarray())
print('模型混淆矩阵:','\n',confusion_matrix(y_test,y_pred))
fig = plt.figure(figsize=(10,8))
sns.heatmap(confusion_matrix(y_test,y_pred),annot=True,linewidths=0.5,annot_kws={'fontsize':18},fmt='d')
plt.xlabel('Predicted Class',fontdict={'fontsize':16})
plt.ylabel('True Class',fontdict={'fontsize':16})
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
plt.title('GaussianNB',fontsize=20)
plt.show()
print('模型分类报告:','\n',classification_report(y_test,y_pred))
# 画出ROC曲线
y_prob = gnb.predict_proba(x_test.toarray())[:,1]
false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_prob)
roc = auc(false_positive_rate, true_positive_rate)
plt.figure(figsize=(10,10))
plt.title('ROC')
plt.plot(false_positive_rate,true_positive_rate, color='red',label = 'AUC = %0.2f' % roc)
plt.legend(loc = 'lower right')
plt.plot([0, 1], [0, 1],linestyle='--')
plt.axis('tight')
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()
# 使用朴素贝叶斯模型进行预测,发现十个当作有一个预测错误
result = pd.DataFrame()
result['真实值'] = y_test
result['预测值'] = y_pred
result.head(10)