การจัดกลุ่มข้อมูลเชิงหมวดหมู่ sklearn

ฉันใช้ฟังก์ชันการจัดกลุ่ม sklearn และ agglomerative ฉันมีข้อมูลแบบผสมซึ่งรวมถึงคอลัมน์ข้อมูลทั้งตัวเลขและระบุ คอลัมน์ที่ระบุของฉันมีค่าเช่น "เช้า" "บ่าย" "เย็น" "กลางคืน" ถ้าฉันแปลงข้อมูลที่ระบุเป็นตัวเลขโดยกำหนดค่าจำนวนเต็มเช่น 0,1,2,3; ระยะทางยุคลิดจะคำนวณเป็น 3 ระหว่าง "กลางคืน" และ "เช้า" แต่ 1 ควรส่งคืนค่าเป็นระยะทาง

X = pd.read_csv("mydata.csv", sep=",", header=0, encoding="utf-8")
X = StandardScaler().fit_transform(X)
print("n_samples: %d, n_features: %d" % X.shape)

km = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='average')
km.fit(X)

print("k = %d,  Silhouette Coefficient: %0.3f" % (x,
   metrics.silhouette_score(X, km.labels_, sample_size=None)))

นี่คือรหัสของฉัน

ฉันจะปรับแต่งฟังก์ชันระยะทางใน sklearn หรือแปลงข้อมูลที่ระบุเป็นตัวเลขได้อย่างไร


person eaytan    schedule 13.11.2018    source แหล่งที่มา
comment
คุณสามารถใช้ labelencoder sklearn ในตัวได้ไหม   -  person G. Anderson    schedule 14.11.2018
comment
คุณต้องการใช้ OneHotEncoder จริงๆ   -  person Andreas Mueller    schedule 14.11.2018


คำตอบ (2)


ฉันคิดว่าคุณมี 3 ตัวเลือกในการแปลงคุณสมบัติหมวดหมู่เป็นตัวเลข:

  1. ใช้ OneHotEncoder คุณจะแปลงคุณลักษณะหมวดหมู่เป็นสี่คอลัมน์ใหม่ โดยจะมีเพียง 1 หนึ่งคอลัมน์และคอลัมน์อื่นๆ 0 ปัญหาคือความแตกต่างระหว่าง "เช้า" และ "บ่าย" นั้นเหมือนกับ "เช้า" และ "เย็น"
  2. ใช้ OrdinalEncoder คุณแปลงคุณลักษณะตามหมวดหมู่ให้เป็นคอลัมน์เดียว "เช้า" ถึง 1, "บ่าย" ถึง 2 เป็นต้น ความแตกต่างระหว่าง "เช้า" และ "บ่าย" จะน้อยกว่า "เช้า" และ "เย็น" ซึ่งก็ดี แต่ความแตกต่างระหว่าง "เช้า" และ "กลางคืน" จะ ยิ่งใหญ่ที่สุดซึ่งอาจไม่ใช่สิ่งที่คุณต้องการ
  3. ใช้การแปลงที่ฉันเรียกว่า two_hot_encoder มันคล้ายกับ OneHotEncoder มีเพียง 1 สองอันในแถว ความแตกต่างระหว่าง ความแตกต่างระหว่าง "เช้า" และ "บ่าย" จะเหมือนกับความแตกต่างระหว่าง "เช้า" และ "กลางคืน" และจะน้อยกว่าความแตกต่างระหว่าง "เช้า" และ "เย็น" ฉันคิดว่านี่เป็นทางออกที่ดีที่สุด ตรวจสอบรหัส

รหัส:

def two_hot(x):
    return np.concatenate([
        (x == "morning") | (x == "afternoon"),
        (x == "afternoon") | (x == "evening"),
        (x == "evening") | (x == "night"),
        (x == "night") | (x == "morning"),
    ], axis=1).astype(int)

x = np.array([["morning", "afternoon", "evening", "night"]]).T
print(x)
x = two_hot(x)
print(x)

เอาต์พุต:

[['morning']
 ['afternoon']
 ['evening']
 ['night']]
[[1 0 0 1]
 [1 1 0 0]
 [0 1 1 0]
 [0 0 1 1]]

จากนั้นเราสามารถวัดระยะทางได้:

from sklearn.metrics.pairwise import euclidean_distances
euclidean_distances(x)

เอาท์พุท:

array([[0.        , 1.41421356, 2.        , 1.41421356],
       [1.41421356, 0.        , 1.41421356, 2.        ],
       [2.        , 1.41421356, 0.        , 1.41421356],
       [1.41421356, 2.        , 1.41421356, 0.        ]])
person Tomáš Přinda    schedule 14.11.2018
comment
แม้ว่าตอนเช้าตามลำดับเวลาควรจะใกล้กับช่วงบ่ายมากกว่าตอนเย็น แต่ในเชิงคุณภาพในข้อมูลอาจไม่มีเหตุผลที่จะสรุปได้ว่าเป็นเช่นนั้น การเข้ารหัสแบบ hot หนึ่งครั้งปล่อยให้เครื่องคำนวณว่าหมวดหมู่ใดคล้ายกันมากที่สุด ฉันชอบแนวคิดเบื้องหลังวิธีการเข้ารหัสสุดฮอตสองวิธีของคุณ แต่อาจบังคับให้สมมติฐานของตนเองเข้าสู่ข้อมูล - person jwil; 14.11.2018
comment
คุณพูดถูกว่ามันขึ้นอยู่กับงาน สำหรับงานบางอย่าง การพิจารณาแต่ละวันแตกต่างกันอาจเป็นการดีกว่า แต่คำสั่ง One hot encoding ปล่อยให้เครื่องคำนวณว่าหมวดหมู่ใดคล้ายกันมากที่สุดนั้นไม่เป็นความจริงสำหรับการทำคลัสเตอร์ การจัดกลุ่มจะคำนวณคลัสเตอร์ตามระยะทางของตัวอย่าง ซึ่งขึ้นอยู่กับคุณลักษณะต่างๆ ดังนั้นเราจึงควรออกแบบคุณลักษณะเพื่อให้ตัวอย่างที่คล้ายกันควรมีเวกเตอร์คุณลักษณะที่มีระยะทางสั้น - person Tomáš Přinda; 15.11.2018

ปัญหานี้เกิดขึ้นกับแอปพลิเคชันการเรียนรู้ของเครื่อง คุณต้องกำหนดหมวดหมู่หนึ่งเป็นหมวดหมู่พื้นฐาน (ไม่สำคัญว่าหมวดหมู่ใด) จากนั้นจึงกำหนดตัวแปรตัวบ่งชี้ (0 หรือ 1) สำหรับแต่ละหมวดหมู่อื่นๆ กล่าวอีกนัยหนึ่ง ให้สร้างตัวแปรใหม่ 3 ตัวที่เรียกว่า "เช้า" "บ่าย" และ "เย็น" แล้วกำหนดตัวแปรหนึ่งให้กับหมวดหมู่ใดก็ตามที่แต่ละการสังเกตการณ์มี หากเป็นการสังเกตการณ์ตอนกลางคืน ให้ปล่อยให้ตัวแปรใหม่แต่ละตัวเป็น 0

person jwil    schedule 13.11.2018