本文是基于Python語言結(jié)合基礎(chǔ)的機器學習算法來對微博傳播廣度下的微博轉(zhuǎn)發(fā)次數(shù)來進行預測的,并分析了微博在轉(zhuǎn)發(fā)過程中有可能出現(xiàn)峰值的時刻彪见。
1萌腿、環(huán)境準備
- 使用語言:python
- 軟件IDE:PyCharm
- 數(shù)據(jù)來源:DataCastle(數(shù)據(jù)城堡)原始發(fā)布數(shù)據(jù)
2腻暮、理論知識儲備以及機器學習算法原理圖解
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ā)廣度就為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)的標簽仅淑,然后往此數(shù)據(jù)中輸入新的無任何標簽的數(shù)據(jù)值,然后比較新輸入數(shù)據(jù)的特征與已有的特征作對比胸哥,找出數(shù)據(jù)特征最為相近的數(shù)據(jù)值涯竟,將其貼上最多的數(shù)據(jù)值所具有的標簽。
2.3 決策樹算法
決策樹算法是屬于機器學習監(jiān)督學習分類算法中的空厌,一般在理解隨機森林之前要對決策樹有所理解庐船,其中決策樹就是一個比較簡單的是否問題,對所有的問題都只會有是和否兩種結(jié)果供選擇嘲更,不同的選擇會導致不同的樹的走向筐钟,直到最終走向葉子結(jié)點,決策樹就是在這種不斷分類中而形成的一種樹形的分類算法赋朦。
從上圖就可以看出篓冲,其實決策樹就是If()語句的層層嵌套李破,會一直根據(jù)判斷是否來樹狀延伸下去。
2.4 隨機森林算法
隨機森林首先是一種有放回的分類算法壹将,是基于決策樹的一種算法嗤攻,其中隨機森林是通過決策樹隨機構(gòu)建的,并且每一棵決策樹之間都是沒有任何關(guān)聯(lián)的诽俯,并且對數(shù)據(jù)也是進行隨機采樣的妇菱,對特征的選取也是完全隨機的,然后對數(shù)據(jù)分別進行訓練暴区,訓練完成之后以一種投票的方式來決定最終的結(jié)果闯团,隨機森林這種通過隨機和森林的方式可以保證模型的方差降低而不需要進行剪枝,也可以取得比較好的泛化能力和抗擬合能力仙粱。
2.5 決策樹算法改進原理
本次對決策樹算法的改進是通過使用sklearn.grid_search庫下的GridSearchCV方法偷俭,通過對原始數(shù)據(jù)集進行訓練,再通過構(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)建中去,來分析算法改進前后的性能差異济炎。
2.6 隨機森林算法改進原理
首先隨機森林是一種隨機構(gòu)建特征值的機器學習算法川抡,其包含眾多決策樹算法模型,且每一個決策樹之間都沒有任何聯(lián)系须尚,基于這種情況崖堤,可以采用對特征值進行劃分的方法,將不同的特征值應(yīng)用到不同的隨機森林模型中去進行訓練耐床,對同一條微博的不同預測所產(chǎn)生的值去構(gòu)建集合密幔,就可以得到每條微博預測值集合,在所統(tǒng)計的集合中選擇出最佳的單條微博預測值撩轰,最終將最佳預測結(jié)果進行整合胯甩,構(gòu)成最佳預測集合】吧總的來說偎箫,改進后的隨進森林是通過構(gòu)建多隨機森林對數(shù)據(jù)集進行多次預測,每次取出最佳預測值皆串,然后組成預測集合淹办,再從集合中取出誤差最小的,最后再將所有誤差最小的預測結(jié)果進行整合恶复,構(gòu)成最佳預測集合怜森。
在微博傳播廣度下使用機器學習算法進行預測的完整代碼如下(其中包括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
# 讀取數(shù)據(jù)
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):
# 預測出來的數(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):
# 預測出來的數(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):
# 預測出來的數(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'])
# 訓練數(shù)據(jù)集 使用預測值訓練真實值
best_decision_tree_classifier.fit(x_train, y_train)
# 預測數(shù)據(jù)集
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算法預測出的結(jié)果
res_knn = knn_algorithm(x_train, y_train)
error_list.append(res_knn[0])
accuracy_list.append(res_knn[1])
# 決策樹算法預測出的結(jié)果
res_decisoinTree = decisionTree_algorithm(x_train, y_train)
error_list.append(res_decisoinTree[0])
accuracy_list.append(res_decisoinTree[1])
# 隨機森林算法預測出的結(jié)果
res_randomForest = randomForest_algorithm(x_train, y_train)
error_list.append(res_randomForest[0])
accuracy_list.append(res_randomForest[1])
# 改進之后的決策樹算法預測出的結(jié)果
res_improve_decisionTree = imporve_decisionTree(x_train, y_train)
error_list.append(res_improve_decisionTree[0])
accuracy_list.append(res_improve_decisionTree[1])
# 改進之后的隨機森林算法預測出的結(jié)果
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)
在微博傳播廣度下各數(shù)據(jù)特征之間的關(guān)系以及峰值出現(xiàn)的時刻圖:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : Moxiaofei
# @File : draw.py
# @Software: PyCharm
# 繪圖
# 導入所需要的模塊
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ù)進行預測的代碼的展示;此外流纹,還對微博深度下的特征進行了預測研究糜烹,預測了其可能出現(xiàn)峰值的時刻。需要完整代碼可移步至此