R Üzerinde Zaman Serisi Analizi Bölüm 1: Zaman Serisi Regresyonu

Selamlar, bu yazıyla birlikte blogda zaman serileri analizine dair bir yazı dizisi yayınlayacağım. Bu yazı dizisi 3 ya da 4 yazıdan oluşacak. Bu ilk yazıda, Ocak 1966 ve Ekim 1975 yılları arasında Boston’da aylık silahlı soygunların verisini inceleyerek, zaman serisi regresyonu metodu vasıtasıyla bir zaman serileri analizi gerçekleştireceğiz.

Verinin tanımını üstte yaptık. Zaman serisi verilerinde elimizdeki tek özellik zaman olduğundan, burada ne olduklarını açıklayabileceğimiz kolonlar bulunmuyor. Aslına bakarsanız zaman serisi verisi sadece ne zaman gözlemlendikleri bilinen sayılar kümesinden oluşan bir seridir. Bu gözlemlenme aşaması düzenli veya düzensiz aralıklarla olabilir. Farklı gözlem frekansları için farklı analiz metodları bulunmaktadır.

Veri ile alakalı gerekli bilgi ve indirme linki burada bulunabilir.

O zaman her zamanki gibi “csv” formatındaki veriyi R üzerine alarak başlayalım.

Data <- read.csv("MonthlyBostonArmedRobberies.csv",
                 stringsAsFactors = FALSE,
                 sep = ";")
nrow(Data)
ncol(Data)
head(Data, n = 10)

Veriyi yine "read.csv" komutu ile içeri aldık. Bu kez ayraç operatörü noktalı virgül olduğu için sep = ";" argümanı ile bunu belirttik. Sonrasında veriyi inceledik. Sonuca bakarsak:

1

Veri 118 satır ve 2 sütundan oluşuyor. Aşağıda gördüğümüz gibi sütunlar da değerin kaydedildiği ay ve değerin kendisinden oluşuyor.

Zaman serisi verisi ile çalışabilmek için öncelikle bu verinin bir zaman serisi olduğunu R’a tanıtmamız gerekiyor. Her ne kadar veri içerisinde değerler ve o değerlerin kaydedildiği zamanlar yer alsa da, R için bu verinin normal bir veri setinden farkı yok. Bu farkı R’a göstermek için, “ts(time series)” komutunu kullanacağız.

install.packages("fpp2")
library(fpp2)

Data_ts <- ts(data = Data$Value,
              start = c(1966, 01),
              end = c(1975, 10),
              frequency = 12)

İlk satırda zaman serisi analizi için içerisinde tüm araçları barındıran "fpp2" paketini indirdik ve "library" komutunu kullanarak da R içerisine çağırdık. Sonra, bir zaman serisi objesi olduğunun belli olması açısından "Data_ts" adlı bir obje yarattık ve buna "ts" komutu ile oluşturduğumuz veri setini atadık. Komutun argümanlarını inceleyecek olursak; ilk argüman hangi veriden zaman serisi oluşturmak istediğimizi belirtiyor. Dikkat edelim ki verinin tamamını bu argümana vermedik, sadece değerleri içeren kolonu verdik. Zaten diğer argümanları da atadığımızda, R bu değerlerin ne zaman başlayıp ne zaman bittiğini biliyor olacak. Verinin başlangıç tarihi 1966 Ocak ayı olduğundan, bunu "c(1966, 01)" olarak verdik. Bitiş tarihi de aynı şekilde 1975 yılının Ekim ayı. Son argüman ise frekans, yani verinin hangi sıklıkla gözlemlendiği. Kullandığımız "ts" komutu, bu frekansları varsayılan olarak 1 yıllık bir periyod üzerinden düşünür. Bizim veri setimiz de aylık gözlemlenen bir veri seti olduğundan, bir yıl içerisinde 12 gözlem barındırıyor. Yani frekans değeri 12.

Veri setinin şimdi nasıl göründüğüne bakacak olursak:

2

Görüleceği gibi veri artık çok daha düzenli bir biçimde ve tam bir zaman serisi halinde görüntülenebiliyor. “ts” komutu ile dönüşümü gerçekleştirdikten sonra, R veriyi bu şekilde düzenliyor.

Evet devam edelim. Zaman serisi verisini oluşturduktan sonra, yapılabilecek en doğru hareket bu veriyi bir grafiğe dökmek olacaktır. Böylece serinin neye benzediğini tam anlamıyla görmüş olacağız:

autoplot(Data_ts) +
  ggtitle("Boston Aylık Silahlı Soygun Verisi") +
  xlab("Ay") +
  ylab("Sayı")

“autoplot” komutu verinin grafiğe dökülmesini sağlıyor. Bu komut, otomatik olarak içerisine verilen nesneye uygun bir grafik bulmaya çalışır. Bizim verimiz de zaman serisi verisi olduğu için, tabii ki en uygun grafik çizgi olacaktır. Diğer fonksiyonlarla da grafik başlığını, x ve y eksenlerinin isimlerini ayarladık. Grafiği aşağıdaki gibi:

3

Grafiği incelemeye geçmeden önce, zaman serisi verilerinde çok görülen kavramlardan bahsedelim.

Trend: Trend, basitçe açıklamak gerekirse verideki uzun süreli iniş ya da çıkışlardır. Bu iniş veya çıkışlar doğrusal olmak zorunda değildir.

Mevsimsellik: Mevsimsellik, verinin mevsimsel faktörlerden etkilenmesi ile oluşur. Örneğin ayın belli bir günü, yılın belli bir ayı veya her yıl aynı zaman diliminde yapılan bir kutlama bile olabilir. Mevsimselliğin frekansı(oluşma sıklığı) sabittir.

Periyodik hareketler: Mevsimselliğin tersine, sabit frekansta gerçekleşmeyen iniş ya da çıkış hareketleridir. Süreleri genelde en az 2-2.5 yıl arasındadır. Bunlar mevsimsel etkilerden ziyade, ekonomik durumlar, krizler gibi olaylardan kaynaklanırlar.

Üstte de bahsettiğimiz gibi, mevsimsellik hareketlerinin frekansı sabitken periyodik hareketlerin sabit değildir. Ayrıca buradaki en önemli fark da, mevsimsellik oluşabilmesi için mevsimsel etkilerin olması, yani takvim ile alakalı bazı etkilerin söz konusu olması gerekmektedir. Periyodik hareketlerde ise durum böyle değildir. Ayrıca yine periyodik hareketlerin süresi mevsimsel hareketlerden uzundur. Aynı durum büyüklükleri için de geçerlidir. Periyodik hareketler mevsimsel hareketlere göre çok daha büyük değişimlere sahne olur.

Burada anlattığımız kavramlar, tahminleme metodunun seçilmesinde de tabii ki önemli rol oynaması gereken kavramlardır. Şimdi bu kavramlara göre üstteki grafiği yorumlayalım.

Grafiğe baktığımızda, ilk tespit ettiğimiz nokta açık ve net bir trendin var olduğu. Bu trend yukarı yönlü ve oldukça da yüksek düzeyde. 1966 yılında soygun sayısı 50’nin altındayken  1975’te 500 civarlarına kadar dahi çıktığını görebiliyoruz. Bu da aslında trendin büyüklüğünü ve suç sayısındaki artışı gözler önüne seriyor. 1972 yılından sonra, yılın ilk zamanlarında suç sayılarında bariz düşüşler görülüyor ki bu mevsimsel bir hareket olarak görülebilir. Son 2 yılda Mart aylarında görülen büyük düşüşler, mevsimsellik belirtisi ve serinin devamı elimizde olsaydı, devam ettiğini görebilirdik. Veri seti çok fazla dalgalanma gösteriyor, patern çok net değil. Bu da tahmin aşamasında bize zorluk çıkaracak.

Serideki mevsimselliği görmenin en iyi yollarından biri, mevsimsellik grafiğini çizdirmektir. Bu grafik sayesinde verideki mevsimsel patern daha net görülebilir. Aşağıdaki kod bloğu ile çizdirelim:

ggseasonplot(x = Data_ts,
             year.labels = TRUE) +
  ylab("Sayı") +
  ggtitle("Silahlı Soygun Verisi Mevsimsel Grafiği")

“ggseasonplot” komutu ile serinin mevsimsellik grafiğini çizdirdik. Yine eksen başlıklarını ve grafik adını verdikten sonra aşağıdaki grafiği elde ettik:

4

Grafik bize yıllar bazında mevsimsel hareketi gösteriyor. Baktığımızda, her yıl benzer bir mevsimsel patern olduğundan bahsedemeyiz. Fakat bazı yıllar birbirlerine çok benzer özellikler göstermekte. Örneğin, 1973 ve 1974 yılları, 1968 ve 1969 yılları, 1966 ve 1967 yılları gibi bazı ikililerin paternleri birbirine çok benzer. Seri sonlara doğru yıl başına benzer paternler sergilemeye başlıyor. Dikkatli bakıldığında, Temmuz ve Ağustos aylarındaki yükselişler görülebilir. Haziran’dan sonra suç oranlarında neredeyse her yıl yükseliş görülüyor. Bu da bariz bir mevsimsellik örneği. Aynı şekilde yılın başlarında yani Ocak ve Şubat aylarında suç oranı genelde düşük.

Başka bir mevsimsellik grafiği kullanarak da mevsimselliğe göz atabiliriz. Bu da bize mevsimsel alt serileri gösterecek. Aşağıdaki kod bloğu ile görelim:

ggsubseriesplot(x = Data_ts) +
  ylab("Sayı") +
  ggtitle("Silahlı Soygun Verisi Mevsimsel Alt Seri Grafiği")

Yine “ggsubseriesplot” metoduyla grafiği çizdirdik. Sonuç:

5

Grafiği dikkatli incelediğimizde, bize yıl içerisindeki her ay bazında mevsimsel paterni verdiğini görebiliriz. Bu grafik, mevsimselliği daha iyi anlamamıza yardımcı oluyor. Mavi çizgiler ortalama değerlerini gösteriyor. İlk yıllarda tüm aylar suç oranında yükselişlere sahne olurken, 1967 yılında genel anlamda bir düşüş olduğunu görüyoruz. Neredeyse her ayın grafiği o yılda aşağı doğru yön değiştirmiş. Zaten veri genel olarak suç oranında bir artış olduğunu gösterdiğinden, her ayın grafiği yukarı doğru yönelmiş durumda. Diğer aylardan farklı olarak, Haziran ayında suç oranı hiç düşmemiş. Bu da ilginç bir durum olarak grafikte gözüküyor.

Grafik üzerinde bu yorumlamaları yaptıktan sonra, bir de otokorelasyon kavramına değinip, otokorelasyon fonksiyonunun grafiğini çizelim. Otokorelasyon, bir zaman serisinin geçmiş değerleri ile arasındaki doğrusal ilişkinin derecesini ölçer. Nasıl iki değişken arasındaki doğrusal ilişkinin derecesini korelasyon ile ölçüyorsak, buradaki ikinci değişkenin de elimizdeki zaman serisinin geçmiş değerleri olduğunu düşünebiliriz. Otokorelasyon da bu değişken ile serinin kendi değerleri arasındaki doğrusal ilişkiyi ölçer. Bu durum, ne kadar geriye gidilmek istendiğiyle de alakalıdır. Örneğin bir zaman serisinin, bir önceki değerleriyle de, iki önceki değerleriyle de, n önceki değerleriyle de arasındaki otokorelasyon ölçülebilir. Hepsinin ayrı bir otokorelasyon katsayısı bulunur. Otokorelasyon fonksiyonu ise bu katsayıların grafiğe dökülmüş halini gösterir. Bu grafiği çizdirelim:

ggAcf(Data_ts, lag = 60) +
  ggtitle("Otokorelasyon Fonksiyonu Grafiği")

Sonuç:

6

Grafiği çizdirirken geriye dönük 60 gecikme kullanmasını, yani 60 önceki değere kadar otokorelasyon hesaplamasını devam ettirmesini söyledik. Öncelikle, grafiğin genel anlamda azalarak ilerlediğini görüyoruz. Bu da aslında serinin geçmiş değerleri ile arasındaki otokorelasyonun gittikçe düştüğünü gösteriyor. Zaten serideki son değerler ilk değerlere göre çok daha büyük olduğu için, böyle bir durumun ortaya çıkmış olması normal.  Küçük “lag(gecikme)” değerleri için otokorelasyon katsayılarının daha büyük olması aslında serideki yükselen trendin sonucu. Yani birbirlerine yakın değerler aynı zamanda büyüklük olarak da birbirlerine yakınlar. Bu da daha düşük gecikmedeki değerler ile seri arasındaki otokorelasyon katsayısının büyük olmasına sebep oluyor. Gecikme büyüklüğü arttıkça ise otokorelasyon katsayısı düşüyor çünkü değerlerin arasındaki büyüklük farkı gittikçe açılıyor. Burada tabii ki birinci gecikme derken, serinin bir önceki değerlerinden bahsediyoruz. Grafikte bir başka dikkat çeken nokta ise, otokorelasyon fonksiyonu genel olarak düşüş göstermesine rağmen, bazı gecikmelerdeki otokorelasyon katsayılarının artış göstermesi. Buna örnek olarak 11 ve 22. gecikmeler örnek verilebilir. 11 ve 22. gecikmelerdeki otokorelasyon katsayılarının diğerlerine nazaran yüksek olup, düşüş değil de artış göstermesi, 11 ayda bir görülen bir mevsimselliğin göstergesi olabilir. Fakat bu çok da bariz değil. Yani net olarak böyle bir mevsimsellikten bahsetmek doğru olmayacaktır, çünkü eğer olsaydı 11’in katları olan diğer gecikmelerdeki otokorelasyon katsayıları da aynı davranışı gösteriyor olurdu, fakat göstermiyor. Mevsimselliğin net olarak görüldüğü zaman serilerinde, mevsimsel periyodlardaki otokorelasyon katsayıları yüksek olur. Çünkü o zamanlardaki gözlemler, büyüklük olarak birbirine yakın olacaktır. Son olarak, otokorelasyon katsayılarının 42. gecikmeden sonra eksiye düştüğünü görüyoruz. Bu da aslında serideki değerlerin, 42’den sonraki gecikmelerle aralarındaki ilişkinin negatif yönlü olduğunu gösteriyor. Yani serinin kendi değeri artarken, bu değerin 42 ve daha büyük geçmiş değerlerinin büyüklüğü azalıyor.

Otokorelasyon fonksiyonunun grafiğini inceledikten sonra, biraz da beyaz gürültü(white noise) kavramı üzerine konuşalım. Tek bir cümleyle tanımlayacak olursak, herhangi bir otokorelasyon göstermeyen zaman serileri beyaz gürültüdür diyebiliriz. Bunu tamamen rastgele dalgalanmalara sahip bir zaman serisi olarak düşünelim. Bir zaman serisinin otokorelasyon göstermesi demek, geçmiş verileriyle arasında doğrusal bir ilişki olması demektir. Beyaz gürültüde ise anlamlı bir otokorelasyon olmadığından, seride rastgele dalgalanmalar görülür. Tabii ki bu otokorelasyon katsayılarının sıfır olacağı anlamına gelmez.  Tam anlamıyla sıfır olmayacaktır çünkü seride her zaman bir rastgele değişim vardır. Fakat beyaz gürültü serileri için, otokorelasyon fonksiyonundaki katsayıların %90-95’inin sıfırdan anlamlı bir uzaklık seviyesinde olmamasını bekleriz. Beyaz gürültüye örnek olarak, sayısal loto rakamlarını verebiliriz. Bu rakamlar her zaman rastgele çekildiğinden geçmiş değerleriyle aralarında bir otokorelasyon yoktur.

Veri üzerindeki incelemelerden sonra, artık verinin analizine başlayalım. Analizi başlatmadan önce, veride bazı düzeltmeler yapılabilir mi, yapılması gerekiyor mu gibi soruları cevaplandırmak gerekir. Örneğin, bir satış zaman serisi ile alakalı tahminleme yapıyorsanız, bu serideki değerler paranın zaman değerinden etkilenecektir ve enflasyon da hesaba katılarak tahmin yapılmalıdır ve seri düzeltilmelidir. Aynı şekilde farklı ayların gün sayıları da farklı olduğundan direk adetlere bağlı olan zaman serileri ay bazında tahminlenmek yerine, gün başına düşen ortalama üzerinden tahminlenebilir. Biz de burada bu şekilde bir düzeltme yapabiliriz çünkü soygun adetleri üzerinden ilerliyoruz. Fakat soygun adetleri, örneğin bir eşyanın, yiyeceğin vs. üretim adetleri kadar bu etkenden etkilenmeyeceği için, bu işlem burada biraz daha opsiyonel kalıyor. İsterseniz siz bu düzeltmeyi aylık veriyi gün sayısına bölerek yapabilirsiniz ve ay bazında günlük ortalamaları elde edebilirsiniz. Sonrasında tahminleri de bunlardan çıkarabilirsiniz. Ben burada bu işlemi gerçekleştirmeyeceğim.

Ben bu veri üzerinde düzeltmelerden ziyade, veri dönüşümlerine gideceğim. Veriye uygulanan dönüşümlerin ve düzeltmelerin asıl amacı, verideki paterni sadeleştirmektir çünkü sade paternler her zaman daha doğru tahminlere götürür. Üstte verinin grafiğini oluşturmuştuk. Onu burada bir kez daha görelim:

3

Veriye bakacak olursak, verinin değişkenliği serinin farklı seviyelerinde çoğu kez değişiyor. Yani seri başlarda daha az değişken iken, ortalarda bu değişkenlik artıyor, sonlarda ise maksimum düzeye geliyor. Değişkenlikten kastım, verinin içerisinde oynadığı sınırlar diyebiliriz. Çok küçük sınırlarda dalgalanırken, bu dalgalanma çok büyüyor. Bu değişkenliğin değişimi ise paterni karmaşıklaştırıyor ve tahmini zorlaştırıyor. Biz bu veriye dönüşüm uygulayarak, bu paterni sadeleştirmeye çalışacağız. Bunun için de çok kullanılan bir dönüşüm olan Box-Cox dönüşümünü uygulayacağız.

Box-Cox dönüşümü, bir “lambda” parametresi üzerine kuruludur. Detayı aşağıdaki gibidir:

7

Üstte de göreceğimiz gibi Box-Cox fonksiyonu, “lambda” parametresi 0 iken seriye “log” dönüşümü uyguluyor. Buradaki log doğal logaritma, yani e tabanında. 0 harici değerler için ise bir üs alma dönüşümü söz konusu. İyi lambda değerine karar verirken, hangi değerin serideki değişkenliği sadeleştirdiğine bakacağız. Bunu da R üzerinde otomatik olarak belirleyebiliyoruz:

lambda <- BoxCox.lambda(Data_ts)
lambda
autoplot(BoxCox(Data_ts,lambda))

"BoxCox.lambda" metodu, bizim serimiz için uygun olan lambda değerini belirledi ve son satırda da o lambda değeri üzerinden "BoxCox" metoduyla bir dönüşüm yaptık ve grafiğini çizdirdik. Sonuç:

8

Üstte elde ettiğimiz seriyi, iki üstteki asıl seri ile karşılaştırdığımızda görüyoruz ki alttaki seride değişkenlik neredeyse serinin tüm seviyelerinde birbirine yakın durumda. Tabii ki %100 aynı değil fakat daha sadeleşmiş gözüküyor. Bu da BoxCox dönüşümünün etkisi ve bize tahminleme aşamasında yardımcı olacak. Burada unutulmaması gereken önemli bir nokta var, tahminleme yaparken bu seriyi, yani dönüştürülmüş seriyi kullanacağız. Fakat daha sonra bu tahminleri tekrar geri dönüştürerek verinin orjinal ölçeğinde asıl elde etmek istediğimiz tahminleri görmemiz gerekiyor.

Artık veriyi tahminlemek adına bir zaman serisi regresyonu kuralım ve daha sonra bu modelin performansını ve özelliklerini inceleyelim.

Daha önceki yazılarımda regresyondan bahsetmiş ve örnekler yapmıştım. Teorik temel yine aynı olduğu için, o konuda fazla detaya girmeyeceğim. Gereken yerlerde hatırlatmalar yapacak ve teknik detaylardan bahsedeceğim. Çoklu regresyon yaparken, birden fazla tahminci değişkenin kullanıldığını biliyoruz. Aynı değişkenler zaman serisi için de kullanılabilir ve çoklu regresyon yapılabilir. Sonuçta değişkenleri teker teker incelediğimizde, hepsi kendi içinde birer zaman serisidir. Fakat biz burada, farklı zaman serileri kullanmak yerine, elimizdeki serinin kendisinden çıkacak olan değişkenleri regresyon modelinin içinde kullancağız. Örneğin, verinin içerisindeki trend ve mevsimsellik gibi. Tahminci olarak birçok değişken kullanılabilir. Trend ve mevsimselliğin yanı sıra, satış verisi için bir ay içerisindeki iş günü sayısı bir değişken olarak modele eklenebilir. Ya da gün bazında zaman serilerinde haftanın hangi günleri olduğu da modele değişken olarak eklenebilir. Bir yıl içerisindeki özel etkinlikler, kutlamalar, kısacası elimizdeki zaman serisi verisine etki edebilecek her olay modele kukla değişkenler vasıtasıyla eklenebilir. Yani o olayın olduğu zaman diliminde bu değişken 1 değerini, geriye kalan tüm zaman dilimlerinde 0 değerini alacak gibi. Biz de burada 2-3 farklı model kuracak ve hepsinin performans denemesini yapacağız.

Birinci tip modelimiz, verideki trendi ve mevsimselliği tahminci değişken olarak kullanacak. Veriye baktığımızda, trend bariz olarak gözüküyor. Bu trendi doğrusal mı yoksa doğrusal olmayan regresyonun mu daha iyi kapsayacağını göreceğiz. Ek olarak, kukla değişken kullanımını göstermek amacıyla da her yıl içerisinde paskalya bayramına denk gelen tarihleri modele tahminci değişken olarak ekleyeceğiz. Buradaki düşüncemiz de bu tarz tatil günlerinde dışarıdaki kalabalıktan dolayı suç miktarının artabileceği. Tabii ki daha birçok farklı kukla değişkenler modele katılabilir, fakat bu yazı için fazla uzatmamak adına bu kadarı ile sınırlı kalacağız.

Trendi modele eklemek, aynı yeni bir tahminci değişken eklemekten farksız:

9

Burada “t” harfi ile gösterdiğimiz trend, aynı herhangi bir “x” tahminci değişkeninden farksız bir görev yapıyor.

Tabii ki modelleri kurmaya başlamadan önce, her zamanki gibi ilk aşama olarak veriyi train ve test setler olarak ikiye bölecek ve modelin performansını test set üzerinde ölçeceğiz.

train_ts <- window(Data_ts, end = c(1973, 12))
test_ts <- window(Data_ts, start = c(1974, 01))

"window" fonksiyonunu kullanarak veriyi belirli noktalardan böldük. 1974 yılının başına kadar olan kısmı training set, geriye kalanını da test set olarak belirledik.

O zaman aşağıdaki kod bloğuyla training set üzerinde ilk modeli kuralım:

easter <- easter(train_ts)
Model_Linear <- tslm(train_ts ~ trend + season + easter)
summary(Model_Linear)

Evet kod bloğunu inceleyelim. "easter" fonksiyonu, üstte de bahsettiğim paskalya bayramının sene içerisinde ne tarihe denk geldiğini hesaplayıp o tarihteki gözlemlere "1" , diğerlerine "0" değeri atayarak "easter" değişkenini oluşturuyor. Sonuç aşağıdaki gibi:

10

Görüleceği gibi kukla değişken oluşmuş durumda. Bazı gözlemlerde 1 değeri dışında ondalıklı sayılıar bulunuyor ki bu da paskalya bayramının iki aya yayıldığı durumlarda oluyor. Bu değişkeni oluşturmamızın amacı, üstte de söylediğimiz gibi kukla değişken kullanımını göstermek ve tatil günlerinde de suç sayısının artabileceğini düşünmek. Daha çok gösterim amacıyla kullanıyoruz.

Sonrasında “tslm” fonksiyonu(time-series linear model) bizim için doğrusal regresyon modelini kuruyor ve “trend + season” ile de verideki trendi ve mevsimselliği kullanmasını söylüyoruz. “Summary” fonksiyonunun sonucuna bakacak olursak:

11

Bu tarz bir regresyon çıktısını önceki yazılarımda yorumlamıştım. Yine yorumlayalım, “Intercept” değişkeni, doğrusal model çizgisinin nerede başladığını belirtiyor ve tüm tahmincilerin değerinin “0” olduğu noktaya denk geliyor. “Estimate” kolonunun altındaki tüm veriler, karşılık gelen değişkenlerin tahminlenmiş olan katsayılarını bize veriyor. Ya da diğer bir değişle eğimlerini(slope). Örneğin trend değişkenine bakacak olursak, seride aydan aya ortalama 3.33 adetlik yükselen bir trend olduğunu görüyoruz. Buradaki adet tabii ki soygun sayısına denk geliyor. Ayrıca, ikinci ay birinci aya göre ortalama 10.33 adet daha düşük soyguna sahipken, onikinci ay birinci aya göre ortalama 14.95 adet daha yüksek soyguna sahip. Dikkat edelim ki burada elimizdeki tüm ayları, regresyon çıktısında görünmeyen ay olan birinci aya göre yorumluyoruz. Veri aylık bazda olduğu için, mevsimsellik değişkeni de bize mevsimselliği aylık bazda veriyor. Easter değişkeni ise paskalya bayramının olduğu tarihlerde ortalama 2.77 adet daha fazla soygun görüldüğünü gösteriyor.  Bir de tahmincilerin altındaki kısmı inceleyelim. Burada ilk dikkatimizi çeken nokta, Multiple R-squared ve Adjusted R-squared değerleri. Bunların ne olduğundan önceki yazılarda bahsetmiştik. Modele aldığımız değişkenler, bağımlı değişkendeki değişkenliğin %89.04’ünü açıklar nitelikte görünüyor(Multiple R-squared = 0.8904). Tabii ki performans ölçümünde Adjusted R-squared değerine bakmanın daha güvenilir olduğunu çünkü Multiple R-squared değerinin modele her değişken eklendiğinde arttığını, Adjusted R-squared değerinin ise eklenen değişkenin işe yarar bir bilgi sağlayıp sağlamadığını ölçtüğü için her seferinde artmadığını söylemiştik.

Modeli kurduktan sonra ikinci adım, modelin bazı varsayımları sağlayıp sağlamadığını test etmek. Bu varsayımların neler olduğuyla alakalı da yine gerekli bilgileri vermiştim, bu yüzden hızlıca hatırlatarak geçiyorum:

1. Kalıntılar arasında otokorelasyon olmamalıdır. Eğer var ise, veri içerisinde modelin kapsayamadığı bilgiler kalmış demektir.
2. Kalıntıların ortalaması sıfır olmalıdır. Bu koşulun sağlanmaması da tahminlerin yanlı tahminler olmasına neden olacaktır.
3. Kalıntıların varyansı sabit olmalıdır.
4. Kalıntılar normal dağılmalıdır.

Son 2 madde de güven aralıklarının hesaplanmasının doğru olması için gerekli maddelerdir. Fakat model bazında düşünecek olursak, ilk 2 maddenin sağlanması daha kritiktir.

Bu varsayımların tamamını aşağıdaki fonksiyon ile kontrol edebiliriz:

checkresiduals(Model_Linear)

Sonuç:

12

Sonucu incelediğimizde, kalıntıların ortalamasının sıfır olmadığını ve sabit bir varyansla hareket etmediklerini görüyoruz. Aynı zamanda kalıntılar arasında otokorelasyon kaldığı da ACF grafiğinde bariz olarak görülüyor. Kalıntılar arasındaki otokorelasyonun varlığını istatistiksel olarak test eden “Breusch-Godfrey” testi de istatistiksel olarak anlamlı bir otokorelasyonun varlığını bize aşağıdaki çıktıyla bildiriyor:

13

p değerinin 0.05’ten küçük olması, kalıntılar arasındaki otokorelasyonu bu model ile kapatamadığımızı gösteriyor. Modelin veriye nasıl oturduğunu görmek adına, tahminlenen değerleri serideki değerler ile grafik vasıtasıyla karşılaştıralım:

14

Trend olarak güzel takip etse de, tahminlenen veriler training verilerini yakalamakta bazı noktalarda çok başarısız kalıyor.

Şimdi kuracağımız modelde, doğrusal olmayan regresyon metodunu kullanalım. Böylece serinin akışını doğrusal olmayan metotlarla yakalamaya çalışalım.

train_ts %>%
  splinef(h = 22, lambda=BoxCox.lambda(train_ts)) %>%
  checkresiduals()

train_ts %>%
  splinef(h=22, lambda=BoxCox.lambda(train_ts)) %>% autoplot() +
    scale_y_continuous(limits=c(0, 500))

Buradaki “splinef” metodu, doğrusal regresyonun aksine kübik bir fonksiyon kullanarak veriye oturmaya çalışıyor ve aynı zamanda 22 adım(ay) ötesini tahmin ediyor. Burada tahmin adımını 22 olarak ayarlamamızın sebebi, test setin 22 aydan oluşması ve bizim de o seti tahminleyecek olmamız. Ek olarak dikkat edelim ki burada BoxCox dönüşümü de uygulayarak verideki değişkenliği sabitlemeye çalıştık. Bunu üstte anlatmıştık. “splinef” metodu direkt olarak bir “forecast” nesnesi yani tahmin döndürüyor. Bu da üstteki “tslm” fonksiyonundan bir başka farkı. Kalıntı incelemesine baktığımızda:

15

Burada kalıntılar sabit bir varyansla hareket ediyor ve ortalamaları da sıfır civarında. ACF grafiğine baktığımızda ise bir lag hariç diğer hiçbir lagda anlamlı bir otokorelasyon katsayısı görmüyoruz. Kalıntılar tam olarak normal dağılmış diyemeyiz. Fakat genel olarak grafiği incelediğimizde, kalıntı varsayımları bir önceki modelden daha iyi duruyor. Bir de tahminlenen değerler ile training set değerlerini karşılaştıralım:

16

Baktığımızda, fitted değerlerin bir önceki modele göre veriye daha iyi oturduğunu görüyoruz. En sondaki mavi çizgi ise tahminlenen 22 aylık süreç. Bu fonksiyon direkt “forecast” nesnesi döndürdüğü için, tahmin değerlerini de grafikte görüyoruz.

Fakat yine de unutmamak gerekir ki, her ne kadar veriye oturma konusunda ve kalıntı varsayımları konusunda doğrusal modelden iyi olsa da, test başarısını ölçmede doğrusal model ile karşılaştırma yapmamız gerekiyor. Bu iki modelin performans karşılaştırmasını yaparken, aynı zamanda bazı “benchmark” metodlarla da kurduğumuz modellerin performans karşılaştırmalarını yapacağız. Bu şu anlama geliyor; zaman serilerinde kullanılan bazı basit fakat yerine göre etkili metodlar vardır. Bunlara “benchmark” metodlar diyebiliriz. Bunların arasında “ortalama metodu”, “naive metod” gibi metodlar bulunur. Kısaca değinecek olursak, ortalama metodu, tahminlenecek olan bağımlı değişkeni, serinin geri kalanının ortalamasına eşit kabul eder ve o şekilde tahmin eder. Yani elinizdeki zaman serisinin ortalamasını alırsanız, bu serinin bir sonraki değerini de o ortalama değeri olarak tahmin etmiş olursunuz. Naive metodda ise elinizdeki serinin son değerini, direkt olarak tahmin değeri olarak belirlersiniz. Bu tarz basit metodlar yerine göre çok etkili olabilir ve sizin kendi kurduğunuz model performansta bu basit metodları geçemiyorsa, modelinizi geliştirmeniz gerektiğine işarettir. Şimdi elimizdeki metodların performanslarını karşılaştıralım:

f_Linear <- forecast(Model_Linear, h = 22, newdata = data.frame(easter = easter(test_ts)))
f_Cubic <- splinef(train_ts, h = 22, lambda=BoxCox.lambda(train_ts))
f_Mean <- meanf(train_ts, h = 22)
f_Naive <- naive(train_ts, h = 22)

Öncelikle her modelden bir tahmin ürettik. "forecast" fonksiyonu, lineer modelden tahminleri üretirken, geriye kalan "splinef", "meanf" ve "naive" fonksiyonları ise direkt olarak tahmin ürettikleri için ekstra bir fonksiyona ihtiyacımız yok. Burada dikkat edilmesi gereken ilk nokta, lineer model ek olarak bir kukla değişken kullandığı için, o değişkenin değerini modele vermiş olmamız. Kübik modelin kuruluşunda dönüşüm kullandık, diğerlerinde ise böyle bir şey yapmadık. Tahmin adımımız da yukarıda bahsettiğimiz gibi test set büyüklüğü ile aynı, yani 22. Sonuçları inceleyelim:

accuracy(f_Linear, test_ts)
accuracy(f_Cubic, test_ts)
accuracy(f_Mean, test_ts)
accuracy(f_Naive, test_ts)

"accuracy" fonksiyonu, bizim için gerekli hata metriklerini hesaplayacak. Dikkat edelim ki tahminlerin hata metriklerini test set üzerinde hesaplıyoruz.

17

Sonuçları inceleyelim. Aynı veri seti üzerinde farklı modellerin denenmesinde en çok kullanılan hata metrikleri MAE(Mean Absolute Error) ve RMSE(Root Mean Squared Error)’dır. Ortalama metodunun değerleri çok kötü olduğundan onu değerlendirmeye almıyorum. MAE değeri lineer model için 26.7 iken, kübik model için 32.27 ve Naive model için ise 25.6. RMSE değeri ise lineer model için 33.14, kübik model için 44.33 ve Naive model için 34.63. Bu durumda MAE baz alındığında en iyi model Naive iken, RMSE baz alındığında en iyi model lineer model olarak karşımıza çıkıyor. Diğer hata metrikleri de baz alınarak incelemeler yapılabilir. Fakat unutulmamalıdır ki her hata metriğinin kendine has özellikleri vardır ve durumlara göre kullanımları farklılaşır. Hatırlarsanız üstte veriye en iyi oturan model kübik modeldi. Fakat tahminlemede sonuç değişti. Lineer model MAE ve RMSE bazında daha iyi sonuçlar ortaya çıkardı. Tabii ki farklı hata metriklerinde(Örnek: MAPE) kübik model, lineer modelden daha iyi sonuçlar çıkarmış olabilir. Fakat biz MAE ve RMSE için baktığımızdan, lineerin performansı daha iyi. Hatta bu hatalar bazında Naive model de kübik modelden daha iyi performans göstermiş. Bu da kalıntı varsayımlarının ve veriye oturmanın sonuçlarının iyi olmasının tahminlerin de iyi olacağı anlamına gelmediğini gösteriyor.

Şimdi bu üç farklı modelin tahminlerini bir de grafik üzerinde inceleyelim:

autoplot(Data_ts) +
  autolayer(f_Linear, series = "Lineer Model", PI=F) +
  autolayer(f_Cubic, series = "Kübik Model", PI=F) +
  autolayer(f_Naive, series = "Naive Model", PI=F) +
  guides(colour=guide_legend(title="Tahmin")) +
  scale_y_continuous(limits = c(0, 500))

“autoplot” komutuyla asıl veriyi çizdirirken, “autolayer” komutuyla da tahminleri grafiğe ekstra tabakalar olarak ekledik. “series” argümanıyla hepsinin adını belirledik ve “PI” ile de güven aralığı hesaplanmamasını istedik. Bunun sebebi güven aralıklarının diğer tahminlerin üstünü kapatmasıydı. Net görünmeleri açısından güven aralığını iptal ettim. Dikkat edelim ki training setini değil, tüm veriyi çizdirdik. Çünkü test set de grafikte gözükmeli ve tahminlerle karşılaştırmalıyız. Sonuca bakalım:

18

Evet sonuçları inceleyelim.  Kırmızı olan çizgi, kübik modelin tahminleri ve hiç de mantıklı görünmüyor. Zaten test set ile de karşılaştırdığımızda, tamamen alakasız bir tahmin. Performans metriklerinde iyi görünen Naive model ise tahminlerde hiç de iyi bir iş çıkartamamış. Zaten tüm tahminleri son gözlem olarak değerlendirdiği için, böyle bir beklentimiz yoktu. Test setine en yakın tahmin, lineer modelin tahmini gibi gözüküyor. Değerlerde yakalayamamış olsa bile, en azından trendde yakalamış gibi. Düşüşler ve yükselişlerde gerçek data ile tutarlı hareket etmiş.

Genel olarak baktığımızda, en iyi tahmini lineer model vermiş durumda fakat o da son derece başarılı diyemeyiz. Bunun sebebi, bu yazıda çok da kompleks ve üst düzey modeller denememiş olmamız. Fakat yine de son derece basit modeller kurmamıza rağmen, göreceli olarak başarılı sonuçlar aldık. İkinci yazıda görüşmek üzere.

NOTLAR

  1. Serinin bu ilk yazısında, kompleks modellere fazla girmeden, basit regresyon metodlarıyla tahminleme yapmaya çalıştık. Fakat sonraki yazılarda, daha kompleks modellere değineceğiz.
  2. Çoklu regresyon modeline, başka değişkenler de eklenerek performansı artırılıbilir ve daha doğru tahminler çıkarması sağlanabilirdi. Fakat burada zaman serisi regresyonunun nasıl çalıştığını göstermek ve yazıyı da mümkün olduğunca kısa tutabilmek için, bu işlemi yapmadık.

REFERANSLAR

fpp2.pdf erişimi için tıklayın

Ch10_Basic%20Time%20Series_ver1.pdf erişimi için tıklayın

https://otexts.org/fpp2/

R Üzerinde Zaman Serisi Analizi Bölüm 1: Zaman Serisi Regresyonu” için 5 yorum

  1. Giris anlaminda fikir verici, devamini bekliyoruz. Modellerden tahmin uretilen kod parcasini aktarirken maddi bir hata olmus sanirim, araya html tag leri girmis.

    Beğen

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Google fotoğrafı

Google hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Connecting to %s