banner

手把手带你进入TOP20的商超销售预测

作者: afenxi来源: afenxi时间:2017-02-23 12:56:590

摘要:如果说学习数据科学的最佳途径是什么——就是解决实际问题或亲自参与数据科学项目。因为只有当自己动手解决问题时,你才真正开始学习数据科学。

“商超销售预测”这一题目在一个月前一经提出,已有624名数据科学家报名参加,其中77名提交了答案。不管你是在开始时感到无从下手还是过程中遭遇瓶颈,本文都将带大家体验商超销售预测工作的全过程。

希望本文能够帮助越来越多的人走上数据科学之路。 手把手带你进入TOP20的商超销售预测-数据分析网

我们的探索将按照如下步骤进行:

1.假设生成——对影响因素进行头脑风暴,以便更好地理解问题。

2.数据探索——对类别性和持续性的特征进行观察总结,并推理数据。

3.数据清理——输入数据中的丢失值,并检查异常值。

4.特征工程——修改现有变量,建立新的分析变量。

5.建模——根据数据建立预测模型。

那么,闲话少说,现在言归正传!

1、假设生成

数据分析的关键一步,它包括陈述问题和对积极影响因素做出假设,这是观察数据的前期准备。当然,如果最后能获得数据的话,我们可以列表记下所有可能性分析。问题表述首要步骤就是理解问题表述。大数据科学家们收集了2013年十家不同地区商店的1559件商品的销售数据,每件产品的特性也已一一列明。目的就是建立预测模型,了解这些商店里每个产品的销售情况。

通过运用这一模型,商超销售预测将试图抓取那些对提高销售额起重要作用的产品特性和商店特点。

所以关键就是找出这些特性。我们首先进行可行性分析,然后再提出假设。假设对此问题我进行了如下假设(仅为个人想法,大家或许有更多思路)。既然讨论的是商店和产品,首先要建立不同的数据组。关于商店的假设:

1. 城市类型:位于城区或一线城市的商店的销量应更多,因为这里人群的消费水平更高。

2. 人口密度:人口稠密地区的商店的销量应更多,因为需求更大。

3. 商店规模:规模较大的商店的销量应更多,因为它们以一站式服务的方式运营,人们更喜欢在一个地方买全所有所需产品。

4. 竞争对手:陈设布置类似的商店的销量应更小,因为竞争更加激烈。

5. 营销:设有独特的促销区域的商店的销量应更大,因为促销区通过巧妙定格和广告会更吸引顾客。

6. 位置:位于繁华市场的商店的销量应更大,因为更接近顾客。

7. 顾客行为:保持产品陈列整齐以满足本地顾客需求的商店的销量应更大。

氛围:员工彬彬有礼的商店预计顾客会更多,销量也更多。

关于产品的假设:

1. 品牌:名牌产品销量应更高,因为顾客更加信任。

2. 包装:包装精美的产品可以吸引顾客,销量更好。

3. 用途:相比特殊用途产品,日常用品销量应更高。

4. 展示区:在商店占据较大货架的产品更容易首先吸引消费者,因而更畅销。

5. 店内可见度:商店内产品的摆放会影响销售。放在门口的商品比靠后的商品更吸引顾客。

6. 广告:商店里广告做得好的产品多数情况下销量更高。

7. 促销:有促销和折扣的商品更畅销。

这仅仅是我做的15个假设,大家还可以有更深入的思考,创建自己的假设。请记住,数据可能不足以检测所有假设,但是做这些假设能帮助你更好地理解问题,如果可能的话我们还可以寻找开放源信息。

下面让我们来到数据探索环节,仔细观察数据。

2、数据探索

在此做基本的数据探索并提出关于数据的猜测。我们会试着找出一些异常情况,并在下个环节解决。

第一步是观察数据,并尝试发现根据已有数据做出的假设信息。数据词典和假设的对比显示如下:

手把手带你进入TOP20的商超销售预测-数据分析网 我们可总结发现如下: 手把手带你进入TOP20的商超销售预测-数据分析网 你一定会发现你所假设的特征,但是数据不能直接反映特征,特征也不是靠数据直观体现。这时,大家可以寻找一些开放源数据来填补漏洞。我们首先加载所需的函数库和数据。可以从页面下载这些数据。 import pandas as pd import numpy as np#Read files: train = pd.read_csv("train.csv") test = pd.read_csv("test.csv") 一般来说,我们会先合并训练数据和测试数据,运行特征工程后再把它们分离。这省去了对训练数据和测试数据重复操作的麻烦。我们可以把它们合并到一个数据框“数据”中,用“源”这一列注明每个观察结果应归为哪一列。 train[source]=train test[source]=test data = pd.concat([train, test],ignore_index=True) print train.shape, test.shape, data.shape 手把手带你进入TOP20的商超销售预测-数据分析网 这样我们就能看到数据可能有相同的列,而行就相当于测试和训练。挑战之一就是丢失值,我们可以先检查一下哪些列含有丢失值。 data.apply(lambda x: sum(x.isnull())) 手把手带你进入TOP20的商超销售预测-数据分析网 请注意Item_Outlet_Sales是目标变量,而丢失值是测试组的变量,所以不必担心。不过我们要在数据清理环节中把丢失值输入到Item_Weight和Outlet_Size中。

我们来观察一组数字变量的统计: data.describe() 手把手带你进入TOP20的商超销售预测-数据分析网 观察结果如下: 1.  Item_Visibility最小值为0,没有实际意义,因为当产品在商店销售时,可见度不可能为0.

2.  Outlet_Establishment_Years变化范围是从1985到2009。数值以这种格式出现可能不太恰当。不过,如果我们能够将它们转化为商店的历史,这些数值对销量应该会产生更积极的作用。

3.  Item_Weight和Item_Outlet_Sales的数值较低证实了丢失值检查得出的发现。

提到名义变量,我们来观察一下每组中的特殊值。 data.apply(lambda x: len(x.unique())) 手把手带你进入TOP20的商超销售预测-数据分析网 由图可知有1559个产品和10家商店(这些在问题陈述中也提到)。另一个值得关注的是Item_Type有16个特殊值。让我们通过每一个名义变量中的不同类别的频率来进一步探索。显然,这里不涉及ID 和源变量。 #Filter categorical variables categorical_columns = [x for x in data.dtypes.index if data.dtypes[x]==object] #Exclude ID cols and source: categorical_columns = [x for x in categorical_columns if x not in [Item_Identifier,Outlet_Identifier,source]] #Print frequency of categories for col in categorical_columns: print Frequency of Categories for varible %s%colprint data[col].value_counts() 手把手带你进入TOP20的商超销售预测-数据分析网 由上数据得出如下结果: 1. Item_Fat_Content: 一些‘Low Fat’值被误编码为‘low fat’和‘LF’。此外,一些‘Regular’变成了‘regular’。

2. Item_Type: 并非所有类别都有实数,合并类别似乎可以得出更好结果。

3. Outlet_Type: Supermarket Type2 and Type3可以合并,不过动手前要考虑这个想法是否可取。

3、数据清理 这一步骤主要包括录入丢失值和处理异常值。尽管去除异常值在拟合技能中非常重要,基于树的高级算法却对异常值没有影响。所以这一部分留给大家自己尝试。我们在此只关注录入这一关键步骤。

注意:我们在此将广泛使用一些Pandas library。如果你对Pandas还不太熟悉,可以参考相关文章,浏览更多Pandas相关文章! 录入丢失值 我们发现两个有丢失值的变量——Item_Weight和 Outlet_Size。这时按照一个物品的平均重量录入物品重量,步骤如下: #Determine the average weight per item: item_avg_weight = data.pivot_table(values=Item_Weight, index=Item_Identifier)#Get a boolean variable specifying missing Item_Weight values miss_bool = data[Item_Weight].isnull()#Impute data and check #missing values before and after imputation to confirm print Orignal #missing: %d% sum(miss_bool) data.loc[miss_bool,Item_Weight] = data.loc[miss_bool,Item_Identifier].apply(lambda x: item_avg_weight[x]) print Final #missing: %d% sum(data[Item_Weight].isnull())

手把手带你进入TOP20的商超销售预测-数据分析网 以上步骤证实列中目前没有丢失值。我们按照某商店类别录入Outlet_Size。 Import mode function: from scipy.stats import mode#Determing the mode for each outlet_size_mode = data.pivot_table(values=Outlet_Size, columns=Outlet_Type,aggfunc=(lambda x:mode(x).mode[0]) ) print Mode for each Outlet_Type: print outlet_size_mode#Get a boolean variable specifying missing Item_Weight values miss_bool = data[Outlet_Size].isnull()

#Impute data and check #missing values before and after imputation to confirm print Orignal #missing: %d% sum(miss_bool) data.loc[miss_bool,Outlet_Size] = data.loc[miss_bool,Outlet_Type].apply(lambda x: outlet_size_mode[x]) print sum(data[Outlet_Size].isnull())

手把手带你进入TOP20的商超销售预测-数据分析网 这表明数据中没有丢失值。现在我们来看特征工程。 4、特征工程 在数据探索阶段,我们发现数据之间也有细微不同,所以一定要解决问题。根据现阶段的变量做好分析时,我们也会建立一些新变量。 步骤一:考虑合并店铺类型(Outlet_Type) 探索过程中,我们决定考虑合并Supermarket Type2 和Type3变量。这个想法怎么样?快速检查的方法是通过商店类型分析平均销售量,如果销售很相近,那么合并数据也不会有很大意义。 data.pivot_table(values=Item_Outlet_Sales,index=Outlet_Type) 手把手带你进入TOP20的商超销售预测-数据分析网 上图表明了两者之间的巨大区别,我们按原貌表现出来。请注意这只是其中一种方法,面对不同的情景可以采用其他的分析方法,针对其他特征也可以采用同样的方法。 步骤二:修改Item_Visibility 我们注意到最小值是0, 没有实际意义,把它当做丢失信息,按照产品的平均可见性进行输入。 #Determine average visibility of a product visibility_avg = data.pivot_table(values=Item_Visibility, index=Item_Identifier)#Impute 0 values with mean visibility of that product: miss_bool = (data[Item_Visibility] == 0)print Number of 0 values initially: %d%sum(miss_bool) data.loc[miss_bool,Item_Visibility] = data.loc[miss_bool,Item_Identifier].apply(lambda x: visibility_avg[x]) print Number of 0 values after modification: %d%sum(data[Item_Visibility] == 0)

手把手带你进入TOP20的商超销售预测-数据分析网 这样就能看出任何一个值都不为0。

在步骤一中,我们假设有更高可见度的产品更畅销。但是对产品进行比较的同时,我们也要看到具体某家商店产品的可见度和所有商店同类产品的平均可见度。这使我们知道该产品在某商店与其他商店相比的重视程度。我们可以用上文的‘visibility_avg’变量做到。 #Determine another variable with means ratio data[Item_Visibility_MeanRatio] = data.apply(lambda x: x[Item_Visibility]/visibility_avg[x[Item_Identifier]], axis=1) print data[Item_Visibility_MeanRatio].describe() 手把手带你进入TOP20的商超销售预测-数据分析网 这样就成功创造出了新变量。再次,这也仅仅是如何创造新特征的一例。强烈建议大家多多尝试,因为优秀的特征可以大大提高模型运行效果,而且无一例外地表现为优秀模型和普通模型的区别。 步骤三:建立范围广的品类 刚才我们看到Item_Type变量有16个类别,这在分析中可能会有用,所以合并是个不错的想法。其中一个方法就是手动将类别分配给每一个变量。不过这有一个问题:如果你观察Item_Identifier,也就是每个物品各自的ID,开头一般都是FD、DR 或者NC。如果观察这些类别,它们主要就是食品、饮品和非消耗品。所以我用Item_Identifier变量创造新的一列。 #Get the first two characters of ID: data[Item_Type_Combined] = data[Item_Identifier].apply(lambda x: x[0:2]) #Rename them to more intuitive categories: data[Item_Type_Combined] = data[Item_Type_Combined].map() submission.to_csv(filename, index=False)

我添加了标注。如果难以理解编码,欢迎在评论中留言。 线性拟合模型 我们现在建立第一个线性——拟合模型。 from sklearn.linear_model import LinearRegression, Ridge, Lasso predictors = [x for x in train.columns if x not in [target]+IDcol] # print predictors alg1 = LinearRegression(normalize=True) modelfit(alg1, train, test, predictors, target, IDcol, alg1.csv) coef1 = pd.Series(alg1.coef_, predictors).sort_values() coef1.plot(kind=bar, title=Model Coefficients)  公共领导榜排名:1202

可以看出这比基准模型排名靠前。不过,如果你注意到系数的话,会发现表示过度拟合的程度很高。为了实现这个目标,可以使用岭回归模型。想要了解更多关于Ridge & Lasso拟合技巧,请在公众号中回复“销售预测”即可下载! 岭回归模型 predictors = [x for x in train.columns if x not in [target]+IDcol] alg2 = Ridge(alpha=0.05,normalize=True) modelfit(alg2, train, test, predictors, target, IDcol, alg2.csv) coef2 = pd.Series(alg2.coef_, predictors).sort_values() coef2.plot(kind=bar, title=Model Coefficients) 手把手带你进入TOP20的商超销售预测-数据分析网

公共领导榜:1203

尽管回归系数看起来更佳,但是排名几乎一样。可以微调模型参数使成绩更好,但我认为不会有显著进步。使用交叉验证发现也是收效甚微,所以不能指望有更出色的表现了。 决策树模型 我们来尝试下决策树模型,看看结果是否会有所改善。 from sklearn.tree import DecisionTreeRegressor predictors = [x for x in train.columns if x not in [target]+IDcol] alg3 = DecisionTreeRegressor(max_depth=15, min_samples_leaf=100) modelfit(alg3, train, test, predictors, target, IDcol, alg3.csv) coef3 = pd.Series(alg3.feature_importances_, predictors).sort_values(ascending=False) coef3.plot(kind=bar, title=Feature Importances) 手把手带你进入TOP20的商超销售预测-数据分析网

公共领导榜排名:1162

可以看出RMSE 是1058, CV  是1091,这告诉我们模型有些过度拟合。我们尝试一下只用4个首要变量建立决策树,max_depth 为8,min_samples_leaf 为150. predictors = [Item_MRP,Outlet_Type_0,Outlet_5,Outlet_Years] alg4 = DecisionTreeRegressor(max_depth=8, min_samples_leaf=150) modelfit(alg4, train, test, predictors, target, IDcol, alg4.csv) coef4 = pd.Series(alg4.feature_importances_, predictors).sort_values(ascending=False) coef4.plot(kind=bar, title=Feature Importances) 手把手带你进入TOP20的商超销售预测-数据分析网

公共领导榜排名:1157

也可以使用其他参数进一步微调,这一步留给大家尝试。 随机森林模型 我们也尝试下随机森林,看看是否有改善。 from sklearn.ensemble import RandomForestRegressor predictors = [x for x in train.columns if x not in [target]+IDcol] alg5 = RandomForestRegressor(n_estimators=200,max_depth=5, min_samples_leaf=100,n_jobs=4) modelfit(alg5, train, test, predictors, target, IDcol, alg5.csv) coef5 = pd.Series(alg5.feature_importances_, predictors).sort_values(ascending=False) coef5.plot(kind=bar, title=Feature Importances) 手把手带你进入TOP20的商超销售预测-数据分析网

公共领导排名:1154

你也许觉得改善不太明显,然而,随着模型越来越好,进哪怕微小的提高都变得难上加难。我们尝试一下max_depth 为 6 和tree为400的算法进行另一种随机森林。增加决策树数量使模型更加有效,然而计算成本也在提高。 predictors = [x for x in train.columns if x not in [target]+IDcol] alg6 = RandomForestRegressor(n_estimators=400,max_depth=6, min_samples_leaf=100,n_jobs=4) modelfit(alg6, train, test, predictors, target, IDcol, alg6.csv) coef6 = pd.Series(alg6.feature_importances_, predictors).sort_values(ascending=False) coef6.plot(kind=bar, title=Feature Importances) 手把手带你进入TOP20的商超销售预测-数据分析网

公共领导榜排名:1152

这又是一次增长性变化,它会送你进入TOP10甚至TOP5。进一步微调参数提高准确性。目前的模型把你送入TOP20已经绰绰有余。我曾试过基本的GBM,微调后名次到了TOP10。大家可以尝试用GBM 和 XGBoost集成方法这样更佳的算法进一步提高成绩。

本环节到此结束。如果你想要iPython notebook 形式的建模编码, 请从GitHub repository下载。 尾注: 本文带大家走遍了解决数据科学问题的全过程。首先,我们没有观察的情况下根据数据做出假设。其次,我们进行数据探索,发现数据里的细微偏差需要纠正。接着,我们进行数据清理和特征工程,输入丢失值,解决异常情况,建立新特征,还通过独热码使数据更加适应模型。最后,我们进行拟合,决策树和随机森林模型,并大致了解了如何微调能得出更好结果。我相信本文每位读者都能在商超销售预测中取得很好的成绩。对初学者而言,你的得分至少应为1150,对于已经遥遥领先的选手来说,可以使用这里的一些特征工程小技巧来进一步提高。祝大家一切顺利!

你认为本文有用吗?你还可以做出其他更有趣的假设吗?你还创造了其他什么特征?你能够通过GBM 和 XGBoost获得很高分数吗?欢迎在下面的评论中留言与我们分享你的经历,或在讨论端口与我们互动。 【文件下载】链接: 销售预测 密码: v4ma

原创文章,作者:灯塔大数据,如若转载,请注明出处:《手把手带你进入TOP20的商超销售预测》https://www.afenxi.com/post/10722

banner
看过还想看
可能还想看
热点推荐

永洪科技
致力于打造全球领先的数据技术厂商

申请试用
Copyright © 2012-2024开发者:北京永洪商智科技有限公司版本:V10.2
京ICP备12050607号-1京公网安备110110802011451号 隐私政策应用权限