Clustering für gemischte numerische und nominale diskrete Daten

9

Meine Daten enthalten binäre (numerische) und nominelle / kategoriale Umfrageantworten. Alle Antworten sind diskret und auf individueller Ebene.Momentaufnahme der Daten

Die Daten haben eine Form (n = 7219, p = 105).

Paar Dinge:

  • Ich versuche, eine Clustering-Technik mit einem Ähnlichkeitsmaß zu identifizieren, das für kategoriale und numerische Binärdaten funktioniert. Es gibt Techniken in R kmodes Clustering und kprototype, die für diese Art von Problem entwickelt wurden, aber ich verwende Python und benötige eine Technik aus sklearn Clustering, die bei dieser Art von Problemen gut funktioniert.

  • Ich möchte Profile von Segmenten von Individuen erstellen. Dies bedeutet, dass sich diese Gruppe von Personen mehr um diese Funktionen kümmert.

km
quelle
Ich glaube nicht, dass ein Clustering aussagekräftige Ergebnisse für solche Daten liefert. Stellen Sie sicher, dass Sie Ihre Ergebnisse validieren . Beachten Sie auch die Implementierung eines Algorithmus selbst, und trägt es zu sklearn. Sie können jedoch versuchen, z. B. DBSCAN mit Würfelkoeffizienten oder eine andere Distanzfunktion für binäre / kategoriale Daten zu verwenden .
Hat aufgehört - Anony-Mousse
1
In diesen Fällen ist es üblich, kategorial in numerisch umzuwandeln. Siehe hier scikit-learn.org/stable/modules/generated/… . Auf diese Weise haben Sie jetzt nur Binärwerte in Ihren Daten, sodass beim Clustering keine Skalierungsprobleme auftreten. Sie können jetzt ein einfaches k-Mittel ausprobieren.
Vielleicht wäre dieser Ansatz nützlich: zeszyty-naukowe.wwsi.edu.pl/zeszyty/zeszyt12/…
Sie sollten von der einfachsten Lösung ausgehen, indem Sie versuchen, die kategorialen Darstellungen in One-Hot-Coding-Darstellungen wie oben angegeben zu konvertieren.
Geompalik
Dies ist das Thema meiner 1986 am IBM France Scientific Center und der Pierre et Marie Currie-Universität (Paris 6) verfassten Doktorarbeit mit dem Titel Neue Codierungs- und Assoziationstechniken bei der automatischen Klassifizierung. In dieser Arbeit schlug ich Datencodierungstechniken vor, die als Triordonnance bezeichnet werden, um eine Menge zu klassifizieren, die durch numerische, qualitative und ordinale Variablen beschrieben wird.
Sagte Chah Slaoui

Antworten:

8

Einen Stich machen:

Ich versuche, eine Clustering-Technik mit einem Ähnlichkeitsmaß zu identifizieren, das für kategoriale und numerische Binärdaten funktioniert.

Gower Distance ist eine nützliche Entfernungsmetrik, wenn die Daten sowohl kontinuierliche als auch kategoriale Variablen enthalten.

Es gibt Techniken in R kmodes Clustering und kprototype, die für diese Art von Problem entwickelt wurden, aber ich verwende Python und benötige eine Technik aus sklearn Clustering, die bei dieser Art von Problemen gut funktioniert.

Ich konnte keine Implementierung von Gower Distance in Python finden, als ich vor ungefähr 4-5 Monaten danach suchte. Also habe ich mir eine eigene Implementierung ausgedacht.

import pandas as pd
import numpy as np
from sklearn.neighbors import DistanceMetric


def gower_distance(X):
    """
    This function expects a pandas dataframe as input
    The data frame is to contain the features along the columns. Based on these features a
    distance matrix will be returned which will contain the pairwise gower distance between the rows
    All variables of object type will be treated as nominal variables and the others will be treated as 
    numeric variables.
    Distance metrics used for:
    Nominal variables: Dice distance (https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient)
    Numeric variables: Manhattan distance normalized by the range of the variable (https://en.wikipedia.org/wiki/Taxicab_geometry)
    """
    individual_variable_distances = []

    for i in range(X.shape[1]):
        feature = X.iloc[:,[i]]
        if feature.dtypes[0] == np.object:
            feature_dist = DistanceMetric.get_metric('dice').pairwise(pd.get_dummies(feature))
        else:
            feature_dist = DistanceMetric.get_metric('manhattan').pairwise(feature) / np.ptp(feature.values)

        individual_variable_distances.append(feature_dist)

    return np.array(individual_variable_distances).mean(0)

Der Link zum selben Code: https://github.com/matchado/Misc/blob/master/gower_dist.py

In Bezug auf die Clustering-Technik habe ich die von Ihnen erwähnten nicht verwendet. Aber ich habe in der Vergangenheit mit Erfolg hierarchisches Clustering in R zusammen mit Gower-Distanz verwendet.

Mit Blick auf die in scikit learn verfügbaren Clustering-Techniken scheint Agglomerative Clustering genau das Richtige für Sie zu sein. http://scikit-learn.org/stable/modules/clustering.html#hierarchical-clustering

Ich möchte Profile von Segmenten von Individuen erstellen. Dies bedeutet, dass sich diese Gruppe von Personen mehr um diese Funktionen kümmert.

Nachdem Sie jeder Zeile Ihrer Daten Cluster-Labels zugewiesen haben, überprüfen Sie für jeden Cluster die Verteilung der Features (Zusammenfassungsstatistiken für kontinuierliche Variablen und Häufigkeitsverteilungen für kategoriale Variablen). Dies ist einfacher visuell zu analysieren, wenn Ihre Anzahl von Funktionen verwaltbar ist (<20 vielleicht?).

Da Sie jedoch über 100 Funktionen verfügen, empfehle ich einen besser organisierten Ansatz. Erstellen Sie eine Matrix mit Cluster-Beschriftungen in den Spalten und der Zusammenfassung der Features in den Zeilen (ich empfehle, den Median für die kontinuierliche Variable und das prozentuale Auftreten des häufigsten Werts im Cluster für die kategoriale Variable zu verwenden).

Es könnte ungefähr so ​​aussehen.

╔═══════════════════════╦═══════════╦═══════════╦════╦═══════════╗
║        Feature        ║ Cluster 1 ║ Cluster 2 ║ …  ║ Cluster N ║
╠═══════════════════════╬═══════════╬═══════════╬════╬═══════════╣
║ Numeric feature 1     ║ 15        ║ 37        ║ .. ║ 1         ║
║ Numeric feature 2     ║ 34        ║ 56        ║ …  ║ 56        ║
║ Categorical feature 1 ║ 47%       ║ 87%       ║ …  ║ 25%       ║
║ …                     ║ …         ║ …         ║ …  ║ …         ║
║ Categorical feature N ║ 25%       ║ 91%       ║ …  ║ 11%       ║
║ Numeric feature N     ║ 0.2       ║ 0.7       ║ …  ║ 0.5       ║
╚═══════════════════════╩═══════════╩═══════════╩════╩═══════════╝
Gregorymatchado
quelle
Solide Antwort, gut gemacht.
Astrid
Ausgezeichnet! Vielen Dank für Ihre Zeit
Gonzalo Garcia
2

Ich habe meine Antwort auf diese Frage unten angehängt - ihr habt im Wesentlichen dasselbe gefragt.


Diese Frage scheint wirklich Repräsentation zu sein und nicht so sehr Clustering.

Kategoriale Daten sind ein Problem für die meisten Algorithmen beim maschinellen Lernen. Angenommen, Sie haben beispielsweise eine kategoriale Variable namens "Farbe", die die Werte Rot, Blau oder Gelb annehmen könnte. Wenn wir diese einfach numerisch als 1,2 bzw. 3 codieren, wird unser Algorithmus annehmen, dass Rot (1) tatsächlich näher an Blau (2) liegt als an Gelb (3). Wir müssen eine Darstellung verwenden, die dem Computer verständlich macht, dass diese Dinge tatsächlich alle gleich unterschiedlich sind.

Eine einfache Möglichkeit besteht darin, eine so genannte One-Hot-Darstellung zu verwenden, und genau das, was Sie sich vorgestellt haben. Anstatt eine Variable wie "Farbe" zu haben, die drei Werte annehmen kann, teilen wir sie in drei Variablen auf. Dies wären "Farbe-Rot", "Farbe-Blau" und "Farbe-Gelb", die alle nur den Wert 1 oder 0 annehmen können.

Dies erhöht die Dimensionalität des Raums, aber jetzt können Sie einen beliebigen Clustering-Algorithmus verwenden. Es ist manchmal sinnvoll, die Daten nach diesem Vorgang zu bewerten oder aufzuhellen, aber Ihre Idee ist definitiv vernünftig.

Jordan A.
quelle
1

Die von @gregorymatchado implementierte Entfernungsmetrik weist einen Fehler auf. Bei numerischen Attributen gibt der Bereich durchgehend NaN für dieselben Werte an. Dafür brauchen wir max(np.ptp(feature.values),1)stattdessen eine Änderungsnutzung np.ptp(feature.values). Vollständiger Code unten:

import pandas as pd
import numpy as np
from sklearn.neighbors import DistanceMetric


def gower_distance(X):
"""
This function expects a pandas dataframe as input
The data frame is to contain the features along the columns. Based on these features a
distance matrix will be returned which will contain the pairwise gower distance between the rows
All variables of object type will be treated as nominal variables and the others will be treated as 
numeric variables.
Distance metrics used for:
Nominal variables: Dice distance (https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient)
Numeric variables: Manhattan distance normalized by the range of the variable (https://en.wikipedia.org/wiki/Taxicab_geometry)
"""
individual_variable_distances = []

for i in range(X.shape[1]):
    feature = X.iloc[:,[i]]
    if feature.dtypes[0] == np.object:
        feature_dist = DistanceMetric.get_metric('dice').pairwise(pd.get_dummies(feature))
    else:
        feature_dist = DistanceMetric.get_metric('manhattan').pairwise(feature) / max(np.ptp(feature.values),1)

    individual_variable_distances.append(feature_dist)

return np.array(individual_variable_distances).mean(0)
Rana
quelle
0

Ich denke du hast auch einen Bug. Wenn der Merkmalsvektor einen sehr kleinen Maßstab hat. dann ist deine Entfernung nutzlos. Also würde ich wie folgt konvertieren:

epsilon = 10**(-8)
... / max(np.ptp(feature.values), epsilon)
Oseong Kwon
quelle