Який хороший спосіб перетворити циклічні звичайні атрибути?


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, дивіться оновлення
Mangat Rai Modi

Відповіді ви можете знайти тут: datascience.stackexchange.com/questions/4967/…
MrMeritology

Вибачте, але я не можу коментувати. @ AN6U5 Ви можете, будь ласка, продовжити, як одночасно розглядати день тижня та годину, наступні за вашим дивовижним підходом? Я боюся з цим вже тиждень, і я також розмістив Q, але ви цього не прочитали.
Сеймур

Відповіді:


33

Найбільш логічний спосіб перетворити годину на дві змінні, які розгойдуються назад і назад з раковини. Уявіть положення кінця годинної руки цілодобового годинника. У 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!


Блискучий спосіб впоратися з цим. Це дасть 0 і 23 години подібних балів, але чи не це також зробить час ранку / вечора подібним? Що насправді розділено вікном 12 годин.
Mangat Rai Modi

Час 12 годин (AM / PM) не працює, просто перетворіть його на 24 години.
AN6U5

Я щойно помітив, що ти ділишся на 24. Коли ти дав аналогію годиннику, я подумав, що це стандартний 12-годинний годинник. Однак ви берете цілодобовий годинник. Мені здається, це найкращий спосіб трансформуватися. Дякую тобі!
Mangat Rai Modi

Дивовижна відповідь Саме те, що я шукав Спасибі ..
Aditya

Прийнята відповідь, що поєднує гріх () та вартість (), чудова; тут як доповнення до ще одного дуже детального та приємного пояснення цього Ian London.
FlorianH

3

Питання дуже цікаве, і я не пам’ятаю читати про цікаві відповіді. Через це я наважуюся дати вам одне можливе рішення, навіть якщо воно виглядає досить божевільним.

Зазвичай можна уникати отримання однакової інформації у кількох функціях, оскільки багато алгоритмів не можуть з цим впоратися. Але це не стосується випадкових лісів. Контрастна лінійна регресія (і всі моделі, засновані на подібних ідеях), випадкові ліси перевіряють усі особливості, беручи до уваги кожну особливість по черзі. Таким чином можна кодувати ту саму інформацію кількома способами, не впливаючи на продуктивність навчання, просто місце та час роботи.

(год+оffсет)

Це витрачає певний простір та час, але я б дав спробувати побачити, як це працює.


0

В ідеалі вам не потрібна якась трансформація. Відносна різниця в часі між двома точками може використовуватися як функція відстані. Де класифікація може ґрунтуватися на цьому.

в java:

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);
        }
    }
}

1
Все гаразд, але питання потребує чогось іншого ..
Aditya
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.