本代码设计由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/
相关问题汇总
我们其实从历史数据可以看出, 新增关注属于少数情况, 出现次数并不多, 所以使用预测模型时是有一定概率出现确实没有新增关注的情况的. 这里题目挑选的用户编号是随机进行挑选的, 不一定会出现必然关注的情况.
作为基础的预测类代码, 主要难点在于数据的预处理以及样本的选择. 我们的代码可以明显看出, 我们需要筛选出合适的训练样本需要大量的时间. 同时论文的写作方面, 需要明确注意叙述哪些作为输入, 哪些作为输出是最重要的. 到底是用关注这个数据本身去预测未来的关注数量, 还是使用多个指标一起进行关注数量的预测需要明确进行说明.