sklearn категориальная кластеризация данных

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

Код:

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
Хотя в хронологическом порядке утро должно быть ближе к полудню, чем, например, к вечеру, качественно в данных может не быть оснований предполагать, что это так. Одно горячее кодирование позволяет машине вычислить, какие категории наиболее похожи. Мне нравится идея, лежащая в основе ваших двух методов горячего кодирования, но она может навязывать данные вашим собственным предположениям. - person jwil; 14.11.2018
comment
Вы правы, это зависит от задачи. Для некоторых задач может быть лучше рассматривать каждый день по-разному. Но утверждение «Одно горячее кодирование» позволяет машине вычислять, какие категории наиболее похожи, неверно для кластеризации. Кластеризация вычисляет кластеры на основе расстояний примеров, которые основаны на функциях. Таким образом, мы должны проектировать функции таким образом, чтобы аналогичные примеры имели векторы функций с коротким расстоянием. - person Tomáš Přinda; 15.11.2018

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

person jwil    schedule 13.11.2018