Nominal / dairesel değişkenler için SOM kümelemesi


11

Nominal girdileri kümelemeye aşina olup olmadığını merak etmek. SOM'a bir çözüm olarak bakıyordum ama görünüşe göre sadece sayısal özelliklerle çalışıyor. Kategorik özellikler için herhangi bir uzantı var mı? Özellikle 'Haftanın Günleri'ni olası bir özellik olarak merak ediyordum. Tabii ki bunu sayısal bir özelliğe dönüştürmek mümkündür (yani Mon - Sun, 1-7 no'lu sayılara karşılık gelir), ancak Güneş ve Pzt (1 ve 7) arasındaki Öklid mesafesi, Pzt ile Salı (1 ve 2) arasındaki mesafe ile aynı olmaz. ). Herhangi bir öneri veya fikir çok takdir edilecektir.


(+1) çok ilginç bir soru
steffen

2
Döngüsel değişkenler en iyi Kompleks düzlemindeki birim çemberin elemanları olarak düşünülür. Bu nedenle, haftanın günlerini tecrübe(2jπben/7) , j=0,...,6 ; yani , (marul(0),günah(0)) , (marul(2π/7),günah(2π/7)) , ... (marul(12π/7),günah(12π/7)) .
whuber

1
daha sonra döngüsel değişkenlere özgü kendi mesafe matrisi kodlamak zorunda mıyım? sadece bu tür kümeleme için zaten var olan algoritmalar olup olmadığını merak ediyorum. thx
Michael

@Michael: Uygulamanız için uygun olan ve sadece DOW değil, verilerinizdeki tüm boyutlar üzerinde tanımlanan kendi mesafe metriğinizi belirtmek isteyeceğinize inanıyorum . Resmi olarak, x, y veri alanınızdaki noktaları belirtmek için, normal özelliklere sahip bir metrik işlev d (x, y) tanımlamanız gerekir: d (x, x) = 0, d (x, y) = d (y , x) ve d (x, z) <= d (x, y) + d (y, z). Bunu yaptıktan sonra, SOM'yi oluşturmak mekaniktir. Yaratıcı zorluk, d () yöntemini uygulamanıza uygun "benzerlik" kavramını yakalayacak şekilde tanımlamaktır.
Arthur Small

Yanıtlar:


7

Arka fon:

Saati dönüştürmenin en mantıklı yolu, senkronizasyondan ileri geri sallanan iki değişkendir. 24 saatlik saatin saat ibresinin sonunun pozisyonunu hayal edin. xKonum hali ile ileri eşitlenmemiş geri ypozisyonda. 24 saatlik saat biçimi için size bu başarabilirsiniz x=sin(2pi*hour/24), y=cos(2pi*hour/24).

Her iki değişkene de ihtiyacınız var veya zaman içinde doğru hareket kaybediliyor. Bunun nedeni, günah veya cos türevinin zaman içinde değişmesidir, oysa (x,y)pozisyon birim çemberin etrafında dolaşırken sorunsuz bir şekilde değişir.

Son olarak, ilk kaydın başlangıcından itibaren saat (veya dakika veya saniye) veya bir Unix zaman damgası veya benzeri bir şey olarak oluşturulabilecek doğrusal zamanı izlemek için üçüncü bir özellik eklemenin faydalı olup olmadığını düşünün. Bu üç özellik daha sonra zamanın hem döngüsel hem de doğrusal ilerlemesi için proxy sağlar; örneğin insanların hareketindeki uyku döngüleri gibi döngüsel olayları ve ayrıca nüfus ve zaman gibi lineer büyümeyi ortaya çıkarabilirsiniz.

Başarılı olup olmadığına örnek:

# Enable inline plotting
%matplotlib inline

#Import everything I need...

import numpy as np
import matplotlib as mp

import matplotlib.pyplot as plt
import pandas as pd

# Grab some random times from here: https://www.random.org/clock-times/
# put them into a csv.
from pandas import DataFrame, read_csv
df = read_csv('/Users/angus/Machine_Learning/ipython_notebooks/times.csv',delimiter=':')
df['hourfloat']=df.hour+df.minute/60.0
df['x']=np.sin(2.*np.pi*df.hourfloat/24.)
df['y']=np.cos(2.*np.pi*df.hourfloat/24.)

df

resim açıklamasını buraya girin

def kmeansshow(k,X):

    from sklearn import cluster
    from matplotlib import pyplot
    import numpy as np

    kmeans = cluster.KMeans(n_clusters=k)
    kmeans.fit(X)

    labels = kmeans.labels_
    centroids = kmeans.cluster_centers_
    #print centroids

    for i in range(k):
        # select only data observations with cluster label == i
        ds = X[np.where(labels==i)]
        # plot the data observations
        pyplot.plot(ds[:,0],ds[:,1],'o')
        # plot the centroids
        lines = pyplot.plot(centroids[i,0],centroids[i,1],'kx')
        # make the centroid x's bigger
        pyplot.setp(lines,ms=15.0)
        pyplot.setp(lines,mew=2.0)
    pyplot.show()
    return centroids

Şimdi deneyelim:

kmeansshow(6,df[['x', 'y']].values)

resim açıklamasını buraya girin

Gece yarısından önce yeşil gece kümesine dahil olan gece yarısından sonra zamanlar olduğunu neredeyse hiç görebilirsiniz. Şimdi kümelerin sayısını azaltalım ve gece yarısından önce ve sonra tek bir kümeye daha ayrıntılı olarak bağlanabileceğini gösterelim:

kmeansshow(3,df[['x', 'y']].values)

resim açıklamasını buraya girin

Mavi kümenin gece yarısından önce ve sonra aynı kümede birlikte kümelenmiş zamanları nasıl içerdiğini görün ...

Bunu zaman, haftanın günü, ayın haftası, ayın günü ya da sezonu veya herhangi bir şey için yapabilirsiniz.


Yardımcı oldu (+1). Bu dikdörtgen olmayan kare olan grafiklerin gerçekten önemli olduğu bir uygulamadır. Yazılımınızı bilmiyorum ama en boy oranını varsayılandan 1'e ayarlayabileceğinizi düşünüyorum.
Nick Cox

Bu @NickCox için doğru. Veya sadece
kafanızdaki

2

Genel olarak nominal değişkenler SOM'de kullanıldığında kukla kodlanır (örneğin, Pazartesi 0 için 0 için 1, Salı için vb. İle bir değişken).

Bitişik günlerin birleşik kategorilerini oluşturarak ek bilgiler ekleyebilirsiniz. Örneğin: Pazartesi ve Salı, Salı ve Çarşamba, vb. Bununla birlikte, verileriniz insan davranışıyla ilgili ise, Hafta içi ve Hafta Sonu kategorileri olarak kullanmak genellikle daha yararlıdır.


2

Nominal değişkenler için, bir nöral ağda veya elektrik mühendisliği bağlamında tipik kodlamaya "bir-sıcak" denir - 0'ların tümünün vektörü, bir 1 değişkenin değeri için uygun pozisyondadır. Örneğin, haftanın günleri için yedi gün vardır, bu nedenle tek sıcak vektörleriniz yedi uzunluktadır. Sonra Pazartesi [1 0 0 0 0 0 0], Salı [0 1 0 0 0 0 0] vb. Olarak temsil edilir.

Tim'in işaret ettiği gibi, bu yaklaşım, rastgele her bir boolean özellik vektörünü kapsayacak şekilde kolayca genelleştirilebilir; burada vektördeki her konum, verilerinizle ilgilenen bir özelliğe karşılık gelir ve konum, bunun varlığını veya yokluğunu göstermek için 1 veya 0'a ayarlanır. özellik.

İkili vektörleriniz olduğunda, Hamming mesafesi doğal bir metrik haline gelir, ancak Öklid mesafesi de kullanılır. Bir sıcak ikili vektörler için, SOM (veya başka bir fonksiyon tahmincisi) doğal olarak her vektör pozisyonu için 0 ile 1 arasında enterpolasyon yapar. Bu durumda, bu vektörler genellikle bir Boltzmann veya nominal değişken alanı üzerindeki softmax dağılımının parametreleri olarak muamele edilir; bu tedavi vektörleri bir çeşit KL ıraksama senaryosunda kullanmak için bir yol sağlar.

Devirli değişkenler çok daha karmaşıktır. Arthur'un yorumlarda söylediği gibi, değişkenin döngüsel doğasını içeren bir mesafe metriği tanımlamanız gerekir.


1

Haftanın gününün (dow) [0, 6] 'dan geçtiğini varsayarsak, verileri bir daireye yansıtmak yerine başka bir seçenek kullanmaktır:

dist = min(abs(dow_diff), 7 - abs(dow_diff))

Nedenini anlamak için aşağıyı bir saat olarak düşünün

  6  0
5      1
4      2
    3

6 ve 1 arasındaki fark 6 - 1 = 5 (1'den 6'ya kadar saat yönünde gidiyor) veya 7 - (6 - 1) = 2 olabilir. Her iki seçeneğin de en azını almak hile yapmalıdır.

Genel olarak şunları kullanabilirsiniz: min(abs(diff), range - abs(diff))


0

Haftanın Günlerini (ve Yılın Aylarını) yorumunda whuber'ın vurguladığı gibi bir grup (cos, sin) olarak başarıyla kodladım. Öklid mesafesinden daha fazla.

Bu, r'deki kod örneğidir:

circularVariable = function(n, r = 4){
 #Transform a circular variable (e.g. Month so the year or day of the week) into two new variables (tuple).
 #n = upper limit of the sequence. E.g. for days of the week this is 7.
 #r =  number of digits to round generated variables.
 #Return
 #
 coord = function(y){
   angle = ((2*pi)/n) *y
   cs = round(cos(angle),r)
   s = round(sin(angle),r)
   c(cs,s)
 }
 do.call("rbind", lapply((0:(n-1)), coord))
}

0 ile 6 arasındaki öklid mesafesi 0 ve 1'e eşittir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.