Özellik Oluşumu ve Özellik Seçimi(Feature Selection)-1

Merhaba Arkadaşlar,

Bu yazımda model kurmadan önce en önemli adım olan değişkenleri belirlemek ve doğru değişkenleri seçmek konusunu ele alacağım. Özellik seçimi için bahsedeceğim bazı popüler metotlara basit python örnekleri vererek biraz daha anlaşılır ve uygulamada yol gösterici olmasını sağlamaya çalışacağım. Yazımdaki maddelerin bazıları detaylı bir yazı konusu olabilir fakat az detay ile değişken seçimi konusunun zihinlerde kalıcı olarak yer edinmesi için büyük resmi anlatmaya çalışacağım. Uzun bir yazı olacağı içinde 3 bölüm şeklinde yayınlayacağım.

İÇERİK

BÖLÜM-1

1-Değişken Seçimine Giriş
2-Doğru Değişkenlerinden Emin Olmak

3Neden Değişken Seçeriz ve Nereden Başlarız?
4-Özellik Seçme Yöntemleri
4.1 Temel Temizlik
i) Kayıp Değerler (Missing Values)
ii) Tüm değerleri aynı olan kategorik değişken
iii) Tüm değerleri farklı olan kategorik değişken
iv) Düşük varyanslı değişken (Low Variance)

4.2 Özellik ile Hedef Değişken arasındaki ilişkiye göre seçim (Filter Methods)
i) Pearson Korelasyonu (Pearson Correlation)
ii) Ki-Kare Testi (Chi2 )
iii) Anova Testi (Anova)
v) Bilgi Kazanımı (Information Gain)

BÖLÜM-2

4.3 Ardışık olarak değişkenleri ekleyerek ve çıkartarak seçme (Sarmal Yöntemler- Wrapped Methods)
i) Ardışık İleri Yönde Seçim ( Sequential Forward Selection (SFS))
ii) Ardışık Geri Yönde Seçim ( Sequential Backward Selection (SBS))
iii) L ekle- R Çıkar ( plus l – minus r)
iv) Ardışık İleri Yönde Kayan Seçim ( Sequential Forward Floating Selection (SFFS))
v) Ardışık Geri Yönde Kayana Seçim ( Sequential Backward Floating Selection (SBFS))

 

BÖLÜM-3

4.4 Özyinelemeli olarak özellik seçme ( Recursive Feature Elimination)

4.5 Başka bir modelin sonuçlarını kullanarak özellik seçme ( Select From Model)
4.6 Boyut İndirgeme (Dimensionality Reduction)
i) Temel Bileşenler Analizi (Principal Component Analysis (PCA))
ii) Lineer Diskriminant Analizi (Linear Discriminant Analysis (LDA))
iii) Genelleştirilmiş Diskriminant Analizi (Generalized Discriminant Analysis (GDA))

GİRİŞ

Analitik dünyasında kullandığımız uygulamalar ve modeller birer araçtır. Hepsi bizim elimizdeki problemimizi çözmeye yarayacak araç ve gereçlerdir. En optimum sonuca ulaşırken ihtiyacın olan uygulama ve çözümleri kullanabilirsin. Analitik modeller yani algoritmalar her yerde aynı şekilde çalışır. Benim bilgisayarımda farklı senin bilgisayarında farklı çalışmaz.
Analitik araçların kullanımı açısından yorumlayacak olursak algoritmalar farklı ortamlarda yine aynı şekilde çalışır. R’daki sinir ağı modeli ile Python’daki sinir ağları modelleri aynı parametrelerle aynı işi yapar. Analitik araçların birbirine karşı farklı üstünlükleri vardır ama bu aynı koşullarda model başarı performansı değildir.

Elimizdeki problemin çözümü için günümüzde sürekli daha iyi sonuç veren algoritmalar çıkıyor ve veri bilimi dünyası geliştikçe de çıkacaktır. Dünyanın iki farklı ucundaki kişiler bu yeni algoritmaları ve paylaşım ekosistemindeki tüm algoritmaları problemini çözmek için kullanabilirler. Bu kısımda aynı veri seti ve aynı algoritmalar olduğu için çözümde bir farklılaşma yoktur.

Aynı problem için sonuçlarda farkı oluşturan o model için kullandığın özelliklerdir. Öznitelikler diye de söylebiliriz. Yani model için kullanacağın girdi değişkenleridir. Hem özellik oluşturma kısmı hem de o özelliklerden hangilerini modelde kullanacağın kısım, senin aynı problemde farklı sonuçlar elde etmeni sağlar.
İşte bu yüzden en baştan doğru değişkenler oluşturmak ve seçmek bu işin en önemli kısmıdır. Öyle iyi ve kaliteli özellikler ortaya çıkarır ve hazırlarsın ki model yerine kural bazlı kuracağın yapılar bile çok iyi sonuç verecektir. Başarının ana kriteri doğru özellikleri bulup temizlenmiş şekilde kullanarak modeli kurmaktır.

DOĞRU DEĞİŞKENLERDEN EMİN OLMAK

5 elemanlı bir kümenin kaç tane altkümesi vardır?

Evet soru sizi ortaokul lise yıllarına götürmüş olabilir. Tamda burada bu sorunun cevabını anlamaya ihtiyacımız var.
5 değişkenli bir veri setiniz olduğunu düşünelim. Bu değişkenleri kullanarak kaç farklı şekilde model kurabilirsin? 5 değişkenli bir kümenin 2^5=32 farklı alt kümesi vardır. Boş kümeyi saymaz isen 31 farklı şekilde alt küme vardır. İşte sen elindeki 5 değişkenle en uygun modeli kurmak için 31 defa model kurman gerekir ki en doğru sonuca hangi değişkenlerle ulaştığından emin olabilesin. Buna kapsamlı arama veya komple arama diyebiliriz. Kısaca tüm kombinasyonları tarıyorsun. O zaman rahatlıkla hangi kombinasyonun en başarılı sonucu verdiyse onu kullanabilirsin. Ben x1,x2,x5 değişkenlerini kullanacağım sadece çünkü en başarılı sonuç sadece bu 3 değişken kullandığımız zaman çıkmıştır diyebilirsin.

Peki biz her defasında bu 31 kombinasyonu deneyecek miyiz? Veya 5 değilde 100 değişkenimiz olursa 2^100 = #*? olursa ne yapacağız? Bu yöntem en sağlıklı yöntem olmakla birlikte en primif yöntemdir. Dolayısıyla tek bir modele karar vermek bile yıllar sürecek bir zaman ihtiyacını doğurur. Bu da gerçek hayatta mümkün değildir. Bu yönteminde bazı teknik detaylar ile birlikte alt dalları bulunmaktadır fakat o kadar detaya inmek bu yazının konusu değil.

İşte bu özellik seçme sürecinde elimizdeki uygulayabileceğimiz adımları uyguluyoruz ki doğru kombinasyonu en optimum şekilde seçelim. Her açıdan tasarruf edeceğimiz ve doğru sonuca ulaşabileceğimiz bir yapı kuralım. Yapacağımız şey tam olarak budur.

Şekil-1 : Bu kadar veriden hangilerini seçeceğim?

NEDEN İHTİYACIMIZ VAR?

Neden değişkenleri seçmeye ihtiyacımız var ?

• Çok fazla değişken kullanmak modelin performansını düşürebilir. En iyi performans sonucu elde etmek için, en optimum değişkenleri belirleyip onlar ile model kurmak gerekir. Çok fazla değişken kullanmak her zaman iyi birşey değildir.

• Daha kolay anlaşılır model elde etmek için ihtiyacımız var. Modellerin çok karmaşık olması çok özenilir bir durum değildir, ne kadar basit ve açıklayıcı olursa o kadar iyidir diyebiliriz. Model sonuçlarını anlayarak ve ona göre de aksiyonlar belirlenip o modelden fayda sağlanmasıdır zaten amacımız. Model sonuçlarını gerçek hayata uygulamak daha kolay olacaktır.

• Daha hızlı çalışan model elde etmek için ihtiyacımız var. Örnek veri setlerinde çalışmanın dışında gerçek hayata geldiğimizde, sürekli çalışan ve sonuç üreten modellere ihtiyacımız olabilir ve o zaman modelin hız performansı çok önemli hale gelir. Özellik azaltarak model başarı performansından ödün vermeden daha hızlı çalışan modeller elde edebiliriz. Hatta bazen model başarı performansından az ölçüde feragat edip modelin hız performasını anlamlı ölçüde arttıracak sonuçları tercih edeceğimiz yerler olabilir.

• Aşırı öğrenme riskini azaltır. Çok fazla değişken ile model karmaşıklığı artarak ezberlemeye geçebilir. Daha az değişken kullanmak aşırı öğrenme riskini de azaltmış olur.

ÖZELLİK SEÇMEYE NEREDEN BAŞLARSIN?

Özellik seçmeden önce tabi ki elinde özellikler olmalı yani eğer kaggle gibi ortamlardan hazır aldıysan veriyi tabi ki özellikleri seçme aşamasına geçebilirsin. Ama kendi iş yerinde veya hayatında bir problem çözmek için bir işe başladıysan değişkenleri önce kendin oluşturman gerekecek. Bunun içinde en önemli ihtiyacın iş bilgisi olacak. Özellik oluşturma iş problemine göre çok fazla üzerine konuşulabilecek bir konu olabilir.

İlk olarak kuracağımız ML modeli ile ulaşmak istediğimiz sonucu açıklayabilecek olan değişkenleri, bizlerin iş bilgisi ve varsa geçmiş tecrübesi ile ortaya çıkarması gerekir. Tabi ki verinin kaynağını anlayarak ve keşif ederek ulaşabileceğimiz değişkenler de olabilir. Fakat burada analitik yok henüz, diyelim ki müşterinin çıkış ihtimalini yani churn durumunu hesaplamak istiyorsun, müşteriyi bu çıkışa götüren sebepleri ve adımları iyi bilip anlaman lazım. Ona göre de ham veriden değişken oluşturacak şekilde bir adım atarak işe başlayabilirsin. Eğer sen o önemli olabilecek, değer katabilecek değişkeni yani özelliği hiç almadıysan zaten onun model için anlamlı mı etkisi var mı yok diye değerlendiremeyeceksin.

Demografik özellikleri, hesap hareketleri, çağrı merkezi kayıtları ve belki müşterinin yaptığı ama sende olmayan dış kaynak verisi (ulaşılabilir ve izinli koşulu) gibi değişkenler senin model kuracağın değişkenler olacaktır. Model performansına yani doğru tahmin etmene yardım edecek her değişkeni kullanamak için düşünebilirsin.

ÖZELLİK SEÇME ELEME YÖNTEMLERİ

1) Temel Temizlik

i) Kayıp Değerleri olan değişkeni çıkart

İlgili değişkendeki kayıp değerleri belli bir seviyenin üstünde ise, örneğin %80’i boş ise o değişkeni modele girdi olarak vermek anlamsız olur. %20 si dolu fakat %80 boş kısım için bir model bir yorum yapamayacaktır. Burada kayıp değerlerini bir takım yöntemler ile doldurmakta çözümleri var fakat burada bahsettiğimiz yüksek seviyede kayıp değerler içeren ve kayıp değerleri doldurmanın performansının düşük olacağı durumlardan bahsediyoruz.

Örnek: Örnek olarak oluşturduğumuz ufak tablomuzda %80 üzerinde kayıp değer içeren özellik var ise onları bu şekilde eleyebiliriz. id_group özelliği yüzde 80’i boş olduğu için eleniyor. Parçalı şekilde adım adım çalıştırarak daha anlaşılır şekilde görebilirsin.

import pandas as pd
import numpy as np
df = pd.DataFrame({'group':list('aaaab'),
'val':[1,3,3,np.NaN,5],
'id_group':[1,np.NaN,np.NaN,np.NaN,np.NaN]})
df2 = df.loc[:, df.isnull().mean() < .8]
df2

ii) Tüm değerleri aynı olan kategorik değişkeni çıkart

Bunu da kayıp değerlere benzetebilirsiniz. Yukarıda %80 kayıp değerdi yani boş gözlemlerdi. Burada da kategorik değişkende %80’den fazla aynı içerik var. Mesela 100 gözleminiz var. Elinizde şehir değişkenin 80 tanesi İstanbul olan gözlem var. Model bu değişkende tabi ki yorum yapamayacaktır. Neredeyse hepsi İstanbul zaten ben bunu başka bir şehir ile karşılaştırmak için elimde yeterli örnek yok. Tüm müşterilerin adresi İstanbul ise hedef değişkenin şehire göre farkılaşan bir durumu zaten oluşmuyor. Değişken dediğimiz şey değişmiyor . 80 verdiğimiz sınır yorumlamanıza kontrollerinize göre değişebilir. Sizin veriniz için 90 daha doğru bir kısıt olabilir.

iii) Tüm değerleri farklı olan kategorik değişkeni çıkart

Eğer bir değişkende tüm gözlemler farklı ise model burada da bir bağıntı yakalayamaz. Yine aynı örnek üzerinden bakalım: 100 gözlemlik veri setinde şehir değişkeninde 81 ilimiz var ise sadece 18 tane gözlemde tekrar edecek. Modelin şehirler arasında hedef değişken için anlamlı bir fark bulabilmesi için yeterli sayıda örnek olması gerekir. Amasyadan 1 kişi ile Bursa’dan 1 kişi üzerinden modelin Bursa veya Amasya için bir karar vermesi yanlış olacaktır.

Örnek: 2.ve 3.madde için
Pythonda df.nunique() komutunu kullanarak dataframe’deki tüm değişkenlerin tekil sayılarını bulabilirsiniz ve satır sayınız ile karşılaştırıp eleme yapabilirsiniz. Sadece kategorik değişkenler için uygulamanız gerekir. Aynı probleme sayısal değişkenlerde varyans durumuna bakıyoruz.

df = pd.DataFrame({
'SözleşmeID': [101, 102, 103, 104, 105, 106, 107, 108],
'MüşteriSüre': [10, 11, 12, 10, 11, 10, 12, 10],
'Şehir': ['Bursa', 'Bursa', 'Kocaeli', 'Bursa', 'Bursa', 'Bursa', 'Bursa', 'Bursa'],
'FaturaTutar': ['100', '120', '110', '90', '80', '150', '45', '65']
})
df.dtypes
df.nunique()

iv) Düşük varyanslı değişkeni çıkart

Varyans tanımını hatırlayalım:
Bütün değerlerin ortalamadan uzaklıklarının karelerinin ortalaması şeklinde bulunan bir ölçüdür. Eğer ki bütün değerler aynı ise varyans = 0 olur. Yukarıda yazdığımız 2.madde ile aynı içerik sadece varyans sayısal değişken için kontrol ediyoruz. Yine örnek verelim, 100 gözlemlik bir veri setinde tüm müşterilerin yaşı 35 ise yaş değişkeni model için bir anlam ifade edebilir mi? Herkesin 35 yaşında olduğu bir veri setinde nasıl karşılaştırma yapabilirsin.

Örnek:
Örnekte 1.ve 4.gözlem değerleri varyansları 0 olduğu için veri setinden çıkartılmıştır. Varyans eşik değerini farklı bir sayı girerseniz ona göre eleme yapabilirsiniz. Burada varyans statistics kütüphanesindeki variance ile hesaplanıp işlemler ilerletilebilir fakat örneğimizde sklearn kütüphanesi altındaki feature_selection variancethreshold komutu ile yapıyoruz.

Örnekte 1.ve 4.gözlem değerleri varyansları 0 olduğu için veri setinden çıkartılmıştır. Varyans eşik değerini farklı bir sayı girerseniz ona göre eleme yapabilirsiniz. Burada varyans statistics kütüphanesindeki variance ile hesaplanıp işlemler ilerletilebilir fakat örneğimizde sklearn kütüphanesi altındaki feature_selection variancethreshold komutu ile yapıyoruz.

from sklearn.feature_selection import VarianceThreshold
X = [[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]]
selector = VarianceThreshold()
X1=selector.fit_transform(X)
X1

İlk 4 maddede değişkenleri sadece kendi içinde bir değerlendirmeye tabi tuttuk aslında bir takım veri temizliği gibi bu süreç. Buradaki adımları uygulamak çok karmaşık değil ve hızlı karar alınabilir adımlar. Değişkenlerin içerisinden çürükleri eledik gibi düşünebilirsiniz. Bu değişkenlerin kendi tutarsızlıkları ve dengesizlikleri var dolayısıyla model için anlamlı olmaları zaten düşünülemez.

2) Hedef Değişken ile Özelliklerin İlişkileri

Girdi değişkenlerinin hedef değişken ile olan ilişkisini istatiksel yöntemlerle tespit ederek en güçlü ilişkileri olan değişkenleri seçebiliriz. Yani aslında özelliklerden sadece o özellik elimizde olsaydı bu özelliğin değişimi hedef değişkeni ne kadar değiştirir sorusunun cevabına bakıyoruz.

Değişkenler arasında ilişkileri incelerken sayısal ve kategorik değişkenler için farklı yöntemler uygularız.


i) Pearson Korelasyonu
Korelasyon, iki değişkenin arasındaki doğrusal ilişkinin, değişiminin bir ölçüsüdür. Korelasyon katsayısı matematiksel olarak -1 ile +1 arasında değerler alır. Pearson Korelasyonunu kullanarak özellikler ile hedef değişken arasında bir ilişki var mı diye bakıyoruz. Sayısal değişkenler için kullanılır.

from sklearn.datasets import load_boston
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
x = load_boston()
df = pd.DataFrame(x.data, columns = x.feature_names)
df["MEDV"] = x.target
X = df.drop("MEDV",1)
#Özellikler
y = df["MEDV"]
#Hedef Değişken
df.head()
#Pearson Korelasyon
plt.figure(figsize=(12,10))
cor = df.corr()
sns.heatmap(cor, annot=True, cmap=plt.cm.Reds)
plt.show()
#Hedef değişken ile olan korelasyon
cor_target = abs(cor["MEDV"]) #korelasonu yönü önemli olmadığı şiddeti bizim için önemli o yüzden mutlak değerini alıyoruz.
#Yüksek korelasyonlu olanları seçme
relevant_features = cor_target[cor_target>0.5]
relevant_features

ii) Ki kare Testi

Ki kare testi kategorik değişkenler arasındaki ilişkiyi ölçmek için kullanılır. Chaid karar ağacı algoritması da model öncesi değişken seçiminde bu yöntemi kullanmaktadır. Ki-kare testini kullanarak, kategorik özellik ile hedef değişken arasında ilişkiyi ölçtükten sonra en iyi k kadar (SelectKBest) özelliği seç veya en iyi %k dilimine (SelectPercentile ) giren özellikleri seç diyebileceğimiz hazır fonksiyonlar vardır. SelectPercentile ve SelectKBest seçme yöntemi diğer methodlarda da kullanılabilir. Bunlar sadece seçme yöntemidir asıl ilişkiyi hesaplayan içerisindeki algoritmadır.

Her ikisinde de kullanımı görmek adına basit örnekleri verelim.

Örnek:

SelectKBest kullanarak:

#Kütüphaneleri ve datayı yükleme
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
iris_dataset = load_iris()
#Girdi ve Çıktı Değişkeni
X = iris_dataset.data
y = iris_dataset.target
#iris veri seti nümerik bir veri seti buradaki sayılar tam sayıya çevrilerek kategorik gibi algınlanması sağlanıyor. Aslında veriniz nümerikte olsa kategorik ifade edilebilir birşeye dönüştürebilirsiniz.
X = X.astype(int)
#Ki kare testine göre en iyi sonuç veren 2 özelliği seç
chi2_features = SelectKBest(chi2, k = 2)
X_kbest_features = chi2_features.fit_transform(X, y)
#Azaltılmış Özellikler
print('Orjinal Özellik Sayısı:', X.shape[1])
print('Seçilmiş Özellik Sayısı:', X_kbest_features.shape[1])

SelectPercentile kullanarak :

from sklearn.datasets import load_digits
from sklearn.feature_selection import SelectPercentile, chi2
X, y = load_digits(return_X_y=True)
X.shape
(1797, 64)
X_new = SelectPercentile(chi2, percentile=10).fit_transform(X, y)
X_new.shape
(1797, 7)

iii) Anova Testi

 Anova testi, 3 ya da daha çok grup arasında, belirli bir değişkene dayalı olarak farklılık olup olmadığını belirlemek amacıyla kullanılır.
Yani kategorik bir değişken ile sayısal bir değişken arasındaki ilişkiyi ölçmek için kullanırız. Kategorik değişkenin grupları arasındaki değişim ile sayısal değişkeni anlamlı olarak değiştiriyor mu diye bakabiliriz. Bunun için scikit_learn kütüphanesinde f_classif fonksiyonunu kullanıyoruz.

Burada seçme işlemini SelectKBest ile yapıcaz, SelectPercentile ile ilgili yukarıda kullanım şekli için örnek vermiştik.

Örnek:

from sklearn.datasets import make_classification
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif
#generate dataset
X, y = make_classification(n_samples=100, n_features=20, n_informative=2)
#define feature selection
fs = SelectKBest(score_func=f_classif, k=2)
#apply feature selection
X_selected = fs.fit_transform(X, y)
print(X.shape)
print(X_selected.shape)

iv) Bilgi Kazancı (Information Gain)

Bilgi Kazancı (Information Gain): Bilgi kazancı dediğimiz metot, her özellik ile hedef değişkeni açıklayıcılığını ölçer. ID3, C4.5 gibi karar ağacı algoritmasıda bilgi kazancı kullanarak çalışır. Bilgi Kazancı ölçümünde entropi kullanılır. Entropi dediğimz şeyde aslında kısaca düzensizliği ölçer diyebiliriz.

from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_selection import mutual_info_classif
from sklearn.feature_extraction.text import CountVectorizer
categories = [‘talk.religion.misc’,
‘comp.graphics’, ‘sci.space’]
newsgroups_train = fetch_20newsgroups(subset=’train’,
categories=categories)
X, Y = newsgroups_train.data, newsgroups_train.target
cv = CountVectorizer(max_df=0.95, min_df=2,
max_features=10000,
stop_words=’english’)
X_vec = cv.fit_transform(X)
res = dict(zip(cv.get_feature_names(),
mutual_info_classif(X_vec, Y, discrete_features=True)
))
print(res)
Şekil-2: Hangi veri tipi hangi yöntem

SONUÇ

Temel temizlik ve istatistiksel yöntemlere göre değişken eleme ve seçme işlemlerini işledik. Temel temizlik adımları mutlaka yapılması gereken adımlardır. İstatiksel yöntemlere geldiğinizde, istatistik kelimesini duyduğunuzda varsayımları mutlaka aklımıza getirmemiz gerekir. Yukarıdaki yöntemlerin varsayımları vardır. Anova ‘da varyansların homojenliği varsayımı önemlidir. Pearson’s veriler normal dağılım gösteriyorsa kullanılır ama normal dağılım göstermiyor ise Spearmans’s yöntemi kullanılır. Bunlar bu yöntemleri uygularken dikkat etmemiz gereken ve incelik ile bakmamız gereken konulardır. Akademik dışında varsayımların pekte kontrol edildiği söylenemez ama yapılması gereken budur.

Veri temizleme ve özellik seçme alanında uygulamalar yaptıkça bu yazdığımız adımlar konusunda pratiklik kazanılacaktır. Kendi problemleriniz için de yöntemlerin detaylarına inip araştırma yapma ihtiyaçları olabilir.

Yukarıdaki Şekil-2, istatiksel yöntemlerin hangi veri tiplerinde kullanılacağını gösteren bir görsel, kafalar karıştığında buradan kontrol ederek ilerlemek faydalı olacaktır.

Özellik seçiminin 2. yazısında görüşmek dileğiyle, gelişim için sorularınız ve yorumlarınız olursa çok memnun olurum.

Kaynak:

https://www.geeksforgeeks.org/ml-chi-square-test-for-feature-selection/
https://towardsdatascience.com/feature-selection-with-pandas-e3690ad8504
https://stackoverflow.com/questions/46752650/information-gain-calculation-with-scikit-learn

 

Yazar Hakkında
Toplam 8 yazı
Taner Kocakafa
Taner Kocakafa
Yıldız Teknik Üniversitesi İstatistik Bölümü Mezunu. 2012’den beri perakende ve sigorta sektöründe analitik konularında çalışmıştır. Şirket içi analitik bakış açısı ve analitik araçlarla ilgili eğitimler vermektedir.
Yorumlar (1 Yorum)
Ali Hakan Büyüklü
Ali Hakan Büyüklü Yanıtla
- 10:23

Merhaba Taner,
Başarılar dilerim. Güzel olmuş.
Ali Hakan Büyüklü

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

×

Bir Şeyler Ara