Machine Learning Academy · Oppitunti

Päivämäärä- ja aikapiirteiden erottaminen

Oppijat purkavat datetime-sarakkeet vuodeksi, kuukaudeksi, viikonpäiväksi ja tunniksi sekä muodostavat sykliset sini- ja kosinikoodaukset jaksollisuuden kuvaamiseksi.

Oppitunti 2/413 vaihetta

Päivämäärä- ja aikapiirteiden erottaminen on ilmainen Machine Learning Academy-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Machine Learning Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Machine Learning Academy-kurssilla on yhteensä 4 oppituntia.

Miksi raakaaikaleimat ovat hyödyttömiä

Raaka Unix-aikaleima, kuten 1718784000, tai datetime-merkkijono, kuten '2024-06-19 14:30:00', sisältää runsaasti tietoa — vuorokaudenajan, viikonpäivän ja kuukauden — mutta malli ei voi käyttää tätä tietoa suoraan raaka-arvosta. Lineaarinen malli näkee aikaleiman yhtenä suurena kokonaislukuna ja voi oppia vain, että myöhemmät aikaleimat ennustavat suurempia tai pienempiä kohdearvoja, mutta se ei havaitse jaksollisia kuvioita. Ominaisuuksien poiminta pilkkoo aikaleiman mielekkäiksi numeerisiksi osiksi, joita mallit voivat käyttää suoraan.

Datetime-sarakkeiden jäsentäminen Pandasilla

Jäsentäkää päivämäärä- ja aika-arvot aina pd.Timestamp- tai datetime64-tyyppisiksi käyttämällä pd.to_datetime()-funktiota ennen ominaisuuksien poimimista. Jäsennyksen jälkeen Pandas tarjoaa .dt-aksessorin, jossa on kymmeniä attribuutteja: .dt.year, .dt.month, .dt.day, .dt.hour, .dt.minute, .dt.dayofweek (0=maanantai), .dt.dayofyear, .dt.quarter, .dt.is_weekend ja monia muita. Jokaisesta attribuutista tulee uusi kokonaislukusarake ominaisuusmatriisiin.

import pandas as pd

dates = pd.Series(['2024-01-15 08:30:00', '2024-06-21 17:45:00', '2024-12-25 12:00:00'])
dts = pd.to_datetime(dates)

df = pd.DataFrame({
    'year': dts.dt.year,
    'month': dts.dt.month,
    'day': dts.dt.day,
    'hour': dts.dt.hour,
    'dayofweek': dts.dt.dayofweek,  # 0=Mon, 6=Sun
    'quarter': dts.dt.quarter,
    'is_weekend': (dts.dt.dayofweek >= 5).astype(int)
})
print(df.to_string())

Raakojen jaksollisten ominaisuuksien ongelma

Tunnit 23 ja 0 ovat vierekkäisiä (vain tunnin päässä toisistaan), mutta numeerisesti kaukana toisistaan (23 yksikköä). Jos tunti koodataan kokonaislukuna välillä 0–23, lineaarinen malli ei voi oppia, että keskiyön kuviot muistuttavat kello 23:n kuvioita. Sama koskee kuukausia (joulukuu ja tammikuu ovat vierekkäisiä), viikonpäiviä (sunnuntai=6 ja maanantai=0) ja kaikkia muita jaksollisia suureita. Näiden käsitteleminen raakoina kokonaislukuina luo jakson rajalle keinotekoisen epäjatkuvuuden, jota mallien on yritettävä kiertää.

Jaksollinen koodaus sinillä ja kosinilla

Ratkaisu on koodata jaksolliset ominaisuudet sinipareina ja kosinipareina. Muuttuja, jonka arvot ovat välillä 0–T-1, koodataan seuraavasti: sin(2π × value / T) ja cos(2π × value / T). Tämä kuvaa jakson ympyräksi kaksiulotteiseen avaruuteen. Tunnit 23 ja 0 ovat nyt ympyrällä vierekkäisiä pisteitä, joten niiden euklidinen etäisyys on pieni. Kaikki etäisyyksiä tai lineaarisia yhdistelmiä laskevat mallit voivat nyt kuvata jaksolliset kuviot oikein käyttämällä sini- ja kosinikomponentteja yhdessä.

import numpy as np
import pandas as pd

hours = np.arange(24)
df = pd.DataFrame({'hour': hours})
df['hour_sin'] = np.sin(2 * np.pi * df['hour'] / 24)
df['hour_cos'] = np.cos(2 * np.pi * df['hour'] / 24)

# Distance between hour 23 and hour 0 on the circle
def circle_dist(h1, h2):
    s1, c1 = df.loc[df['hour'] == h1, ['hour_sin', 'hour_cos']].values[0]
    s2, c2 = df.loc[df['hour'] == h2, ['hour_sin', 'hour_cos']].values[0]
    return np.sqrt((s1-s2)**2 + (c1-c2)**2)

print('Distance 23 to 0:', round(circle_dist(23, 0), 4))  # small
print('Distance 0 to 12:', round(circle_dist(0, 12), 4))  # large

Jaksollisen koodauksen soveltaminen useisiin ominaisuuksiin

Jaksollinen koodaus yleistyy kaikkiin jaksollisiin ominaisuuksiin: kuukausi (T=12), viikonpäivä (T=7), tunti (T=24), minuutti (T=60) ja vuodenpäivä (T=365). Jokaisesta jaksollisesta ominaisuudesta muodostetaan kaksi uutta ominaisuutta (sini ja kosini). Puupohjaisilla malleilla raaka kokonaislukukoodaus toimii usein hyvin, koska puut jakavat arvot kynnysten perusteella ja voivat kuvata jaksollisia kuvioita useilla jaoilla. Lineaarisille malleille, neuroverkoille ja etäisyyspohjaisille algoritmeille jaksollinen koodaus on kuitenkin tärkeä.

import numpy as np
import pandas as pd

def cyclical_encode(df, col, period):
    df[col + '_sin'] = np.sin(2 * np.pi * df[col] / period)
    df[col + '_cos'] = np.cos(2 * np.pi * df[col] / period)
    return df

df = pd.DataFrame({'hour': [8, 12, 20, 23], 'month': [1, 6, 11, 12], 'dow': [0, 2, 4, 6]})
df = cyclical_encode(df, 'hour', 24)
df = cyclical_encode(df, 'month', 12)
df = cyclical_encode(df, 'dow', 7)
print(df[['hour', 'hour_sin', 'hour_cos', 'month', 'month_sin', 'month_cos']].round(3))

Aika vertailuhetkestä: suhteelliset aikaleimat

Kalenterikomponenttien poimimisen sijaan joskus olennaista on tapahtumasta kulunut aika: päivät viimeisimmästä ostoksesta, tunnit järjestelmän uudelleenkäynnistyksestä tai kuukaudet tilin luomisesta. Nämä suhteellisen keston ominaisuudet kuvaavat tuoreusvaikutuksia, joita absoluuttiset kalenteriominaisuudet eivät tavoita. Laskekaa ne yksinkertaisina erotuksina: (now - event_date).dt.days tai (now - event_date).dt.total_seconds(). Tuoreusominaisuudet ovat erityisen hyödyllisiä asiakaskäyttäytymisen malleissa (poistuma, LTV) ja ennakoivassa kunnossapidossa.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'last_purchase': pd.to_datetime(['2024-01-10', '2024-05-20', '2024-06-15']),
    'signup_date': pd.to_datetime(['2023-01-01', '2023-06-15', '2024-01-01'])
})
reference = pd.Timestamp('2024-06-19')
df['days_since_purchase'] = (reference - df['last_purchase']).dt.days
df['account_age_days'] = (reference - df['signup_date']).dt.days
print(df[['days_since_purchase', 'account_age_days']])

Viikonloppu- ja työaikailmaisimet

Aikaleimoista johdetut Boolen ilmaisimet ovat yksinkertaisia mutta usein tehokkaita. is_weekend, is_business_hours, is_holiday, is_month_end — nämä muodostavat selkeitä binäärisiä jakoja, joita puumallit voivat hyödyntää yhdellä jaolla. Myös lineaariset mallit hyötyvät, koska nämä ilmaisimet muodostavat erillisiä vakiotermin muutoksia. Arkipyhäilmaisimen lisääminen voi vaikuttaa erityisen paljon vähittäismyynnin, liikenteen ja energiankulutuksen malleihin, joissa pyhät aiheuttavat järjestelmällisiä muutoksia kysynnässä.

import pandas as pd

dates = pd.to_datetime(['2024-06-17', '2024-06-19', '2024-06-21', '2024-06-22', '2024-12-25'])
df = pd.DataFrame({'date': dates})
df['is_weekend'] = (df['date'].dt.dayofweek >= 5).astype(int)
df['is_month_end'] = df['date'].dt.is_month_end.astype(int)
df['is_quarter_end'] = df['date'].dt.is_quarter_end.astype(int)
df['week_of_year'] = df['date'].dt.isocalendar().week.astype(int)
print(df.to_string())

Viiveominaisuudet ja liukuvat tilastot

Aikasarjadatassa kohdemuuttujan aiemmat arvot ovat usein parhaiden ennustajien joukossa. Viiveominaisuudet siirtävät kohdemuuttujaa N aika-askelta: df['target_lag1'] = df['target'].shift(1) muodostaa ominaisuuden, joka vastaa edellisen päivän kohdearvoa. Liukuvat tilastot tiivistävät lähihistoriaa: df['rolling_mean_7'] = df['target'].rolling(7).mean() antaa seitsemän päivän liukuvan keskiarvon. Nämä ominaisuudet kuvaavat ajallista momenttia ja kausivaihtelua, joita pelkät kalenteriominaisuudet eivät pysty tavoittamaan.

import pandas as pd
import numpy as np

np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=10)
sales = np.array([100, 120, 95, 130, 110, 145, 160, 155, 170, 180])
df = pd.DataFrame({'date': dates, 'sales': sales})

df['lag_1'] = df['sales'].shift(1)
df['lag_7'] = df['sales'].shift(7)
df['rolling_mean_3'] = df['sales'].rolling(3).mean()
df['rolling_std_3'] = df['sales'].rolling(3).std()
print(df.to_string())

Päivämääräominaisuuksien yhdistäminen putkessa

Jotta päivämääräominaisuuksien poimintaa voi käyttää scikit-learnin Pipeline-putkessa ilman tietovuotoa, luokaa mukautettu muunnin käyttämällä BaseEstimator- ja TransformerMixin-luokkia. Näin päivämääräominaisuudet lasketaan yhdenmukaisesti ja toistettavasti ristiinvalidoinnin jokaisessa ositteessa. Olkaa viive- ja liukuvien ominaisuuksien kanssa erityisen varovaisia — koko datasta (myös tulevasta testidatasta) lasketut liukuvat tilastot vuotavat tietoa. Laskekaa viive- ja liukuvat ominaisuudet aina vain opetusdatan katkaisupäivään asti.

import numpy as np
import pandas as pd
from sklearn.base import BaseEstimator, TransformerMixin

class DateFeatureExtractor(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        return self
    def transform(self, X):
        X = X.copy()
        dt = pd.to_datetime(X['date'])
        X['hour'] = dt.dt.hour
        X['dayofweek'] = dt.dt.dayofweek
        X['month'] = dt.dt.month
        X['hour_sin'] = np.sin(2 * np.pi * X['hour'] / 24)
        X['hour_cos'] = np.cos(2 * np.pi * X['hour'] / 24)
        X = X.drop('date', axis=1)
        return X

df = pd.DataFrame({'date': ['2024-06-19 08:00', '2024-06-20 15:30'], 'value': [10, 20]})
print(DateFeatureExtractor().fit_transform(df))

Ominaisuuksien valinta toimialatuntemuksen perusteella

Tehokas datetime-ominaisuuksien muodostaminen edellyttää ymmärrystä siitä, mitkä ajalliset kuviot ovat ongelman kannalta merkityksellisiä. Kyytipalvelun kysynnässä ratkaisevia ovat vuorokaudenaika ja viikonpäivä. Vähittäismyynnissä tärkeitä ovat viikonpäivä, vuodenaika, pyhien läheisyys ja vuosittainen trendi. Verkkohyökkäysten tunnistamisessa olennaisia ovat aika viimeisimmästä tapahtumasta ja pursketaajuus. Energiankulutuksessa merkityksellisiä ovat tunnin, päivän ja lämpötilan yhteisvaikutukset. Aloittakaa aina piirtämällä kohdemuuttuja kunkin ajallisen komponentin suhteen, jotta voitte tunnistaa näkyvät jaksolliset kuviot ennen ominaisuuksien muodostamista.

Useiden aikavyöhykkeiden käsittely

Kun aineisto kattaa useita aikavyöhykkeitä, muuntakaa aikaleimat aina yhteen vertailuaikavyöhykkeeseen ennen ominaisuuksien poimimista. UTC:n käyttäminen kanonisena aikavyöhykkeenä on vakiintunut käytäntö. Ominaisuuksien poimimisen jälkeen voitte lisätä paikallisen ajan siirtymät takaisin, jos paikalliset kuviot ovat merkityksellisiä (esimerkiksi asiakkaan paikallisen ajan tunti ennustaa käyttäytymistä paremmin kuin UTC-tunti). Pandasin dt.tz_localize()- ja dt.tz_convert()-menetelmät käsittelevät aikavyöhykkeiden muuntamisen siististi.

import pandas as pd

# Timestamps in mixed timezones
timestamps = ['2024-06-19 08:00:00-05:00',  # US/Chicago
              '2024-06-19 14:00:00+01:00',   # Europe/London
              '2024-06-19 22:00:00+09:00']   # Asia/Tokyo
df = pd.DataFrame({'ts': pd.to_datetime(timestamps, utc=True)})
df['utc_hour'] = df['ts'].dt.hour  # all in UTC after conversion
df['ts_ny'] = df['ts'].dt.tz_convert('America/New_York')
df['ny_hour'] = df['ts_ny'].dt.hour  # local time hour
print(df[['utc_hour', 'ny_hour']])

Pikatesti

Testatkaa tämän oppitunnin päivämäärä- ja aikaominaisuuksien poiminnan ymmärtämistä.

Oppitunnin yhteenveto

Tässä oppitunnissa opitte, että raakaaikaleimat on pilkottava mielekkäiksi komponenteiksi ennen niiden käyttöä ominaisuuksina, jaksolliset ominaisuudet, kuten tunti ja kuukausi, edellyttävät sini- ja kosinikoodausta rajojen epäjatkuvuuksien välttämiseksi ja viive- ja liukuvat ominaisuudet kuvaavat ajallisia kuvioita aikasarjaennustamisen tehtävissä. Seuraavaksi tutustumme ominaisuuksien valintaan Variance Threshold- ja SelectKBest-menetelmillä informatiivisten ominaisuuksien karsimiseksi.

Aloita maksutta

Opi Python tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
30
Oppitunnit
120

Usein kysytyt kysymykset

Onko oppitunti ”Päivämäärä- ja aikapiirteiden erottaminen” ilmainen?

Kyllä – oppitunnin ”Päivämäärä- ja aikapiirteiden erottaminen” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Machine Learning Academy-kurssin, päivitä CoddyKit PROhon. Machine Learning Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Päivämäärä- ja aikapiirteiden erottaminen”?

Oppijat purkavat datetime-sarakkeet vuodeksi, kuukaudeksi, viikonpäiväksi ja tunniksi sekä muodostavat sykliset sini- ja kosinikoodaukset jaksollisuuden kuvaamiseksi. Harjoittelet Machine Learning Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Machine Learning Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Machine Learning Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”Päivämäärä- ja aikapiirteiden erottaminen”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Machine Learning Academy-oppitunnilla?

Kyllä. Jokainen Machine Learning Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Uusien piirteiden luominen: logaritmimuunnokset, luokittelu ja interaktiot
  2. Päivämäärä- ja aikapiirteiden erottaminen
  3. Piirteiden valinta: Variance Threshold ja SelectKBest
  4. Piirteiden rekursiivinen eliminointi ristivalidoinnilla
← Takaisin: Machine Learning Academy