数学建模预测模型实例(二)---表白墙影响力量化模型
數學建模預測模型實例–表白墻影響力量化模型
數學建模預測模型實例(一)–大學生體測數據模型
數學建模預測模型實例(二)—表白墻影響力量化模型
python預測模型–線性回歸
建立模型的目的
本篇文章中,假設獲取到了某高校表白墻建墻以來至2020年12月21日發布的所有說說的文字內容,發布時間,點贊數,評論數。目的是通過前期數據挖掘探索性數據分析等建立表白墻影響力量化模型,進而得出發布尋物類消息的最佳時機以及持續影響力,最大影響人數等指標。
數據分析的基本過程包括:獲取數據、數據清洗、中文分詞聚類、探索性數據挖掘、數據可視化、基于SIR模型的表白墻影響力量化模型。
獲取數據
在這里我們用selenium模擬登錄qq空間,然后用xpath解析網頁
#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):# 獲取瀏覽器驅動driver = webdriver.Chrome(executable_path='chromedriver')# 瀏覽器窗口最大化driver.maximize_window()# 瀏覽器地址定向為 qq 登陸頁面driver.get('http://i.qq.com')# 所以這里需要選中一下 frame,否則找不到下面需要的網頁元素driver.switch_to.frame('login_frame')# 自動點擊賬號登陸方式driver.find_element_by_id('switcher_plogin').click()# 賬號輸入框輸入已知 QQ 賬號driver.find_element_by_id('u').send_keys(user)# 密碼框輸入已知密碼driver.find_element_by_id('p').send_keys(pw)# 自動點擊登陸按鈕driver.find_element_by_id('login_button').click()time.sleep(10)# 讓 webdriver 操縱當前頁driver.switch_to.default_content()# 跳到說說的 url,friend 你可以任意改成你想訪問的空間driver.get('http://user.qzone.qq.com/' + friend + '/311')next_num = 0 # 初始“下一頁”的 idwhile True:# 下拉滾動條,使瀏覽器加載出動態加載的內容# 我這里是從 1 開始到 6 結束分 5 次加載完每頁數據for i in range(1, 6):height = 20000 * i# 每次滑動 20000 像素strWord = "window.scrollBy(0," + str(height) + ")"driver.execute_script(strWord)time.sleep(4)# 很多時候網頁由多個<frame>或<iframe>組成,webdriver 默認定位的是最外層的 frame# 所以這里需要選中一下說說所在的 frame,否則找不到下面需要的網頁元素driver.switch_to.frame('app_canvas_frame')selector = etree.HTML(driver.page_source)divs = selector.xpath('//*[@id="msgList"]/li/div[3]')# 這里使用 a 表示內容可以連續不清空寫入with open(r'C:\Users\15643\Desktop\公眾號\表白墻\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)# 當已經到了尾頁,“下一頁”這個按鈕就沒有 id 了,可以結束了if driver.page_source.find('pager_next_' + str(next_num)) == -1:break# 找到“下一頁”的按鈕,因為下一頁的按鈕是動態變化的,這里需要動態記錄一下driver.find_element_by_id('pager_next_' + str(next_num)).click()# "下一頁"的 idnext_num += 1# 因為在下一個循環里首先還要把頁面下拉,所以要跳到外層的 frame 上driver.switch_to.parent_frame()if __name__ == '__main__':friend = 'xxxx' # 朋友的 QQ 號,朋友的空間要求允許你能訪問user = 'xxxx' # 你的 QQ 號pw = 'xxxx' # 你的 QQ 密碼text(friend, user, pw)最終獲取到一個包含所有說說內容,發布時間,點贊數,評論數的excel文件,隨后再將說說文本提取到一個txt文件里面便于之后進行分詞。
最終獲取到的數據:說說數據.xlsx
說說文本.txt
數據:表白墻數據 提取碼:klh0
數據清洗—中文文本分詞
首先先對txt里的說說數據進行分詞、并刪去停用詞,無效符號。考慮到表白墻中一些詞語的連貫性,我們引入了自定義詞典
求同好
大橘
首醫
墻墻
表白墻
一教
二教
隨后運用jieba分詞庫進行分詞處理
import jieba# 加載停用詞列表 def load_stopword():f_stop = open('stopword.txt', encoding='utf-8') # 自己的中文停用詞表sw = [line.strip() for line in f_stop] # strip() 方法用于移除字符串頭尾指定的字符(默認為空格)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)分詞結束后再應用 jiaba.analyse.extract_tags() 中默認的TF-IDF模型對文檔進行分析。
TF-IDF的基本思想是:詞語的重要性與它在文件中出現的次數成正比,但同時會隨著它在語料庫中出現的頻率成反比下降 。也就是說TD-IDF綜合考慮了兩方面因素,排除了那些看似詞頻很高實則是無效常見詞的情況(例如:的,包括)。因此某個詞對文章的重要性越高,它的TF-IDF值就越大
從以上結果可以看出,提取到的分詞數據所制成的詞云圖與關鍵詞相呼應,表明“表白,求助,吐槽,失物招領,一周cp”是表白墻的主題內容。表白墻不愧為表白墻,表白還是占了絕大多數。
探索性數據分析–表白+吐槽
確定思路
在進行過初始的數據清洗之后我們找到了表白墻的五大主題,為了方便接下來的分析,我們將這五大主題劃歸為三大類:表白,吐槽,尋物,在這里我們認為前兩類是帶有明顯且強烈的情感暗示的內容,因此這兩類說說的點贊,評論,乃至發布時間可能會遵循某種分布。以下為對這兩類說說的分析
注:為保證數據的真實性,我們刪去了新冠疫情期間的所有表白墻數據(2020/3-2020/8)
時間分析
為了衡量表白墻發布這兩類投稿的偏好時間,我們對一天三個時間段表白墻針對這兩個主題說說的發布情況進行了統計。
##以吐槽說說的分析過程為例 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])
從以上結果我們可以很明顯的看出晚間實際上是投稿的高峰期,晚上的確是多愁善感的網抑云時間。
熱度分析
為了衡量這兩類說說在不同時間段的熱度,我們首先對熱度進行定義:
隨后定義了一學期中的三個時間段:
| 學期中 |
| 學期末:最后一個月 |
根據以上的定義進行數據篩選
#以吐槽說說學期末熱度分析為例 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
從上圖結果可以很明顯的看出:同學們總是傾向于在學期初進行吐槽,并且在學期末集中表白。對此我們可以解釋為學期初新生進校,自然與老生們的各方沖突都比較激烈,而且大家也沒有習慣校園生活,因此此時吐槽的投稿會有較高的關注度;而學期末情況則趨于穩定,經過一整個學期大家都有了一定的相互了解,因此此時表白的投稿更能引發同學們的熱情。
探索性數據分析–尋物類
確定思路
在對表白以及吐槽類說說分析完成之后,我們將目光轉向了尋物類說說。首先我們想要分析在一天三個時間段中發布說說的最佳時間。
最佳時段分析
為達到此目標,我們選擇刪去所有帶有“表白,提醒,注意,吐槽”等關鍵詞的說說,排除由這些說說帶來的情感暗示的影響;將剩下的說說看作表白墻的以尋物為主的其他類說說,并進行分時段熱度分析。
#總有效-表白-吐槽 去除帶有強烈情感暗示的 import numpy as np import pandas as pd import re excel_path_2 = r'C:\Users\15643\Desktop\公眾號\表白墻\說說數據.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點說說尋找熱度最高的時間段 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')
通過以上結果我們可以發現,三個時間段發布說說的最佳時間分別為:8:21、15:31、19:08 分別對應了早課開始二十分鐘犯困拿出手機的上學人,下午第一節課下課回到宿舍刷空間換換腦子的,晚上吃完飯再玩玩手機消食的干飯人。
表白墻影響力量化模型的建立
確定思路
基于剛剛的探索性數據分析我們得出了發布說說的最佳時段(最佳時段發布的投稿受到的關注度最高),因此我們選擇在19:08這個時間點作為我們模型的假設。
我們假設表白墻在19:08發布了一條失物招領的說說內容,我們設法做到了促使表白墻在相似的時間點發布尋物說說,并按分鐘為單位統計到了瀏覽量的累計變化數據(一共30分鐘)。
確立模型
對于信息的傳播方式,特別是針對高校表白墻而言,我們提出了自己的看法:我們認為高校表白墻的服務群體較為單一,且是由一個個聚集程度較高的熟人網絡所構成的社交網,而在此種封閉式聚集式的環境下的信息傳播應該具有病毒式傳播的特點。
大家有沒有想象過自己的投稿是一個石子,在發布到社交網絡后一石激起千層浪,你的聲音在這之中被不斷放大,而這一切僅僅需要幾分鐘的時間。
所以我們在這里大膽的拋棄了傳統的社會傳播模型,轉而應用經典的傳染病模型試圖解釋病毒式傳播這一現象。
在這里我們應用了經典的SIR模型
參數辨識
通過SIR模型的三個微分方程我們構建了以下基于實際增長瀏覽量數據的優化問題:
該優化問題的目標函數為信息傳播強度β\betaβ,在這里我們選取5-10分鐘的瀏覽量數據作為參數識別的數據,假設信息傳播時每個人每分鐘可能接觸到的人數為5,信息更新率γ=1/6\gamma = 1/6γ=1/6,信息傳播系統中總人數為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 = '退出傳播系統',marker = '.')plt.title('SIR 信息傳播模型')plt.legend()plt.xlabel('分鐘(min)')plt.ylabel('人數')plt.savefig(r'C:\Users\15643\Desktop\公眾號\表白墻\SIR.jpg')plt.show()
基于真實的失物招領的瀏覽量數據我們建立以上模型,得出了失物招領這一信息的傳播強度為0.517,傳染數為3。為了更好的幫助大家理解這兩個指標,我們引入了基于同一模型的新冠疫情的傳播強度0.196,以及傳染數2.7。信息是超越新冠病毒的存在!
在證實信息的病毒式傳播之后我們繼續探索,最終找到了大家想要的答案,大家發布的失物招領的投稿的最大傳播數為625人,而達到最大傳播數只需要短短的23分鐘。
也就是說,我們每投稿一次,會有全校三分之一的同學接收到到我們的投稿信息,這么看來影響力還是十分不錯的,靠表白墻找卡有希望了!但是這個影響力是有時效性的,要是在23分鐘內沒有找到失主,信息可能會被逐漸淹沒,乃至遺忘。
但是大家還是可以放心的,表白墻的影響力以及病毒式信息傳播可不是蓋的。
那么就祝大家找卡順利!
討論
1.在前期數據獲取過程中出現了部分說說點贊數據的缺失,可能會對結果造成一定影響
2.將完完全全的傳染病模型應用于社會輿論傳播力衡量未免有失偏頗,應用SIR模型純粹是編者自己的私心,之后有機會會去研究正經的傳播力模型并作修改。
喜歡這篇數學建模案例的話,歡迎關注我們和我們一起交流!
奇趣多多,數模多多!
總結
以上是生活随笔為你收集整理的数学建模预测模型实例(二)---表白墙影响力量化模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 宝塔nginx运行vue项目刷新404问
- 下一篇: gdb命令中attach使用