Для решения задач анализа был разработан класс Аналитик, методы, необходимые, чтобы скрыть детали реализации системы, предоставить интерфейс функций, которые необходимы для получения информации.
UML - диаграмма класса представлена на рис. 3.4.
Рисунок 3.4 - UML-диаграмма класса Аналитик.
Функция прогнозирования вынесена в рамках отдельного модуля. Прогнозирование аукционует класс Forecaster. С модулем, доступно им класс Forecaster, можно ознакомиться в приложении D. UML диаграмма класса Forecaster доступен на рис. 3.5
Рисунок 3.5 - UML-диаграмма класса Forecaster.
Метод get_model генерирует множество моделей и сравнивает их с помощью AIC, присваивает модели, у которых AIC минимален. Код этого параметра отображается в листинге 7.
Листинг 7. Код метод аget_model.
defget_model (self):
p = d = q = диапазон (RANGE_LOW, RANGE_HIGH)
pdq = list (itertools. product (p, d, q))
сезонный = [(x [0], x [1], x [2], 12) для x в pdq]
aic = VERY_BIG_NUMBER
модель = {'pdq':(0,0,0), 'PDQs':(0,0,0,12)}
модель ['s'] = 12
для параметра в pdq:
для s_param в сезон:
пытаться:
mod = sm.tsa.statespace.SARIMAX (у,
порядок = пары,
seasonal_order = s_param,
|
|
enforce_stationarity = False,
enforce_invertibility = False)
результат = mod.fit ()
печать (result.aic)
ifresult.aic<aic:
печать(«ЛУЧШЕ»)
aic = result.aic
модель ['pdq'] = парам
модель ['PDQs'] = s_param
Кроме:
Продолжать
самостоятельно. модель = модель
returnmodel
Get_modelсоздает список значений параметров, обходит этот список, включает значения в модели, расчитывает AIC и сравнивает с ранее имеющимся минимальным значением.
Метод fit_model () разрешает обучить модель закономерностям базам данных на входе. Статистические свойства модели показаны в консоли. После подготовки модель готова для создания прогнозов.
Метод get_prediction () возвращает список прогнозированных значений. Это самый значительный метод класса Прогноз: он использует методы, которые подготавливают модель, вычисляет прогноз и доверительные интервалы.
На листинге 8 показано, как работает метод get_prediction ().
Листинг 8. Кодget_prediction ()
defget_prediction (self, data, start, as_ts = False):
fit = self.fit_model (данные)
печать (self.model)
pred = fit.get_forecast (steps = 10)
печать (pred.predicted_mean)
pred_ci = pred.conf_int ()
еслиas_ts:
return [{'date': start, 'total': pred}]
возврат (начало, пред, пред_ци)
Сначала вызывается метод fit_model, он вызывает дает метод get_ model. Прогнозируется на 20 дней вперед переменной pred.Доверительный интервал записывают в переменную pred_ci.
Тестовые данные
Информация о продажах является коммерческой тайной. Это создало необходимость генерировать данные самостоятельно.
За модуль тестовых данных отвечает на модуль mock.py. Использована следующая система:
1. В названии продукта есть имена из 4 латинских букв. Эти буквы показывают определенное свойство товара. Первая буква- в каком количестве покупается товар. Клиенты чаще покупают этот продукт. Второй - продаваемость товара, выраженная как вероятность покупки, третий - цена, четвертый - качество.
|
|
2. При вычислении вероятности покупки товара используются следующие оценки:
a. Для последних трех букв: MARK_WEIGHT_5 = {'A': 0,255, 'B': 0,240, 'C': 0,233, 'D': 0,200, 'E': 0,153}.
b. Для первой буквы: MARK_WEIGHT_2 = {'A': 0,6, 'B': 0,4,}.
c. Для категорий (см. CATEGORY_WEIGHTв приложении 1).
3. Формула для этой вероятности: p = fr * ca * (1-pr) * qu + a, где p – вероятность, ca – вес категории, pr – вес цены, qu – вес качества, a – случайная величина.
4. Количество посетителей и число покупателей - случайные числа с распределением Пуассона в окрестностях некоторой точки, которые назначены разработчиком из соображений личного опыта.
Полный код модуля mock.py отображен в приложении 1.
Вывод
Программное обеспечение было разработано для анализа и прогнозирования продаж в супермаркете. Были рассмотрены проблемы интерграции больших web-приложений, рассмотрены проблемы их интерграции библиотек и тщательно изучено решение поставленных задач.
Кроме того, были изучены некоторые аспекты анализа прогнозов с помощью линейных авторегрессионных моделей.
В работе рассмотрены в анализе безубыточности методы, которые используются чаще в анализе и прогнозировании продаж в зависимости от того, рассчитывается ли точки безубыточности по отношению к объему продаж в рублях или количеству продаваемых единиц. С развитием бизнеса-рынка методология прогнозирования продаж и прибыли усложняется. К новым формам управленческой отчетности добавляются показатели, позволяющие учитывать динамику рынка и ряд переменных факторов, существенно влияющих на стоимость товаров в рамках ценовой политики предприятия.
Разработка программного продукта: от внешнего вида до математических моделей прогнозирования. Реализованы спроектированные ранее модули и созданы проектируемое программное обеспечение. Была реализована поставленная задача.
Заключение
Программное обеспечение было разработано для анализа и прогнозирования продаж в супермаркетах. Были рассмотрены проблемы интеграции больших веб-приложений, рассмотрены проблемы их интеграции библиотек, а также было тщательно изучено их решение.
Кроме того, были изучены некоторые аспекты анализа прогнозов с помощью линейных авторегрессионных моделей.
В работе также рассмотрели в анализе безубыточности методы, которые используйся чаше в анализ прогрессирования продаж в зависимости от того, рассчитывается ли точка безубыточности по отношению к объему продаж в рублях или количеству продаваемых единиц. С развитием компетенций предпринимается и бизнес, методология прогнозирования продаж и прибыли существенно усложняется. Как правило, к новым формам управленческой отчетности добавляются показатели, позволяющие учитывать динамику рынка и ряд переменных факторов, существенно влияющих на стоимость товаров (работ, услуг) в рамках ценовой политики предприятия.
Список литературы
1. Kate, A. Smith. Neural Networks in Business: Techniques and Applications / A. Smith. Kate, N. D. Jatinder. – Лондон: Idea Group Publishing, 2002. – 272 c.
2. Django over view [Электронный ресурс]. – Режим доступа: https://www.django project.com/start/overview/, свободный. – Загл. с экрана.
3. How to Perform Sales Trend Analysis For Your Retail Business [Электронный ресурс]. – Режим доступа: https://www.nchannel.com/blog/how-to-perform-sales-trend-analysis/, свободный. – Загл. с экрана.
4. A Guide to Time Series Forecasting with ARIMA in Python 3 [Электронный ресурс]. – Режим доступа: https://www.digitalocean.com/community/tutorials/a-guide-to-time-series-forecasting-with-arima-in-python-3, свободный. – Загл. с экрана.
5. Stats Models Documentation [Электронный ресурс]. – Режим доступа:http://www.statsmodels.org/dev/index.html, свободный. – Загл. с экрана.
6. SARIMAX Analysis | Seasonal ARIMA Exogenous | Reference Manual | Num XL [Электронный ресурс]. – Режим доступа: http://www.spiderfinancial.com/support/documentation/numxl/reference-manual/arma-analysis/sarimax-analysis, свободный. – Загл. с экрана.
|
|
7. NumPyReference [Электронный ресурс]. – Режим доступа: https://docs.scipy.org/doc/numpy/reference/, свободный. – Загл. с экрана.
8. Стив, Макконнелл. Совершенный код. Мастер-класс / Макконнелл. Стив. – М.: "Русская редакция", 2010. – 889 c.
9. Sunil, Supra. Artificial Neural Networks: State of the Art in Business Intelligence / Supra. Sunil. // Business and Economics Journal. – 2016. – 7. –
С. 1-2.
10. Autoregressive integrated moving average - Wikipedia [Электронный ресурс]. – Режим доступа: https://en.wikipedia.org/wiki/Autoregressive_integrated_moving_average, свободный. – Загл. с экрана.
11. Akaike information criterion - Wikipedia [Электронный ресурс]. – Режим доступа: https://en.wikipedia.org/wiki/Akaike_information_criterion, свободный. – Загл. с экрана.
Приложения
Приложение А
fromcore.modelsimport *
fromdatetime import datetime, timedelta,date
import django.utils.timezone as tz
import random
from math import exp, pi,sqrt
from numpy.random import normal,standard_normal, poisson, ranf,sample,choice
#Constants
VISITORS_MEAN = 50
VISIT_TIME_MEAN = 18
HOURS_PER_DAY = 24
VISITOR_WANTS_TO_BUY_EDGE = 0.4
PRODUCTS_MEAN = 5
ITEMS_OBSERVED_MEAN = 12
ITEMS_BOUGHT_MEAN = 6
# Weights of categories
CATEGORY_WEIGHT = {
1:16/30,
2:20/30,
3:16/30,
4:12/30,
5:18/30,
6:14/30,
7:18/30,
8:13/30,
9:19/30,
10:13/30,
11:17/30,
12:10/30
}
MARK_WEIGHT_5 = {
'A': 0.255,
'B':0.245,
'C':0.233,
'D':0.204,
'E':0.153,
}
MARK_WEIGHT_2 = {
'A': 0.6,
'B': 0.4,
}
def get_probability_of_buying_product(product):
count, frequency, price, quality = tuple(product.name)
count_w = MARK_WEIGHT_2[count]
frequency_w = MARK_WEIGHT_5[frequency]
price_w = MARK_WEIGHT_5[price]
quality_w = MARK_WEIGHT_5[quality]
category_w = CATEGORY_WEIGHT[product.category.id]
return frequency_w*category_w*(1 - price_w)*quality_w+ranf(1)[0]
def create_product(signature,category):
"""
Create product with signature and price of given category
"""
costs_marks={'A':1000,'B':800,'C':600,'D':400,'E':200}
cost_price = costs_marks[signature[2]]
sale_price = cost_price*1.6
prod = Product.objects.create(name=signature, cost_price=cost_price, sale_price=sale_price,category = category)
print("Product creating: {0}%".format(Product.objects.all().count()/3000*100))
def create_products():
"""
Create some products with different names in different categories
"""
categories = Category.objects.all()
for q in ['A','B']:
#Q: A - is bought in single, B - clients prefer to buy a lot of this Product at once
for f in ['A','B','C','D','E']:
# f: Frequency(or popularity) A - popular; E - sometimes taken
for p in ['A','B','C','D','E']:
# p: Price; A - expensive; E - cheap
for qu in ['A','B','C','D','E']:
# qu: Quality: A - wow! E - nope;
for category in categories:
signature = q+f+p+qu
create_product(signature,category)
def imitate_clients_buying_stuff(date):
|
|
"""
Randomly chooses items to buy and their count
"""
order = Order.objects.create(date=tz.make_aware(date),total=0)
items_count = poisson(ITEMS_OBSERVED_MEAN,1)%Product.objects.all().count()
products = choice(Product.objects.all(),size=items_count)
ps_of_products = [get_probability_of_buying_product(x) for x in products]
scale = 1/sum(ps_of_products)
ps_of_products = list(map(lambda x:x*scale,ps_of_products))
basket = choice(products,size=ITEMS_BOUGHT_MEAN, p = ps_of_products)
for x in set(basket):
product_count = poisson(PRODUCTS_MEAN,1)
po = ProductsOrders.objects.create(order=order,product=x,count=product_count,total=x.get_revenue(product_count))
order.total+=po.total
order.save()
def time(year,month,day,hours):
"""
Produces datetime object with given parameters, but if hours has remainder, minutes are also obtained.
For example, 23.50 -> 23 hours and 30 minutes
"""
h = int(hours)
minutes = (hours-h)*60
return datetime(year=year, month=month,day=day,hour=h, minute=int(minutes))
def imitate_clients_entering_shop(dateFrom, dateTo):
"""
Populate database with information about client behavior
"""
time_cursor = dateFrom
days_between = (dateTo-dateFrom).days
while time_cursor<dateTo:
days_passed = (time_cursor-dateFrom).days
print('Populating...{0}%'.format(round(days_passed/days_between*100,2)))
# Let count of incomers be Poisson-distributed variable with mean VISITORS_MEAN
incomers = poisson(VISITORS_MEAN,1)
visit_times = normal(VISIT_TIME_MEAN,sqrt(HOURS_PER_DAY),incomers) # Times when visitor entered shop is normally distributed with mean at 18:00 and SD=sqrt(24)
for hour in visit_times:
day = time(time_cursor.year,time_cursor.month, time_cursor.day, hour%HOURS_PER_DAY)
Client.objects.create(date=tz.make_aware(day))
visitor_wants_to_buy = ranf(1) # Assume that visitor's intention to buy is normally distributed
shock = ranf(1) # Normally distributed error
visitor_buys = shock + visitor_wants_to_buy
if visitor_buys >= VISITOR_WANTS_TO_BUY_EDGE:
imitate_clients_buying_stuff(day)
time_cursor+=timedelta(days=1)
def populate(dateFrom,dateTo):
#create_products()
imitate_clients_entering_shop(dateFrom,dateTo)
return Client.objects.all().count()
d1 = date.today()-timedelta(days=365)
d2 = date.today()+timedelta(days=1)
print("Clients added: ",populate(d1,d2))
ПриложениеB
from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
import core.utils as utils
from django.db.models import Sum
from datetime import datetime, timedelta,date
# Constants
CHAR_FIELD_MAX_LENGTH = 40
TOP_SIZE = 10
# Create your models here.
PROFILING = False
DEBUG = True
from core.utils import Profiler
def prepare_date(dt):
return dt.strftime('%Y-%m-%d')
class Client(models.Model):
date = models.DateField(null=False, blank=False)
def __str__(self):
return 'Client entered at: '+self.date.__str__()
def get_total_incomers(dateframe):
clients = Client.objects.filter(date__range=utils.get_interval(date.today(),dateframe))
return clients.count()
def get_conversion(dateframe):
purchases = Order.get_orders(dateframe).count()
incomers = Client.get_total_incomers(dateframe)
if incomers ==0:
return 0
return round(purchases/incomers*100,2);
class Category(models.Model):
name = models.CharField(null=False, blank=False,max_length=CHAR_FIELD_MAX_LENGTH)
def __str__(self):
return self.name
def get_top_products(self, topsize, dateframe):
"""
Returns sorted list of bestseller products
"""
profiler = Profiler("Category.get_antitop_products")
profiler.start()
# Form query for dateframe
today = datetime.today()
result = ProductsOrders.objects.values('product').\
filter(order__date__range=utils.get_interval(today,dateframe)).\
filter(product__category=self).\
annotate(prod_count=Sum('count')).\
order_by('-prod_count')[:TOP_SIZE]
result = sorted(result,reverse=True,key=lambda item:item['prod_count'])
profiler.finish()
if PROFILING:
print(profiler.get_verbose())
return [{"name":Product.objects.get(id=x['product']).name, "count":x['prod_count']} for x in result]
def get_antitop_products(self, topsize, dateframe):
"""
Returns sorted list of worstseller products
"""
profiler = Profiler("Category.get_antitop_products")
profiler.start()
# Form query for dateframe
today = datetime.today()
date_query = {
'order__date__year':today.year,
}
if (dateframe == 'month'):
date_query['order__date__month'] = today.month
elif(dateframe=='day'):
date_query['order__date__month'] = today.month
date_query['order__date__day'] = today.day
result = ProductsOrders.objects.values('product').\
filter(**date_query).\
filter(product__category=self).\
annotate(prod_count=Sum('count')).\
order_by('prod_count')[:TOP_SIZE]
result = sorted(result,key=lambda item:item['prod_count'])
profiler.finish()
if PROFILING:
print(profiler.get_verbose())
return [{"name":Product.objects.get(id=x['product']).name, "count":x['prod_count']} for x in result]
class Product(models.Model):
sale_price = models.FloatField(null=False, blank=False) #Price which is used by clients
name = models.CharField(max_length=CHAR_FIELD_MAX_LENGTH, null=False, blank=False)
cost_price = models.FloatField(null=False, blank=False)
category = models.ForeignKey('Category', on_delete=models.CASCADE)
def __str__(self):
return self.name
def get_revenue(self,count):
return self.sale_price *count
def is_category(self, category):
return self.category==category
def get_total_for_day(self,dt):
tomorrow = utils.get_tomorrow()
yesterday = utils.get_yesterday()
pos = ProductsOrders.objects.filter(order__date__gt=yesterday,order__date__lt=tomorrow).\
filter(product=self).aggregate(Sum('total'))
return pos['total__sum']
class Order(models.Model):
date = models.DateField(null=False, blank=False)
total = models.FloatField(default=0)
def __str__(self):
return 'Order<'+self.date.__str__()+'>'
def recalculate_total(self):
self.total = self.productsorders_set.all().aggregate(Sum('total'))['total__sum']
self.save()
def get_orders(dateframe):
"""
Return orders for given dateframe
"""
orders = Order.objects.filter(date__range = utils.get_interval(date.today(),dateframe)) #Empty filterse
return orders
class ProductsOrders(models.Model):
order = models.ForeignKey('Order',on_delete=models.CASCADE)
product = models.ForeignKey('Product', on_delete=models.CASCADE)
count = models.IntegerField(null=False,blank=False)
total = models.FloatField(default=0)
def __str__(self):
return "<"+str(self.order.id)+":"+self.product.name+'-----'+str(self.count)+'>'
def recalculate_total(self):
self.total = self.product.get_revenue(self.count)
self.save()
def get_category_total(category,dateframe='day'):
"""
Returns total income in given dateframe for category
"""
profiler = Profiler("PRoductsOrders.get_category_total")
profiler.start()
today = date.today()
total = 0
pos = ProductsOrders.objects.filter(
product__category=category,
order__date__range=utils.get_interval(today,dateframe))
for pos_rec in pos:
total+=pos_rec.product.get_revenue(pos_rec.count)
profiler.finish()
if PROFILING:
print(profiler.get_verbose())
return total
def get_time_series(dateframe, product,full=False):
today = datetime.today()
if full:
pos = ProductsOrders.objects.all()
else:
pos = ProductsOrders.objects.filter(order__date__range=utils.get_interval(today,dateframe))
dates_total = pos.filter(product=product).\
values('order__date','total')
dates = {prepare_date(x['order__date']) for x in dates_total}
result = dict.fromkeys(dates,0)
for x in dates_total:
result[prepare_date(x['order__date'])]+=x['total']
result = sorted([{'date':x,'total':result[x]}for x in result.keys()],key=lambda x:x['date'])
return result
ПриложениеC
from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
import core.utils as utils
from django.db.models import Sum
from datetime import datetime, timedelta,date
# Constants
CHAR_FIELD_MAX_LENGTH = 40
TOP_SIZE = 10
# Create your models here.
PROFILING = False
DEBUG = True
from core.utils import Profiler
def prepare_date(dt):
return dt.strftime('%Y-%m-%d')
class Client(models.Model):
date = models.DateField(null=False, blank=False)
def __str__(self):
return 'Client entered at: '+self.date.__str__()
def get_total_incomers(dateframe):
clients = Client.objects.filter(date__range=utils.get_interval(date.today(),dateframe))
return clients.count()
def get_conversion(dateframe):
purchases = Order.get_orders(dateframe).count()
incomers = Client.get_total_incomers(dateframe)
if incomers ==0:
return 0
return round(purchases/incomers*100,2);
class Category(models.Model):
name = models.CharField(null=False, blank=False,max_length=CHAR_FIELD_MAX_LENGTH)
def __str__(self):
return self.name
def get_top_products(self, topsize, dateframe):
"""
Returns sorted list of bestseller products
"""
profiler = Profiler("Category.get_antitop_products")
profiler.start()
# Form query for dateframe
today = datetime.today()
result = ProductsOrders.objects.values('product').\
filter(order__date__range=utils.get_interval(today,dateframe)).\
filter(product__category=self).\
annotate(prod_count=Sum('count')).\
order_by('-prod_count')[:TOP_SIZE]
result = sorted(result,reverse=True,key=lambda item:item['prod_count'])
profiler.finish()
if PROFILING:
print(profiler.get_verbose())
return [{"name":Product.objects.get(id=x['product']).name, "count":x['prod_count']} for x in result]
def get_antitop_products(self, topsize, dateframe):
"""
Returns sorted list of worstseller products
"""
profiler = Profiler("Category.get_antitop_products")
profiler.start()
# Form query for dateframe
today = datetime.today()
date_query = {
'order__date__year':today.year,
}
if (dateframe == 'month'):
date_query['order__date__month'] = today.month
elif(dateframe=='day'):
date_query['order__date__month'] = today.month
date_query['order__date__day'] = today.day
result = ProductsOrders.objects.values('product').\
filter(**date_query).\
filter(product__category=self).\
annotate(prod_count=Sum('count')).\
order_by('prod_count')[:TOP_SIZE]
result = sorted(result,key=lambda item:item['prod_count'])
profiler.finish()
if PROFILING:
print(profiler.get_verbose())
return [{"name":Product.objects.get(id=x['product']).name, "count":x['prod_count']} for x in result]
class Product(models.Model):
sale_price = models.FloatField(null=False, blank=False) #Price which is used by clients
name = models.CharField(max_length=CHAR_FIELD_MAX_LENGTH, null=False, blank=False)
cost_price = models.FloatField(null=False, blank=False)
category = models.ForeignKey('Category', on_delete=models.CASCADE)
def __str__(self):
return self.name
def get_revenue(self,count):
return self.sale_price *count
def is_category(self, category):
return self.category==category
def get_total_for_day(self,dt):
tomorrow = utils.get_tomorrow()
yesterday = utils.get_yesterday()
pos = ProductsOrders.objects.filter(order__date__gt=yesterday,order__date__lt=tomorrow).\
filter(product=self).aggregate(Sum('total'))
return pos['total__sum']
class Order(models.Model):
date = models.DateField(null=False, blank=False)
total = models.FloatField(default=0)
def __str__(self):
return 'Order<'+self.date.__str__()+'>'
def recalculate_total(self):
self.total = self.productsorders_set.all().aggregate(Sum('total'))['total__sum']
self.save()
def get_orders(dateframe):
"""
Return orders for given dateframe
"""
orders = Order.objects.filter(date__range = utils.get_interval(date.today(),dateframe)) #Empty filterse
return orders
class ProductsOrders(models.Model):
order = models.ForeignKey('Order',on_delete=models.CASCADE)
product = models.ForeignKey('Product', on_delete=models.CASCADE)
count = models.IntegerField(null=False,blank=False)
total = models.FloatField(default=0)
def __str__(self):
return "<"+str(self.order.id)+":"+self.product.name+'-----'+str(self.count)+'>'
def recalculate_total(self):
self.total = self.product.get_revenue(self.count)
self.save()
def get_category_total(category,dateframe='day'):
"""
Returns total income in given dateframe for category
"""
profiler = Profiler("PRoductsOrders.get_category_total")
profiler.start()
today = date.today()
total = 0
pos = ProductsOrders.objects.filter(
product__category=category,
order__date__range=utils.get_interval(today,dateframe))
for pos_rec in pos:
total+=pos_rec.product.get_revenue(pos_rec.count)
profiler.finish()
if PROFILING:
print(profiler.get_verbose())
return total
def get_time_series(dateframe, product,full=False):
today = datetime.today()
if full:
pos = ProductsOrders.objects.all()
else:
pos = ProductsOrders.objects.filter(order__date__range=utils.get_interval(today,dateframe))
dates_total = pos.filter(product=product).\
values('order__date','total')
dates = {prepare_date(x['order__date']) for x in dates_total}
result = dict.fromkeys(dates,0)
for x in dates_total:
result[prepare_date(x['order__date'])]+=x['total']
result = sorted([{'date':x,'total':result[x]}for x in result.keys()],key=lambda x:x['date'])
return result
ПриложениеD
from core.models import *
# CONSTANT
RANGE_LOW = 0
RANGE_HIGH = 4
VERY_BIG_NUMBER = 10**1000
import pandas as pd
import itertools
import warnings
import statsmodels.api as sm
import matplotlib.pyplot as plt
import numpy as np
class Forecaster:
def get_dataframe(array):
"""Array = list of dict { date: value}"""
return pd.DataFrame(array)
model = None
def get_model(self,data):
p = d = q = range(RANGE_LOW, RANGE_HIGH)
pdq = list(itertools.product(p,d,q))
seasonal = [(x[0],x[1],x[2],12) for x in pdq]
model = {'pdq':(0,0,0),'PDQs':(0,0,0,12)}
model['s'] = 12
aic = 100*10000
for param in pdq:
for s_param in seasonal:
try:
mod = sm.tsa.statespace.SARIMAX(data,
order=param,
seasonal_order=s_param,
enforce_stationarity=False,
enforce_invertibility=False)
result = mod.fit()
print(result.aic)
if result.aic < aic:
print("BETTER")
aic = result.aic
model['pdq'] = param
model['PDQs'] = s_param
except TypeError:
continue
self.model = model
return model
def fit_model(self,data):
pd_data = Forecaster.get_dataframe(data)
pd_data = pd_data.set_index(['date'])
pd_data.index = pd.to_datetime(pd_data.index)
pd_data = pd_data.resample('MS').mean()
pd_data = pd_data.dropna()
print(pd_data)
pd_data = pd_data.fillna(pd_data.bfill())
print(pd_data)
self.get_model(data)
mod = sm.tsa.statespace.SARIMAX(pd_data['total'].astype(float),
order=self.model['pdq'],
seasonal_order=self.model['PDQs'],
enforce_stationarity=False,
enforce_invertibility=False)
result = mod.fit()
print(result.summary().tables[1])
#result.plot_diagnostics(figsize=(15,12))
#plt.show()
return result
def get_prediction(self,data,start,as_ts=False):
fit= self.fit_model(data)
print(self.model)
pred = fit.get_forecast(steps=10)
print(pred.predicted_mean)
pred_ci = pred.conf_int()
if as_ts:
return [{'date':start,'total':pred}]
return (start,pred,pred_ci)