การจัดกลุ่ม SOM สำหรับตัวแปรระบุ / แบบวงกลม


11

เพียงแค่สงสัยว่าถ้าใครคุ้นเคยกับการจัดกลุ่มข้อมูลเข้าเล็กน้อย ฉันได้ดู SOM เป็นวิธีแก้ปัญหา แต่เห็นได้ชัดว่ามันทำงานได้เฉพาะกับคุณลักษณะตัวเลข มีส่วนขยายใด ๆ สำหรับคุณสมบัติหมวดหมู่หรือไม่ โดยเฉพาะฉันสงสัยเกี่ยวกับ 'Days of the Week' เป็นคุณลักษณะที่เป็นไปได้ แน่นอนว่ามันเป็นไปได้ที่จะแปลงให้เป็นคุณลักษณะเชิงตัวเลข (เช่นจันทร์ - อาทิตย์สอดคล้องกับเลข 1-7) อย่างไรก็ตามจากนั้นระยะทางแบบยุคลิดระหว่างดวงอาทิตย์และจันทร์ (1 และ 7) จะไม่เหมือนกับระยะทางจากจันทร์ถึงอังคาร (1 & 2) ) ข้อเสนอแนะหรือความคิดใด ๆ ที่จะได้รับการชื่นชมมาก


(+1) คำถามที่น่าสนใจมาก
steffen

2
ตัวแปรวงจรเป็นความคิดที่ดีที่สุดว่าเป็นองค์ประกอบของวงกลมหน่วยในระนาบเชิงซ้อน ดังนั้นจึงเป็นเรื่องธรรมดาที่จะทำแผนที่วันในสัปดาห์เพื่อพูด (คะแนน) คะแนน , ; ie , , , ...7)) j = 0 , , 6 ( cos ( 0 ) , sin ( 0 ) ) ( cos ( 2 π / 7 ) , sin ( 2 π / 7 ) ) ( cos ( 12 π / 7 ) , บาป( 12 π / 7 )exp(2jπi/7)j=0,,6(cos(0),sin(0))(cos(2π/7),sin(2π/7))(cos(12π/7),sin(12π/7))
whuber

1
ฉันต้องโค้ดเมทริกซ์ระยะทางของตัวเองแล้วเฉพาะกับตัวแปรวงจรหรือไม่ แค่สงสัยว่ามีอัลกอริทึมที่มีอยู่แล้วสำหรับการจัดกลุ่มประเภทนี้หรือไม่ ขอบคุณ
Michael

@Michael: ฉันเชื่อว่าคุณจะต้องการระบุการวัดระยะทางของคุณเองที่เหมาะสมกับแอปพลิเคชันของคุณและนั่นถูกกำหนดเหนือมิติข้อมูลทั้งหมดของคุณไม่ใช่แค่ DOW อย่างเป็นทางการโดยให้ x, y แสดงถึงจุดในพื้นที่ข้อมูลของคุณคุณจะต้องกำหนดฟังก์ชันเมตริก d (x, y) ด้วยคุณสมบัติปกติ: d (x, x) = 0, d (x, y) = d (y , x) และ d (x, z) <= d (x, y) + d (y, z) เมื่อคุณทำสิ่งนั้นเสร็จแล้วการสร้าง SOM เป็นกลไก ความท้าทายที่สร้างสรรค์คือการกำหนด d () ในลักษณะที่สะท้อนแนวคิด "ความคล้ายคลึงกัน" ที่เหมาะสมกับแอปพลิเคชันของคุณ
Arthur Small

คำตอบ:


7

พื้นหลัง:

วิธีที่สมเหตุสมผลที่สุดในการแปลงชั่วโมงคือตัวแปรสองตัวที่แกว่งไปมาระหว่างการซิงค์ ลองนึกภาพตำแหน่งของจุดสิ้นสุดของเข็มชั่วโมงของนาฬิกา 24 ชั่วโมง xชิงช้าตำแหน่งสำรองและออกจากซิงค์กับyตำแหน่ง สำหรับนาฬิกา 24 ชั่วโมงคุณสามารถทำสิ่งนี้ได้ด้วยx=sin(2pi*hour/24), y=cos(2pi*hour/24).

คุณต้องการตัวแปรทั้งสองหรือการเคลื่อนไหวที่เหมาะสมผ่านเวลาจะหายไป นี่คือความจริงที่ว่าอนุพันธ์ของบาปหรือการเปลี่ยนแปลงในเวลาในขณะที่(x,y)ตำแหน่งแตกต่างกันอย่างราบรื่นในขณะที่มันเดินทางไปรอบ ๆ หน่วยยูนิท

ในที่สุดพิจารณาว่ามันคุ้มค่าหรือไม่ที่จะเพิ่มคุณสมบัติที่สามเพื่อติดตามเวลาเชิงเส้นซึ่งสามารถสร้างเป็นชั่วโมง (หรือนาทีหรือวินาที) จากจุดเริ่มต้นของการบันทึกครั้งแรกหรือการประทับเวลา Unix หรือสิ่งที่คล้ายกัน คุณสมบัติทั้งสามนี้จะให้พร็อกซี่สำหรับทั้งความก้าวหน้าและเชิงเส้นของเวลาเช่นคุณสามารถดึงปรากฏการณ์วัฏจักรเช่นวงจรการนอนหลับในการเคลื่อนไหวของผู้คนและการเติบโตเชิงเส้นเช่นประชากรกับเวลา

ตัวอย่างของการสำเร็จ:

# 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

ป้อนคำอธิบายรูปภาพที่นี่

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

ตอนนี้ลองทำดู:

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

ป้อนคำอธิบายรูปภาพที่นี่

คุณเพิ่งจะเห็นว่ามีบางอย่างหลังเที่ยงคืนรวมอยู่ในคลัสเตอร์สีเขียวก่อนเที่ยงคืน ตอนนี้ขอลดจำนวนกลุ่มและแสดงว่าก่อนและหลังเที่ยงคืนสามารถเชื่อมต่อในคลัสเตอร์เดียวโดยมีรายละเอียดเพิ่มเติม:

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

ป้อนคำอธิบายรูปภาพที่นี่

ดูว่าคลัสเตอร์สีน้ำเงินประกอบด้วยเวลาที่มาจากก่อนและหลังเที่ยงคืนที่รวมเข้าด้วยกันในคลัสเตอร์เดียวกัน ...

คุณสามารถทำสิ่งนี้ได้ตามเวลาหรือวันของสัปดาห์หรือสัปดาห์ของเดือนหรือวันของเดือนหรือฤดูกาลหรืออะไรก็ได้


มีประโยชน์ (+1) นี่เป็นแอปพลิเคชั่นเดียวที่กราฟเป็นรูปสี่เหลี่ยมจัตุรัสไม่เป็นรูปสี่เหลี่ยมผืนผ้ามีความสำคัญจริงๆ ฉันไม่รู้ซอฟต์แวร์ของคุณ แต่ฉันคิดว่าคุณสามารถกำหนดอัตราส่วนภาพเป็น 1 ห่างจากค่าเริ่มต้น
Nick Cox

นั่นเป็นความจริง @NickCox หรือคุณสามารถทำการแปลงเชิงเส้นในหัวของคุณ ;-)
user1745038

2

ตัวแปรที่ใช้กันทั่วไปคือรหัสจำลองเมื่อใช้ใน SOM (เช่นหนึ่งตัวแปรสำหรับที่มี 1 สำหรับวันจันทร์ 0 ไม่ใช่วันจันทร์และอีกวันหนึ่งเป็นวันอังคารเป็นต้น)

คุณสามารถรวมข้อมูลเพิ่มเติมโดยสร้างหมวดหมู่รวมกันของวันที่อยู่ติดกัน ตัวอย่างเช่น: วันจันทร์และวันอังคารวันอังคารและวันพุธเป็นต้นอย่างไรก็ตามหากข้อมูลของคุณเกี่ยวข้องกับพฤติกรรมของมนุษย์มักจะมีประโยชน์มากกว่าในการใช้หมวดหมู่วันทำงานและวันหยุดสุดสัปดาห์


2

สำหรับตัวแปรเล็กน้อยการเข้ารหัสทั่วไปในเครือข่ายประสาทหรือบริบทวิศวกรรมไฟฟ้าเรียกว่า"one-hot" - เวกเตอร์ของ 0s ทั้งหมดโดยมี 1 1 อยู่ในตำแหน่งที่เหมาะสมสำหรับค่าของตัวแปร ตัวอย่างเช่นในวันของสัปดาห์มีเจ็ดวันดังนั้นเวกเตอร์ที่ร้อนแรงหนึ่งอันของคุณจะมีความยาวเจ็ด จากนั้นวันจันทร์จะแสดงเป็น [1 0 0 0 0 0 0], วันอังคารเป็น [0 1 0 0 0 0 0 0], ฯลฯ

ดังที่ทิมบอกใบ้วิธีการนี้สามารถสรุปได้อย่างง่ายดายเพื่อรวมเวกเตอร์คุณลักษณะบูลีนโดยพลการซึ่งแต่ละตำแหน่งในเวกเตอร์สอดคล้องกับคุณลักษณะที่น่าสนใจในข้อมูลของคุณและตำแหน่งถูกตั้งค่าเป็น 1 หรือ 0 เพื่อระบุว่ามีหรือไม่มี ลักษณะเฉพาะ.

เมื่อคุณมีเวกเตอร์เลขฐานสองระยะทางของหมิงจะกลายเป็นตัวชี้วัดตามธรรมชาติแม้ว่าจะใช้ระยะทางแบบยุคลิดเช่นกัน สำหรับเวกเตอร์ไบนารี่แบบหนึ่งที่มีความร้อน SOM (หรือตัวประมาณฟังก์ชั่นอื่น ๆ ) จะทำการสอดแทรกระหว่าง 0 และ 1 สำหรับแต่ละตำแหน่งเวกเตอร์โดยธรรมชาติ ในกรณีนี้เวกเตอร์เหล่านี้มักถูกใช้เป็นพารามิเตอร์ของการแจกจ่าย Boltzmann หรือ softmax เหนือพื้นที่ของตัวแปรที่กำหนด การรักษานี้ให้วิธีการใช้เวกเตอร์ในสถานการณ์ divergence KL บางประเภทเช่นกัน

ตัวแปรวงจรเป็นเรื่องยุ่งยากมาก ดังที่อาร์เธอร์กล่าวไว้ในความคิดเห็นคุณจะต้องกำหนดตัวชี้วัดระยะทางด้วยตัวคุณเองซึ่งรวมถึงลักษณะของวัฏจักรของตัวแปร


1

สมมติว่าวันในสัปดาห์ (dow) เปลี่ยนจาก [0, 6] แทนที่จะฉายข้อมูลลงในวงกลมอีกทางเลือกหนึ่งคือ:

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

เพื่อทำความเข้าใจว่าทำไมให้พิจารณาดาวโจนส์เป็นนาฬิกา

  6  0
5      1
4      2
    3

ความแตกต่างระหว่าง 6 และ 1 อาจเป็น 6 - 1 = 5 (เลื่อนตามเข็มนาฬิกาจาก 1 ถึง 6) หรือ 7 - (6 - 1) = 2 การเลือกตัวเลือกทั้งสองอย่างน้อยควรทำเคล็ดลับ

โดยทั่วไปคุณสามารถใช้: min(abs(diff), range - abs(diff))


0

ฉันเข้ารหัสเรียบร้อยแล้ววันของสัปดาห์ (และเดือนของปี) เป็น tuple ของ (cos, sin) ตามที่ whuber เน้นในความคิดเห็นของเขา กว่าระยะทางแบบยุคลิดที่ใช้

นี่คือตัวอย่างของรหัสใน r:

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 และ 6 เท่ากับ 0 และ 1

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.