多模型融合的社交媒体用户与博主互动行为分析及预测代码

作者:全糖奶茶屋 浏览: 发表时间:2025-04-24 00:00:00



    本代码设计由B站up主'全糖奶茶屋'提供, 可以直接在我们讲解思路的视频下发评论区进行留言. 我们收到留言后会将问题在这里汇总, 与技术小哥商议之后, 给大家更准确的答复. 大家也可以添加我们的人工客服微信: quantangnaichawu (如遇暂时加满了, 无法添加, 请后面再尝试).

代码背景


近年来,社交媒体平台打造了多元化的线上交流空间和文化圈,深刻影响着人们社交互动与信息获取。博主基于专业知识或兴趣爱好等创作出高质量内容,吸引并获得用户的关注。B站up: 全糖奶茶屋用户可以随时通过观看、点赞、评论等行为积极参与其中。博主依据平台的推荐机制和用户反馈,调整并提升内容质量,从而提高自身影响力。而用户则通过互动行为,反向影响平台的内容推荐系统。

现某社交媒体平台需深入分析现有用户和博主之间的互动行为关系,来预测用户行为,并优化内容推荐方法。附件1记录了该平台在2024.7.11-2024.7.20之间的数据,包括用户ID、用户行为、B站up: 全糖奶茶屋博主ID、时间。其中用户行为列中,数字1、2、3分别代表用户对博主发布内容的观看、点赞、评论,4代表关注该博主。时间列代表用户行为发生的时间。需要注意的是,用户点赞、评论和关注的行为均代表用户已观看了内容。此外,用户使用该社交媒体平台的频率和时间不同,若某段时间内附件1中没有记录某用户的行为数据,B站up: 全糖奶茶屋则代表该时段内用户没有使用该社交媒体平台。附件2中记录了2024.7.22用户进行观看、点赞、评论的行为数据。


第一部分:博主数据预测结果


基于2024.7.11 - 2024.7.20期间用户与博主的历史交互数据,包括观看、点赞、评论、关注行为,建立数学模型预测各博主在2024.7.21当天新增的关注数。考虑不同类型博主互动与关注转化比例的差异,选择合适的预测模型,如灰色预测、指数平滑法、ARIMA模型、随机森林模型等,或采用组合模型提高预测准确性。最终根据预测结果,找出当日新增关注数最多的5位博主ID及其对应的新增关注数。


步骤1: 数据准备工作

import numpy as np
import pandas as pd
#数据载入
Data1 = pd.read_excel('data1.xlsx',index_col=0)
data1 = Data1.values
Data2 = pd.read_excel('data2.xlsx',index_col=0)
data2 = Data2.values
Data3 = pd.read_excel('data3.xlsx',index_col=0)
data3 = Data3.values
Data4 = pd.read_excel('data4.xlsx',index_col=0)
data4 = Data4.values
for i in range(data1.shape[0]):
    data = np.c_['1',data1[i][:,None],data2[i][:,None],data3[i][:,None],data4[i][:,None]]
    pd.DataFrame(data,index=Data1.columns,columns='观看,点赞,评论,关注'.split(',')).to_excel(fr'.\data\{Data1.index[i]}.xlsx')


步骤2: 博主行为预测

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sympy import rotations
from tqdm import tqdm
name = pd.read_excel(r'data1.xlsx',index_col=0).index
kk = 0
new_pre =[]
for kk in range(name.size):
    upper_time_data = pd.read_excel(rf'.\data\{name[kk]}.xlsx',index_col=0)
    upper_time = upper_time_data.values
    upper_name = upper_time_data.index
    data_x = upper_time[:,:-1]
    data_y = upper_time[:,-1:]
    data_x1 =( data_x -data_x.min())/data_x.ptp()
    data_y1 = ( data_y -data_y.min())/data_y.ptp()
    data_x0 = data_x1[:-1]
    data_y0 = data_y1[1:]
    # 确定网络结构
    '''
    输入n个,中间层 q 个, 输出 m个
    中间层 tanh(x)
    输出层 purelin(x)
    '''
    # 初始化参数
    n,q,m = data_x0.shape[1],30,data_y0.shape[1]
    print(rf'输入{n}个,中间层 {q} 个, 输出 {m}个')
    np.random.seed(0)
    W_qm = np.random.random(size=(q,m))
    the_1m = np.random.random(size=(1,m))
    V_nq = np.random.random(size=(n,q))
    miu_1q = np.random.random(size=(1,q))
    yta = 0.02
    # 定义激活函数
    f1 = lambda x: (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))
    f2 = lambda x: x
    for turn in tqdm(range(100001)):
        for K in range(data_y0.shape[0]):
            # 向前传播
            # 计算b,y
            Xk = data_x0[K][None,:] # (1,n)
            Yk = data_y0[K][None,:] # (1,m)
            b_1q = f1(Xk@V_nq-miu_1q)
            prey_1m = f2(b_1q@W_qm-the_1m)
            # 优化输出层神经元
            dw = b_1q.T@(yta*(prey_1m-Yk)*1)
            W_qm = W_qm - dw
            the_1m = the_1m - yta*(prey_1m-Yk)*1*(-1)
            # 优化中间层神经元
            V_nq = V_nq-Xk.T@((yta*(prey_1m-Yk)*1@W_qm.T)*(1-b_1q**2))
            miu_1q = miu_1q -(yta*(prey_1m-Yk)*1@W_qm.T)*(1-b_1q**2)*(-1)
    #预测21号数据
    Xk = data_x1[-1][None, :]  # (1,m)
    b_1q = f1(Xk @ V_nq - miu_1q)
    prey_1m = f2(b_1q @ W_qm - the_1m)
    pre = np.round(prey_1m.copy()[0]*data_y.ptp()+data_y.min())
    new_pre+[pre[0]]
    print(f'{name[kk]}新增:{pre}')
#保存预测数据
pd.DataFrame(new_pre,index=upper_name,columns=['21号新增关注']).to_excel('pre_BP_UpperNewFoucs.xlsx')


第二部分: 用户行为预测


结合用户2024.7.11 - 2024.7.20的历史行为数据以及2024.7.22当天用户的观看、点赞、评论行为数据,挖掘用户行为之间的关联关系,如“观看某类博主内容且点赞后,在一定时间内关注该博主”的规则。建立数学模型,如BP神经网络模型,预测用户在2024.7.22产生的新关注行为,并展示用户(U7、U6749、U5769、U14990、U52010)在该日新关注的博主ID。


步骤1: 数据准备工作

import numpy as np
import pandas as pd
from tqdm import tqdm
# 读取附件2
At2 = pd.read_csv(r'../附件2 (Attachment 2).csv').values
# 获取博主列表
upper_name = np.unique(At2[:,2])
print('博主数量:',upper_name.size)
# 获取用户列表
user_name = np.unique(At2[:,0])
print(user_name)
print('用户数量:',user_name.size)
# 获取22号的互动数据
user_upper = []
for i in tqdm(range(user_name.size)):
    for j in range(upper_name.size):
        user_data = At2[At2[:,0] == user_name[i]]
        user_upper_data = user_data[user_data[:,2]==upper_name[j]][:,1]
        user_upper += [[user_name[i]+'_'+upper_name[j],np.sum(user_upper_data==1),
                       np.sum(user_upper_data==2),np.sum(user_upper_data==3)]]
user_upper = np.array(user_upper)
# 保存数据
pd.DataFrame(user_upper[:,1:],index=user_upper[:,0],columns=['观看','点赞','评论']).to_excel(r'user_upper.xlsx')


步骤2: 分类树分类模型

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tqdm import tqdm
def tree_node(xy,A = None,lb = np.array([]),rt = 1,maxdeep = 100,deep = 1,replace = 0):
    '''
    xy: 数据集
    A: 特征索引
    lb : 类别
    rt: 是否显示概率
    maxdeep: 树最大深度
    deep: 当前深度
    '''
    X = xy[:,:-1]
    y = xy[:,-1]
    uniy = np.unique(y) # 去重后的类别
    numb = np.array([np.sum(y==i)for i in uniy]) # 每个类别的样本数量
    lb = lb if lb.size else uniy
    A = A if type(A) != type(None) else np.arange(X.shape[1])
    if uniy.size ==1:
        if rt :
            return ['叶子',uniy[0]]
        else :
            lbnb = np.array([np.sum(y==i)for i in lb])
            return ['叶子',lbnb/np.sum(lbnb)]
    if A.shape[0] ==0 or deep>maxdeep:
        if rt :
            return ['叶子',uniy[np.argmax(numb)]]
        else :
            lbnb = np.array([np.sum(y==i)for i in lb])
            return ['叶子',lbnb/np.sum(lbnb)]
    p = numb/np.sum(numb) # 每个类别出现的概率
    Gini_xy = 1 - np.sum(p**2) # 总集合的基尼指数
    Gini_index = []
    for a in A:
        gini_a = []
        for v in X[:,a]:
            Dy = y[X[:,a] v]
            if Dy.size ==0 or dy.size==0:
                continue
            nb1 =np.array([np.sum(Dy==i)for i in uniy])
            nb2 =np.array([np.sum(dy==i)for i in uniy])
            p1 = nb1/np.sum(nb1)
            p2 = nb2/np.sum(nb2)
            gini_a += [[v,Dy.shape[0]/y.shape[0]*(1-np.sum(p1**2))+\
                        dy.shape[0]/y.shape[0]*(1-np.sum(p2**2))]]
        gini_a = np.array(gini_a)
        if gini_a.size ==0:
            Gini_index += [[-99,1e10]]
        else:
            Gini_index += [gini_a[np.argmin(gini_a[:,-1])]]
    Gini_index = np.array(Gini_index)
    Ax = A[np.argmin(Gini_index[:,-1])]
    Dxy = xy[X[:,Ax]Gini_index[np.argmin(Gini_index[:,-1]),0]]
    A_new = np.array([i for i in A if i !=Ax])
    if replace:
        return ['分支',f'{Ax}<={Gini_index[np.argmin(Gini_index[:,-1]),0]}',
                tree_node(Dxy,A,lb,rt,maxdeep =maxdeep,deep = deep+1,replace=replace),
            tree_node(dxy,A,lb,rt,maxdeep =maxdeep ,deep = deep+1,replace=replace)]
    else:
        return ['分支',f'{Ax}<={Gini_index[np.argmin(Gini_index[:,-1]),0]}',
                tree_node(Dxy,A_new,lb,rt,maxdeep =maxdeep,deep = deep+1,replace=replace),
            tree_node(dxy,A_new,lb,rt,maxdeep =maxdeep ,deep = deep+1,replace=replace)]
def print_Tree(tree,n=0):
    print('\t'*n,end = '')
    if tree[0]=='叶子':
        print(*tree)
    else:
        show = tree[1]
        show = show.split('<=')
        show[1] = str(round(eval(show[1]),4))
        print(tree[0],'<='.join(show))
        print_Tree(tree[2],n+1)
        print_Tree(tree[3],n+1)
def tree_predict(x,tree):
    if x.ndim == 1:
        if tree[0]=='叶子':
            return tree[1]
        else:
            C = tree[1].split('0.5],columns='观看,点赞,评论,关注'.split(',')).to_excel('pre_CartTree.xlsx')

第三部分:博主数据预测结果

以用户与博主之间的互动数(点赞数、评论数、关注数之和)为依据,建立数学模型。首先预测指定用户(U9、U22405、U16、U48420)在2024.7.21当天是否在线使用社交媒体平台;若在线,进一步预测该用户可能与博主产生的互动关系,找出可能与其产生互动数最高的3名博主,并将对应的博主ID填入表格。解决此问题需先统计用户每天的在线状态,建立二分类模型预测用户是否在线,再针对上线用户建立预测模型分析其与博主的互动数据。


import numpy as np
import pandas as pd
from tqdm import tqdm
# 库的导入
import matplotlib.pyplot as plt
# 中文的使用
import matplotlib as mpl
mpl.rcParams['font.sans-serif']=['kaiti'] # 设置中文字体
mpl.rcParams['axes.unicode_minus']=False  # 设置减号不改变
np.random.seed(0)
def plot_SSE(data,H = 100,file = None,kmax = None,chip = 1):
    data1 = data.copy()
    ld = 0.1
    n = data1.shape[0]
    sse = []
    if kmax == None:
        kmax =int(n*chip/3)
    for k in range(1,kmax+1):
        S = 0
        for j in range(H):
            index = np.random.choice(np.arange(n),int(n*chip))
            data2 = data1[index]
            S += kmeans(data2,k)[-1]
        S /=H
        sse +=[S]
    sse = np.array(sse)
    f = plt.figure()
    x = np.arange(1,kmax+1,0.0001)
    y1 = sse[0]+(sse[1]-sse[0])*(x-1)
    y2 = sse[-1]+(sse[-1]-sse[-2])*(x-kmax)
    best_k = x[np.argmin(np.abs(y1-y2))]
    print('理论最佳k值为:',round(x[np.argmin(np.abs(y1-y2))],1))
    ax = f.subplots(1,1)
    ax.plot(np.arange(1,kmax+1),sse,color = 'k',marker = 's')
    ax.grid(axis = 'x',color = 'gray')
    ax.plot(np.arange(1,best_k+1,ld),
            sse[0]+(sse[1]-sse[0])*(np.arange(1,best_k+1,ld)-1),
           color = '#EF9A9A',ls = ':')
    ax.plot(np.arange(best_k-1,kmax+1,ld),
            sse[-1]+(sse[-1]-sse[-2])*(np.arange(best_k-1,kmax+1,ld)-kmax),
           color = '#90CAF9',ls = ':')
    ax.set_xlabel('K',fontsize = 14)
    ax.set_ylabel('SSE',fontsize = 14)
    ax.scatter(best_k,sse[0]+(sse[1]-sse[0])*(best_k-1),marker = 'o',color = 'r')
    if file:
        plt.savefig(file,dpi = 500)
    plt.show()
    return 0
def kmeans(data,k):
    data1 = data.copy()
    # STEP1: 确定k 以及 随机产生聚类中心
    n = data1.shape[0] # 样本量
    m = data1.shape[1] # 特征数量
    index = np.random.choice(np.arange(n),size=k,replace = 0)
    center = data1[index].copy() # 随机选取的样本中心
    while 1:
        # STEP2: 对样本进行分配
        L = np.zeros(shape = (n,))
        for i in range(n):
            D = np.sum((center-data1[i])**2,axis =1)**0.5
            L[i] = np.argmin(D)
        # STEP3: 对聚类中心进行优化
        oldcenter = center.copy()
        for i in range(k):
            di = data1[L==i]
            if di.shape[0] ==0:
                index = np.random.choice(np.arange(n),replace = 0)
                center[i] = data1[index].copy()
            else:
                center[i] = np.mean(di,axis=0)
        # STEP4: 判断是否达到终止条件
        if np.all(oldcenter == center):
            break
    SSE = 0
    for i in range(k):
        di = data1[L==i]
        SSE += np.sum(np.sum((di-center[i])**2,axis=1)**0.5)
    SSE /= n
    return center,L,SSE
#设置指定用户
V_user_name = np.array(['U9','U22405','U16','U48420'])
# 读取附件1
At1 = pd.read_csv(r'../附件1 (Attachment 1).csv').values
# 获取时间列表
time_list = np.unique([t.split(' ')[0] for t in At1[:,-1]] )
print('时间长度(天)',time_list.size)
# 获取博主列表
upper_name = np.unique(At1[:,2])
print('博主数量:',upper_name.size)
#获取聚类数据
data = np.zeros(shape = (upper_name.size,V_user_name.size*3))
for i in range(upper_name.size):
    upper_d = At1[At1[:,2]==upper_name[i]]
    ud = []
    for j in range(V_user_name.size):
        uu_d = upper_d[upper_d[:,0]==V_user_name[j]][:,1]
        ud += [np.sum(uu_d==2),np.sum(uu_d==3),np.sum(uu_d==4)]
    ud = np.array(ud)
    data[i] = ud.copy()
plot_SSE(data)
center,L,sse = kmeans(data,k=4)
print(L)
pd.DataFrame(center).to_excel(r'kmeans_center.xlsx')
pd.DataFrame(L[:,None],index = upper_name,columns=['类别']).to_excel('kmeans_result.xlsx')


代码演示与讲解视频

整体思路视频: https://www.bilibili.com/video/BV1M6jEzdECb/


第一二部分详细细节: https://www.bilibili.com/video/BV1KFVuzHE2d/


第三部分详细细节: https://www.bilibili.com/video/BV1FYVJzzEXp/





相关问题汇总


1. 在第二问中是否会出现没有新增关注的情况?

    我们其实从历史数据可以看出, 新增关注属于少数情况, 出现次数并不多, 所以使用预测模型时是有一定概率出现确实没有新增关注的情况的. 这里题目挑选的用户编号是随机进行挑选的, 不一定会出现必然关注的情况.

2. 本代码的关注点和重点主要在哪里?

    作为基础的预测类代码, 主要难点在于数据的预处理以及样本的选择. 我们的代码可以明显看出, 我们需要筛选出合适的训练样本需要大量的时间. 同时论文的写作方面, 需要明确注意叙述哪些作为输入, 哪些作为输出是最重要的. 到底是用关注这个数据本身去预测未来的关注数量, 还是使用多个指标一起进行关注数量的预测需要明确进行说明.

多模型融合的社交媒体用户与博主互动行为分析及预测代码
长按图片保存/分享
2
图片展示
图片展示

Copyright ©2023 All Rights Reserved 鼓楼鑫图南科技工作室 版权所有 苏ICP备2025174882号-1

添加微信好友,详细了解产品
使用企业微信
“扫一扫”加入群聊
复制成功
添加微信好友,详细了解产品
我知道了
苏ICP备2025174882号-1