Каков хороший способ преобразовать циклические порядковые атрибуты?

21

У меня есть поле «час» в качестве моего атрибута, но оно принимает циклические значения. Как я мог преобразовать функцию, чтобы сохранить информацию, как '23' и '0' час близки.

Один способ, которым я мог бы подумать, - это сделать преобразование: min(h, 23-h)

Input: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]

Output: [0 1 2 3 4 5 6 7 8 9 10 11 11 10 9 8 7 6 5 4 3 2 1]

Есть ли какой-нибудь стандарт для обработки таких атрибутов?

Обновление: я буду использовать обучение под наблюдением, чтобы обучить классификатор случайных лесов!

Мангат Рай Моди
источник
1
Отличный первый вопрос! Можете ли вы добавить больше информации о том, какова ваша цель, чтобы осуществить это преобразование конкретной функции? Намереваетесь ли вы использовать эту преобразованную функцию в качестве входа в контролируемую проблему обучения? Если это так, рассмотрите возможность добавления этой информации, поскольку она может помочь другим лучше ответить на этот вопрос.
Нитеш
1
@Nitesh, пожалуйста, смотрите обновление
Мангат Рай Моди
Вы можете найти ответы здесь: datascience.stackexchange.com/questions/4967/…
MrMeritology
Извините, но я не могу комментировать. @ AN6U5 Не могли бы вы рассказать о том, как одновременно считать день недели и час после вашего удивительного подхода? Я борюсь с этим уже неделю, и я также опубликовал вопрос, но вы его не читали.
Сеймур

Ответы:

33

Наиболее логичный способ преобразования часа - это две переменные, которые качаются взад-вперед из раковины. Представьте себе положение конца часовой стрелки на 24-часовых часах. В xкачаются позиции вперед и назад из раковины с yпозицией. Для 24-часовой вы можете сделать это с x=sin(2pi*hour/24), y=cos(2pi*hour/24).

Вам нужны обе переменные или правильное движение во времени потеряно. Это связано с тем, что производная от sin или cos изменяется во времени, когда (x,y)положение плавно меняется при перемещении по единичному кругу.

Наконец, подумайте, стоит ли добавлять третью функцию для отслеживания линейного времени, которая может быть построена из моих часов (или минут или секунд) с начала первой записи, или с отметкой времени Unix, или с чем-то подобным. Эти три функции затем обеспечивают прокси как для циклической, так и для линейной прогрессии времени, например, вы можете вытянуть циклическое явление, такое как циклы сна в движении людей, а также линейный рост, например, численность населения и время.

Надеюсь это поможет!

Добавим соответствующий пример кода, который я сгенерировал для другого ответа:

Пример выполнения:

# Enable inline plotting
%matplotlib inline

#Import everything I need...

import numpy as np
import matplotlib as mp

import matplotlib.pyplot as plt
import pandas as pd

# Grab some random times from here: https://www.random.org/clock-times/
# put them into a csv.
from pandas import DataFrame, read_csv
df = read_csv('/Users/angus/Machine_Learning/ipython_notebooks/times.csv',delimiter=':')
df['hourfloat']=df.hour+df.minute/60.0
df['x']=np.sin(2.*np.pi*df.hourfloat/24.)
df['y']=np.cos(2.*np.pi*df.hourfloat/24.)

df

введите описание изображения здесь

def kmeansshow(k,X):

    from sklearn import cluster
    from matplotlib import pyplot
    import numpy as np

    kmeans = cluster.KMeans(n_clusters=k)
    kmeans.fit(X)

    labels = kmeans.labels_
    centroids = kmeans.cluster_centers_
    #print centroids

    for i in range(k):
        # select only data observations with cluster label == i
        ds = X[np.where(labels==i)]
        # plot the data observations
        pyplot.plot(ds[:,0],ds[:,1],'o')
        # plot the centroids
        lines = pyplot.plot(centroids[i,0],centroids[i,1],'kx')
        # make the centroid x's bigger
        pyplot.setp(lines,ms=15.0)
        pyplot.setp(lines,mew=2.0)
    pyplot.show()
    return centroids

Теперь давайте попробуем это:

kmeansshow(6,df[['x', 'y']].values)

введите описание изображения здесь

Вы едва можете увидеть, что некоторые из них после полуночи включены в зеленый кластер до полуночи. Теперь давайте уменьшим количество кластеров и покажем, что до и после полуночи можно более подробно подключиться к одному кластеру:

kmeansshow(3,df[['x', 'y']].values)

введите описание изображения здесь

Посмотрите, как синий кластер содержит моменты времени до и после полуночи, которые объединены в одном кластере ...

QED!

AN6U5
источник
Прекрасный способ справиться с этим. Это дало бы 0 и 23 часа аналогичные оценки, но не сделает ли это также время в AM / PM? Который фактически отделен 12-часовым окном.
Мангат Рай Моди
12-часовое (AM / PM) время не работает, просто конвертируйте его в 24-часовое время.
AN6U5
Я только заметил, что вы делите на 24. Когда вы дали аналогию с часами, я подумал, что это стандартные 12-часовые часы. Однако вы берете 24-часовые часы. Кажется, это лучший способ для меня. Спасибо!
Мангат Рай Моди
Удивительный ответ. Именно то, что я искал, Спасибо ..
Aditya
Принятый ответ, сочетающий в себе sin () и cost (), великолепен; здесь в качестве дополнения еще одно очень подробное и приятное объяснение этого Яна Лондона.
FlorianH
3

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

Обычно избегают иметь одну и ту же информацию в нескольких функциях, поскольку многие алгоритмы не могут справиться с этим. Но это не случайный лес. В отличие от линейной регрессии (и всех моделей, основанных на сходных идеях), случайные леса проверяют все функции, принимая во внимание каждую функцию по одному. Таким образом, можно кодировать одну и ту же информацию несколькими способами, не влияя на производительность обучения, только пространство и время выполнения.

(час+оееsеT)

Это тратит пространство и время, но я бы попробовал посмотреть, как это работает.

rapaio
источник
0

В идеале вам не нужно никаких преобразований. Относительная разница во времени между двумя точками может использоваться как функция расстояния. Где классификация может быть основана на этом.

в яве:

public class TimeDistanceMeasurer implements DistanceMeasure {

    @Override
    public double compute(double[] a, double[] b) throws DimensionMismatchException {
        String time1 = String.format("%02d", (int)a[0]) + String.format("%02d", (int)a[0]);
        String time2 = String.format("%02d", (int)b[0]) + String.format("%02d", (int)b[0]);

        SimpleDateFormat format = new SimpleDateFormat("HHmm");
        try {
            Date date1 = format.parse(time1);
            Date date2 = format.parse(time2);
            return Math.abs(date2.getTime() - date1.getTime());
        } catch (Exception e) {
            throw new IllegalStateException("Something went wrong.", e);
        }
    }
}
shiva.n404
источник
1
Все в порядке, но вопрос требует чего-то другого ..
Адитья