Python语言结合机器学习算法进行微博预测

本文是基于Python语言结合基础的机器学习算法来对微博传播广度下的微博转发次数来进行预测的,并分析了微博在转发过程中有可能出现峰值的时刻。

1、环境准备
  1. 使用语言:python
  2. 软件IDE:PyCharm
  3. 数据来源:DataCastle(数据城堡)原始发布数据
2、理论知识储备以及机器学习算法原理图解
2.1 微博转发广度

其中a为发送原始微博的用户,b,b1,b2都是用户a的粉丝,所以a所发的微博会被他的所有粉丝看到,假如b转发了a所发的微博,则b的所有粉丝即c,c1,c2都可以看到b所转发的a的那条微博,微博的转发广度就是在被转发人所发布的这条微博被转发者所转发之后所覆盖的所有用户。

微博转发广度示意图.png

故这条微博的转发广度就为6。如果c还继续转发b所转发的a发布的微博,同理,这里不再做演示。

2.2 KNN算法

现已经存在一部分样本数据,并且每个数据都具有相应的标签,然后往此数据中输入新的无任何标签的数据值,然后比较新输入数据的特征与已有的特征作对比,找出数据特征最为相近的数据值,将其贴上最多的数据值所具有的标签。

KNN原理图解.jpg
2.3 决策树算法

决策树算法是属于机器学习监督学习分类算法中的,一般在理解随机森林之前要对决策树有所理解,其中决策树就是一个比较简单的是否问题,对所有的问题都只会有是和否两种结果供选择,不同的选择会导致不同的树的走向,直到最终走向叶子结点,决策树就是在这种不断分类中而形成的一种树形的分类算法。

决策树算法原理.png

从上图就可以看出,其实决策树就是If()语句的层层嵌套,会一直根据判断是否来树状延伸下去。

2.4 随机森林算法

随机森林首先是一种有放回的分类算法,是基于决策树的一种算法,其中随机森林是通过决策树随机构建的,并且每一棵决策树之间都是没有任何关联的,并且对数据也是进行随机采样的,对特征的选取也是完全随机的,然后对数据分别进行训练,训练完成之后以一种投票的方式来决定最终的结果,随机森林这种通过随机和森林的方式可以保证模型的方差降低而不需要进行剪枝,也可以取得比较好的泛化能力和抗拟合能力。

随机森林算法原理.png
2.5 决策树算法改进原理

本次对决策树算法的改进是通过使用sklearn.grid_search库下的GridSearchCV方法,通过对原始数据集进行训练,再通过构建决策树中的参数列表来使用网格搜索和交叉验证的暴力搜索方式来对决策树中的各个参数的取值进行验证,每次获取某个参数的最佳值应用到下一次搜索中去,使用迭代的思想对参数值进行穷尽搜索,根据得分情况来对参数的取值进行统计,最终取出最佳分数值以及对应的最佳参数列表,直接将最佳参数的取值应用到决策树算法模型构建中去,来分析算法改进前后的性能差异。

决策树算法改进原理.png
2.6 随机森林算法改进原理

首先随机森林是一种随机构建特征值的机器学习算法,其包含众多决策树算法模型,且每一个决策树之间都没有任何联系,基于这种情况,可以采用对特征值进行划分的方法,将不同的特征值应用到不同的随机森林模型中去进行训练,对同一条微博的不同预测所产生的值去构建集合,就可以得到每条微博预测值集合,在所统计的集合中选择出最佳的单条微博预测值,最终将最佳预测结果进行整合,构成最佳预测集合。总的来说,改进后的随进森林是通过构建多随机森林对数据集进行多次预测,每次取出最佳预测值,然后组成预测集合,再从集合中取出误差最小的,最后再将所有误差最小的预测结果进行整合,构成最佳预测集合。

改进后的随机森林算法原理图.png

在微博传播广度下使用机器学习算法进行预测的完整代码如下(其中包括KNN算法、决策树算法改进前后、随机森林算法改进前后):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Moxiaofei
# @File    : handle.py
# @Software: PyCharm
# 微博传播广度下预测

# 导入所需要的模块
import pandas
from sklearn.neighbors import KNeighborsClassifier
from sklearn import tree
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV


# 读取数据
data = pandas.read_csv('handle.csv', sep=' ')
# 定义用于训练时的特征
x_col = ["emotional_level", "follow_num", "at_flag", "topic_flag", "url_flag", "content_length",
         "time_step", "fans_num", "width1", "width2", "width3", "width4"]
# 定义自变量和目标变量
x_train = data[x_col][:14717]
y_train = data['repost_num'][:14717]
# 定义需要预测的自变量和目标变量
predict_value = data[x_col][14717:]
true_value = data['repost_num'][14717:]


# KNN算法
def knn_algorithm(x_train, y_train):
    # 预测出来的数据
    pre_data = (KNeighborsClassifier().fit(x_train, y_train)).predict(predict_value)
    # 平均绝对百分比误差
    avg_error = calculate_avg_error(pre_data, true_value)
    accuracy = (100 - avg_error*100)/100
    return avg_error, accuracy


# 决策树算法
def decisionTree_algorithm(x_train, y_train):
    # 预测出来的数据
    pre_data = (tree.DecisionTreeClassifier().fit(x_train, y_train)).predict(predict_value)
    # 平均绝对百分比误差
    avg_error = calculate_avg_error(pre_data, true_value)
    accuracy = (100 - avg_error * 100) / 100
    return avg_error, accuracy


# 随机森林算法
def randomForest_algorithm(x_train, y_train):
    # 预测出来的数据
    pre_data = (RandomForestClassifier().fit(x_train, y_train)).predict(predict_value)
    # 平均绝对百分比误差
    avg_error = calculate_avg_error(pre_data, true_value)
    accuracy = (100 - avg_error * 100) / 100
    return avg_error, accuracy


# 改进的决策树算法
def imporve_decisionTree(x_train, y_train):
    decision_tree_classifier = tree.DecisionTreeClassifier(max_features='sqrt')
    # 要选择的参数列表
    parameter_grid = {'max_depth': list(range(1, 10)),
                      'min_samples_split': list(range(2, 10)),
                      'min_samples_leaf': list(range(1, 10))}
    # 使用GridSearchCV来查找最佳参数
    gridsearch = GridSearchCV(decision_tree_classifier, param_grid=parameter_grid, cv=5)
    gridsearch.fit(x_train, y_train)
    # 取出得分最高的参数值,并构建最佳的决策树
    best_param = gridsearch.best_params_
    print(best_param)
    best_decision_tree_classifier = tree.DecisionTreeClassifier(max_depth=best_param['max_depth'],
                                                                min_samples_split=best_param['min_samples_split'],
                                                                min_samples_leaf=best_param['min_samples_leaf'])
    # 训练数据集  使用预测值训练真实值
    best_decision_tree_classifier.fit(x_train, y_train)
    # 预测数据集
    best_pre_value = best_decision_tree_classifier.predict(predict_value)
    # 计算真实值与预测值之间的平均百分比
    best_avg_error = calculate_avg_error(best_pre_value, true_value)
    best_accuracy = (100-100*best_avg_error)/100
    return best_avg_error, best_accuracy


# 改进的随机森林算法
def improve_randomForest(x_train, y_train):
    # n_estimators的取值范围
    n_estimators_options = list(range(10, 100, 10))
    sample_leaf_options = list(range(1, 10, 1))
    results = []
    for leaf_size in sample_leaf_options:
        for n_estimators_size in n_estimators_options:
            alg = RandomForestClassifier(min_samples_leaf=leaf_size, n_estimators=n_estimators_size, random_state=50)
            alg.fit(x_train, y_train)
            predict = alg.predict(predict_value)
            average_err = calculate_avg_error(predict, true_value)
            # 用一个三元组,分别记录当前的 min_samples_leaf,n_estimators, 和平均误差
            results.append((leaf_size, n_estimators_size, predict, average_err))
    # 打印精度最大的那一个三元组
    min_pre = min(results, key=lambda x: x[3])
    accuracy_rate = (100 - min_pre[3]*100)/100
    return min_pre[3], accuracy_rate


# 计算平均绝对百分比误差
def calculate_avg_error(pre_value, true_value):
    return float(format(((abs(pre_value - true_value) / true_value).sum()) / len(pre_value), '.2f'))


if __name__ == '__main__':
    error_list = []
    accuracy_list = []

    # KNN算法预测出的结果
    res_knn = knn_algorithm(x_train, y_train)
    error_list.append(res_knn[0])
    accuracy_list.append(res_knn[1])

    # 决策树算法预测出的结果
    res_decisoinTree = decisionTree_algorithm(x_train, y_train)
    error_list.append(res_decisoinTree[0])
    accuracy_list.append(res_decisoinTree[1])

    # 随机森林算法预测出的结果
    res_randomForest = randomForest_algorithm(x_train, y_train)
    error_list.append(res_randomForest[0])
    accuracy_list.append(res_randomForest[1])

    # 改进之后的决策树算法预测出的结果
    res_improve_decisionTree = imporve_decisionTree(x_train, y_train)
    error_list.append(res_improve_decisionTree[0])
    accuracy_list.append(res_improve_decisionTree[1])

    # 改进之后的随机森林算法预测出的结果
    res_improve_randomForest = improve_randomForest(x_train, y_train)
    error_list.append(res_improve_randomForest[0])
    accuracy_list.append(res_improve_randomForest[1])

    # 打印所使用的算法的预测平均绝对百分比误差
    print(error_list)
    # 打印所使用的算法的预测准确率
    print(accuracy_list)

在微博传播广度下各数据特征之间的关系以及峰值出现的时刻图:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Moxiaofei
# @File    : draw.py
# @Software: PyCharm
# 绘图

# 导入所需要的模块
from matplotlib import pyplot as plt
import pandas as pd

# *******************************
# 微博传播广度下的图形绘制
# *******************************
# 读取数据
data = pd.read_csv('handle.csv', sep=' ')

# ------用户粉丝数与转发数的关系散点图------  #
plt.figure(figsize=(7, 5))
fans_num = data['fans_num']
repost_num = data['repost_num']
plt.scatter(fans_num, repost_num)
plt.title('The relationship between fans_num and repost_num')
plt.xlabel('the number of the fans')
plt.ylabel('the number of the repost')
# 保存图片到本路径下
# plt.savefig('repost_fans.png', dpi=400, bbox_inches='tight')
# plt.show()

# ------计算在某个时间段内转发次数最多的,绘制成图显示峰值------  #
res = []
# i的取值为[1,11]
for i in range(1, 12):
    res.append(data['width'+str(i+1)] - data['width'+str(i)])
time_repost_num = []
MAX_TIME_DICT = []
for j in range(0, 14767):
    # [32, 85, 1, 267, 95, 74, 18, 8, 103, 33, 17]  所有的差值
    line = [x[j] for x in res]
    # print(line)
    # 最大值所出现的时刻
    max_sub_time = line.index(max(line)) + int(1)
    MAX_TIME_DICT.append(max_sub_time)
    # 在差值里面统计时刻和最大差值
time_count = []
for i in range(1, 12):
    # 输出出现最大差值的时刻的数量
    time_count.append(MAX_TIME_DICT.count(i))
plt.figure(figsize=(7, 5))
time = range(1, 12)
plt.plot(time, time_count)
plt.title('The relationship between time and D-value')
plt.xlabel('the number of the time')
plt.ylabel('the number of the D-value')
# plt.savefig('top.png', dpi=400, bbox_inches='tight')
# plt.show()


#  ------峰值 微博3小时传播次数和总传播次数的散点图------  #
plt.figure(figsize=(7, 5))
x1 = data['width12']
y1 = data['repost_num']
plt.scatter(x1, y1)
plt.title('The relationship between spread_num and repost_num')
plt.xlabel('the number of the spread_num')
plt.ylabel('the number of the repost_num')
# plt.savefig('3_all.png', dpi=400, bbox_inches='tight')
# plt.show()

这里只是简述了所使用算法的原理,并对微博传播广度下的转发数进行预测的代码的展示;此外,还对微博深度下的特征进行了预测研究,预测了其可能出现峰值的时刻。需要完整代码可移步至此

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容