склеарн категориальная кластеризация данных - PullRequest
0 голосов
/ 13 ноября 2018

Я использую склеарн и функцию агломерационной кластеризации.У меня есть смешанные данные, которые включают числовые и номинальные столбцы данных.Мои номинальные столбцы имеют такие значения, как «Утро», «Полдень», «Вечер», «Ночь».Если я преобразую свои номинальные данные в числовые, присваивая целочисленные значения, такие как 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 или преобразовать мои номинальные данные в числовые?

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Я думаю, у вас есть 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.        ]])
0 голосов
/ 14 ноября 2018

Эта проблема характерна для приложений машинного обучения. Вам нужно определить одну категорию в качестве базовой (неважно, какую), а затем определить переменные индикатора (0 или 1) для каждой из других категорий. Другими словами, создайте 3 новые переменные с именами «Утро», «Полдень» и «Вечер» и назначьте единицу для каждой категории, к которой относится каждое наблюдение. Если это ночное наблюдение, оставьте каждую из этих новых переменных равной 0.

...