1 项目背景
部门在研究如何给店铺选址,并找到了现有的应用成果。一位同事谈到:“如何从他们的逻辑来辅助我们进行研究?”。
起初,本人认为无法求解。随后,找到一位教统计学课程的老师交流,他也认为没法做模型。然而,笔者下意识认为可能有点机会,因此决定尝试。
2 项目结果
理论价值:当特征全部为有序分类变量,标签为连续性数值时,依然可以用多元线性回归模型进行拟合。
现实意义:复现了现有的应用成果,帮助研究人员更有效率地开展研究工作。
3 数据介绍与预览
数据集地址: https://www.kesci.com/mw/dataset/605e344b474ded0015729257/file
竞争店品牌(1、2、3、4、5):无竞争店、次要三线品牌、次要二线品牌、次要一线品牌、主要一线品牌
距离(1、2、3、4、5):无竞争店、200米以上、150-200米、100-150米、100米内
相对位置(1、2、3、4、5):无竞争店、对面、一面、包夹、扇形
营业时间(1、2、3、4):无竞争店、短时间、接近本店时间、长时间或24小时
竞争店开业时间(1、2、3、4):无竞争店、半年以内、半年至一年、一年以上
贩烟(1、2):无烟、有烟
动线(1、2、3、4、5):无竞争店、不同动线、动线相反、动线后、动线前
停车配置(1、2、3):不可、困难、可以
卖场面积(1、2、3):小型店、中型店、大型店
竞争评估点:最高分为100分
4 数据预处理
4.1 导入库与数据集
import pandas as pd
from sklearn import model_selection,preprocessing
from sklearn.linear_model import LinearRegression
df = pd.read_excel(r'C:\Users\LEGION\Desktop\选址系数.xlsx')
4.2 划分特征与标签
location_y = df.iloc[:,-1]
location_x = df.loc[:,"竞争店品牌":"卖场面积"]
4.3 划分训练集与测试集
location_x_train,location_x_test,location_y_train,location_y_test=model_selection.train_test_split(location_x,location_y,test_size=0.3,random_state=42)
5 建立多元线性回归模型
lr = LinearRegression()# 模型实例化
lr.fit(location_x_train,location_y_train)#用训练集拟合模型
lr.score(location_x_test,location_y_test)#用测试集查看R^2
[out]: 0.9985216027033551
意外发现,线性模型的R2高达0.99。
lr.coef_,lr.intercept_#查看系数与截距
[out]: (array([-5. , -4. , -2.875, -1. , -1.375, -4. , -3.25 , -5.875, -5.875]), 133.75)
6 实现更清晰的解释
6.1 对特征进行命名
df_tempt1=pd.DataFrame(location_x.columns)
df_tempt1.columns=['Features']
6.2 对系数进行命名
df_tempt2=pd.DataFrame(lr.coef_)
df_tempt2.columns=['Coef']
6.3 将特征与系数进行合并,对模型做出解释
df_finally=pd.concat([df_tempt1 ,df_tempt2], axis=1, join='inner')
df_finally.sort_values(by='Coef',ascending=True)
停车配置、卖场面积、竞争店品牌对模型影响相对较高。
模型解释:例如,在其他变量不变的情况下,每增加一个单位量的【停车配置】,分数会减少6分。其他变量也可以参照这样的逻辑进行解释。
6.4 还原初始分
已知条件:当所有特征特征为1时,竞争评估为100分,用100✖(系数/系数之和)可以得到大致的初始分数。
df_ini_points = pd.DataFrame(
[x for x in np.array(pd.DataFrame(100*(df_finally["Coef"]/df_finally["Coef"].sum())).T)]
,columns=[x for x in np.array(df_finally.loc[:,"Features"])]
,index = ["初始分"])
df_ini_points
7 模型验证
7.1 传递x的测试集,来预测分数
location_y_pre = pd.Series(lr.predict(location_x_test))
location_y_pre
[out]:
0 100.50
1 44.00
2 92.50
3 67.25
4 75.50
5 87.50
dtype: float64
location_y_test#真实值
[out]:
0 100
5 44
11 92
1 67
8 74
16 88
Name: 竞争评估, dtype: int64
从这发现,location_y_test的索引值有问题,不方便后续表格合并。
7.2 恢复location_y_test的索引值
for i in [location_y_test]:
i.index = range(i.shape[0])
df_final_test = pd.concat([location_y_test ,location_y_pre], axis=1, join='inner')
7.3 真实值与预测值的对比
7.3.1 测试集的预测效果
df_final_test.rename({"竞争评估":"评分真实值",0:"评分预测值"}, axis='columns')
7.3.2 总的对比效果
final_df = pd.concat([df,pd.Series(lr.predict(location_x))], axis=1, join='inner')
final_df.rename({"竞争评估":"竞争评估真实值",0:"竞争评估预测值"}, axis='columns')
8 项目总结与思考
1.极大程度地帮助同事更有效率地研究前人的应用成果。
2.目前仅找到什么样的一级指标如何影响分数,未能找到更加智能的方法去查看二级指标,只能通过手动查询。
3.由于本次拟合模型的准确率较高,因此没有采用传统评估回归模型的方式进行模型评估。
4.为何这么少的数据集能跑出这么高的分数?一个解释是样本量过小,另一个合理的解释是,这个app的原模型本身是通过主观的专家打分法创建出来的,是刻意控制下生成而来的结果。是一系列封闭数据,而非开放、动态、有误差,且具有“时间”概念的数据。
5.在采集数据时,应该加强对数据分布的谋划。例如y标签的数据采集一组偏态分布的数据集,再做一组近似正太分布的数据集,进行两两之间的模型比较。
6.本人通过聚类对标签y进行离散化,效果十分好。然而,用决策树和随机森林的分类器进行建模,准确率只有50%,尚不清楚真实原因。