精华内容
下载资源
问答
  • kaggle销售预测数据-数据
  • SalesForecasting:在聚类数据之后根据先前的销售数据预测销售
  • WalmartSalesPrediction:预测沃尔玛数据销售
  • 使用LSTM对销售数据(吉恩销售数据集)进行预测
  • 口红销量数据-数据集

    2021-03-14 18:47:55
    口红-data.xlsx
  • 数据分析 - 时间序列分析 - 预测销售环境准备数据准备正文 环境准备 EDA过程中使用了的环境和第三方库:: python 3.7.2 Jupyter Notebook(代码均在此测试成功) pandas 0.23.4 numpy 1.15.4(数据处理) ...

    数据分析 - 时间序列分析 - 预测销售

    环境准备

    EDA过程中使用了的环境和第三方库::

    • python 3.7.2
    • Jupyter Notebook(代码均在此测试成功)
    • pandas 0.23.4
    • numpy 1.15.4(数据处理)
    • matplotlib 3.0.2
    • seaborn 0.9.0(数据可视化)

    数据准备

    数据字段简介,训练集与测试集下载地址:
    https://www.kaggle.com/c/8587/download-all.

    正文

    开工前准备,导入第三方库:

    # data processing
    import pandas as pd
    import numpy as np
    import random as rd
    import datetime
    # visulization
    import matplotlib.pyplot as plt
    import seaborn as sns
    # Time series analysis
    from statsmodels.tsa.arima_model import ARIMA
    from statsmodels.tsa.statespace.sarimax import SARIMAX
    from pandas.plotting import autocorrelation_plot
    from statsmodels.tsa.stattools import adfuller, acf, pacf,arma_order_select_ic
    import statsmodels.formula.api as smf
    import statsmodels.tsa.api as smt
    import statsmodels.api as sm
    import scipy.stats as scs
    # settings
    import warnings
    warnings.filterwarnings("ignore")
    pd.set_option('max_columns',None)
    

    该案例的任务是根据历史日常销售数据,预测测试集中每个商店的商品销售额,其中商品或商店可能每个月会有细微的变化,要求模型具备一定的鲁棒性来应对这种情况。
    数据集简介:

    • sales_train: 训练集,近300万行,包含从2013.1到2015.10的历史销售数据;
    • item_cat: 商品分类信息;
    • item: 商品补充信息;
    • shops: 商店信息;
    • test: 测试集,近20万行;
    • sample_submission: 提交样例;

    第一步,加载数据:

    # train
    sales=pd.read_csv("dataset/sales_train.csv")
    item_cat=pd.read_csv("dataset/item_categories.csv")
    item=pd.read_csv("dataset/items.csv")
    shops=pd.read_csv("dataset/shops.csv")
    # test
    test=pd.read_csv("dataset/test.csv")
    sub=pd.read_csv("dataset/sample_submission.csv")
    

    先看一下表sales:

    sales.head()
    
    datedate_block_numshop_iditem_iditem_priceitem_cnt_day
    002.01.201305922154999.001.0
    103.01.20130252552899.001.0
    205.01.20130252552899.00-1.0
    306.01.201302525541709.051.0
    415.01.201302525551099.001.0

    日期格式不规范,用strptime方法将其转化成标准日期格式:

    sales['date']=sales['date'].apply(lambda d: datetime.datetime.strptime(d,'%d.%m.%Y'))
    

    统计销量前十的商品分类,发现item_category_id="40"的销量最高:

    x=item.groupby('item_category_id').count()
    x=x.sort_values(by=['item_id'],ascending=False)
    x=x.iloc[:10].reset_index()
    
    plt.figure(figsize=(10,4))
    ax=sns.barplot(x['item_category_id'],x['item_id'],alpha=0.7)
    plt.title('Number of Items per Category')
    plt.xlabel('Category Id',fontsize=12)
    plt.ylabel('Number of Items',fontsize=12)
    plt.show()
    

    在这里插入图片描述
    通过以上简单了解数据,以下直接进入正题,时间序列分析。
    案例目标是预测每个商店-商品组合在下一个月的销售额,因此先熟悉如何单序列预测,这里以总销售额为例,首先计算该公司每个月的总销售额:

    monthlyall=sales.groupby(['date_block_num'])['item_cnt_day'].sum()
    plt.figure(figsize=(10,4))
    plt.title('Number of Saled Itemsper Month')
    plt.xlabel('date_block_num',fontsize=12)
    plt.ylabel('Number of Items',fontsize=12)
    plt.plot(monthlyall)
    

    在这里插入图片描述
    尝试以移动平均和移动标准差分析数据,消除周期性波动,观察整体趋势,取窗口大小为12个月:

    plt.figure(figsize=(16,6))
    plt.plot(monthlyall.rolling(window=12,center=False).mean(),label='Rolling Mean')
    plt.plot(monthlyall.rolling(window=12,center=False).std(),label='Rolling Std')
    plt.legend()
    

    在这里插入图片描述
    也可以通过以下方法快速分离趋势、季节性、残差,选择不同的model参数,会有不同的分离结果。
    当model=‘additive’,即 观察值=趋势值+季节性值+残差,如下所示:

    res=sm.tsa.seasonal_decompose(monthlyall.values,freq=12,model='additive')
    fig=res.plot()
    

    在这里插入图片描述
    当model=‘multiplicative’,即 观察值=趋势值x季节性值x残差,如下所示:

    res=sm.tsa.seasonal_decompose(monthlyall.values,freq=12,model='multiplicative')
    fig=res.plot()
    

    在这里插入图片描述
    那么如何判断时间序列是否满足模型要求?这里将引入“稳定”的概念,如果时间序列是稳定的,那么建模也将更容易,而且一般统计模型都要求或认为输入的时间序列是稳定的。稳定的时间序列有以下三个特征:

    • 该时间序列的移动平均值与时间无关;
    • 该时间序列的移动标准差值与时间无关;
    • 该时间序列的任意两个区间的协方差与时间无关;

    判断时间序列是否稳定主要有以下三个方法:

    • ADF( Augmented Dicky Fuller Test)
    • KPSS
    • PP (Phillips-Perron test)

    比较常用的是ADF检验,statsmodels提供了ADF检验接口,以下对每月销售总额序列进行检验:

    # Stationarity tests
    def test_stationarity(timeseries):
        # Perform Dickey-Fuller Test
        print("Result of Dickey-Fuller Test:")
        dftest=adfuller(timeseries,autolag='AIC')
        dfoutput=pd.Series(dftest[:4],index=['Test Statistics','p-value','Lags Used','Number of Observations Used'])
        for key,value in dftest[4].items():
            dfoutput[f'Critical Value {key}']=value
        print(dfoutput)
    
    test_stationarity(monthlyall)
    

    Result of Dickey-Fuller Test:
    Test Statistics -2.395704
    p-value 0.142953
    Lags Used 0.000000
    Number of Observations Used 33.000000
    Critical Value 1% -3.646135
    Critical Value 5% -2.954127
    Critical Value 10% -2.615968
    dtype: float64

    在去除趋势和季节性因素前,ADF检验发现,t检验值比10%关键值大,所以无法拒绝原假设(即非稳定)。
    尝试去除趋势和季节性因素:

    
    def difference(dataset,interval=1):
        diff=list()
        for i in range(interval,len(dataset)):
            diff.append(dataset[i]-dataset[i-interval])
        return Series(diff)
        
    # 原时间序列
    ts=sales.groupby(['date_block_num'])['item_cnt_day'].sum()
    ts.astype('float')
    plt.figure(figsize=(16,16))
    plt.subplot(311)
    plt.title('Original')
    plt.xlabel('Time')
    plt.ylabel('Sales')
    plt.plot(ts)
    # 去除趋势性因素
    plt.subplot(312)
    plt.title('After De-Trend')
    plt.xlabel('Time')
    plt.ylabel('Sales')
    new_ts1=difference(ts)
    plt.plot(new_ts1)
    # 去除季节性因素
    plt.subplot(313)
    plt.title('After De-seasonalization')
    plt.xlabel('Time')
    plt.ylabel('Sales')
    new_ts2=difference(ts,12)   # assuming the seasonality is 12 months long
    plt.plot(new_ts2)
    

    在这里插入图片描述
    去除趋势性因素后时间序列,ADF检验:

    # 去除趋势性因素的时间序列
    test_stationarity(new_ts1)
    

    Result of Dickey-Fuller Test:
    Test Statistics -1.363622e+01
    p-value 1.686395e-25
    Lags Used 1.000000e+01
    Number of Observations Used 2.200000e+01
    Critical Value 1% -3.769733e+00
    Critical Value 5% -3.005426e+00
    Critical Value 10% -2.642501e+00

    去除季节性因素后时间序列,ADF检验:

    test_stationarity(new_ts2)
    

    Result of Dickey-Fuller Test:
    Test Statistics -3.270101
    p-value 0.016269
    Lags Used 0.000000
    Number of Observations Used 21.000000
    Critical Value 1% -3.788386
    Critical Value 5% -3.013098
    Critical Value 10% -2.646397
    dtype: float64

    两次检验的t值都在5%内,且p值也很小,可以认为输入的时间序列是稳定的,即以上的处理方式可以得到稳定的时间序列。

    建模分析

    Prophet

    使用prophet进行时间序列分析。

    层次时间序列

    展开全文
  • 基于BP的CRM系统销售预测数据挖掘.pdf
  • 原标题:Python对商店数据进行lstm和xgboost销售量时间序列建模预测分析原文链接:http://tecdat.cn/?p=17748在数据科学学习之旅中,我经常处理日常工作中的时间序列数据集,并据此做出预测。我将通过以下步骤:探索...

    原标题:Python对商店数据进行lstm和xgboost销售量时间序列建模预测分析

    原文链接:http://tecdat.cn/?p=17748

    在数据科学学习之旅中,我经常处理日常工作中的时间序列数据集,并据此做出预测。

    我将通过以下步骤:

    探索性数据分析(EDA)

    问题定义(我们要解决什么)

    变量识别(我们拥有什么数据)

    单变量分析(了解数据集中的每个字段)

    多元分析(了解不同领域和目标之间的相互作用)

    缺失值处理

    离群值处理

    变量转换

    预测建模

    LSTM

    XGBoost

    问题定义

    我们在两个不同的表中提供了商店的以下信息:

    商店:每个商店的ID

    销售:特定日期的营业额(我们的目标变量)

    客户:特定日期的客户数量

    StateHoliday:假日

    SchoolHoliday:学校假期

    StoreType:4个不同的商店:a,b,c,d

    CompetitionDistance:到最近的竞争对手商店的距离(以米为单位)

    CompetitionOpenSince [月/年]:提供最近的竞争对手开放的大致年份和月份

    促销:当天促销与否

    Promo2:Promo2是某些商店的连续和连续促销:0 =商店不参与,1 =商店正在参与

    PromoInterval:描述促销启动的连续区间,并指定重新开始促销的月份。

    利用所有这些信息,我们预测未来6周的销售量。

    # 让我们导入EDA所需的库:

    import numpy as np # 线性代数

    import pandas as pd # 数据处理,CSV文件I / O导入(例如pd.read_csv)

    import matplotlib.pyplot as plt

    import seaborn as sns

    from datetime import datetime

    plt.style.use("ggplot") # 绘图

    #导入训练和测试文件:

    train_df = pd.read_csv("../Data/train.csv")

    test_df = pd.read_csv("../Data/test.csv")

    #文件中有多少数据:

    print("在训练集中,我们有", train_df.shape[0], "个观察值和", train_df.shape[1], 列/变量。")

    print("在测试集中,我们有", test_df.shape[0], "个观察值和", test_df.shape[1], "列/变量。")

    print("在商店集中,我们有", store_df.shape[0], "个观察值和", store_df.shape[1], "列/变量。")

    在训练集中,我们有1017209个观察值和9列/变量。

    在测试集中,我们有41088个观测值和8列/变量。

    在商店集中,我们有1115个观察值和10列/变量。

    首先让我们清理 训练数据集。

    #查看数据

    train_df.head().append(train_df.tail()) #显示前5行。

    train_df.isnull().all()

    Out[5]:

    Store False

    DayOfWeek False

    Date False

    Sales False

    Customers False

    Open False

    Promo False

    StateHoliday False

    SchoolHoliday False

    dtype: bool

    让我们从第一个变量开始-> 销售量

    opened_sales = (train_df[(train_df.Open == 1) #如果商店开业

    opened_sales.Sales.describe()

    Out[6]:

    count 422307.000000

    mean 6951.782199

    std 3101.768685

    min 133.000000

    25% 4853.000000

    50% 6367.000000

    75% 8355.000000

    max 41551.000000

    Name: Sales, dtype: float64

    看一下顾客变量

    In [9]:

    train_df.Customers.describe()

    Out[9]:

    count 1.017209e+06

    mean 6.331459e+02

    std 4.644117e+02

    min 0.000000e+00

    25% 4.050000e+02

    50% 6.090000e+02

    75% 8.370000e+02

    max 7.388000e+03

    Name: Customers, dtype: float64

    train_df[(train_df.Customers > 6000)]

    我们看一下假期 变量。

    train_df.StateHoliday.value_counts()

    0 855087

    0 131072

    a 20260

    b 6690

    c 4100

    Name: StateHoliday, dtype: int64

    train_df.StateHoliday_cat.count()

    1017209

    train_df.tail()

    train_df.isnull().all() #检查缺失

    Out[18]:

    Store False

    DayOfWeek False

    Date False

    Sales False

    Customers False

    Open False

    Promo False

    SchoolHoliday False

    StateHoliday_cat False

    dtype: bool

    让我们继续进行商店分析

    store_df.head().append(store_df.tail())

    #缺失数据:

    Store 0.000000

    StoreType 0.000000

    Assortment 0.000000

    CompetitionDistance 0.269058

    CompetitionOpenSinceMonth 31.748879

    CompetitionOpenSinceYear 31.748879

    Promo2 0.000000

    Promo2SinceWeek 48.789238

    Promo2SinceYear 48.789238

    PromoInterval 48.789238

    dtype: float64

    In [21]:

    让我们从缺失的数据开始。第一个是 CompetitionDistance

    store_df.CompetitionDistance.plot.box()

    让我看看异常值,因此我们可以在均值和中位数之间进行选择来填充NaN

    缺少数据,因为商店没有竞争。 因此,我建议用零填充缺失的值。

    store_df["CompetitionOpenSinceMonth"].fillna(0, inplace = True)

    让我们看一下促销活动。

    store_df.groupby(by = "Promo2", axis = 0).count()

    如果未进行促销,则应将“促销”中的NaN替换为零

    我们合并商店数据和训练集数据,然后继续进行分析。

    第一,让我们按销售量、客户等比较商店。

    f, ax = plt.subplots(2, 3, figsize = (20,10))

    plt.subplots_adjust(hspace = 0.3)

    plt.show()

    从图中可以看出,StoreType A拥有最多的商店,销售和客户。但是,StoreType D的平均每位客户平均支出最高。只有17家商店的StoreType B拥有最多的平均顾客。

    我们逐年查看趋势。

    sns.factorplot(data = train_store_df,

    # 我们可以看到季节性,但看不到趋势。 该销售额每年保持不变

    我们看一下相关图。

    "CompetitionOpenSinceMonth", "CompetitionOpenSinceYear", "Promo2

    我们可以得到相关性:

    客户与销售(0.82)

    促销与销售(0,82)

    平均顾客销量 vs促销(0,28)

    商店类别 vs 平均顾客销量 (0,44)

    我的分析结论:

    商店类别 A拥有最多的销售和顾客。

    商店类别 B的每位客户平均销售额最低。因此,我认为客户只为小商品而来。

    商店类别 D的购物车数量最多。

    促销仅在工作日进行。

    客户倾向于在星期一(促销)和星期日(没有促销)购买更多商品。

    我看不到任何年度趋势。仅季节性模式。

    最受欢迎的见解

    1.在python中使用lstm和pytorch进行时间序列预测

    2.python中利用长短期记忆模型lstm进行时间序列预测分析

    3.使用r语言进行时间序列(arima,指数平滑)分析

    4.r语言多元copula-garch-模型时间序列预测

    5.r语言copulas和金融时间序列案例

    6.使用r语言随机波动模型sv处理时间序列中的随机波动

    7.r语言时间序列tar阈值自回归模型

    8.r语言k-shape时间序列聚类方法对股票价格时间序列聚类

    9.python3用arima模型进行时间序列预测返回搜狐,查看更多

    责任编辑:

    展开全文
  • 本文将主要讲述如何使用BLiTZ(PyTorch贝叶斯深度学习库)来建立贝叶斯LSTM模型,以及如何在其上使用序列数据进行训练与推理。 原创文章 54获赞 109访问量 18万+ 关注 私信 展开阅读全文 作者:deephub
  • 实际上,这是一个分类问题,即将输入的图片数据分成 0-9 共 10 个类别,而且我们的数据都是直接使用 MNIST 上下载的处理好的数据。 在现实生产中,我们的数据源通常来自于数据库,是没有经过预处理的,那么我们该做...

    image

    《【Get】用深度学习识别手写数字》 中,我们通过一个手写数字识别的例子,体验了如何使用 深度学习 + tensorflow 解决一个具体的问题。

    实际上,这是一个分类问题,即将输入的图片数据分成 0-9 共 10 个类别,而且我们的数据都是直接使用 MNIST 上下载的处理好的数据。

    在现实生产中,我们的数据源通常来自于数据库,是没有经过预处理的,那么我们该做些什么来让这些数据库里的数据能够用于进行机器学习呢?

    机器学习的前置步骤,数据预处理就是解决这个问题的。

    本篇 CoorChice 将会通过一个回归预测问题,来展示如何进行这个过程。

    原始数据

    我们用于机器学习的数据的量不能太少,否则训练效果会极差。但是我们个人如何才能获取到大量的数据来进行训练呢?

    CoorChice 推荐 kaggle:https://www.kaggle.com/datasets,这是全球最大的数据科学社区和数据竞赛平台。在这个美妙的地方,我们可以轻松的找到各种各样的,海量的,精彩绝伦的数据。

    image

    打开链接就可以看到海量的数据,我们很随意的选择其中一个数据源来进行训练。

    就选第一条吧!

    第一条数据是关于一个面包店的交易的数据。点击进入后,找到下载就可以下载这套数据了。

    image

    也许你可能不能立刻下载,因为他会要求你先登录。那就成为 Kaggle 的会员吧。

    我们使用表格打开刚刚下载的数据观察观察。

    image

    My God! 这是一堆简陋不堪的数据,共有 21293 条数据,每条只有 4 个特征! 4 个特征! 4 个特征!

    没关系,我们只是学习如何处理数据的过程,所以就凑合着用一下吧。

    开始数据处理

    实际上,通常我们的数据呆在数据库中,就是这种表格的形式。

    在开始之前,需要先安装一下 Pandas 这个 Python 库,它被用来读取我们的表格数据,和进行增、删、改、查等操作。

    下好了,我们就开始吧…

    观察数据

    进行数据处理最重要的一步,就是对数据进行观察和分析。通过观察和分析,我们要除去一些无关紧要的数据列,比如在预测天气预报的时候,我们就应该把 ‘李雷早上吃了什么’ 这个数据列去掉,因为对模型训练毫无帮助。

    同时,我们要从数据中挖掘出一些隐藏的信息,以扩充特征。日入在预测产品的交易信息时,我们从日期这个数据列,就能知道当天是否是一个节日,是什么节日。

    在我们下载的这堆面包店的交易数据中,仅有惨不忍睹的 4 个类目!

    通常,当我们使用机器学习来解决问题时,都会有一个目的。比如,在这堆数据中,CoorChice 希望通过机器学习训练一个模型,能够用于预测未来一定条件下的某种类型的面包所能达到的交易量是多少。

    因此,我们将交易量 Transaction 这一列数据作为数据集的标签数据。

    接下来剩下的只有 日期、时间、面包类目 这三个特征了。

    从数据中挖掘更多的信息

    仅有这三个特征来进行训练,结果可想而知会有多差。比你想的差还要差,所以我们需要从现有的数据中挖掘出更多的信息来。比如,在图片数据中,通常会进行一些旋转、平移之类的操作,来补充数据量。

    日期 Date

    首先看看日期能挖掘到什么有用的信息?

    1. 当然是星期啦。今天是星期一、星期二、…、对交易肯定是有影响的。我们通过 Date 可以计算出当前日期是周几。

    2. 还有什么可挖掘的吗?嗯,左思右想…咦,节日肯定也是影响面包交易量的一个重要因素,有了 Date 我们也能知道当前日期是什么节日。

    3. 然后,通过观察可以发现,随着日期的增加,交易量也是在累加的,所以日期的大小也可直接作为一个特征。

    4. 由于 CoorChice 要尝试预测的是未来某个时间、某种面包所能达到的交易量,所以日期的大小对结果必然是有影响的。但我们不能直接将日期转换为一个形如 20161030 这样的数字,因为一年只有 12 个月,每一个月天数不一样的,所以这个数值跳跃度比较大,这样就大大增加了训练的难度和准确率。我们需要的是一个统一标准的数值。如果确定某一天为基准,然后把日期转换为和这一天的距离,那量化标准自然就是很明了的了。因为数据是从 2016-10-30 开始,那么把这天作为基准日就再合适不过了。

    时间 Time

    接下来观察 Time 有什么可用的没。

    1. Time 本身是一些比较密集的数据,间隔不大。我们可以把它划归到小时里,因此就会有 24 个小时。比如,“10:13:03” 就让它属于 10 点这个小时吧。

    2. 通过时间,我们还可以知道现在是处于 早晨、上午、中午、下午、傍晚、晚上、深夜 中的那个时间段。不同的时间段或多或少也会影响交易量。

    确定好了思路,接下来就开始找着这个思路处理数据了。

    处理原始数据

    处理数据的第一步当然是先读取数据啦,我们前面下载的 Pandas 就使用来干这个的。

    读取数据

    # 读取数据
    datas = pd.read_csv('data/BreadBasket_DMS.csv')
    

    读取数据后,输出一下看看长什么样子。

    print(datas.head())
    ->> 
             Date      Time  Transaction           Item
    0  2016-10-30  09:58:11            1          Bread
    1  2016-10-30  10:05:34            2   Scandinavian
    2  2016-10-30  10:05:34            2   Scandinavian
    3  2016-10-30  10:07:57            3  Hot chocolate
    4  2016-10-30  10:07:57            3            Jam
    
    [5 rows x 4 columns]
    

    增强数据

    然后,我们对原始数据按照上面分析的思路进行处理。

    # 挖掘,周几对交易量的影响
    datas['Weekday'] = datas['Date']
    datas['Weekday'] = datas['Weekday'].map(lambda x: get_weekday(x))
    
    # 挖掘,各个节日对交易量的影响
    datas['Festival'] = datas['Date']
    datas['Festival'] = datas['Festival'].map(lambda x: get_festival(x))
    
    # 挖掘,当前所处的时间段对交易量的影响
    datas['Time_Quantum'] = datas['Time']
    datas['Time_Quantum'] = datas['Time_Quantum'].map(lambda x: get_time_quantum(x))
    
    # 将 Date 一列变为与 2016-10-30 这天的距离
    datas['Date'] = datas['Date'].map(lambda x: get_delta_days(x))
    # 将时间转变为时段
    datas['Time'] = datas['Time'].map(lambda x: get_time_range(x))
    # 缩小数据大小
    datas['Transaction'] = datas['Transaction'].map(lambda x: (float(x) / 1000.))
    

    现在,再输出一下数据看看。

    print(datas.head())
    ->> 
    
       Date Time  Transaction  ...  Weekday Festival Time_Quantum
    0   0.0    9        0.001  ...        6     null           上午
    1   0.0   10        0.002  ...        6     null           上午
    2   0.0   10        0.002  ...        6     null           上午
    3   0.0   10        0.003  ...        6     null           上午
    4   0.0   10        0.003  ...        6     null           上午
    
    [5 rows x 7 columns]
    

    从表格数据中可以看到,Date 和 Transaction 都变成浮点数了,因为把它们进行缩小,有利于后面的梯度下降,否则 loss 会非常非常的大。

    现在,我们已经扩充了一些特征。

    进行 One-Hot 编码

    接下来,对于离散的数据,比如 Weekday、Time 这样的,它的大小并不会对交易产生影响,但这种离散的特征的类别取值是会对结果产生影响的。比如,春节这天会对食物的交易量产生影响。

    我们需要对这样的特征数据进行 独热编码 。关于 独热编码 ,你可以在 CoorChice 的 《机器学习,看完就明白了》 这篇文章,了解相关信息。

    ont_hot_data = pd.get_dummies(datas, prefix=['Time', 'Item', 'Weekday', 'Festival', 'Time_Quantum'])
    

    看看现在数据表变成了什么样子了。

    print(ont_hot_data.head())
    ->>
       Date  Transaction ...  Time_Quantum_晚上  Time_Quantum_深夜
    0   0.0        0.001 ...                0                0
    1   0.0        0.002 ...                0                0
    2   0.0        0.002 ...                0                0
    3   0.0        0.003 ...                0                0
    4   0.0        0.003 ...                0                0
    
    [5 rows x 136 columns]
    

    经过独热编码后,columns 已经扩充到了惊人的 136 列!

    之所以需对数据进行独热编码,还有一个原因是在训练时,独热编码在分类是 0 和 1 的关系,而如果用 1,2,3,… 的分类标签方式,是不利于梯度下降的,计算出的梯度往往比较大。

    对 Date、Transaction,可以看到表格中,CoorChice 还对他们进行缩小,目的是为了把数值范围变小,这样有利于梯度下降的求解。

    我们看看现在数据的分布情况:

    image

    打乱数据

    接下来,我们需要将元素的有序的数据进行打乱,这样有助于提高训练出来的模型的泛化能力。

    ont_hot_data = ont_hot_data.sample(frac=1, replace=False)
    ont_hot_data = ont_hot_data.sample(frac=1, replace=False)
    ont_hot_data = ont_hot_data.sample(frac=1, replace=False)
    

    一遍不够,要打乱 3 遍!

    image

    看 Date 一列,说明数据已经被打的足够乱了。

    保存数据

    最后,我们要把处理好的数据分为训练集和测试集,CoorChice 按大概 30% 取测试集数据,然后分别保存。

    # 测试数据集大小
    test_count = 6000
    train_count = ont_hot_data.shape[0] - test_count
    # 切割出训练数据集
    train_data = ont_hot_data[:train_count]
    # 切割出测试数据集
    test_data = ont_hot_data[train_count:]
    # 分别保存两个数据集
    train_data.to_csv('data/train_data.csv', index=False, header=True)
    test_data.to_csv('data/test_data.csv', index=False, header=True)
    

    保存处理好的数据很简单,使用 Pandas 提供的 to_csv() 就可以把数据存 csv 格式。

    index 和 header 分别表示是否保存行号和列名称。

    image

    现在,我们已经把原始数据处理好,并且分割成了训练集和测试集。我们有 15,293 条训练数据,和 6000 条测试数据。

    开始训练吧!

    在开始之前,建议先看一看这一篇 《【Get】用深度学习识别手写数字》 ,因为套路基本上是一样的,只是有的地方需要根据具体情况调整。

    在手写数字识别中,我们构建的是一个简单 4 层网络,它由两个卷积层,一个全链接层和一个输出层组成。

    image_graph

    回顾一下这个网络结构。

    发生了欠拟合!

    一开始,CoorChice 直接使用了这个网络进行训练,经过 10w 次的漫长训练之后发现,准确率最高不过 0.1%。

    起初 CoorChice 减小 lr(学习率),想着可能是学习率过大,导致震荡了。然而,毫无作用。

    出现这种现象,基本可以判断大概率上是发生欠拟合了。

    发生欠拟合,可以通过以下步骤一步步的排除问题和改进网络。

    使用适合的权重初始化方案

    本次训练中,权重的初始化沿用了上次的正太分布初始化方案,应该是比较优秀的方案了,所以就不做改动了。

    image_truncated

    选择适当的激活函数

    在上一次的网络构建中,卷积层、全链接层都用的是 ReLu 激活函数,输出层使用的是 Softmax 激活函数。而这次 CoorChice 把激活函数全换成了优秀的 ReLu 激活函数,这应该也是没毛病的。

    image

    选择适合的优化器和学习率

    image

    这是一张各种优化器的比较图,从图中可以看到,有一个名叫 Adadelta 的优化器表现十分亮眼啊!

    Adadelta 是一种自适应的优化器,它能够自动的计算自变量更新量的平方的指数加权移动的平均项来作为学习率。因此,我们设置的学习率实际上影响已经不是太大了。

    从图中可以看到,这种优化器在训练之初和中期又能够快速下降,只不过到接近最优解的时候会出现小幅震荡。而 SGD 因全程都保持一个学习率,所以在设置合适的情况下,在最优解附近收敛的更干脆。

    # 使用 Adadelta 进行损失函数的梯度下降求解
    train_step = tf.train.AdadeltaOptimizer(0.0001).minimize(cross_entropy)
    

    但由于 Adadelta 实际训练过程中与我们起初告诉它的学习率关系不大,就是不受控,训练起来到后面还是很难受的,所以 CoorChice 尝试之后还是选择换成 SGD 。

    lr = tf.Variable(1e-5)
    # 使用 SGD 进行损失函数的梯度下降求解
    train_step = tf.train.GradientDescentOptimizer(lr).minimize(cross_entropy)
    

    而且,CoorChice 使用了一个变量 lr 来设置优化器的学习率,这样在训练过程中,我们还可以动态的额控制当前的学习率。

    增加网络深度、宽度

    当发生欠拟合时,也有可能是网络过于简单,权重太少,导致无法学习到足够的信息。在本次训练中,CoorChice 仍然使用了上次的 4 层单核网络,似乎确实是太简单了。

    那就加强它吧。

     # coding=utf-8
    from cnn_utils import *
    
    
    class CnnBreadBasketNetwork:
        def __init__(self):
            with tf.name_scope("input"):
                self.x_data = tf.placeholder(tf.float32, shape=[None, 135], name='x_data')
                # 补位
                input_data = tf.pad(self.x_data, [[0, 0], [0, 1]], 'CONSTANT')
                with tf.name_scope("input_reshape"):
                    # 变形为可以和卷积核卷积的张量
                    input_data = tf.reshape(input_data, [-1, 17, 8, 1])
                    tf.summary.image("input", input_data, 1)
                self.y_data = tf.placeholder(tf.float32, shape=[None], name='y_data')
    
            # ------------------------构建第一层网络---------------------
            with tf.name_scope("hidden1"):
                # 第一个卷积
                with tf.name_scope("weights1"):
                    W_conv11 = weight_variable([3, 3, 1, 64])
                    variable_summaries(W_conv11, "W_conv11")
                with tf.name_scope("biases1"):
                    b_conv11 = bias_variable([64])
                    variable_summaries(b_conv11, "b_conv11")
                h_conv11 = tf.nn.relu(conv2(input_data, W_conv11) + b_conv11)
                tf.summary.histogram('activations_h_conv11', h_conv11)
                # 第二个卷积
                with tf.name_scope("weights2"):
                    W_conv12 = weight_variable([3, 3, 64, 64])
                    variable_summaries(W_conv12, "W_conv12")
                with tf.name_scope("biases2"):
                    b_conv12 = bias_variable([64])
                    variable_summaries(b_conv12, "b_conv12")
                h_conv12 = tf.nn.relu(conv2(h_conv11, W_conv12) + b_conv12)
                tf.summary.histogram('activations_h_conv11', h_conv12)
                # 池化
                h_pool1 = max_pool_2x2(h_conv12)
                tf.summary.histogram('pools_h_pool1', h_pool1)
    
            # ------------------------构建第二层网络---------------------
            with tf.name_scope("hidden2"):
                # 第一个卷积核
                with tf.name_scope("weights1"):
                    W_conv21 = weight_variable([3, 3, 64, 128])
                    variable_summaries(W_conv21, 'W_conv21')
                with tf.name_scope("biases1"):
                    b_conv21 = bias_variable([128])
                    variable_summaries(b_conv21, 'b_conv21')
                h_conv21 = tf.nn.relu(conv2(h_pool1, W_conv21) + b_conv21)
                tf.summary.histogram('activations_h_conv21', h_conv21)
                # 第二个卷积核
                with tf.name_scope("weights2"):
                    W_conv22 = weight_variable([3, 3, 128, 128])
                    variable_summaries(W_conv22, 'W_conv22')
                with tf.name_scope("biases2"):
                    b_conv22 = bias_variable([128])
                    variable_summaries(b_conv22, 'b_conv22')
                h_conv22 = tf.nn.relu(conv2(h_conv21, W_conv22) + b_conv22)
                tf.summary.histogram('activations_h_conv22', h_conv22)
                # 池化
                self.h_pool2 = max_pool_2x2(h_conv22)
                tf.summary.histogram('pools_h_pool2', self.h_pool2)
    
            shape_0 = self.h_pool2.get_shape()[1].value
            shape_1 = self.h_pool2.get_shape()[2].value
            h_pool2_flat = tf.reshape(self.h_pool2, [-1, shape_0 * shape_1 * 128])
    
            # ------------------------ 构建第一层全链接层 ---------------------
            with tf.name_scope("fc1"):
                with tf.name_scope("weights"):
                    W_fc1 = weight_variable([shape_0 * shape_1 * 128, 4096])
                    variable_summaries(W_fc1, 'W_fc1')
                with tf.name_scope("biases"):
                    b_fc1 = bias_variable([4096])
                    variable_summaries(b_fc1, 'b_fc1')
                h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
                tf.summary.histogram('activations_h_fc1', h_fc1)
    
    
            # ------------------------构建输出层---------------------
            with tf.name_scope("output"):
                with tf.name_scope("weights"):
                    W_out = weight_variable([4096, 1])
                    variable_summaries(W_out, 'W_out')
                with tf.name_scope("biases"):
                    b_out = bias_variable([1])
                    variable_summaries(b_out, 'b_out')
                # 注意⚠️,此处的激活函数已经替换成 ReLu 了
                self.y_conv = tf.nn.relu(tf.matmul(h_fc1, W_out) + b_out)
                tf.summary.histogram('activations_y_conv', self.y_conv)
    
    

    这就是经过改进后的网络的全部代码了。

    可以看到,还是熟悉的套路。以下是版本更新内容:

    • 每个卷积核的 size 由 5x5 变成了 3x3

    • 第一个卷积层的卷积核通道数由原来的 32 增加到了 64。将卷积核数量提高一倍。

    • 卷积核层数仍然是两层,但每层都多增加了一个卷积核组。

    • 全链接层的神经元个数由原来的 1024 个增加至 4096 个。

    再说一下网络中的一些变化。

    self.x_data = tf.placeholder(tf.float32, shape=[None, 135], name='x_data')
        # 补位
    input_data = tf.pad(self.x_data, [[0, 0], [0, 1]], 'CONSTANT')
        # 变形为可以和卷积核卷积的张量
    input_data = tf.reshape(input_data, [-1, 17, 8, 1])
    self.y_data = tf.placeholder(tf.float32, shape=[None], name='y_data')
    

    定义占位的时候,由于表格数据中只有 135 列,所以先定义一个 shape 为 [None,135] 的占位。但是比较尴尬的是,135 是一个奇数,无法转换成能和卷积核卷积的张量,所以 CoorChice 给它补了一列,通过 tensorflow 提供的 pad() 函数。

    input_data = tf.pad(self.x_data, [[0, 0], [0, 1]], 'CONSTANT')
    

    第二个参数中的数字分别表示需要在原张量的 上、下、左、右 补充多少行或列。这里 CoorChice 再原张量的右边补充了一列 0。

    现在,就可以变形成可和卷积核卷积的张量了。

    input_data = tf.reshape(input_data, [-1, 17, 8, 1])
    
    • **小技巧:**通常,经过多层的卷积和池化之后,进入第一层全链接层或者直接进入输出层的时候,我们需要知道上一层的形状是怎样的,然后才能设计全链接层或者输出层的权重形状。可以通过如下方式方便的获得输入的形状:
    # 获得最后一个池化层的宽
    shape_0 = self.h_pool2.get_shape()[1].value
    # 获得最后一个池化层的高
    shape_1 = self.h_pool2.get_shape()[2].value
    
    # 变形为全链接层可乘的形状
    h_pool2_flat = tf.reshape(self.h_pool2, [-1, shape_0 * shape_1 * 128])
    

    实际上,这个网络可能不是太好,深度不够,可能导致准确率不够。但受设备限制,设计的太深,会导致每次训练都会花费大量的时间,所以 CoorChice 就尽量精简一点,主要看这个过程是怎样进行的。

    这是新的网络结构:

    image

    看看局部的两组卷积 hidden 层:

    image

    开启训练!

    # coding=utf-8
    import time
    from cnn_model import *
    from BBDATA import *
    
    train_times = 20000
    base_path = ".../BreadBasket/"
    save_path = base_path + str(train_times) + "/"
    
    # 读取数据
    BBDATA = read_datas('data/')
    
    # 创建网络
    network = CnnBreadBasketNetwork()
    x_data = network.x_data
    y_data = network.y_data
    y_conv = network.y_conv
    keep_prob = network.keep_prob
    # ------------------------构建损失函数---------------------
    with tf.name_scope("cross_entropy"):
        # 创建正则化对象,此处使用的是 L2 范数
        regularization = tf.contrib.layers.l2_regularizer(scale=(5.0 / 500))
        # 应用正则化到参数集上
        reg_term = tf.contrib.layers.apply_regularization(regularization)
        # 在损失函数中加入正则化项
        cross_entropy = tf.reduce_mean(tf.square((y_conv - y_data))) + reg_term
        tf.scalar_summary('loss', cross_entropy)
    
    with tf.name_scope("train_step"):
        lr = tf.Variable(1e-5)
        # 使用 SGD 进行损失函数的梯度下降求解
        train_step = tf.train.GradientDescentOptimizer(lr).minimize(cross_entropy)
    
    # 记录平均差值
    with tf.name_scope("difference_value"):
        dv = tf.reduce_mean(tf.abs(y_conv - y_data))
        tf.scalar_summary('difference_value', cross_entropy)
    
    # ------------------------构建模型评估函数---------------------
    with tf.name_scope("accuracy"):
        with tf.name_scope("correct_prediction"):
            correct_prediction = tf.less_equal(tf.abs(y_conv - y_data), 0.5)
        with tf.name_scope("accuracy"):
            # 计算准确率
            accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    tf.scalar_summary('accuracy', accuracy)
    
    # 创建会话
    sess = tf.InteractiveSession()
    
    summary_merged = tf.merge_all_summaries()
    train_writer = tf.train.SummaryWriter(save_path + "graph/train", sess.graph)
    test_writer = tf.train.SummaryWriter(save_path + "graph/test")
    
    start_time = int(round(time.time() * 1000))
    
    # 初始化参数
    sess.run(tf.initialize_all_variables())
    
    global loss
    loss = 0
    global train_accuracy
    for i in range(train_times):
        # 从训练集中取出 200 个样本进行一波训练
        batch = BBDATA.train_data.batch(200)
    
        if i % 100 == 0:
            summary, train_accuracy, test_loss, dv_value = sess.run([summary_merged, accuracy, cross_entropy, dv],
                                               feed_dict={x_data: BBDATA.test_data.data, y_data: BBDATA.test_data.label, keep_prob: 1})
            test_writer.add_summary(summary, i)
            consume_time = int(round(time.time() * 1000)) - start_time
            print("当前共训练 " + str(i) + "次, 累计耗时:" + str(consume_time) + "ms,实时准确率为:%g" % (train_accuracy * 100.) + "%, "
                 + "当前误差均值:" + str(dv_value) + ", train_loss = " + str(loss) + ", test_loss = " + str(test_loss))
        if i % 1000 == 0:
            run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
            run_metadata = tf.RunMetadata()
            summary, _, loss = sess.run([summary_merged, train_step, cross_entropy],
                                  feed_dict={x_data: batch.data, y_data: batch.label, keep_prob: 0.6}, options=run_options,
                                  run_metadata=run_metadata)
            train_writer.add_run_metadata(run_metadata, str(i))
            train_writer.add_summary(summary, i)
        else:
            summary, _, loss = sess.run([summary_merged, train_step, cross_entropy],
                                  feed_dict={x_data: batch.data, y_data: batch.label, keep_prob: 0.6})
            train_writer.add_summary(summary, i)
    
        # 每训练 2000 次保存一次模型
        if i != 0 and i % 1000 == 0:
            test_accuracy, test_dv = sess.run([accuracy, dv], feed_dict={x_data: BBDATA.test_data.data, y_data: BBDATA.test_data.label, keep_prob: 1})
            save_model(base_path + str(i) + "_" + str(test_dv) + "/", sess, i)
    
    # 在测试集计算准确率
    summary, final_test_accuracy, test_dv = sess.run([summary_merged, accuracy, dv],
                                      feed_dict={x_data: BBDATA.test_data.data, y_data: BBDATA.test_data.label, keep_prob: 1})
    train_writer.add_summary(summary)
    print("测试集准确率:%g" % (final_test_accuracy * 100.) + "%, 误差均值:" + str(test_dv))
    
    print("训练完成!")
    train_writer.close()
    test_writer.close()
    # 保存模型
    save_model(save_path, sess, train_times)
    
    sess.close()
    

    这是完整的训练代码,基本上和 《【Get】用深度学习识别手写数字》 中是一样的。只不过 CoorChice 多加了一个 MAE 作为模型评估的指标。

    dv = tf.reduce_mean(tf.abs(y_conv - y_data))
    

    因为是进行回归预测,所以使用 MAE 均方方差来作为一个评估模型好坏的指标。平均绝对差越小,表明模型预测结果越接近于真实情况。

    此外,由于是做回归预测,所以之前分类使用的交叉熵损失函数就不是特别合适了,我们换成均方误差损失函数。

    image

    cross_entropy = tf.reduce_mean(tf.square((y_conv - y_data))) + reg_term
    

    需要注意的是:

    correct_prediction = tf.less_equal(tf.abs(y_conv - y_data), 0.5)
    

    评估模型现在不应该再是比较预测值和标签值是否相等了,在回归预测中,要做到模型能够预测出的值和真实值完全相等几乎是不可能的。我们把评估模型改造成绝对差 <500 即接受该预测结果,毕竟是在个人设备上跑,要达到比较高的精度还是很难的。

    loss 不下降了

    上面这段代码中,SGD 优化器的学习率变量实际上是 CoorChice 后来加上的。在此前,使用的固定的,但当 run 起来开始训练的时候,发现 loss 总在一个值很大,但范围很小的区间内波动,而且准确率也在小范围的波动,提升不上去。

    • 损失变化曲线

    image

    • 准确率变化曲线

    image

    此时的准确大概在 10.5% 附近徘徊开来,loss 趋势变化也不大。

    这说明训练基本处于停滞不前的状态了,但显然,我们的模型精度是不够的。出现这种情况可能是以下几种情况。

    陷入局部最优解

    image

    如图,在多特征的高维 loss 曲面中,可能存在很多 A 点旁边的小坑。当进入小坑的底部时,loss 的一阶导数也是为 0 的,就网上常常说的陷入了局部最优解中,而没有到真正的 Global Minima。

    实际上,上面代码中我们采取的 mini-patch 抽样进行训练,一定程度上也是能减小陷入局部最优解的情况的。因为可能这批样本陷入了局部最优中,下一批样本的波动又把你从坑里拽出来了。当然有的时候我们可能会看到 loss 反而增大了,也是因为这种方式导致的。

    骑在鞍点上

    image

    如图,在 loss 的曲面中,会有比局部最优坑还多的马鞍型曲面。

    image

    憨态可掬的?…

    当我们骑到马鞍上的鞍点是,此处的导数也是为0的,那么是真正的收敛了吗?不是的。看图中,我们在x轴方向上是极小值,但在y轴方向上是极大值。

    image

    如果落在这样正在进入鞍点的尴尬位置,那么你的训练就会看起来几乎毫无波动,走出这个区域需要花费很长的时间。

    幸运的是,通过适当增大学习率或者适当减小 batch,都有助于尽快逃离这个区域。

    无尽的平缓面

    image

    然后在 loss 曲面中,同时存在着如上图一样的大面积的平缓曲面,处于这些区域中的点,虽然导数不为 0 ,但值却及其的小,即使一遍又一遍的反复训练,仍然看起来几乎没有变化。

    可怕的是,我们无法分辨出是处于局部最优,还是处于马鞍区域,或者干脆就是在类平面上。

    如何处理?

    出现以上几种情况,都会导致看起来不学习的情况,特别是在性能有限的个人设备上。但我们还是有一些套路可以尽量减小这种情况的发生的。

    1. 检查数据。确保数据标签对应正常。

    2. 修改调整网络结构。尽量使用一些开源的大牛们产出的网络模型,如 VGG 系列。在它们的基础上修改大概率上比自己捣腾靠谱。

    3. 调整 batch 大小。batch过大导致训练时间过长,也容易进入局部最优或者马鞍区域。过小又回导致震荡比较剧烈,不容易找到最优解。

    4. 多尝试不同的参数初始化。如果足够幸运的话,没准初始化就落到了 Global Minima 的坑里去了。

    5. 动态学习率。一成不变的小的学习率当陷入局部最优时就算是掉坑里了,或者在平滑面上移动的特别慢。如果大了又容易错过最优解。所以像 Adam 这样动态的学习率优化器能一定程度上减少这些问题的发生。当然,我们也可以在 SGD 的基础上,根据 loss 的情况自己动态的增大学习率,在 loss 很大却不变的时候,在 loss 较小的时候减小学习率,避免错过最优解。

    通过 loss 大致的判断问题

    • train loss 不断下降,test loss不断下降,说明网络仍在学习;

    • train loss 不断下降,test loss趋于不变,说明网络过拟合;

    • train loss 趋于不变,test loss不断下降,说明数据集100%有问题;

    • train loss 趋于不变,test loss趋于不变,说明学习遇到瓶颈,需要减小学习率或批量数目;

    • train loss 不断上升,test loss不断上升,说明网络结构设计不当,训练超参数设置不当,数据集经过清洗等问题。

    通过 loss 可以大致的判断一些问题,上述规律可以最为参考,但不保证一定准确。

    总结

    最后,一张图做个总结:

    image

    • 抽出空余时间写文章分享需要动力,各位看官动动小手点个赞哈,信仰还是需要持续充值的?
    • CoorChice 一直在不定期的分享新的干货,想要上车只需进到 CoorChice的【个人主页】 点个关注就好了哦。
    展开全文
  • 在此数据集中,为求职者提供了位于不同地区的45家沃尔玛商店的...已知这些降价会影响销售,但是要预测受影响的部门和影响的范围具有挑战性。 stores.csv test.csv sampleSubmission.csv features.csv train.csv
  • BigMart销售预测 使用五种不同的算法来分析商品销售数据集。 建立模型以根据先前的销售历史预测商品出口销售
  • # # 数据分析 # In[59]: # 一般一起用才会管用,否则可能会显示混乱 get_ipython().run_line_magic('config', ZMQInteractiveShell.ast_node_interactivity='all') get_ipython().run_line_magic('pprint', '') # In...
  • 现提供本店最近1年至今的经营数据,包括如下字段: 商品:种类,定价和总销量 订单:订单id,会员信息,交易时间,交易门店id和订单中的商品数量 门店:门店名称,店长姓名,销售额目标 请协助该地区的营运负责人...

    业务背景

    3W咖啡店是一家连锁餐饮品牌,以咖啡(coffee)、冰品(ice cream)、软饮(soft drink)、茶(Tea)、美食(Pastry)等商品零售为主业,目前在北京有8家分店。现提供本店最近1年至今的经营数据,包括如下字段:

    • 商品:种类,定价和总销量
    • 订单:订单id,会员信息,交易时间,交易门店id和订单中的商品数量
    • 门店:门店名称,店长姓名,销售额目标

    在这里插入图片描述
    请协助该地区的营运负责人评估各门店的经营状况。你的任务是:

    • 设计一个表格,追踪各门店本月每日的销售额目标完成进度
    • 根据本月1~15号的销售数据,试预测各个门店本月是否能完成销售任务

    计算周权重和日权重指数

    首先观察历年全店销售额数据,按星期汇总后得到如下曲线图。可以看出,3W咖啡店的销售额呈现以周为单位变化的趋势,符合线下零售的特点。每周销售峰值出现在周四/周五,推测可能是由线下会员日促销活动引起的。据此,可以尝试使用权重指数分析法对各门店销售情况进行分析。

    在这里插入图片描述

    1. 数据清洗和特殊日期筛选

    对原始数据进行清洗(去重、一致化、异常值排除),然后按日期进行排序,并汇总各店每日销售数据得到企业的每日销售额。

    由于计算周权重指数时需要排除特殊日期(节假日),因此以国务院假日办公布的放假日期为准,制作假日表。
    在这里插入图片描述
    相应地,在销售数据大表中添加“假日标志”字段,可使用IF+COUNTIF查表判断当前日期是否为假日,公式如下

    IF(COUNTIF(假期表’!A:A,[@日期])=0,0,1)

    2. 计算周权重指数

    使用上一年(2019年)的销售数据计算周权重指数。将汇总后的企业销售数据除去节假日,然后以周为单位分别计算各星期数的平均销售额。取其中的最小值(6888.8)为基准,对应星期二的权重指数记为1.0;其余星期数对应的权重指数按下式计算:

    星期N的权重指数 = 星期N的周均销售额 / 星期二的周均销售额 × 1.0

    计算结果如下图所示(注意图中由于篇幅限制省略了第4~第50周数据),取各星期数对应的权重指数之和即为周权重指数(又称为企业标准),计算值为10.58。

    在这里插入图片描述

    3. 计算各分店的日权重指数

    考虑到分店的销售规律受时效性影响较大,因此取最近3个月数据(2020.6 - 2020.8)计算分店的日权重指数。同样地,首先利用假日表排除掉特殊日期的销售数据以免影响常规日期的销售规律,然后按周计算各星期数的平均销售额。

    各分店的日权重指数统一根据企业的周权重指数来导出,以便于数据的标准化应用,具体计算公式如下。

    分店日权重 = 星期N的销售额平均值 / 周平均销售额 × 企业周权重

    需要注意的是,由于过滤掉了节假日的销售数据,因此周平均销售额的值应取星期N销售额平均值之和,以确保日权重之和等于企业周权重。即

    周平均销售额 = ∑星期N的销售额平均值

    此外,可以使用数据透视表+筛选器来处理各门店的数据,提高工作效率:

    在这里插入图片描述
    最后将各门店的日权重计算结果汇总为一张表,以便于后续分析使用。

    在这里插入图片描述

    销售追踪与预测

    目标追踪是促进销售最大化的有力手段,而高质量的目标追踪离不开科学的销售目标设置和任务分解。结合各门店的月销售额目标数据和销售日权重值,可以将销售目标分解到日,按天追踪各分店的目标完成进度,并能据此预测当月的销售水平。

    月销售目标的分解

    销售目标的分解主要依据销售规律来进行,根据销售日权重指数占月权重值的比例将月度销售目标分解到日,计算式如下

    第n日销售目标 = 本月销售目标 ×(第n日权重指数 / ∑本月的日权重指数)

    这里需要注意,若当月有特殊日期,则相应日期的权重数据应当替换为特殊日期的日权重值。由于2020年9月份没有节假日和促销活动,因此本例中省略了特殊日期指标的计算,直接查找上述日权重计算表的结果代入公式即可。

    以西单店为例展示计算结果,如下图所示。西单店9月的销售目标为38353元,截至本月15号共销售19824.4元,每日销售目标的完成度主要分布在71%~129%之间,整体呈现上升趋势。

    在这里插入图片描述
    在这里插入图片描述

    月度销售额的预测

    在累积了一定本月销售数据的基础上(通常需要在10天以上),可以通过日权重指数预测当月的销售额。其原理是利用销售的周期性,假定每天的销售进度与本月历史销售目标完成度相同,从而根据目前实际达成的销售额,反求本月累计销售额,具体计算式如下

    n日累计销售额预测值 = ∑n日销售额 ÷ (∑n日权重指数 / ∑本月的日权重指数 )
    *式中,n>=10

    同样地,使用日权重指数计算月销售额的预测值时也需要考虑特殊日期的影响,将相应日期的权重数据替换为特殊日期的日权重值。另外,由于历史销售完成情况是一个累计值,因此需要每日更新预测值。

    仍以西单店为例,根据9月1-15日的销售数据预测当月的销售额。首先计算出1-15日的销售额合计值为19824.4元,截至15日的累计权重指数为22.5,本月权重指数之和为44.4(无特殊日期),代入计算式可得当月销售额预测值为39194.6元,有希望超额完成本月销售目标(38353元)。

    在这里插入图片描述
    为了提高计算效率,减少重复计算各门店数据的工作量,可以利用函数根据门店名称获取计算所需要的数据。本例中使用了SUMIFS从销售订单表中获取了日销售额数据,使用VLOOKUP从权重表中获取日权重值,使用OFFSET查找门店目标表中的月度目标销售额。通过数据有效性设置下拉列表,即可轻松查看各门店的日销售完成度与最新的月目标预测值。
    (此处有一张gif,待补)

    小结

    本文以连锁咖啡店销售数据为基础,采用权重指数法计算了企业的周权重指数以及各门店的日权重指数,并据此将各门店的月销售目标分解到日,实现了销售情况的实时追踪。同时,利用历史销售数据结合日权重指数进行了月度销售额的预测,有助于提升对各店运营状态的掌控。上述计算通过Excel数据透视表和函数完成,实现了各门店指标计算的模板化,减少了繁琐的重复计算,有利于提高工作效率以及线下门店的推广使用。

    展开全文
  • 基于数据挖掘的快消行业销售预测.pdf
  • 模块四 数据描述性分析 4.3.店铺销量趋势预测 一任务目标 完成对店铺销量趋势预测分析 二任务背景 对店铺商品销量趋势分析与...1已知羽绒服近四年各季度销量数据计划在2019年提高20%的销量预测出羽绒服2019年各季度的
  • matlab代码影响深度学习项目-时间序列数据预测(Matlab,LSTM) 作家:姜浩林 有组织的博客 韩文的“自述”发布位于以下地址。 项目主题 第一个主题是分析在线产品价格数据预测当前产品价格。 但是,由于与大量...
  • 基于数据挖掘算法的汽车销售预测模型的应用研究.pdf
  • 题目:有某服装实体店5.1~5.24每天的销售数据表,要求根据现有的销量数据预测接下来一星期,也就是5.25 ~ 5.30的销量,图表大致信息如下 此时需要用到Excel对按照时间序列进行的数据进行分析,使用到预测工作表,...
  • 若按照书上代码运行会出现如下报错(这是因为代码在截取数据时将属性值转为了矩阵): AttributeError: 'numpy.ndarray' object has no attribute 'columns' 解决办法: 方法一:添加代码:x=pd.DataFrame(x) 方法...
  • BigMart销售预测 BigMart销售数据集包含2013年销售数据,这些数据来自不同城市的10个不同网点的1559种产品。 以下项目的目标是建立一个回归模型,以预测下一年在10个不同的BigMart网点中每种1559产品的销售情况。 ...
  • 数据分析|销量预测模型

    万次阅读 多人点赞 2019-06-25 14:13:29
    一、什么是预测 ...我们主要来看下定量预测,因为最好还是数据说话。 4.1时间序列方法 (解释:对未来影响不同,权重也不同,离的近的权重大,离的远的权重小) (解释:这时候预测12月的...
  • 数据分析: kaggle比赛 - 销量预测

    千次阅读 2020-07-05 16:18:32
    继之前的Kaggle比赛实战记录,参考其他kaggler的经验,总结一篇数据分析,以作日后参考。 Part I: 数据读取 import pandas as pd import numpy as np import matplotlib.pylab as plt import seaborn as sns from...
  • 本文先将数据进行预处理得到实验数据, 然后着重分析朴素贝叶斯判别分析算法、 AdaBoost 算法以及随机森林算法在口红销量预测中的效果, 并在随机森林算法中进行模型优化。 通过实验结果表明总评价数、 价格和描述...
  • 某个地区的公路运量主要与该地区的人数、机动车数量和公路面积有关,已知该地区20年(1990-2009)的公路运量相关数据如下:样本数据较多,且已知影响数据的因素(三大因素:该地区的人数、机动车数量和公路面积),可...
  • 1. os 模块获取上一级目录的绝对地址 2. pands 读取 sqlite3 数据库中的数据 3. 用sklearn中的线性回归模型预测销售数据 4. pyecharts 绘制柱状图
  • 基于数据挖掘对电商促销活动的销量预测研究.pdf
  • bigmart销售数据

    2018-12-11 22:41:55
    著名的bigmart销售数据集。
  • 依据近十年的双色球与大乐透的销售数据,我们对数据进行了回归分析,并通过回归分析得到的数据分别对未来三年、五年以及十年的两种彩票的销售额进行了合理的预测。彩票的销售收入可用于国家的各种福利事业或者体育...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 73,046
精华内容 29,218
关键字:

预测销售数据

友情链接: scrambler.zip.zip