Applicazioni pratiche di machine learning/Previsione di vendite future
Caricamento librerie[modifica]
library(dplyr)
library(gbm)
library(ggplot2)
Parte 1: Dati[modifica]
Avendo un set di dati temporali composto da vendite giornaliere,gentilmente fornito da una delle più grandi società di software russe - 1C Azienda (http://1c.ru/eng/title.htm) è possibile prevedere quali saranno le vendite future dell'azienda . Nel dataset sales_train ci sono 2.935.849 registrazioni giornaliere con 11 variabili a cui ne verranno aggiunte altre nei prossimi mesi. In tutto ci sono 60 negozi, 22170 articoli e 84 categorie.
Descrizioni dei files:
- sales_train.csv : Dati storici giornalieri da gennaio 2013 a ottobre 2015.
- items.csv - informazioni supplementari su articoli/prodotti.
- item_categories.csv - informazioni supplementari su categorie di articoli.
- shops.csv - informazioni supplementari sui negozi.
Variabili contenute nei datasets:
- ID : un ID che rappresenta un negozio o un articolo all'interno del set di dati
- shop_id : identificatore univoco di un negozio
- item_id : identificatore univoco di un prodotto
- item_category_id - identificatore univoco della categoria di articoli
- item_cnt_day - numero di prodotti venduti. Si vuole predire un valore mensile di questo dato
- item_price - prezzo corrente di un articolo
- data - data nel formato gg/mm/aaaa
- date_block_num - un numero di mese consecutivo, utilizzato per comodità. Gennaio 2013 è 0, febbraio 2013 è 1, ...,Ottobre 2015 è il 33
- item_name : nome dell'articolo
- name_shop : nome del negozio
- item_category_name - nome della categoria dell'articolo
Caricamento dei dati:
sales_train <- read.csv("sales_train_v2.csv")
items2 <-read.csv("items.csv")
items <- read.csv("items-translated.csv")
items <- cbind(items,item_category_id=items2$item_category_id)
shops <- read.csv("shops-translated.csv")
categories <- read.csv("item_categories-translated.csv")
items <- merge(items,categories, by =c("item_category_id"), all.x = TRUE)
sales_train <- merge(sales_train,items, by =c("item_id"), all.x = TRUE)
sales_train <- merge(sales_train,shops, by =c("shop_id"), all.x = TRUE)
Creazione di nuove variabili nel dataset :
#Creazione delle variabili: week_day, month , week_year
sales_train$date <- as.Date(sales_train$date,tryFormats=c("%d.%m.%Y"))
p <- as.POSIXlt(sales_train$date)
sales_train <- cbind(sales_train,week_day=p$wday +1)
sales_train <- cbind(sales_train,month=p$mon +1)
week_year<-as.numeric(strftime(p, format = "%V"))
sales_train <- cbind(sales_train,week_year)
'''#Creazione della variabile: Media delle vendite di ogni articolo per ogni mese
df1<-sales_train %>%'''
group_by(date_block_num,item_id) %>%
summarise(date_item_avg=mean(item_cnt_day))
sales_train <- merge(sales_train, as.data.frame(df1),
by=c("date_block_num","item_id"), all.x = TRUE)
'''#Creazione della variabile: Media delle vendite per categoria per ogni mese'''
df1<-sales_train %>%
group_by(date_block_num,shop_id, item_category_id) %>%
summarise(date_shop_cat_avg=mean(item_cnt_day))
sales_train <- merge(sales_train, as.data.frame(df1),
by=c("date_block_num","shop_id","item_category_id"), all.x =TRUE)
'''#Creazione variabile da predire item_cnt_month (vendite totali mensili)'''
df1<-sales_train %>%
group_by(date_block_num,week_year,week_day,shop_id,item_category_
id,item_id,item_price, date_item_avg, date_shop_cat_avg) %>%
summarise(item_cnt_month=sum(item_cnt_day))
sales_train <- merge(sales_train, as.data.frame(df1),
by=c("date_block_num","week_year","week_day","shop_id","item_category_id","item_id","item_price", "date_item_avg","date_shop_cat_avg"), all.x = TRUE)
E' possibile migliorare il modello aggiungendo nuove variabili e/o modificando il tuning degli iperparametri (DA FARE)
Parte 2: Domanda di ricerca[modifica]
Si vogliono predire le vendite totali per ogni prodotto e negozio nel prossimo mese disponibile (novembre 2015)
Parte 3: Esplorazione dei dati[modifica]
sales_train %>%
group_by(item_category_name_translated) %>%
summarise(total = sum( item_cnt_day)) %>%
filter(total>10000) %>%
mutate(item_category_name_translated=reorder(item_category_name_translated,total)) %>%
ggplot(aes(item_category_name_translated,total,fill=item_category_name_translated)) +
geom_bar(stat="identity")+
coord_flip()+
scale_y_continuous(breaks=seq(0,650000,80000))+
theme(legend.position = "none") +
xlab("Category") +
ylab("Total sales") +
ggtitle("Categories with total sales > 10000", subtitle = "from 2013/01 to 2015/09")




Parte 4: Modellizzazione[modifica]
Cancellazione degli outliers: Nelle variabili prezzo item_price e numero dei prodotti venduti item_cnt_day ci sono valori anomali, troppo grandi e rari che occorre cancellare :
sales_train %>%
ggplot(aes(item_id,item_price))+
geom_boxplot()
sales_train %>%
ggplot(aes(item_id,item_cnt_day))+
geom_boxplot()
sales_train <- sales_train[-which(sales_train$item_price>10000) ,]
sales_train <- sales_train[-which.max(sales_train$item_cnt_day) ,]
max(sales_train$item_price)
max(sales_train$item_cnt_day)


I dati per creare il modello previsionale sono quelli anteriori a ottobre 2015 e costituiscono il cosiddetto training set (date_block_num <33), mentre quelli relativi a ottobre 2015 (date_block_num = 33) costituiscono il validation set .
sales_validation <-
sales_train[which(sales_train$date_block_num==33),]
sales_train <- sales_train[which(sales_train$date_block_num<33),]
Per prevedere le vendite mensili totali a ottobre 2015 il pacchetto gbm adotta la strategia del gradiente stocastico, una piccola ma importante modifica dell'algoritmo di base.
gbm_model = gbm(item_cnt_month ~ shop_id + item_id +
item_category_id + date_block_num + item_price + week_day +
week_year + date_item_avg + date_shop_cat_avg , data=sales_train,
shrinkage = 0.01,
distribution = "gaussian",
n.trees = 1000,
interaction.depth = 5,
bag.fraction = 0.5,
train.fraction = 0.8,
# cv.folds = 5,
n.cores = -1,
verbose = T)
Parte 5: Previsione[modifica]
Dopo aver ottenuto il modello, è possibile prevedere le vendite totali mensili sia sul training set che sul validation set (ottobre 2015) e si può calcolare l'errore quadratico medio (RMSE) per valutare la correttezza della previsione.
p1 = predict(gbm_model,newdata = sales_train, n.trees = 1000)
print(paste("RMSE_train=",sqrt((1/nrow(sales_train))*sum((p1-
sales_train$item_cnt_month)^2))))
## [1] "RMSE_train= 1.74599536656872"
p1 = predict(gbm_model,newdata = sales_validation, n.trees =
1000)
rmse <-sqrt((1/nrow(sales_validation))*sum((p1-
sales_validation$item_cnt_month)^2))
print(paste("RMSE_validation=",rmse))
## [1] "RMSE_test= 3.70520797224124"
Inoltre è possibile rispondere alla domanda di ricerca prevedendo le vendite mensili sul testing set (November 2015):
p1 = predict(gbm_model,newdata = sales_test, n.trees = 1000)
sub2 = data.frame(ID = sales_test$ID,item_cnt_month =
write.csv(sub2, "submission.csv", row.names = F)