深度学习:基于Keras,使用长短期记忆神经网络模型LSTM和RMSProp优化算法进行销售预测分析

news2024/11/16 5:23:04

sales

前言

系列专栏:【机器学习:项目实战100+】【2024】✨︎
在本专栏中不仅包含一些适合初学者的最新机器学习项目,每个项目都处理一组不同的问题,包括监督和无监督学习、分类、回归和聚类,而且涉及创建深度学习模型、处理非结构化数据以及指导复杂的模型,如卷积神经网络、门控循环单元、大型语言模型和强化学习模型

预测是使用过去的值和许多其他因素来预测未来的值。在本文中,我们将使用 Keras 功能 API 创建一个销售预测模型。

目录

  • 1. 相关库和数据集
    • 1.1 相关库介绍
    • 1.2 数据集介绍
  • 2.数据处理
      • 2.2.1 数据预处理
      • 2.2.2 数据预处理
  • 3. 数据建模(LSTM)
    • 3.1 数据准备
    • 3.2 使用 RMSprop 编译模型
    • 3.3 拟合模型
    • 3.4 模型评估

1. 相关库和数据集

1.1 相关库介绍

Python 库使我们能够非常轻松地处理数据并使用一行代码执行典型和复杂的任务。

  • Pandas – 该库有助于以 2D 数组格式加载数据框,并具有多种功能,可一次性执行分析任务。
  • Numpy – Numpy 数组速度非常快,可以在很短的时间内执行大型计算。
  • Matplotlib/Seaborn – 此库用于绘制可视化效果,用于展现数据之间的相互关系。
  • Keras – 是一个由Python编写的开源人工神经网络库,可以作为Tensorflow、Microsoft-CNTK和Theano的高阶应用程序接口。
import pandas as pd                     # to extract data from dataset(.csv file)
import csv                              #used to read and write to csv files
import numpy as np                      #used to convert input into numpy arrays to be fed to the model
import matplotlib.pyplot as plt         #to plot/visualize sales data and sales forecasting
import tensorflow as tf                 # acts as the framework upon which this model is built
from tensorflow import keras            #defines layers and functions in the model
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense,LSTM,Flatten
from tensorflow.keras.layers import concatenate
#here the csv file has been copied into three lists to allow better availability
list_row,date,traffic = get_data('/home/abh/Documents/Python/Untitled Folder/Sales_dataset')

外部库的使用已经保持在最低限度,以提供一个更简单的界面,您可以用已经存在于已建立的库中的函数替换本教程中使用的函数。

1.2 数据集介绍

它使用过去的销售额、季节性、节日、经济状况等数据来确定当前或未来的销售额。所以,这个模型在提供了一定的输入后,会预测某一天的销售额。
5 年销售数据原始数据集:
在这里插入图片描述
2015 年 1 月至 2019 年 12 月的销售数据

如您所见,销售数据似乎每年都遵循类似的模式,峰值销售值似乎在 5 年的时间框架内随着时间的推移而增加。在这 5 年的时间框架内,前 4 年将用于训练模型,最后一年将用作测试集。现在,一些辅助函数用于处理数据集和创建所需形状和大小的输入。它们如下:

  1. get _ data–用于使用指向数据集位置的路径加载数据集。
  2. date _ to _ day–提供每天的日期。例如,2/2/16 是星期六,9/5/15 是星期一。
  3. date _ to _ enc–将数据编码成一个热点向量,这为模型提供了更好的学习机会。

这里无法解释这些函数和一些其他函数的所有属性,因为这会花费太多时间。

2.数据处理

首先,所有输入都经过预处理,以便机器能够理解。这是一个基于监督学习的线性回归模型,因此输出将与输入一起提供。然后,输入连同期望的输出一起被馈送到模型。该模型将绘制(学习)输入和输出之间的关系(函数)。然后,该函数或关系用于预测特定输入集的输出。在这种情况下,像日期和以前的销售额这样的输入参数被标记为输入,销售额被标记为输出。该模型将预测 0 到 1 之间的一个数字,因为 sigmoid 函数用于最后一层。这个输出可以乘以一个特定的数字(在这种情况下是最大销售额),这将是我们某一天对应的销售额。然后,该输出作为输入提供,以计算第二天的销售数据。这一系列步骤将持续到某一天到来。

2.2.1 数据预处理

最初,数据集只有两列:日期和流量(销售额)。

在添加不同的列并对值进行处理/标准化之后,数据包含了所有这些值。

  1. 日期
  2. 交通
  3. 假期与否
  4. 一天

所有这些参数都必须转换成机器可以理解的形式,这将使用下面的这个函数来完成。

它不是将日期、月份和年份作为一个单独的实体,而是被分成三个不同的输入。原因是这些输入中的年份参数在大多数情况下是相同的,这将导致模型变得自满,即它将开始过度拟合当前数据集。为了增加不同输入之间的可变性,日期和月份被分别标记。下面的函数转换()将创建六个列表,并向它们追加适当的输入。这就是 2015 年到 2019 年的编码
{2015:数组([1。, 0., 0., 0., 0.],dtype=float32),2016: array([0。, 1., 0., 0., 0.],dtype=float32),2017: array([0。, 0., 1., 0., 0.],dtype=float32),2018: array([0。, 0., 0., 1., 0.],dtype=float32),2019: array([0。, 0., 0., 0., 1.],dtype=float32)

每一个都是长度为 5 的 NumPy 数组,1 和 0 表示它的值

def conversion(week,days,months,years,list_row):
  #lists have been defined to hold different inputs
  inp_day = []
  inp_mon = []
  inp_year = []
  inp_week=[]
  inp_hol=[]
  out = []
  #converts the days of a week(monday,sunday,etc.) into one hot vectors and stores them as a dictionary
  week1 = number_to_one_hot(week)
  #list_row contains primary inputs
  for row in list_row:
        #Filter out date from list_row
        d = row[0]
        #the date was split into three values date, month and year.
        d_split=d.split('/')
        if d_split[2]==str(year_all[0]):
          #prevents use of the first year data to ensure each input contains previous year data as well.
          continue
        #encode the three parameters of date into one hot vectors using date_to_enc function.
        d1,m1,y1 = date_to_enc(d,days,months,years) #days, months and years and dictionaries containing the one hot encoding of each date,month and year.
        inp_day.append(d1) #append date into date input
        inp_mon.append(m1) #append month into month input
        inp_year.append(y1) #append year into year input
        week2 = week1[row[3]] #the day column from list_is converted into its one-hot representation and saved into week2 variable
        inp_week.append(week2)# it is now appended into week input.
        inp_hol.append([row[2]])#specifies whether the day is a holiday or not
        t1 = row[1] #row[1] contains the traffic/sales value for a specific date
        out.append(t1) #append t1(traffic value) into a list out
  return inp_day,inp_mon,inp_year,inp_week,inp_hol,out #all the processed inputs are returned

inp_day,inp_mon,inp_year,inp_week,inp_hol,out = conversion(week,days,months,years,list_train)
#all of the inputs must be converted into numpy arrays to be fed into the model
inp_day = np.array(inp_day)
inp_mon = np.array(inp_mon)
inp_year = np.array(inp_year)
inp_week = np.array(inp_week)
inp_hol = np.array(inp_hol)

我们现在将处理一些剩余的其他输入,使用所有这些参数背后的原因是为了提高模型的效率,您可以尝试移除或添加一些输入。

过去七天的销售数据被作为输入传递,以创建销售数据的趋势,这将使预测值不会完全随机。同样,前一年当天的销售数据也被提供。

以下函数(other_inputs)处理三个输入:

  • 过去七天的销售数据
  • 上一年同一天的销售数据
  • 季节性——季节性被添加到夏季销售等趋势中。

2.2.2 数据预处理

def other_inputs(season,list_row):
  #lists to hold all the inputs
  inp7=[]
  inp_prev=[]
  inp_sess=[]
  count=0 #count variable will be used to keep track of the index of current row in order to access the traffic values of past seven days.
  for row in list_row:
    ind = count
    count=count+1
    d = row[0] #date was copied to variable d
    d_split=d.split('/')
    if d_split[2]==str(year_all[0]):
      #preventing use of the first year in the data
      continue
    sess = cur_season(season,d) #assigning a season to to the current date
    inp_sess.append(sess) #appending sess variable to an input list
    t7=[] #temporary list to hold seven sales value
    t_prev=[] #temporary list to hold the previous year sales value
    t_prev.append(list_row[ind-365][1]) #accessing the sales value from one year back and appending them
    for j in range(0,7):
        t7.append(list_row[ind-j-1][1]) #appending the last seven days sales value
    inp7.append(t7)
    inp_prev.append(t_prev)
  return inp7,inp_prev,inp_sess

inp7,inp_prev,inp_sess = other_inputs(season,list_train)
inp7 = np.array(inp7)
inp7= inp7.reshape(inp7.shape[0],inp7.shape[1],1)
inp_prev = np.array(inp_prev)
inp_sess = np.array(inp_sess)

这么多输入背后的原因是,如果将所有这些组合成一个数组,它将具有不同长度的不同行或列。这样的数组不能作为输入。

将所有值线性排列在单个数组中会导致模型具有高损耗。

线性排列将导致模型一般化,因为连续输入之间的差异不会太大,这将导致有限的学习,降低模型的准确性。

3. 数据建模(LSTM)

3.1 数据准备

八个独立的输入被处理并连接成一个单独的层,并传递给模型。

最终输入如下:

  1. 日期
  2. 一天
  3. 前七天销售额
  4. 上一年的销售额
  5. 季节
  6. 假期与否

在这里的大部分图层中,我已经使用了 5 个单位作为输出形状,你可以进一步用它来实验,以提高模型的效率。

#an Input variable is made from every input array
input_day = Input(shape=(inp_day.shape[1],),name = 'input_day')
input_mon = Input(shape=(inp_mon.shape[1],),name = 'input_mon')
input_year = Input(shape=(inp_year.shape[1],),name = 'input_year')
input_week = Input(shape=(inp_week.shape[1],),name = 'input_week')
input_hol = Input(shape=(inp_hol.shape[1],),name = 'input_hol')
input_day7 = Input(shape=(inp7.shape[1],inp7.shape[2]),name = 'input_day7')
input_day_prev = Input(shape=(inp_prev.shape[1],),name = 'input_day_prev')
input_day_sess = Input(shape=(inp_sess.shape[1],),name = 'input_day_sess')
# The model is quite straight-forward, all inputs were inserted into a dense layer with 5 units and 'relu' as activation function
x1 = Dense(5, activation='relu')(input_day)
x2 = Dense(5, activation='relu')(input_mon)
x3 = Dense(5, activation='relu')(input_year)
x4 = Dense(5, activation='relu')(input_week)
x5 = Dense(5, activation='relu')(input_hol)
x_6 = Dense(5, activation='relu')(input_day7)
x__6 = LSTM(5,return_sequences=True)(x_6) # LSTM is used to remember the importance of each day from the seven days data
x6 = Flatten()(x__10) # done to make the shape compatible to other inputs as LSTM outputs a three dimensional tensor
x7 = Dense(5, activation='relu')(input_day_prev)
x8 = Dense(5, activation='relu')(input_day_sess)
c = concatenate([x1,x2,x3,x4,x5,x6,x7,x8]) # all inputs are concatenated into one
layer1 = Dense(64,activation='relu')(c)
outputs = Dense(1, activation='sigmoid')(layer1) # a single output is produced with value ranging between 0-1.
# now the model is initialized and created as well
model = Model(inputs=[input_day,input_mon,input_year,input_week,input_hol,input_day7,input_day_prev,input_day_sess], outputs=outputs)
model.summary() # used to draw a summary(diagram) of the model

模型

3.2 使用 RMSprop 编译模型

RMSprop 非常擅长处理随机分布,因此在这里使用它。

from tensorflow.keras.optimizers import RMSprop

model.compile(loss=['mean_squared_error'],
              optimizer = 'adam',
              metrics = ['acc'] #while accuracy is used as a metrics here it will remain zero as this is no classification model
              )                  # linear regression models are best gauged by their loss value

3.3 拟合模型

该模型现在将被输入和输出数据,这是最后一步,现在我们的模型将能够预测销售数据。

history = model.fit(
           x = [inp_day,inp_mon,inp_year,inp_week,inp_hol,inp7,inp_prev,inp_sess],
           y = out,
           batch_size=16,
           steps_per_epoch=50,
           epochs = 15,
           verbose=1,
           shuffle =False
           )
#all the inputs were fed into the model and the training was completed

拟合模型
现在,为了测试模型,input()接受输入并将其转换为适当的形式:

def input(date):
    d1,d2,d3 = date_to_enc(date,days,months,years)   #separate date into three parameters
    print('date=',date)
    d1 = np.array([d1])                        
    d2 = np.array([d2])
    d3 = np.array([d3])
    week1 = number_to_one_hot(week)        #defining one hot vector to encode days of a week
    week2 = week1[day[date]]
    week2=np.array([week2])
    //appeding a column for holiday(0-not holiday, 1- holiday)
    if date in holiday:
        h=1
        #print('holiday')
    else:
        h=0
        #print("no holiday")
    h = np.array([h])
    sess = cur_season(season,date)        #getting seasonality data from cur_season function
    sess = np.array([sess])                            
    return d1,d2,d3,week2,h,sess

预测销售数据不是我们来这里的目的,所以我们还是继续预测工作吧。

销售预测

定义预测 _ 测试功能,预测提供日期后一年的销售数据:

该功能的工作原理如下:

  • 需要输入一个日期来预测从一年前到上述日期的销售数据
  • 然后,我们访问前一年当天的销售数据和前 7 天的销售数据。
  • 然后,使用这些作为输入,预测新的值,然后在七天值中,第一天被移除,并且预测的输出被添加作为下一次预测的输入

我们要求预测到 2019 年 12 月 31 日为止的一年

  • 首先,记录了 2018 年 12 月 31 日(一年前)的日期,以及从(2018 年 12 月 25 日–2018 年 12 月 31 日)开始的七天销售
  • 然后收集一年前,即 2017 年 12 月 31 日的销售数据
  • 将这些数据作为其他数据的输入,预测第一个销售数据(即 1/1/2019)
  • 然后删除 2018 年 12 月 24 日的销售数据,添加 2019 年 1 月 1 日的预测销售额。如此循环,直到预测出 2019 年 12 月 31 日的销售数据。

所以,以前的输出作为输入。

def forecast_testing(date):
    maxj = max(traffic) # determines the maximum sales value in order to normalize or return the data to its original form
    out=[]
    count=-1
    ind=0
    for i in list_row:
        count =count+1
        if i[0]==date: #identify the index of the data in list
            ind = count
    t7=[]
    t_prev=[]
    t_prev.append(list_row[ind-365][1]) #previous year data
    # for the first input, sales data of last seven days will be taken from training data
    for j in range(0,7):
          t7.append(list_row[ind-j-365][1])
    result=[] # list to store the output and values
    count=0
    for i in list_date[ind-364:ind+2]:
        d1,d2,d3,week2,h,sess = input(i) # using input function to process input values into numpy arrays
        t_7 = np.array([t7]) # converting the data into a numpy array
        t_7 = t_7.reshape(1,7,1)
        # extracting and processing the previous year sales value
        t_prev=[]
        t_prev.append(list_row[ind-730+count][1])
        t_prev = np.array([t_prev])
        #predicting value for output
        y_out = model.predict([d1,d2,d3,week2,h,t_7,t_prev,sess])
        #output and multiply the max value to the output value to increase its range from 0-1
        print(y_out[0][0]*maxj)
        t7.pop(0) #delete the first value from the last seven days value
        t7.append(y_out[0][0]) # append the output as input for the seven days data
        result.append(y_out[0][0]*maxj) # append the output value to the result list
        count=count+1
    return result

运行预测测试功能,将返回包含该年所有销售数据的列表,结果=预测 _ 测试(’ 2019 年 12 月 31 日’,日期)

3.4 模型评估

预测值和实际值的图表,用于测试模型的性能

plt.plot(result,color='red',label='predicted')
plt.plot(test_sales,color='purple',label="actual")
plt.xlabel("Date")
plt.ylabel("Sales")
leg = plt.legend()
plt.show()

在这里插入图片描述
在这里插入图片描述
2019 年 1 月 1 日至 2019 年 12 月 31 日的实际值

在这里插入图片描述
预测值和实际值之间的比较

如你所见,预测值和实际值非常接近,这证明了我们模型的有效性。如果上述文章中有任何错误或改进的可能性,请随时在评论部分提及。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1643423.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot+vue课程作业成绩可视化大屏分析系统

教师的登录功能。 教师需要可以拥有每学期新增课程的功能。 新增的课程有作业成绩,考勤成绩,考试成绩,实验成绩,其中作业成绩是平时作业1到作业8的平均成绩,最后根据占比得出学期的总评成绩。(参考我发的表…

Shell编程debug

debug调试 debug方法 sh -x显示脚本执行过程set命令设置开始debug和结束debug的位置显示脚本某一部分执行过程,解决复杂脚本故障 示例: sh -x 显示脚本执行过程 set显示脚本的部分执行过程 set -x 开始调试,从这里开始显示脚本的详细执行过…

【C++】模板初阶:泛型编程的起点

💞💞 前言 hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页&#x…

day02-分布式事务

1.分布式事务问题 1.1.本地事务 本地事务,也就是传统的单机事务。在传统数据库事务中,必须要满足四个原则: 1.2.分布式事务 分布式事务,就是指不是在单个服务或单个数据库架构下,产生的事务,例如&#xf…

鸿蒙组件样式复用简介

鸿蒙组件样式复用简介 使用Style进行复用在Component内部复用在Component外部复用使用Extend复用指定类型组件Extend支持参数传递 使用Style进行复用 在页面开发过程中,会遇到多个组件都在使用相同的样式,这时候就要考虑是不是可以将相同的样式的进行复…

Python中的`return`语句详解

Python中的return语句详解 对于初学Python或任何编程语言的人来说,理解函数如何返回值是非常重要的。在Python中,return语句用于从函数中返回结果。本篇博客将详细介绍return语句的基本用法,以及如何在不同情境中有效使用它。 什么是return…

mac安装虚拟机linux系统

需要下载的有:centos8镜像 , 虚拟器 VMware 软件包 , Termius 或者xshell 1. CentOS系统下载 linux系统一般有: CentOS、ubuntu、redhat,选择一种进行安装就可以 CentOS 2024 年开始停止维护和发布 CentOS8的下载与安装(windows下安装) 镜…

cloudreve离线下载报错Insufficient capacity

报错内容: [Warning] 2024-05-03 22:57:40 Failed to update status of download task "c0xxxxxxxxx749": Insufficient capacity 使用motrix作为离线程序,报错后,会自动暂停下载 报错原因: 初始容量只有1G&#xff0c…

算法提高之潜水员

算法提高之潜水员 核心思想&#xff1a;二维01背包 两个容量v1v2注意状态计算时j和p可以<各自的v #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 1010,M 80,K 22;int f[K][M];int k,V1,V2;int main(){ci…

中国真实婚恋相亲服务平台有哪些?分享7款专注相亲交友的脱单软件平台

终于脱单了&#xff0c;盘点一下&#xff0c;我都有用过哪些脱单App&#xff5e; 第一个&#xff0c;珍爱网&#xff0c;作为老牌相亲软件&#xff0c;拥有线上和线下门店服务&#xff0c;海量会员。优点&#xff1a;资源多&#xff0c;软件使用界面整洁干净&#xff0c;设计人…

关于 Vue.js 双向数据绑定基本实现认知

写在前面 很早的一篇博客&#xff0c;整理了部分&#xff0c;蹭假期整理完博文内容涉及:双向数据绑定 实现方式简单介绍基于发布订阅、数据劫持的双向数据绑定两种不同实现(ES5/ES6) Demo&#xff0c;以及代码简单分析Object.defineProperty && Proxy API 介绍以及特性…

Web API之BOM

BOM 一、window的常见事件1.窗口加载事件2. 调节窗口大小事件 二、定时器1.setTimeout( , )2.setInterval()3.发送短信例子4.this指向问题 三、js执行机制四、location对象1.常见属性2.例子、3.常见方法 五、navigator对象六、history对象 简介&#xff1a; BOM是浏览器对象模型…

python数据分析中数据可视化简单入门

1.折线图表 首先引入相关包pyecharts&#xff0c;如果没下载可以先下载 pip install pyecharts from pyecharts.charts import Lineline Line() # 添加x轴 line.add_xaxis([呱了个呱,羊村,牟多,蜂地,喵帕斯]) # 添加y轴 line.add_yaxis("GDP",[50,30,40,34,63,22])…

我发现不少培训班的就业辅导老师,简直是面试官的卧底——再论培训班学员的就业方式(java方向)

本人知乎账号同公众号&#xff1a;老胡聊Java&#xff0c;欢迎留言并咨询 我最近在帮一些朋友做java方面的就业辅导&#xff0c;其中有些朋友是经过培训班加持后入行java的。由于我本人做过一些大厂和外企的java技术面试官&#xff0c;我发现其中一些朋友的简历甚至根本没法通过…

基于Spring Boot的学生在线答疑系统设计与实现

基于Spring Boot的学生在线答疑系统设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 管理员登录界面 教师登陆界面 问题发布信息界面&am…

word中取消分页符或分段符前后的空格

在Word中&#xff0c;有时候&#xff0c;我们添加分页符后&#xff0c;从分页符后面的文字就全部掉到了下一页&#xff0c;那么如何避免呢&#xff1f; 选择word选项--高级&#xff0c;然后下滑到下面&#xff0c;将“取消分页符或分段符前后的空格”选中&#xff0c;如下图所…

Java:Map和Set

一、搜索树 在真正学习Map和Set之前&#xff0c;我们有必要先来了解一种树型结构&#xff1a;二叉搜索树&#xff01; 1、概念 二叉搜索树又被称为【二叉排序树】&#xff0c;顾名思义&#xff0c;这是一颗排好序的树&#xff01;它或者是一颗空树&#xff0c;或者是具有以下性…

未来人类文明的可持续发展

未来人类文明若要实现永远延续,建立一个演化模型确实是一个有远见的想法。演化模型可以帮助我们预测和规划未来,从而更好地应对可能出现的挑战。以下是对这个想法的展开论述: 建立演化模型:首先,我们需要收集当前节点的人类文明数据,包括科技、经济、政治、文化、环境等方…

C语言【文件操作】(1)

文章目录 1.为什么使用文件2.文件是什么&#xff1f;2.1程序文件2.2数据文件 3.二进制文件和文本文件4.文件的打开和关闭4.1流和标准流流标准流 4.2文件指针4.3文件的打开和关闭 结语 1.为什么使用文件 很简单 长久的存储数据 如果没有文件&#xff0c;我们写程序所产生的数据…

【Docker】如何注册Hub账号并上传镜像到Hub仓库

一、创建Hub账户 浏览器访问&#xff1a;hub.docker.com 点击【Sign up】注册账号 输入【邮箱】【用户名】【密码】 ps&#xff1a;用户名要有字母数字&#xff1b;订阅不用勾选 点击【Sign up】注册即可 点击【Sign in】登录账号 输入【邮箱】【密码】 点击【Continue】登录 二…