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 или преобразовать мои номинальные данные в числовые?

Можно ли использовать встроенный склеарн Лабеленкодер?

G. Anderson 13.11.2018 22:04

Вы действительно хотите использовать OneHotEncoder.

Andreas Mueller 14.11.2018 02:15
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
2
14 049
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Ответ принят как подходящий

Я думаю, у вас есть 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.        ]])

Хотя в хронологическом порядке утро должно быть ближе к полудню, чем, например, к вечеру, качественно в данных может не быть оснований предполагать, что это так. Одно горячее кодирование позволяет машине вычислить, какие категории наиболее похожи. Мне нравится идея, лежащая в основе ваших двух методов горячего кодирования, но она может навязывать данные вашим собственным предположениям.

jwil 14.11.2018 17:40

Вы правы, это зависит от задачи. Для некоторых задач может быть лучше рассматривать каждый день по-разному. Но утверждение: «Одно горячее кодирование позволяет машине вычислять, какие категории наиболее похожи» неверно для кластеризации. Кластеризация вычисляет кластеры на основе расстояний примеров, которые основаны на функциях. Таким образом, мы должны проектировать функции таким образом, чтобы аналогичные примеры имели векторы функций с коротким расстоянием.

Tomáš Přinda 15.11.2018 07:21

Другие вопросы по теме