Python語言結(jié)合機器學(xué)習(xí)算法進行微博預(yù)測

本文是基于Python語言結(jié)合基礎(chǔ)的機器學(xué)習(xí)算法來對微博傳播廣度下的微博轉(zhuǎn)發(fā)次數(shù)來進行預(yù)測的,并分析了微博在轉(zhuǎn)發(fā)過程中有可能出現(xiàn)峰值的時刻。

1、環(huán)境準備
  1. 使用語言:python
  2. 軟件IDE:PyCharm
  3. 數(shù)據(jù)來源:DataCastle(數(shù)據(jù)城堡)原始發(fā)布數(shù)據(jù)
2、理論知識儲備以及機器學(xué)習(xí)算法原理圖解
2.1 微博轉(zhuǎn)發(fā)廣度

其中a為發(fā)送原始微博的用戶,b,b1,b2都是用戶a的粉絲,所以a所發(fā)的微博會被他的所有粉絲看到,假如b轉(zhuǎn)發(fā)了a所發(fā)的微博,則b的所有粉絲即c,c1,c2都可以看到b所轉(zhuǎn)發(fā)的a的那條微博,微博的轉(zhuǎn)發(fā)廣度就是在被轉(zhuǎn)發(fā)人所發(fā)布的這條微博被轉(zhuǎn)發(fā)者所轉(zhuǎn)發(fā)之后所覆蓋的所有用戶。

微博轉(zhuǎn)發(fā)廣度示意圖.png

故這條微博的轉(zhuǎn)發(fā)廣度就為6。如果c還繼續(xù)轉(zhuǎn)發(fā)b所轉(zhuǎn)發(fā)的a發(fā)布的微博,同理,這里不再做演示。

2.2 KNN算法

現(xiàn)已經(jīng)存在一部分樣本數(shù)據(jù),并且每個數(shù)據(jù)都具有相應(yīng)的標(biāo)簽,然后往此數(shù)據(jù)中輸入新的無任何標(biāo)簽的數(shù)據(jù)值,然后比較新輸入數(shù)據(jù)的特征與已有的特征作對比,找出數(shù)據(jù)特征最為相近的數(shù)據(jù)值,將其貼上最多的數(shù)據(jù)值所具有的標(biāo)簽。

KNN原理圖解.jpg
2.3 決策樹算法

決策樹算法是屬于機器學(xué)習(xí)監(jiān)督學(xué)習(xí)分類算法中的,一般在理解隨機森林之前要對決策樹有所理解,其中決策樹就是一個比較簡單的是否問題,對所有的問題都只會有是和否兩種結(jié)果供選擇,不同的選擇會導(dǎo)致不同的樹的走向,直到最終走向葉子結(jié)點,決策樹就是在這種不斷分類中而形成的一種樹形的分類算法。

決策樹算法原理.png

從上圖就可以看出,其實決策樹就是If()語句的層層嵌套,會一直根據(jù)判斷是否來樹狀延伸下去。

2.4 隨機森林算法

隨機森林首先是一種有放回的分類算法,是基于決策樹的一種算法,其中隨機森林是通過決策樹隨機構(gòu)建的,并且每一棵決策樹之間都是沒有任何關(guān)聯(lián)的,并且對數(shù)據(jù)也是進行隨機采樣的,對特征的選取也是完全隨機的,然后對數(shù)據(jù)分別進行訓(xùn)練,訓(xùn)練完成之后以一種投票的方式來決定最終的結(jié)果,隨機森林這種通過隨機和森林的方式可以保證模型的方差降低而不需要進行剪枝,也可以取得比較好的泛化能力和抗擬合能力。

隨機森林算法原理.png
2.5 決策樹算法改進原理

本次對決策樹算法的改進是通過使用sklearn.grid_search庫下的GridSearchCV方法,通過對原始數(shù)據(jù)集進行訓(xùn)練,再通過構(gòu)建決策樹中的參數(shù)列表來使用網(wǎng)格搜索和交叉驗證的暴力搜索方式來對決策樹中的各個參數(shù)的取值進行驗證,每次獲取某個參數(shù)的最佳值應(yīng)用到下一次搜索中去,使用迭代的思想對參數(shù)值進行窮盡搜索,根據(jù)得分情況來對參數(shù)的取值進行統(tǒng)計,最終取出最佳分數(shù)值以及對應(yīng)的最佳參數(shù)列表,直接將最佳參數(shù)的取值應(yīng)用到?jīng)Q策樹算法模型構(gòu)建中去,來分析算法改進前后的性能差異。

決策樹算法改進原理.png
2.6 隨機森林算法改進原理

首先隨機森林是一種隨機構(gòu)建特征值的機器學(xué)習(xí)算法,其包含眾多決策樹算法模型,且每一個決策樹之間都沒有任何聯(lián)系,基于這種情況,可以采用對特征值進行劃分的方法,將不同的特征值應(yīng)用到不同的隨機森林模型中去進行訓(xùn)練,對同一條微博的不同預(yù)測所產(chǎn)生的值去構(gòu)建集合,就可以得到每條微博預(yù)測值集合,在所統(tǒng)計的集合中選擇出最佳的單條微博預(yù)測值,最終將最佳預(yù)測結(jié)果進行整合,構(gòu)成最佳預(yù)測集合??偟膩碚f,改進后的隨進森林是通過構(gòu)建多隨機森林對數(shù)據(jù)集進行多次預(yù)測,每次取出最佳預(yù)測值,然后組成預(yù)測集合,再從集合中取出誤差最小的,最后再將所有誤差最小的預(yù)測結(jié)果進行整合,構(gòu)成最佳預(yù)測集合。

改進后的隨機森林算法原理圖.png

在微博傳播廣度下使用機器學(xué)習(xí)算法進行預(yù)測的完整代碼如下(其中包括KNN算法、決策樹算法改進前后、隨機森林算法改進前后):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Moxiaofei
# @File    : handle.py
# @Software: PyCharm
# 微博傳播廣度下預(yù)測

# 導(dǎo)入所需要的模塊
import pandas
from sklearn.neighbors import KNeighborsClassifier
from sklearn import tree
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV


# 讀取數(shù)據(jù)
data = pandas.read_csv('handle.csv', sep=' ')
# 定義用于訓(xùn)練時的特征
x_col = ["emotional_level", "follow_num", "at_flag", "topic_flag", "url_flag", "content_length",
         "time_step", "fans_num", "width1", "width2", "width3", "width4"]
# 定義自變量和目標(biāo)變量
x_train = data[x_col][:14717]
y_train = data['repost_num'][:14717]
# 定義需要預(yù)測的自變量和目標(biāo)變量
predict_value = data[x_col][14717:]
true_value = data['repost_num'][14717:]


# KNN算法
def knn_algorithm(x_train, y_train):
    # 預(yù)測出來的數(shù)據(jù)
    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):
    # 預(yù)測出來的數(shù)據(jù)
    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):
    # 預(yù)測出來的數(shù)據(jù)
    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')
    # 要選擇的參數(shù)列表
    parameter_grid = {'max_depth': list(range(1, 10)),
                      'min_samples_split': list(range(2, 10)),
                      'min_samples_leaf': list(range(1, 10))}
    # 使用GridSearchCV來查找最佳參數(shù)
    gridsearch = GridSearchCV(decision_tree_classifier, param_grid=parameter_grid, cv=5)
    gridsearch.fit(x_train, y_train)
    # 取出得分最高的參數(shù)值,并構(gòu)建最佳的決策樹
    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'])
    # 訓(xùn)練數(shù)據(jù)集  使用預(yù)測值訓(xùn)練真實值
    best_decision_tree_classifier.fit(x_train, y_train)
    # 預(yù)測數(shù)據(jù)集
    best_pre_value = best_decision_tree_classifier.predict(predict_value)
    # 計算真實值與預(yù)測值之間的平均百分比
    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)
            # 用一個三元組,分別記錄當(dāng)前的 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算法預(yù)測出的結(jié)果
    res_knn = knn_algorithm(x_train, y_train)
    error_list.append(res_knn[0])
    accuracy_list.append(res_knn[1])

    # 決策樹算法預(yù)測出的結(jié)果
    res_decisoinTree = decisionTree_algorithm(x_train, y_train)
    error_list.append(res_decisoinTree[0])
    accuracy_list.append(res_decisoinTree[1])

    # 隨機森林算法預(yù)測出的結(jié)果
    res_randomForest = randomForest_algorithm(x_train, y_train)
    error_list.append(res_randomForest[0])
    accuracy_list.append(res_randomForest[1])

    # 改進之后的決策樹算法預(yù)測出的結(jié)果
    res_improve_decisionTree = imporve_decisionTree(x_train, y_train)
    error_list.append(res_improve_decisionTree[0])
    accuracy_list.append(res_improve_decisionTree[1])

    # 改進之后的隨機森林算法預(yù)測出的結(jié)果
    res_improve_randomForest = improve_randomForest(x_train, y_train)
    error_list.append(res_improve_randomForest[0])
    accuracy_list.append(res_improve_randomForest[1])

    # 打印所使用的算法的預(yù)測平均絕對百分比誤差
    print(error_list)
    # 打印所使用的算法的預(yù)測準確率
    print(accuracy_list)

在微博傳播廣度下各數(shù)據(jù)特征之間的關(guān)系以及峰值出現(xiàn)的時刻圖:

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

# 導(dǎo)入所需要的模塊
from matplotlib import pyplot as plt
import pandas as pd

# *******************************
# 微博傳播廣度下的圖形繪制
# *******************************
# 讀取數(shù)據(jù)
data = pd.read_csv('handle.csv', sep=' ')

# ------用戶粉絲數(shù)與轉(zhuǎn)發(fā)數(shù)的關(guān)系散點圖------  #
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()

# ------計算在某個時間段內(nèi)轉(zhuǎn)發(fā)次數(shù)最多的,繪制成圖顯示峰值------  #
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)
    # 最大值所出現(xiàn)的時刻
    max_sub_time = line.index(max(line)) + int(1)
    MAX_TIME_DICT.append(max_sub_time)
    # 在差值里面統(tǒng)計時刻和最大差值
time_count = []
for i in range(1, 12):
    # 輸出出現(xiàn)最大差值的時刻的數(shù)量
    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小時傳播次數(shù)和總傳播次數(shù)的散點圖------  #
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()

這里只是簡述了所使用算法的原理,并對微博傳播廣度下的轉(zhuǎn)發(fā)數(shù)進行預(yù)測的代碼的展示;此外,還對微博深度下的特征進行了預(yù)測研究,預(yù)測了其可能出現(xiàn)峰值的時刻。需要完整代碼可移步至此

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容