Makine Öğrenmesi’nde Ham Veri’den Öznitelik Çıkarmak
Merhabalar,
Umarım hepiniz evinizde sağlıklı, mutlu ve verimli günler geçiriyorsunuzdur. Yeni bir yazımla karşınızda olmanın vermiş olduğu heyecanla daha da mutluyum. Bu yazımda farklı bir konuyla karşınızdayım. Makine Öğrenmesi için elimizde olan bir verisetinden öznitelik(feature) seçerken nelere dikkat etmemiz gerektiğini, yani iyi bir özniteliğin özelliklerinden bahsetmeye çalışacağım. Tahmin edebileceğiniz üzere yine girizgah bölümü hazırladım. (Bu sefer daha kısa :)) Eğer hazırsanız kemerlerinizi bağlayın, sizlerle ham veriden iyi bir öznitelik nasıl seçilir, nasıl seçilmez keşfedeceğiz :)
Girizgah-Terminoloji
Representation: Veriyi kullanışlı featurelara mapleme işlemine denir.
Feature engineering (Öznitelik Mühendisliği): Ham veriden öznitelikleri ayıklama sürecidir.
Bu yazımda Feature Engineering’in detaylarına değinmeyeceğim yalnız meraklıları için buraya linki bıraktım.
Öznitelik Çıkarmak mı? O da ne?
Makine Öğrenmesi algoritmamız ona verdiğimiz feature ve label verilerini öğrenerek daha önce vermediğimiz bir feature seti üzerinden bir label tahmininde bulunur. (Bu kısımdan sonra feature’a öznitelik denecektir.)
Bu bağlamda modelimizi tasarlamadan önce modelimizde kullanmayacağımız özniteliklerimizi ham veriden ayıklamak çok önemlidir çünkü muhtemelen hamverimizdeki her özniteliğe ihtiyacımız olmayacaktır. Bu kolay bir iş gibi görünse de aslında pek değildir. Hamverideki bir feature’ı modelinize almadığınızda aslında verideki bir kısım bilgiyi saf dışı ederek o veriseti hakkında daha az bilgiye sahip oluyorsunuz. Yani eğer modelinizden çıkarmamanız gereken bir feature’ı çıkarırsanız modeliniz çok efektif çalışmayacaktır.
İyi de Hangi Öznitelikleri Tutmamız Gerekiyor?
Aslında bunu bilmenin kesin bir yolu yok fakat iyi bir öznitelik için fikir edinebileceğiniz 4 özellik mevcuttur. Eğer özniteliğiniz bu 4 özelliği sağlıyorsa seçilebilir diyebiliriz.
1.Nadir Kullanılan Kategorik Öznitelik Verilerden Kaçının
İyi bir kategorik öznitelik verisi verisetimizde en az 5 kez görünmelidir. Bu özelliği sağlamamız label ile özniteliğimiz arasındaki ilişkinin modelimiz tarafından öğrenilmesini sağlar. Bu özellik sayesinde modelimizin özniteliği birçok farklı açıdan görebilmesine olanak sağlanmaktadır. Burada istediğimiz de zaten özniteliklerimizin labellar ile ilişkisini modelimizin öğrenmesini sağlayıp bu öğrendikleri üzerinden tahmin yapmasını sağlayabilmek.
Örneğin elinizde ev özelliklerini fiyatlarıyla içeren bir veriseti olsun. Amacınız bu veriler arasından fiyatı tahmin etmek için modele verilebilecek anlamlı öznitelikler çıkarmak. Bu durumda evin mimarisi özniteliğini modelinizde kullanmak için verisetinizden seçebilirsiniz. Örneğin:
Mimari: Victorian
Victorian değerinizin mimari özniteliğinizde birden çok kullanılması olasıdır. Eğer kullanılıyorsa bu özniteliği modelinizi eğitmek için kullanabilirsiniz. (Verisetimizde Victorian dışında diğer mimarilerinde bu öznitelik için değer olarak kullanılabileceğini de atlamayın.)
Eğer siz ham verisetinizde çok az görünen bir değere sahip özniteliği alırsanız modeliniz bu özniteliğin label ile ilişkisini öğrenemeyeceğinden tahminlerini bu özniteliği kullanarak eksik veya hatalı gerçekleştirecektir. Örneğin:
Ev_id:1234567
Bu feature tahminde hiçbir rol oynamayacaktır çünkü bu feature her eğitim örneği için farklıdır ve muhtemelen labelımızla lineer bir korelasyonu bulunmamaktadır. Bu yüzden de tahminlerimiz eşsiz öznitelikler üzerinden gerçekleştirilemeyecektir.
2.Açık ve Belirgin Bir Anlama Sahip Öznitelikleri Seçin
Hmm güzel ama bu ne demek?
Yani projede siz dışında başkasının da çalıştığını (öyle olduğunu varsayıyorum) unutmayın. Örnek mi? Hemmen geliyor.
Ev_yasi: 123456723 (Saniye cinsinden)
Wow, ev yaşını saniye cinsinden belirttiğimizde eğer Sherlock değilseniz bunun bir saniye bazlı süre belirttiğini anlayamayabilirsiniz.
Aynı zamanda bu saniye bazından verilmiş özniteliğini ölçeklemeniz gerektiğinden bahsetmeme bile gerek yok. (Yoksa var mı?)
Tamam o zaman ne yapalım? Hiç aksiyona girmeden ev_yasi feature değerini yıl cinsinden verelim.
Ev_yasi:27 (yıl cinsinden)
Şimdi oldu değil mi? (Spoiler: oldu)
Dipnot: Ev_yasi özniteliğini yıl cinsinden verdiğinizde de öznitelik ölçeklemesi yapmanız gerekebilir ama bir düşünün, 27'yi mi ölçeklemek daha kolaydır yoksa saniye cinsindeki 123456723'ü mü?
3. “Sihirli değerleri ” Gerçek Veriyle Karıştırmayın
Sihirli değerleri yukarıda gördüğünüz dinazora benzetebilirsiniz, tek fark yutacağı şey siz değil modelinizin performansı olur. Daha teknik anlatmam gerekirse, iyi bir feature değeri garip, range dışı değerler içermez.
Bazı durumlarda bool bir değer içerebilecek bir kolonumuz olabilir. Örneğin ev özelliklerini tutan bir verisetimiz, bu verisetimizde de evin ilanda kalma süresini belli eden ilan_suresi özniteliğimiz olsun. Normal şartlarda bu süremizin 0–20 yıl olmasını bekleriz.(20 yerine istediğiniz sayıyı koyabilirsiniz. Burada dikkat etmeniz gereken husus minimum değerin 0 olacağı.)
ilan_suresi: 3 (yıl cinsinden)
İlan süremizin yıl cinsinden olduğunu farkettiniz değil mi? Bu sayede 2.özelliğimizi pekiştirmiş olduk.
Pekala buraya kadar güzel geldik. Ya evimiz hiç ilana koyulmamışsa? O zaman ilan_suresi öznitelik değerini 0 yapabiliriz dediğinizi duyar gibiyim. Peki ya bir ev 3 aydır ilandaysa? Bu iki adet 0 yıl ilan suresi değerini nasıl ayıracağız? (Hayır 1 yıldan gün alıyormuş gibi düşünüp 3 aydır ilanda olan veri örneğinin ilan_suresi öznitelik değerini 1 yıl, 15 aydır ilanda olan veri örneğinin ilan_suresi özniteliğini 2 yıl yapmadan.)
İlanda olmayan evleri belli edebilmek için aklıma gelen ilk seçenek bu şekilde bir şey yapmak:
ilan_suresi: -1
Bunu yaparsam neler olur?
1. -1 değerini bu özniteliğimize vererek özniteliğimizin doğal aralığını (0–20) bozmuş olduk. Özniteliğimiz artık içinde eğitim sırasında özniteliğimiz ile label değerimiz arasındaki ilişkiyi etkileyecek değerler barındırıyor.
2. Özniteliğimiz tamamen anlamsız oldu çünkü ilan_suresi gerçek hayatta -1 olamaz. Bu da özniteliğimizin eğitimde kullanılabilirliğini oldukça azalttı.
Bunun önüne geçebilmek için ne yapabiliriz?
İlanda olmayan ev örneklerini verisetimizde belli etmek için bool tipinde yeni, sentetik bir öznitelik oluşturabiliriz. Örneğin bu senaryomuzda ilan_yayında_mi özniteliği olabilir. Bu değer bool olmasından ve modelimizin numerik verilerle çalışabilmesinden ötürü binary bir değer alır. (1 veya 0)
Oluşturduğumuz yeni öznitelik sorunu çözdü fakat bu sefer orjinal (ilan_suresi) özniteliğimizde de değer ayarlaması yapmamız lazım. İlanda olmayan veri örnekleri için ilan_suresi özniteliğinin değerini NaN bırakamayız.
Bu kısımda iki adet senaryomuz var. Verilerimizin tipine göre (kategorik veri, numerik veri) ilgili özniteliği doldurmak için farklı aksiyonlar almalıyız.
- Eğer özniteliğiniz sınırlı bir değer kümesi değerine sahipse (kategorik veri) , bu değer kümesine yeni bir değer ekleriz. Değer kümesine yeni eklenen değer özniteliğimizin boş olduğunu simgeleyecek değerdir. (Örneğin takım özniteliğiniz olsun ve bu takım özniteliğinizin değer kümesi başlangıç olarak BJK, FB , GS olsun.) Siz takım tutmayan bir insanı temsil etmek istediğinizde değer kümesine TAKIMSIZ isimli bir değer tanımlayıp bunu takım özniteliğinize verebilirsiniz.)
- Eğer özniteliğimiz sürekli bir değere sahipse(numerik veri), bu özniteliğin değerini, içinde değer olan diğer öznitelikleri eğitim sırasında etkilememesi için ortalama değer olarak veririz. Bunu daha da basitleştirmem gerekirse eğer ben bu özniteliğe değer vermezsem değeri olan özniteliklerinin ortalamasını dolayısıyla da eğitim sırasında modelin doğru bir şekilde eğitilmesini etkileyecektir. Bunun önüne geçebilmem için değeri bulunmayan öznitelikleri etkisiz eleman yapmam lazım. Bunun için de bu öznitelik değerlerine ortalama değeri veriyorum ki ortalama alınırken zaten bu öznitelikler ortalamaya eşit olduğu için ortalama değerinde oynamaya neden olmayacaklardır. (Çok ortalama dedim değil mi…)
4.Öznitelik Değeriniz Sabitlik Varsayımına Uyuyor mu?
Sabitlik(Stationary) Varsayımı, genellemeye (eğitilen modelin daha önce görülmemiş veriyi tahmin etme yeteneği) rehberlik eden 3 temel varsayımdan birisidir. Bu yazımın konusu bu varsayımlar olmadığı için ilgililerine ilgili linki bırakıyorum.
Bir öznitelik değer dağılımının sabit(Stationary) olması demek belli boyutlarda verinin değişim göstermemesidir.Zaman boyutundan ele alırsak verideki dağılım zaman içerisinde değişiklik gösteriyorsa bu özniteliklerinizin sabit olmadığı anlamına gelir. Örneğin siz bir şemsiye firmasıysanız satış verilerinizin dağılımının mevsimsel farklılıklar gösterdiğinizi farkedeceksinizdir (örneğin kış ve sonbahar mevsimlerinde satışların daha çok yapılması). İşte bu farklılıklar sabitliği bozan etkendir. Örneğin elinizde oy sonuçları verilerini içeren bir veriseti ve bu verisetindeki özniteliklerinizden biri de şehir olsun. Şehir öznitelik değerini:
sehir:tr/istanbul
yapmanız doğru bir kullanımdır. Çünkü bu veri zamanla değişiklik gösterme potansiyeline sahip değildir. Bunun için İstanbul şehrinin adını değiştirmeniz gerekir.
Şöyle bir kullanım ise tavsiye edilmemektedir:
sehir:1231
Bunun nedeni her şehre verilecek olan bu sayının yarın öbür gün değişebilme potansiyelidir.
SONUÇ
Ham verisetimizdeki her özniteliğimiz bir bilgiyi temsil ediyor olsa bile her özniteliğimizi modelimizi eğitirken kullanırsak modelimiz overfitting olma riskiyle karşı karşıya kalmakla beraber, eğitim sırasında yanlış eğitilebilir böylece tahminlerimiz ise gerçekten çok uzak sonuçlar verebilme eğilimi gösterir. Bunun yanında eğer çıkarmamamız gereken bir özniteliği çıkarırsak da çok önemli bir bilgiyi kaybetmiş olabiliriz. Hangi öznitelikleri modelimizi eğitirken ham verimizden almamamız konusunda fikir sahibi olabilmek adına 4 yöntem inceledik. Bu yöntemler özniteliğimizin çok önemli bilgi içerme potansiyeline sahip olmuş olsa bile kullanılamayacak durumda olup olmadığını tespit etmemize ve buna bağlı olarak o özniteliği kullanıp kullanmamamıza karar vermemizde yardımcı oluyor.
KAYNAKÇA
KAPANIŞ
Bu yazımda size ham veriden öznitelik çıkarmanın önemini ve kontrol yöntemlerini anlatmaya çalıştım. Umarım faydalı, öğretici ve az sıkıcı bir yazı olmuştur. Buraya kadar geldiyseniz tebrikler ve teşekkürler :)
Herkese bol sağlıklı, mutlu ve evde kaldığımız bu dönemlerde parkurlu günler diliyorum. Daha fazla yazı için lütfen takipte kalın :)
-Fethi Tekyaygil