最不靠谱的 Python 预测:今年双十一的销量是 6213 亿元

x33g5p2x  于2021-11-13 转载在 Python  
字(5.6k)|赞(0)|评价(0)|浏览(395)

不知不觉,双十一到今年已经是13个年头,每年大家都在满心期待看着屏幕上的数字跳动,年年打破记录。而 2019 年的天猫双11的销售额却被一位微博网友提前7个月用数据拟合的方法预测出来了。他的预测值是2675.37或者2689.00亿元,而实际成交额是2684亿元。只差了5亿元,误差率只有千分之一。

但如果你用同样的方法去做预测2020年的时候,发现预测是3282亿,实际却到了 4982亿。原来2020改了规则,实际上统计的是11月1到11日的销量,理论上已经不能和历史数据合并预测,但咱们就为了图个乐,主要是为了练习一下 Python 的多项式回归和可视化绘图。

把预测先发出来:今年双十一的销量是 9029.688 亿元!坐等双十一,各位看官回来打我的脸。欢迎文末技术交流学习,喜欢点赞支持。

NO.1 统计历年双十一销量数据

从网上搜集来历年淘宝天猫双十一销售额数据,单位为亿元,利用 Pandas 整理成 Dataframe,又添加了一列’年份int’,留作后续的计算使用。

  1. import pandas as pd
  2. # 数据为网络收集,历年淘宝天猫双十一销售额数据,单位为亿元,仅做示范
  3. double11_sales = {'2009年': [0.50],
  4. '2010年':[9.36],
  5. '2011年':[34],
  6. '2012年':[191],
  7. '2013年':[350],
  8. '2014年':[571],
  9. '2015年':[912],
  10. '2016年':[1207],
  11. '2017年':[1682],
  12. '2018年':[2135],
  13. '2019年':[2684],
  14. '2020年':[4982],
  15. }
  16. df = pd.DataFrame(double11_sales).T.reset_index()
  17. df.rename(columns={'index':'年份',0:'销量'},inplace=True)
  18. df['年份int'] = [[i] for i in list(range(1,len(df['年份'])+1))]
  19. df
  1. .dataframe tbody tr th {
  2. vertical-align: top;
  3. }
  4. .dataframe thead th {
  5. text-align: right;
  6. }

NO.2 绘制散点图

利用 plotly 工具包,将年份对应销售量的散点图绘制出来,可以明显看到2020年的数据立马飙升。

  1. # 散点图
  2. import plotly as py
  3. import plotly.graph_objs as go
  4. import numpy as np
  5. year = df[:]['年份']
  6. sales = df['销量']
  7. trace = go.Scatter(
  8. x=year,
  9. y=sales,
  10. mode='markers'
  11. )
  12. data = [trace]
  13. layout = go.Layout(title='2009年-2020年天猫淘宝双十一历年销量')
  14. fig = go.Figure(data=data, layout=layout)
  15. fig.show()

NO.3引入 Scikit-Learn 库搭建模型

一元多次线性回归

我们先来回顾一下2009-2019年的数据多么美妙。先只选取2009-2019年的数据:

  1. df_2009_2019 = df[:-1]
  2. df_2009_2019
  1. .dataframe tbody tr th {
  2. vertical-align: top;
  3. }
  4. .dataframe thead th {
  5. text-align: right;
  6. }

通过以下代码生成二次项数据:

  1. from sklearn.preprocessing import PolynomialFeatures
  2. poly_reg = PolynomialFeatures(degree=2)
  3. X_ = poly_reg.fit_transform(list(df_2009_2019['年份int']))

1.第一行代码引入用于增加一个多次项内容的模块 PolynomialFeatures

2.第二行代码设置最高次项为二次项,为生成二次项数据(x平方)做准备

3.第三行代码将原有的X转换为一个新的二维数组X_,该二维数据包含新生成的二次项数据(x平方)和原有的一次项数据(x)

X_ 的内容为下方代码所示的一个二维数组,其中第一列数据为常数项(其实就是X的0次方),没有特殊含义,对分析结果不会产生影响;第二列数据为原有的一次项数据(x);第三列数据为新生成的二次项数据(x的平方)。

  1. X_
  1. array([[ 1., 1., 1.],
  2. [ 1., 2., 4.],
  3. [ 1., 3., 9.],
  4. [ 1., 4., 16.],
  5. [ 1., 5., 25.],
  6. [ 1., 6., 36.],
  7. [ 1., 7., 49.],
  8. [ 1., 8., 64.],
  9. [ 1., 9., 81.],
  10. [ 1., 10., 100.],
  11. [ 1., 11., 121.]])
  1. from sklearn.linear_model import LinearRegression
  2. regr = LinearRegression()
  3. regr.fit(X_,list(df_2009_2019['销量']))
  1. LinearRegression()

1.第一行代码从 Scikit-Learn 库引入线性回归的相关模块 LinearRegression;

2.第二行代码构造一个初始的线性回归模型并命名为 regr;

3.第三行代码用fit() 函数完成模型搭建,此时的regr就是一个搭建好的线性回归模型。

NO.4 模型预测
接下来就可以利用搭建好的模型 regr 来预测数据。加上自变量是12,那么使用 predict() 函数就能预测对应的因变量有,代码如下:

  1. XX_ = poly_reg.fit_transform([[12]])
  1. XX_
  1. array([[ 1., 12., 144.]])
  1. y = regr.predict(XX_)
  2. y
  1. array([3282.23478788])

这里我们就得到了如果按照这个趋势2009-2019的趋势预测2020的结果,就是3282,但实际却是4982亿,原因就是上文提到的合并计算了,金额一下子变大了,绘制成图,就是下面这样:

  1. # 散点图
  2. import plotly as py
  3. import plotly.graph_objs as go
  4. import numpy as np
  5. year = list(df['年份'])
  6. sales = df['销量']
  7. trace1 = go.Scatter(
  8. x=year,
  9. y=sales,
  10. mode='markers',
  11. name="实际销量" # 第一个图例名称
  12. )
  13. XX_ = poly_reg.fit_transform(list(df['年份int'])+[[13]])
  14. regr = LinearRegression()
  15. regr.fit(X_,list(df_2009_2019['销量']))
  16. trace2 = go.Scatter(
  17. x=list(df['年份']),
  18. y=regr.predict(XX_),
  19. mode='lines',
  20. name="拟合数据", # 第2个图例名称
  21. )
  22. data = [trace1,trace2]
  23. layout = go.Layout(title='天猫淘宝双十一历年销量',
  24. xaxis_title='年份',
  25. yaxis_title='销量')
  26. fig = go.Figure(data=data, layout=layout)
  27. fig.show()

NO.5 预测2021年的销量

既然数据发生了巨大的偏离,咱们也别深究了,就大力出奇迹。同样的方法,把2020年的真实数据纳入进来,二话不说拟合一样,看看会得到什么结果:

  1. from sklearn.preprocessing import PolynomialFeatures
  2. poly_reg = PolynomialFeatures(degree=5)
  3. X_ = poly_reg.fit_transform(list(df['年份int']))
  1. ## 预测2020年
  2. regr = LinearRegression()
  3. regr.fit(X_,list(df['销量']))
  1. LinearRegression()
  1. XXX_ = poly_reg.fit_transform(list(df['年份int'])+[[13]])
  1. # 散点图
  2. import plotly as py
  3. import plotly.graph_objs as go
  4. import numpy as np
  5. year = list(df['年份'])
  6. sales = df['销量']
  7. trace1 = go.Scatter(
  8. x=year+['2021年','2022年','2023年'],
  9. y=sales,
  10. mode='markers',
  11. name="实际销量" # 第一个图例名称
  12. )
  13. trace2 = go.Scatter(
  14. x=year+['2021年','2022年','2023年'],
  15. y=regr.predict(XXX_),
  16. mode='lines',
  17. name="预测销量" # 第一个图例名称
  18. )
  19. trace3 = go.Scatter(
  20. x=['2021年'],
  21. y=[regr.predict(XXX_)[-1]],
  22. mode='markers',
  23. name="2021年预测销量" # 第一个图例名称
  24. )
  25. data = [trace1,trace2,trace3]
  26. layout = go.Layout(title='天猫淘宝双十一历年销量',
  27. xaxis_title='年份',
  28. yaxis_title='销量')
  29. fig = go.Figure(data=data, layout=layout)
  30. fig.show()

NO.6多项式预测的次数到底如何选择

在选择模型中的次数方面,可以通过设置程序,循环计算各个次数下预测误差,然后再根据结果反选参数。

  1. df_new = df.copy()
  2. df_new['年份int'] = df['年份int'].apply(lambda x: x[0])
  3. df_new
  1. .dataframe tbody tr th {
  2. vertical-align: top;
  3. }
  4. .dataframe thead th {
  5. text-align: right;
  6. }

  1. # 多项式回归预测次数选择
  2. # 计算 m 次多项式回归预测结果的 MSE 评价指标并绘图
  3. from sklearn.pipeline import make_pipeline
  4. from sklearn.metrics import mean_squared_error
  5. train_df = df_new[:int(len(df)*0.95)]
  6. test_df = df_new[int(len(df)*0.5):]
  7. # 定义训练和测试使用的自变量和因变量
  8. train_x = train_df['年份int'].values
  9. train_y = train_df['销量'].values
  10. # print(train_x)
  11. test_x = test_df['年份int'].values
  12. test_y = test_df['销量'].values
  13. train_x = train_x.reshape(len(train_x),1)
  14. test_x = test_x.reshape(len(test_x),1)
  15. train_y = train_y.reshape(len(train_y),1)
  16. mse = [] # 用于存储各最高次多项式 MSE 值
  17. m = 1 # 初始 m 值
  18. m_max = 10 # 设定最高次数
  19. while m <= m_max:
  20. model = make_pipeline(PolynomialFeatures(m, include_bias=False), LinearRegression())
  21. model.fit(train_x, train_y) # 训练模型
  22. pre_y = model.predict(test_x) # 测试模型
  23. mse.append(mean_squared_error(test_y, pre_y.flatten())) # 计算 MSE
  24. m = m + 1
  25. print("MSE 计算结果: ", mse)
  26. # 绘图
  27. plt.plot([i for i in range(1, m_max + 1)], mse, 'r')
  28. plt.scatter([i for i in range(1, m_max + 1)], mse)
  29. # 绘制图名称等
  30. plt.title("MSE of m degree of polynomial regression")
  31. plt.xlabel("m")
  32. plt.ylabel("MSE")
  1. MSE 计算结果: [1088092.9621201046, 481951.27857828484, 478840.8575107471, 477235.9140442428, 484657.87153138855, 509758.1526412842, 344204.1969956556, 429874.9229308078, 8281846.231771571, 146298201.8473966]
  1. Text(0, 0.5, 'MSE')

从误差结果可以看到,次数取2到8误差基本稳定,没有明显的减少了,但其实你试试就知道,次数选择3的时候,预测的销量是6213亿元,次数选择5的时候,预测的销量是9029亿元,对于销售量来说,这个范围已经够大的了。我也就斗胆猜到9029亿元,我的胆量也就预测到这里了,破万亿就太夸张了,欢迎胆子大的同学留下你们的预测结果,让我们11月11日,拭目以待吧。

NO.7 总结最后

希望这篇文章带着对 Python 的多项式回归和 Plotly可视化绘图还不熟悉的同学一起练习一下。

技术交流

欢迎转载、收藏、有所收获点赞支持一下!

目前开通了技术交流群,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友

  • 方式①、发送如下图片至微信,长按识别,后台回复:加群;
  • 方式②、添加微信号:dkl88191,备注:来自CSDN
  • 方式③、微信搜索公众号:Python学习与数据挖掘,后台回复:加群

相关文章