数学建模预测模型实例(二)---表白墙影响力量化模型
數(shù)學(xué)建模預(yù)測(cè)模型實(shí)例–表白墻影響力量化模型
數(shù)學(xué)建模預(yù)測(cè)模型實(shí)例(一)–大學(xué)生體測(cè)數(shù)據(jù)模型
數(shù)學(xué)建模預(yù)測(cè)模型實(shí)例(二)—表白墻影響力量化模型
python預(yù)測(cè)模型–線(xiàn)性回歸
建立模型的目的
本篇文章中,假設(shè)獲取到了某高校表白墻建墻以來(lái)至2020年12月21日發(fā)布的所有說(shuō)說(shuō)的文字內(nèi)容,發(fā)布時(shí)間,點(diǎn)贊數(shù),評(píng)論數(shù)。目的是通過(guò)前期數(shù)據(jù)挖掘探索性數(shù)據(jù)分析等建立表白墻影響力量化模型,進(jìn)而得出發(fā)布尋物類(lèi)消息的最佳時(shí)機(jī)以及持續(xù)影響力,最大影響人數(shù)等指標(biāo)。
數(shù)據(jù)分析的基本過(guò)程包括:獲取數(shù)據(jù)、數(shù)據(jù)清洗、中文分詞聚類(lèi)、探索性數(shù)據(jù)挖掘、數(shù)據(jù)可視化、基于SIR模型的表白墻影響力量化模型。
獲取數(shù)據(jù)
在這里我們用selenium模擬登錄qq空間,然后用xpath解析網(wǎng)頁(yè)
#coding: utf-8 from imp import reload import time from selenium import webdriver from lxml import etree import pandas as pddef text(friend, user , pw):# 獲取瀏覽器驅(qū)動(dòng)driver = webdriver.Chrome(executable_path='chromedriver')# 瀏覽器窗口最大化driver.maximize_window()# 瀏覽器地址定向?yàn)?qq 登陸頁(yè)面driver.get('http://i.qq.com')# 所以這里需要選中一下 frame,否則找不到下面需要的網(wǎng)頁(yè)元素driver.switch_to.frame('login_frame')# 自動(dòng)點(diǎn)擊賬號(hào)登陸方式driver.find_element_by_id('switcher_plogin').click()# 賬號(hào)輸入框輸入已知 QQ 賬號(hào)driver.find_element_by_id('u').send_keys(user)# 密碼框輸入已知密碼driver.find_element_by_id('p').send_keys(pw)# 自動(dòng)點(diǎn)擊登陸按鈕driver.find_element_by_id('login_button').click()time.sleep(10)# 讓 webdriver 操縱當(dāng)前頁(yè)driver.switch_to.default_content()# 跳到說(shuō)說(shuō)的 url,friend 你可以任意改成你想訪(fǎng)問(wèn)的空間driver.get('http://user.qzone.qq.com/' + friend + '/311')next_num = 0 # 初始“下一頁(yè)”的 idwhile True:# 下拉滾動(dòng)條,使瀏覽器加載出動(dòng)態(tài)加載的內(nèi)容# 我這里是從 1 開(kāi)始到 6 結(jié)束分 5 次加載完每頁(yè)數(shù)據(jù)for i in range(1, 6):height = 20000 * i# 每次滑動(dòng) 20000 像素strWord = "window.scrollBy(0," + str(height) + ")"driver.execute_script(strWord)time.sleep(4)# 很多時(shí)候網(wǎng)頁(yè)由多個(gè)<frame>或<iframe>組成,webdriver 默認(rèn)定位的是最外層的 frame# 所以這里需要選中一下說(shuō)說(shuō)所在的 frame,否則找不到下面需要的網(wǎng)頁(yè)元素driver.switch_to.frame('app_canvas_frame')selector = etree.HTML(driver.page_source)divs = selector.xpath('//*[@id="msgList"]/li/div[3]')# 這里使用 a 表示內(nèi)容可以連續(xù)不清空寫(xiě)入with open(r'C:\Users\15643\Desktop\公眾號(hào)\表白墻\data2.csv',"a",encoding='utf-8')as f:for div in divs:#qq_name = div.xpath('./div[2]/a/text()')qq_content = div.xpath('./div[2]/pre/text()')qq_time = div.xpath('./div[4]/div[1]/span/a/@title')qq_zan = div.xpath('./div[5]/div[2]/a[2]/text()')qq_comment = div.xpath('./div[4]/div[2]/a[3]/text()')#qq_name = qq_name[0] if len(qq_name) > 0 else ''qq_content = qq_content[0] if len(qq_content) > 0 else ''qq_time = qq_time[0] if len(qq_time) > 0 else ''f.write("{}.{}.{}.{}\n".format(qq_content,qq_time,qq_zan,qq_comment))print(qq_time, qq_content,qq_zan,qq_comment)# 當(dāng)已經(jīng)到了尾頁(yè),“下一頁(yè)”這個(gè)按鈕就沒(méi)有 id 了,可以結(jié)束了if driver.page_source.find('pager_next_' + str(next_num)) == -1:break# 找到“下一頁(yè)”的按鈕,因?yàn)橄乱豁?yè)的按鈕是動(dòng)態(tài)變化的,這里需要?jiǎng)討B(tài)記錄一下driver.find_element_by_id('pager_next_' + str(next_num)).click()# "下一頁(yè)"的 idnext_num += 1# 因?yàn)樵谙乱粋€(gè)循環(huán)里首先還要把頁(yè)面下拉,所以要跳到外層的 frame 上driver.switch_to.parent_frame()if __name__ == '__main__':friend = 'xxxx' # 朋友的 QQ 號(hào),朋友的空間要求允許你能訪(fǎng)問(wèn)user = 'xxxx' # 你的 QQ 號(hào)pw = 'xxxx' # 你的 QQ 密碼text(friend, user, pw)最終獲取到一個(gè)包含所有說(shuō)說(shuō)內(nèi)容,發(fā)布時(shí)間,點(diǎn)贊數(shù),評(píng)論數(shù)的excel文件,隨后再將說(shuō)說(shuō)文本提取到一個(gè)txt文件里面便于之后進(jìn)行分詞。
最終獲取到的數(shù)據(jù):說(shuō)說(shuō)數(shù)據(jù).xlsx
說(shuō)說(shuō)文本.txt
數(shù)據(jù):表白墻數(shù)據(jù) 提取碼:klh0
數(shù)據(jù)清洗—中文文本分詞
首先先對(duì)txt里的說(shuō)說(shuō)數(shù)據(jù)進(jìn)行分詞、并刪去停用詞,無(wú)效符號(hào)。考慮到表白墻中一些詞語(yǔ)的連貫性,我們引入了自定義詞典
求同好
大橘
首醫(yī)
墻墻
表白墻
一教
二教
隨后運(yùn)用jieba分詞庫(kù)進(jìn)行分詞處理
import jieba# 加載停用詞列表 def load_stopword():f_stop = open('stopword.txt', encoding='utf-8') # 自己的中文停用詞表sw = [line.strip() for line in f_stop] # strip() 方法用于移除字符串頭尾指定的字符(默認(rèn)為空格)f_stop.close()return sw# 中文分詞并且去停用詞 def seg_word(sentence):file_userDict = 'dict.txt' # 自定義的詞典jieba.load_userdict(file_userDict)sentence_seged = jieba.cut(sentence.strip())stopwords = load_stopword()outstr = ''for word in sentence_seged:if word not in stopwords:if word != '/t':outstr += wordoutstr += " "print(outstr)return outstrif __name__ == '__main__':with open("qq_word.txt", "r",encoding='utf-8') as f:content=f.read()result = seg_word(content)分詞結(jié)束后再應(yīng)用 jiaba.analyse.extract_tags() 中默認(rèn)的TF-IDF模型對(duì)文檔進(jìn)行分析。
TF-IDF的基本思想是:詞語(yǔ)的重要性與它在文件中出現(xiàn)的次數(shù)成正比,但同時(shí)會(huì)隨著它在語(yǔ)料庫(kù)中出現(xiàn)的頻率成反比下降 。也就是說(shuō)TD-IDF綜合考慮了兩方面因素,排除了那些看似詞頻很高實(shí)則是無(wú)效常見(jiàn)詞的情況(例如:的,包括)。因此某個(gè)詞對(duì)文章的重要性越高,它的TF-IDF值就越大
從以上結(jié)果可以看出,提取到的分詞數(shù)據(jù)所制成的詞云圖與關(guān)鍵詞相呼應(yīng),表明“表白,求助,吐槽,失物招領(lǐng),一周cp”是表白墻的主題內(nèi)容。表白墻不愧為表白墻,表白還是占了絕大多數(shù)。
探索性數(shù)據(jù)分析–表白+吐槽
確定思路
在進(jìn)行過(guò)初始的數(shù)據(jù)清洗之后我們找到了表白墻的五大主題,為了方便接下來(lái)的分析,我們將這五大主題劃歸為三大類(lèi):表白,吐槽,尋物,在這里我們認(rèn)為前兩類(lèi)是帶有明顯且強(qiáng)烈的情感暗示的內(nèi)容,因此這兩類(lèi)說(shuō)說(shuō)的點(diǎn)贊,評(píng)論,乃至發(fā)布時(shí)間可能會(huì)遵循某種分布。以下為對(duì)這兩類(lèi)說(shuō)說(shuō)的分析
注:為保證數(shù)據(jù)的真實(shí)性,我們刪去了新冠疫情期間的所有表白墻數(shù)據(jù)(2020/3-2020/8)
時(shí)間分析
為了衡量表白墻發(fā)布這兩類(lèi)投稿的偏好時(shí)間,我們對(duì)一天三個(gè)時(shí)間段表白墻針對(duì)這兩個(gè)主題說(shuō)說(shuō)的發(fā)布情況進(jìn)行了統(tǒng)計(jì)。
##以吐槽說(shuō)說(shuō)的分析過(guò)程為例 import numpy as np import pandas as pd excel_path_1 = r'C:\Users\15643\Desktop\吐槽全.xlsx' df1 = pd.DataFrame(pd.read_excel(excel_path_1)) time_new = pd.to_datetime(df1['time'],format='%H:%M:%S') df1['hour']=time_new.dt.hour m=[] a=[] e=[] for i in range(len(df1)):if 8<=df1.iloc[i,3]<=12:m.append(df1.iloc[i,3])elif 12<=df1.iloc[i,3]<=18:a.append(df1.iloc[i,3])elif 18<=df1.iloc[i,3]<=24:e.append(df1.iloc[i,3])
從以上結(jié)果我們可以很明顯的看出晚間實(shí)際上是投稿的高峰期,晚上的確是多愁善感的網(wǎng)抑云時(shí)間。
熱度分析
為了衡量這兩類(lèi)說(shuō)說(shuō)在不同時(shí)間段的熱度,我們首先對(duì)熱度進(jìn)行定義:
隨后定義了一學(xué)期中的三個(gè)時(shí)間段:
| 學(xué)期中 |
| 學(xué)期末:最后一個(gè)月 |
根據(jù)以上的定義進(jìn)行數(shù)據(jù)篩選
#以吐槽說(shuō)說(shuō)學(xué)期末熱度分析為例 import numpy as np import pandas as pd excel_path_1 = r'C:\Users\15643\Desktop\吐槽全.xlsx df1 = pd.DataFrame(pd.read_excel(excel_path_1)) df1['zan'] = df1['zan'].apply(lambda x :x*0.4 if x != 0 else 0) df1['comment'] = df1['comment'].apply(lambda x :x*0.6 if x != 0 else 0) hot_p_l=[] for i in range(len(df1)):hot_p =df1.iloc[i,2]+df1.iloc[i,3]hot_p_l.append(hot_p) df1['hot_p']=pd.DataFrame(hot_p_l) time_start=pd.datetime(2018,12,15) time_stop =pd.datetime(2019,1,15) df_a_1 = df1[(df1['date'] >= time_start) & (df1['date'] <= time_stop)] df_a_2 = df1[(df1['date'] >= pd.datetime(2019,6,15)) & (df1['date'] <= pd.datetime(2019,7,15))] df_a_3 = df1[(df1['date'] >= pd.datetime(2019,12,15)) & (df1['date'] <= pd.datetime(2020,1,15))] #df_a_4 = df1[(df1['date'] >= pd.datetime(2020,9,25)) ] df_a = pd.concat([df_a_1,df_a_2,df_a_3]) hot_mean=df_a['hot_p'].mean() hot_mean
從上圖結(jié)果可以很明顯的看出:同學(xué)們總是傾向于在學(xué)期初進(jìn)行吐槽,并且在學(xué)期末集中表白。對(duì)此我們可以解釋為學(xué)期初新生進(jìn)校,自然與老生們的各方?jīng)_突都比較激烈,而且大家也沒(méi)有習(xí)慣校園生活,因此此時(shí)吐槽的投稿會(huì)有較高的關(guān)注度;而學(xué)期末情況則趨于穩(wěn)定,經(jīng)過(guò)一整個(gè)學(xué)期大家都有了一定的相互了解,因此此時(shí)表白的投稿更能引發(fā)同學(xué)們的熱情。
探索性數(shù)據(jù)分析–尋物類(lèi)
確定思路
在對(duì)表白以及吐槽類(lèi)說(shuō)說(shuō)分析完成之后,我們將目光轉(zhuǎn)向了尋物類(lèi)說(shuō)說(shuō)。首先我們想要分析在一天三個(gè)時(shí)間段中發(fā)布說(shuō)說(shuō)的最佳時(shí)間。
最佳時(shí)段分析
為達(dá)到此目標(biāo),我們選擇刪去所有帶有“表白,提醒,注意,吐槽”等關(guān)鍵詞的說(shuō)說(shuō),排除由這些說(shuō)說(shuō)帶來(lái)的情感暗示的影響;將剩下的說(shuō)說(shuō)看作表白墻的以尋物為主的其他類(lèi)說(shuō)說(shuō),并進(jìn)行分時(shí)段熱度分析。
#總有效-表白-吐槽 去除帶有強(qiáng)烈情感暗示的 import numpy as np import pandas as pd import re excel_path_2 = r'C:\Users\15643\Desktop\公眾號(hào)\表白墻\說(shuō)說(shuō)數(shù)據(jù).xlsx' df2 = pd.DataFrame(pd.read_excel(excel_path_2)) df2['zan'] = df2['zan'].apply(lambda x :x*0.4 if x != 0 else 0) df2['comment'] = df2['comment'].apply(lambda x :x*0.6 if x != 0 else 0) hot_p_l=[] for i in range(len(df2)):hot_p =df2.iloc[i,4]+df2.iloc[i,5]hot_p_l.append(hot_p) df2['hot_p']=pd.DataFrame(hot_p_l) i_list=[] for i in range(len(df2)):qq_content = df2.iloc[i,3]if re.search("表白",str(qq_content))!=None or re.search("吐槽",str(qq_content))!=None or re.search("提醒",str(qq_content))!=None or re.search("注意",str(qq_content))!=None or re.search("告白",str(qq_content))!=None:i_list.append(i)for i in i_list:df2.drop([i],axis=0,inplace=True) #18-24點(diǎn)說(shuō)說(shuō)尋找熱度最高的時(shí)間段 df2['time_new']=pd.to_datetime(df2['time'],format='%H:%M:%S') df2_e = df2[(df2['time_new'] >= pd.datetime(1900,1,1,8)) & (df2['time_new'] <= pd.datetime(1900,1,1,12))] df2_e.sort_values(by='time_new',inplace=True)#排序 df2_e['hour']=df2_e['time_new'].dt.hour df2_e['min']=df2_e['time_new'].dt.minute result=[] for i in range(8,12):hour=idf_=df2_e.loc[df2_e['hour']==hour]if i!=12:for k in range(0,60):min=kdf_f = df_.loc[df_['min']==min]result_=df_f['hot_p'].mean()result.append(result_)else:result.append(df_['hot_p'].mean()) result = pd.DataFrame(result) result.to_excel(r'C:\Users\15643\Desktop\8-12.xlsx')
通過(guò)以上結(jié)果我們可以發(fā)現(xiàn),三個(gè)時(shí)間段發(fā)布說(shuō)說(shuō)的最佳時(shí)間分別為:8:21、15:31、19:08 分別對(duì)應(yīng)了早課開(kāi)始二十分鐘犯困拿出手機(jī)的上學(xué)人,下午第一節(jié)課下課回到宿舍刷空間換換腦子的,晚上吃完飯?jiān)偻嫱媸謾C(jī)消食的干飯人。
表白墻影響力量化模型的建立
確定思路
基于剛剛的探索性數(shù)據(jù)分析我們得出了發(fā)布說(shuō)說(shuō)的最佳時(shí)段(最佳時(shí)段發(fā)布的投稿受到的關(guān)注度最高),因此我們選擇在19:08這個(gè)時(shí)間點(diǎn)作為我們模型的假設(shè)。
我們假設(shè)表白墻在19:08發(fā)布了一條失物招領(lǐng)的說(shuō)說(shuō)內(nèi)容,我們?cè)O(shè)法做到了促使表白墻在相似的時(shí)間點(diǎn)發(fā)布尋物說(shuō)說(shuō),并按分鐘為單位統(tǒng)計(jì)到了瀏覽量的累計(jì)變化數(shù)據(jù)(一共30分鐘)。
確立模型
對(duì)于信息的傳播方式,特別是針對(duì)高校表白墻而言,我們提出了自己的看法:我們認(rèn)為高校表白墻的服務(wù)群體較為單一,且是由一個(gè)個(gè)聚集程度較高的熟人網(wǎng)絡(luò)所構(gòu)成的社交網(wǎng),而在此種封閉式聚集式的環(huán)境下的信息傳播應(yīng)該具有病毒式傳播的特點(diǎn)。
大家有沒(méi)有想象過(guò)自己的投稿是一個(gè)石子,在發(fā)布到社交網(wǎng)絡(luò)后一石激起千層浪,你的聲音在這之中被不斷放大,而這一切僅僅需要幾分鐘的時(shí)間。
所以我們?cè)谶@里大膽的拋棄了傳統(tǒng)的社會(huì)傳播模型,轉(zhuǎn)而應(yīng)用經(jīng)典的傳染病模型試圖解釋病毒式傳播這一現(xiàn)象。
在這里我們應(yīng)用了經(jīng)典的SIR模型
參數(shù)辨識(shí)
通過(guò)SIR模型的三個(gè)微分方程我們構(gòu)建了以下基于實(shí)際增長(zhǎng)瀏覽量數(shù)據(jù)的優(yōu)化問(wèn)題:
該優(yōu)化問(wèn)題的目標(biāo)函數(shù)為信息傳播強(qiáng)度β\betaβ,在這里我們選取5-10分鐘的瀏覽量數(shù)據(jù)作為參數(shù)識(shí)別的數(shù)據(jù),假設(shè)信息傳播時(shí)每個(gè)人每分鐘可能接觸到的人數(shù)為5,信息更新率γ=1/6\gamma = 1/6γ=1/6,信息傳播系統(tǒng)中總?cè)藬?shù)為2000人。
SIR模型擬合
class SIRModel():def __init__(self, N, beta, gamma):self.beta, self.gamma, self.N = beta, gamma, Nself.t = np.linspace(0, 60, 61)self.setInitCondition()print(self.beta)def odeModel(self, population, t):diff = np.zeros(3)s,i,r = populationdiff[0] = - self.beta * s * i / self.Ndiff[1] = self.beta * s * i / self.N - self.gamma * idiff[2] = self.gamma * ireturn diffdef setInitCondition(self):self.populationInit = [self.N - 1, 1, 0]def solve(self):self.solution = odeint(self.odeModel,self.populationInit,self.t)print(self.solution[:,1].max())for i in range(len(self.solution)):if self.solution[i,1]==self.solution[:,1].max():print(i)def report(self):#plt.plot(self.solution[:,0],color = 'darkblue',label = 'Susceptible',marker = '.')plt.plot(self.solution[:,1],color = 'orange',label = '接收信息',marker = '.')plt.plot(self.solution[:,2],color = 'green',label = '退出傳播系統(tǒng)',marker = '.')plt.title('SIR 信息傳播模型')plt.legend()plt.xlabel('分鐘(min)')plt.ylabel('人數(shù)')plt.savefig(r'C:\Users\15643\Desktop\公眾號(hào)\表白墻\SIR.jpg')plt.show()
基于真實(shí)的失物招領(lǐng)的瀏覽量數(shù)據(jù)我們建立以上模型,得出了失物招領(lǐng)這一信息的傳播強(qiáng)度為0.517,傳染數(shù)為3。為了更好的幫助大家理解這兩個(gè)指標(biāo),我們引入了基于同一模型的新冠疫情的傳播強(qiáng)度0.196,以及傳染數(shù)2.7。信息是超越新冠病毒的存在!
在證實(shí)信息的病毒式傳播之后我們繼續(xù)探索,最終找到了大家想要的答案,大家發(fā)布的失物招領(lǐng)的投稿的最大傳播數(shù)為625人,而達(dá)到最大傳播數(shù)只需要短短的23分鐘。
也就是說(shuō),我們每投稿一次,會(huì)有全校三分之一的同學(xué)接收到到我們的投稿信息,這么看來(lái)影響力還是十分不錯(cuò)的,靠表白墻找卡有希望了!但是這個(gè)影響力是有時(shí)效性的,要是在23分鐘內(nèi)沒(méi)有找到失主,信息可能會(huì)被逐漸淹沒(méi),乃至遺忘。
但是大家還是可以放心的,表白墻的影響力以及病毒式信息傳播可不是蓋的。
那么就祝大家找卡順利!
討論
1.在前期數(shù)據(jù)獲取過(guò)程中出現(xiàn)了部分說(shuō)說(shuō)點(diǎn)贊數(shù)據(jù)的缺失,可能會(huì)對(duì)結(jié)果造成一定影響
2.將完完全全的傳染病模型應(yīng)用于社會(huì)輿論傳播力衡量未免有失偏頗,應(yīng)用SIR模型純粹是編者自己的私心,之后有機(jī)會(huì)會(huì)去研究正經(jīng)的傳播力模型并作修改。
喜歡這篇數(shù)學(xué)建模案例的話(huà),歡迎關(guān)注我們和我們一起交流!
奇趣多多,數(shù)模多多!
總結(jié)
以上是生活随笔為你收集整理的数学建模预测模型实例(二)---表白墙影响力量化模型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 宝塔nginx运行vue项目刷新404问
- 下一篇: gdb命令中attach使用