在B站中学习了BruceQD的课程实战分析,对阿里云天池AI实训平台“蚂蚁金服资金流入流出预测挑战赛”进行讲解。我自己也照猫画虎地跟着学习中......

数据集大家可以去找一找,应该比较容易找到,这个比赛时间跨度大+经典

一部分:

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns

df = pd.read_csv(r"C:\Users\28049\Desktop\user_balance_table.csv")

#先利用简单规则分析,临近数据,中位数,平均数,临近数据的中位数......去求各方案的总得分

sta = df.groupby("report_date",as_index=False)[["total_purchase_amt","total_redeem_amt"]].sum()

#划分数据集,实际预测9月份,先尝试预测8月份(已知)

train_offline = sta[sta["report_date"]<20140801]

test_offline = sta[sta["report_date"]>=20140801]

# 1.要预测8月份,就用临近的7月份

train_offline_1 = train_offline[train_offline["report_date"]>=20140701]

train_offline_1["total_purchase_amt_true"] = test_offline["total_purchase_amt"]

train_offline_1["total_redeem_amt_true"] = test_offline["total_redeem_amt"]

def mape(x_true,x_pred):
    return (x_true-x_pred)/x_true

# 求申购和赎回的总得分,每一天单独计分
def sore (p_t,p_p,r_t,r_p,h=1) :
    p_mape = mape(p_t,p_p)
    r_mape = mape(r_t,r_p)
    return 0.45*10*np.exp(-p_mape/h)+0.55*10*np.exp(-r_mape/h)

# 求总得分
# for i,row in train_offline_1.iterrows:
#     sum+=sore(row["total_purchase_amt_true"],row["total_purchase_amt"],row["total_redeem_amt_true"],row["total_redeem_amt"],h=1)


# 2.平均数,20140801之前的所有数据
train_offline_2 = train_offline
train_offline_2["total_purchase_amt_mean"] = train_offline["total_purchase_amt"].mean()
train_offline_2["total_redeem_amt_mean"] = train_offline["total_redeem_amt"].mean()


# 3.中位数 median()
#......



# 4.基于周期因子的预测
# 周期因子=每日的均值(每一周的每一天)/总体均值
# 再乘base base=最后一周的平均客流
# 思路:先求各report_date对应的weekday(每天对应的星期),再求星期一...星期天的对应(purchase/redeem)均值(每一周的星期1的总和/周数)就得到了周期因子

sta_1 = sta

sta_1["report_date_new"] = pd.to_datetime(sta_1["report_date"].astype(str))

sta_1["weekday"] = sta_1["report_date_new"].dt.weekday+1

train_offline_3 = sta_1[sta_1["report_date"]<20140801]

test_offline_3 = sta_1[sta_1["report_date"]>=20140801]

zjz = train_offline_3["total_purchase_amt"].mean()

list_1 = list(train_offline_3["total_purchase_amt"])

list_3 = pd.DataFrame([list_1[i:i+7] for i in range(0,len(list_1),7)])

list_3.columns = ["week_"+str(i+1) for i in range(7)]

list_4 = (list_3.mean())/zjz

base = list_3.loc[55].sum()/7

list_4 *= base

cont = [i+1 for i in range(7)]

dict_1 = dict(zip(cont,list_4))

test_offline_3["total_purchase_amt_new"] = test_offline_3["weekday"].apply(lambda x:dict_1[x])
# redeem 也一样


# 数据分析与探索(可视化)
# 时序图,时间序列
plt.figure(figsize=(12,6))
plt.plot(sta_1["report_date_new"],sta_1["total_purchase_amt"],label='purchase')
plt.plot(sta_1["report_date_new"],sta_1["total_redeem_amt"],label='redeem')
plt.legend(loc='best')
plt.show()

# 在2014-4月份后,数据才达到稳定,所以,可用的数据是2014-4之后的数据

# 箱型图
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
sns.boxplot(x='weekday',y='total_purchase_amt',data=sta_1)
plt.subplot(1,2,2)
sns.boxplot(x='weekday',y='total_redeem_amt',data=sta_1)
plt.show()


# 折线图
sns.relplot(x="weekday",y="total_purchase_amt",data=sta_1,kind='line',aspect=2,height=6)
plt.show()

以上是基于简单规则+周期因子的预测,通过可视化分析,我们发现在2014-4月之后的数据是稳定的,是可利用的。

再通过看weekday与申购/赎回总额之间的相关性,其在周一到周四较稳定,5,6,7有所下降,依次周期循环。

二部分:

# 利用spearman相关系数,去看weekday与申购/赎回的关系,绘制热力图
# 正相关   一个变量增加时,另一个变量倾向于增加
# 负相关   一个变量增加时,另一个变量倾向于减少

import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder
import seaborn as sns
from matplotlib import pyplot as plt
from 资金流入流出_1 import train_offline_3

df = pd.read_csv(r"C:\Users\28049\Desktop\user_balance_table.csv")

enconder = OneHotEncoder()

weekday_feats = enconder.fit_transform(np.array(train_offline_3["weekday"]).reshape(-1,1)).toarray()

train_offline_4 = pd.concat([pd.DataFrame(weekday_feats),train_offline_3],axis=1)

a = train_offline_4[list(range(7))+["total_purchase_amt","total_redeem_amt"]].corr("spearman")

#将weekday进行编码,例如:星期一:1000000
#                     星期二:0100000
# 因为星期之间不存在大小关系,非连续性



# 热力图
sns.heatmap(a,vmax=0.2,vmin=-0.2)    # 调节色柱
plt.show()

三部分:

对于建模分析的角度:

#只能利用2024-4月之后的数据,进行建模

import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder
from sklearn.ensemble import RandomForestRegressor

df = pd.read_csv(r"C:\Users\28049\Desktop\user_balance_table.csv")

sta = df.groupby("report_date",as_index=False)[["total_purchase_amt","total_redeem_amt"]].sum()

sta["report_date_new"] = pd.to_datetime(sta["report_date"].astype(str))

sta["weekday"] = sta["report_date_new"].dt.weekday+1

train_offline = sta[(sta["report_date"]>=20140401) & (sta["report_date"]<20140801)].reset_index(drop=True)

test_offline = sta[sta["report_date"]>=20140801].reset_index(drop=True)

encoder = OneHotEncoder()

df_1 = pd.concat([train_offline,test_offline]).reset_index(drop=True)

weekday_all = encoder.fit_transform(np.array(df_1["weekday"]).reshape(-1,1)).toarray()

tmp = pd.DataFrame(weekday_all[:len(train_offline)])

for i in range(7):
    train_offline["is_weekday"+str(i+1)] = tmp[i]

tmp = pd.DataFrame(weekday_all[len(train_offline):])

for i in range(7):
    test_offline["is_weekday"+str(i+1)] = tmp[i]


#建模(以purchase为例)
clf = RandomForestRegressor(n_estimators=500,max_depth=6)
clf.fit(train_offline[["is_weekday"+str(i+1) for i in range(7)]],train_offline["total_purchase_amt"])
test_offline["predict"] = clf.predict(test_offline[["is_weekday"+str(i+1) for i in range(7)]])
print(test_offline[["predict","total_purchase_amt"]])

#线上测试,线下可将test加入到train中

之前的基于简单规则得到的中位数,平均数,周期因子等特征,也可以当作特征,去建模。

虽然“主播”还什么都不会,但只有我们努力学习,大家都能得偿所愿!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐