Aihearkisto: Koneoppiminen ja ennakoiva analytiikka

Koneoppimisen käsitteitä

Päivitetty 25.8.2022

Data-analytiikan tasot

Data-analytiikka voidaan jakaa neljään tasoon seuraavasti:

koneoppiminen2

Kuvailevassa analytiikassa esitetään muuttujien jakaumia frekvenssitaulukoina ja tilastollisina tunnuslukuina. Selittävässä analytiikassa tarkastellaan muuttujien välisiä riippuvuuksia ristiintaulukoimalla, tunnuslukujen vertailulla ja korrelaatioilla. Ennakoivaan analytiikkaan käytetään koneoppimisen malleja. Ohjaava analytiikka perustuu kuvailevaan, selittävään ja ennakoivaan analytiikkaan, mutta voi sisältää myös muunlaisia laskentamenetelmiä, esimerkiksi lineaarista optimointia.

Koneoppimisen menetelmien jaottelu

Ennakoivaan analytiikkaan käytettävät koneoppimisalgoritmit voidaan luokitella  seuraavasti:

  • Ohjattu oppiminen (supervised learning): Algoritmi opetetaan opetusdatalla (training data). Esimerkiksi roskapostisuodatin opetetaan sähköpostidatalla, jossa on erilaisia tietoja kustakin sähköpostiviestistä sekä tieto siitä oliko sähköpostiviesti roskapostia. Tämän datan perusteella muodostuu malli, jota käyttäen tulevista sähköpostiviesteistä voidaan tunnistaa roskapostiviestejä.
  • Ohjaamaton oppiminen (unsupervised learning): Esimerkiksi asiakkaiden jakaminen asiakkaiden tietoja sisältävän datan perusteella asiakassegmentteihin.
  • Vahvistusoppiminen (reinforcement learning): Algoritmi suorittaa toimia ja saa niistä palautetta palkkioiden ja rangaistuksen muodoissa. Algoritmi oppii saamistaan palkkioista ja rangaistuksista. Vahvistettua oppimista käytetään esimerkiksi robotiikassa.

Seuraavassa jaotellaan ohjattu ja ohjaamaton oppiminen edelleen alatyyppeihin:

koneoppiminen1

Ohjattu oppiminen

Ohjatussa oppimisessa:

  • Algoritmi muodostaa (oppii) mallin opetusdatan (training set) avulla.
  • Opetusdata koostuu selittävien muuttujien arvoista (feature matrix) ja  kohdemuuttujan arvoista (labels).
  • Opetusdatassa kohdemuuttujan arvot ovat tiedossa!
  • Opetettu malli osaa ennustaa kohdemuuttujan arvoja uudelle datalle.

koneoppiminen3

Ohjatun oppisen prosessi etenee seuraavan kaavion mukaisesti:

koneoppiminen4

Ohjattua oppimista, jossa kohdemuuttuja on kategorinen käytetään esimerkiksi seuraavissa:

  • Roskapostisuodatin
  • Sairauden diagnosointi
  • Maksuhäiriön ennakointi
  • Vakuutuspetoksen tunnistaminen
  • Auton rekisterinumeron koneellinen lukeminen
  • Esineiden tunnistaminen valokuvasta

Tällaisissa tilanteissa kyse on luokittelusta (classification). Suosittuja luokittelumalleja ovat esimerkiksi:

  • Logistinen regressio
  • Päätöspuu (decision tree)
  • Satunnaismetsä (random forest)
  • Gradienttitehostus (gradient boosting)

Käytännössä lineaarisesti erotettavissa olevat luokat ovat helpompia erotella:

luokittelu1

Ohjattua oppimista, jossa kohdemuuttuja on määrällinen käytetään esimerkiksi seuraavissa:

  • Kysynnän ennustaminen
  • Asunnon myyntihinnan ennustaminen
  • Käytetyn auton myyntihinnan ennustaminen

Tällaisissa tilanteissa käytetään erilaisia regressiomalleja. Suosittuja malleja ovat esimerkiksi

  • lineaarinen regressio
  • satunnaismetsä regressio (random forest regressor)
  • gradienttitehostus regressio (gradient boosting regressor)

regressio1.PNG

Ohjaamaton oppiminen

Ohjaamatonta oppimista voidaan käyttää esimerkiksi asiakassegmenttien muodostamiseen. Ohjaamattomassa oppimisessa on käytössä ainoastaan selittävät muuttujat (feature matrix).

ohjaamaton1.PNG

Käytetyin menetelmä on K-means klusterointi, missä K viittaa muodostettavien klusterien lukumäärään, joka tässä menetelmässä päätetään etukäteen.

Datan yksinkertaistamiseen, havainnollistamiseen ja taustalla olevien rakenteiden tunnistamiseen voidaan käyttää pääkomponenttianalyysia (Principal component analysis). Tällä menetelmällä selittävistä muuttujista muodostetaan laskennallisesti pienempi joukko muuttujia.  Seuraavissa kuvioissa on pelkistetty alkuperäinen kolmen muuttujan asetelma kahden muuttujan asetelmaksi.

ohjaamaton2

Pääkomponenttianalyysillä voidaan esimerkiksi eri oppiaineissa menestymisen takaa tunnistaa erilaisia lahjakkuuksia (verbaalinen, matemaattinen jne.).

Neuroverkot

Edellä kuvattuja menetelmiä käytetään etupäässä strukturoidun datan (taulukkomuotoinen data) kanssa. Koneoppimista hyödynnetään myös strukturoimattoman datan kanssa. Strukturoimatonta dataa ovat esimerkiksi tekstit, äänet, kuvat ja videot. Neuroverkkomallit ovat käytännössä osoittautuneet käyttökelpoisiksi strukturoimattoman datan tapauksessa. Neuroverkkomalleja voidaan käyttää esimerkiksi:

  • Käsinkirjoitetun tekstin tunnistamiseen
  • Puheen tunnistamiseen
  • Kielen kääntämiseen
  • Positiivisten ja negatiivisten viestien tunnistamiseen keskustelualueilta
  • Esineiden ja henkilöiden tunnistamiseen kuvista tai videoista
  • Konenäköön

Neuroverkkoihin liittyvää koneoppimista kutsutaan syväoppimiseksi (deep learning).

Koneoppiminen ja scikit-learn -kirjasto

Päivitetty 21.9.2022

Pythonia käytettäessä useimmat koneoppimisen mallit löytyvät sklearn (scikit-learn) -kirjastosta. Tästä artikkelista opit  sklearn-kirjaston mallien käytön perusperiaatteet.

Mallien käyttö sujuu seuraavien vaiheiden kautta:

  • Valmistele data
  • Tuo malli
  • Sovita malli dataan
  • Arvioi mallin sopivuutta dataan
  • Ennusta mallin avulla

Valmistele data

Käytettävään dataan täytyy tutustua huolellisesti etukäteen. Erityisesti kannattaa kiinnittää huomiota seuraaviin:

  • Puuttuvat arvot: Useimmat mallit eivät siedä puuttuvia muuttujien arvoja. Puuttuvia arvoja sisältävät rivit pitää joka poistaa tai korvata puuttuvat arvot tarkoituksenmukaisella tavalla.
  • Kategoriset muuttujat: Useimmat mallit edellyttävät muuttujien olevan määrällisiä. Kategorisia muuttujia voidaan käyttää, jos ne puretaan dikotomisiksi muuttujiksi eli dummy-muuttujiksi (katso https://www.fsd.tuni.fi/fi/palvelut/menetelmaopetus/kvanti/mittaaminen/ominaisuudet/).
  • Skaalaus: Jos selittävät muuttujat poikkeavat suuruusluokaltaan toisistaan, niin yleensä muuttujat kannattaa skaalata samaan suuruusluokkaan. Tämän voi tehdä esimerkiksi muuntamalla muuttujan arvot standardipisteiksi (muuttujan arvosta vähennetään keskiarvo ja erotus jaetaan keskihajonnalla eli lasketaan kuinka monen keskihajonnan päässä keskiarvosta ollaan).

Ohjatun (supervised) oppimisen malleissa tarvitset kaksi dataframea:

  • Selittävien muuttujien arvot (feature-matriisi , x-muuttujat). Selittävien muuttujien dataframen nimeksi voit antaa esimerkiksi X.
  • Kohdemuuttujan arvot (target, labels, y-muuttuja). Kohdemuuttujan dataframen nimeksi voit antaa esimerksi y.

Tuo malli

Tuo malli sklearn-kirjastosta. Esimerkiksi lineaarisen regressiomallin tuot seuraavasti:

from sklearn.linear_model import LinearRegression

Sovita malli dataan

Sovita malli dataan fit-funktiolla ja tallenna syntyvä olio muuttujan arvoksi. Esimerkiksi seuraavassa sovitetaan lineaarinen regressio dataan X (selittävien muuttujien dataframe) ja y (ennustettavan muuttujan arvot).

malli = LinearRegression().fit(X, y)

Syntynyt olio (malli)  sisältää monenlaista tietoa mallista. Monissa netistä ja kirjallisuudesta löytyvissä esimerkeissä edellinen tehdään kahdessa vaiheessa:

malli = LinearRegression()
malli.fit(X, y)

Tuloksena syntynyt malli-olio on sama muodostettiinpa se kummalla tavalla tahansa.
Mallia voidaan tuunata niin kutsutuilla hyperparametreilla. Esimerkiksi seuraavassa muodostetaan lineaarinen regressiomalli, johon ei otetan mukaan lainkaan vakiotermiä (intercept).

malli = LinearRegression(fit_intercept = False).fit(X, y)

Mallien tuunaus hyperparametreilla edellyttää mallien hyvää tuntemusta.

Arvioi mallin sopivuutta

Sopivuuden arviointiin on monia menetelmiä. Regressiomalleille voit esimerkiksi tulostaa selityskertoimen arvon komennolla malli.score(X, y). Selityskerroin ilmoittaa kuinka monta prosenttia selitettävän muuttujan vaihtelusta malli selittää.

Ennusta mallin avulla

Ennakoivassa analytiikassa keskeisin vaihe on tietenkin ennusteiden laskeminen uudelle datalle. Jos dataframe X_uusi sisältää uusia selittävän muuttujan arvoja, niin saat ennusteet komennolla:

malli.predict(X_uusi)

Lisätietoa

Lisätietoa koneoppimisen koodiesimerkeistä https://tilastoapu.wordpress.com/python/

Lineaarinen regressio 3

Jos koneoppiminen ja sklearn (scikit-learn) -kirjasto ovat sinulle täysin uusia, niin lue ennen tätä artikkelia Lineaarinen regressio 1 ja Lineaarinen regressio 2.

Tämän artikkelin ohjelmakoodin ja tulosteet löydät GitHubista:

https://github.com/taanila/tilastoapu/blob/master/linreg3.ipynb

Jos kopioit koodia itsellesi, niin kannattaa käyttää GitHubia. Tästä artikkelista kopioidut koodit eivät välttämättä toimi oikein.

Tämän artikkelin esimerkkidatana käytän sklearn kirjastosta löytyvää dataa Bostonin asuntojen hinnoista. Artikkelin ideat olen lainannut osoitteesta

https://towardsdatascience.com/linear-regression-on-boston-housing-dataset-f409b7e4a155

Ohjelmakirjastojen tuonti

Kuvailevasta analyysistä tutut peruskirjastot ovat tarpeen:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

Datan valmistelu

Lataan esimerkkiaineiston sklearn-kirjastosta seuraavasti:

from sklearn.datasets import load_boston
boston_data = load_boston()

Aineistossa on eroteltu data (features), target (selitettävä muuttuja), feature_names (selittävien muuttujien nimet) ja DESCR (aineiston kuvaus). Tämä selviää keys()-funktiolla:

print(boston_data.keys())

dict_keys([’data’, ’target’, ’feature_names’, ’DESCR’])

Komennolla print(boston_data.DESCR) voit lukea aineiston kuvauksen.

Luon aineiston perusteella boston-nimisen dataframen:

boston = pd.DataFrame(boston_data.data, columns=boston_data.feature_names)
boston['MEDV'] = boston_data.target
boston.head()

linreg9

Selitettävä muuttuja MEDV kuvaa asuntojen mediaanihintoja tuhansina dollareina eri alueilla. Muut muuttujat ovat ehdokkaita mediaanihintaa selittäviksi muuttujiksi (voit lukea lisää aineiston kuvauksesta).

Varmuuden vuoksi kannattaa tarkistaa, onko datassa puuttuvia arvoja:

boston.isnull().sum()

linreg10

Puuttuvia arvoja ei ole, mikä on hyvä asia.

Seuraavaksi katson miten selitettävän muuttujan MEDV arvot ovat jakautuneet. Käytän tarkasteluun seaborn-kirjaston distplot-kuviota ja luokittelen hinnat 30 luokkaan:

sns.distplot(boston['MEDV'], bins=30)

linreg11

Kuvion mukaan asuntojen mediaanihintojen jakauma on oikealle vino. Vinoudesta huolimatta yritetään mallintaa hintoja lineaarisella regressiolla.

Selittävien muuttujien valinnassa voin hyödyntää korrelaatiokertoimia. Seaborn-kirjaston heatmap-funktiolla voin värjätä corr()-funktiolla lasketut korrelaatiokertoimet niiden arvon mukaan. Oletusarvolla heatmap tulostaa vain värilliset ruudut, mutta lisäparametrilla annot=True saan myös korrelaatiokertoimien arvot näkyviin:

correlation_matrix = boston.corr().round(2)
plt.figure(figsize=(12,9))
sns.heatmap(data=correlation_matrix, annot=True)

linreg12

Kaikkein eniten MEDV-muuttujan kanssa korreloivat RM (0,7) ja LSTAT (-0,74). Katson vielä kuvion avulla miltä kyseisten muuttujien korrelaatio MEDV-muuttujan kanssa näyttää. Seuraava koodi toimii vaikka lisäisit enemmänkin muuttujia features-listaan:

features = ['LSTAT', 'RM']
target = boston['MEDV']
plt.figure(figsize=(10, 5))
for i, col in enumerate(features):
   plt.subplot(1, len(features) , i+1)
   plt.scatter(boston[col], target)
   plt.xlabel(col)
   plt.ylabel('MEDV')

linreg13

Riippuvuus on selkeää molemmissa tapauksissa, mutta erityisesti LSTAT-muuttujan kohdalla riippuvuus ei ole täysin suoraviivaista. Tästä huolimatta jatketaan eteenpäin.

Valmistellaan vielä X (features-matriisi) ja y (target) mallintamista varten:

X = boston[['LSTAT', 'RM']]
y = boston['MEDV']

Opetusdata ja testidata

Jos dataa on riittävästi, niin kannattaa jakaa se opetusdataan ja testidataan. Testidatan avulla voidaan arvioida opetusdatan perusteella laadittua mallia. Seuraavassa jaan datan sattumanvaraisesti opetusdataan ja testidataan (20 % datasta). Parametri random_state asettaa satunnaislukugeneraattorin siemenluvun. Jos jätän sen asettamatta, niin saan eri kerroilla erilaisen jaon opetusdataan ja testidataan. Käyttämällä samaa siemenarvoa saan aina saman jaon.

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, 
   test_size = 0.2, random_state=5)
print(X_train.shape)
print(X_test.shape)

(404, 2)
(102, 2)

Huomaan, että opetusdatassa on 404 havaintoa ja testidatassa 102 havaintoa.

Mallin sovitus

Mallin sovitukseen kuuluu LinearRegression-mallin tuonti lineaaristen mallien kirjastosta ja mallin sovitus fit-funktiolla.

from sklearn.linear_model import LinearRegression
malli = LinearRegression()
malli.fit(X_train, y_train)

Tuloksesta näen  mallin lähtötiedot, joita olisin halutessani voinut säätää:

LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)

Mallin sopivuuden arviointi

Mallin sopivuutta arvioin keskivirheen ja selityskertoimen avulla.

RMSE (root mean squared error) eli keskivirhe lasketaan seuraavasti: lasketaan toteutuneiden havaintojen ja mallin ennustamien arvojen erotusten neliöt yhteen ja jaetaan havaintojen lukumäärällä (mean squared error); lopuksi otetaan neliöjuuri.

Mean squared error löytyy sklearn.metrics-kirjastosta:

from sklearn.metrics import mean_squared_error

y_train_predict = malli.predict(X_train)
rmse = (np.sqrt(mean_squared_error(y_train, y_train_predict)))
r2 = malli.score(X_train,y_train)

print('Mallin sopivuus opetusdataan')
print("--------------------------------------")
print('Keskivirhe: {}'.format(rmse))
print('Selityskerroin: {}'.format(r2))
print("n")

y_test_predict = malli.predict(X_test)
rmse = (np.sqrt(mean_squared_error(y_test, y_test_predict)))
r2 = malli.score(X_test, y_test)

print('Mallin sopivuus testidataan')
print('--------------------------------------')
print('Keskivirhe: {}'.format(rmse))
print('Selityskerroin: {}'.format(r2))

Mallin sopivuus opetusdataan
————————————–
Keskivirhe: 5.6371293350711955
Selityskerroin: 0.6300745149331701

Mallin sopivuus testidataan
————————————–
Keskivirhe: 5.137400784702911
Selityskerroin: 0.6628996975186953

Katson vielä kuviona, miten hyvin ennustaminen onnistuu testidatassa:

plt.scatter(y_test, y_test_predict)
plt.xlabel('y_test')
plt.ylabel('y_test_predict')

linreg14

Malli on sitä parempi, mitä lähempänä suoraa viivaa kuvion pisteet ovat.

Mallin parantaminen

Edellä esimerkkinä laskettu malli on kelvollinen, mutta voisin parantaa mallia monin tavoin:

Asuntojen mediaanihinnat eivät ole normaalisti jakautuneet (jakauma on oikealle vino). Mallin parantamiseksi voisin kokeilla jompaa kumpaa seuraavista:

  • pudotan jakauman yläpään suurimmat mediaanihinnat pois opetusdatasta
  • muunnan mediaanihintoja paremmin normaalijakaumaa vastaaviksi.

Selittävien muuttujien ja mediaanihintojen välinen riippuvuus ei ollut aivan suoraviivainen. Tämä saattaisi korjaantua, jos muunnan mediaanihinnat paremmin normaalijakaumaa vastaaviksi. Tarvittaessa voin tehdä myös selittäville muuttujille muunnoksia tai voin valita malliksi ei-lineaarisen mallin.

Malliin voin myös lisätä selittäviä muuttujia. PTRATIO-muuttujan ottamista selittäväksi muuttujaksi kannattaisi kokeilla.

Jos teen korjauksia malliin, niin voin arvioida korjatun mallin sopivuutta vertaamalla sen keskivirhettä ja selityskerrointa tämän artikkelin malliin.

Lineaarinen regressio 2

Jos koneoppiminen ja sklearn (scikit-learn) -kirjasto ovat sinulle täysin uusia, niin lue ennen tätä artikkelia Lineaarinen regressio 1

Tämän artikkelin ohjelmakoodin ja tulosteet löydät GitHubista:

https://github.com/taanila/tilastoapu/blob/master/linreg2.ipynb

Jos kopioit koodia itsellesi, niin kannattaa käyttää GitHubia. Tästä artikkelista kopioidut koodit eivät välttämättä toimi oikein.

Tämän artikkelin esimerkeissä käytän datoja http://taanila.fi/mokki.xlsx ja http://taanila.fi/mokkinew.xlsx

Lineaarisella regressiomallilla voidaan ennustaa jatkuvaluonteisen muuttujan arvoja selittävien muuttujien avulla, jos selittävien muuttujien ja ennustettavan muuttujan välillä on likimain lineaarinen (suoraviivainen) riippuvuus.

Lineaarista regressiomallia voidaan pitää koneoppimisen mallina, jos kone oppii mallin parametrit olemassa olevan datan perusteella.

Tarkastelen esimerkkinä kuvitteellista aineistoa kesämökkien hinnoista. Hintaa selittävinä muuttujina ovat rantaviivan pituus metreinä, mökin pinta-ala neliömetreinä ja dikitominen muuttuja sähköliittymästä (1 = sähköliittymä, 0 = ei sähköliittymää).

Ohjelmakirjastojen tuonti

Tuon kuvailevasta analyysista tutut kirjastot (numpy-kirjastoa en tällä kertaa tarvitse):

import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

Datan valmistelu

Luen datan Excel-tiedostosta dataframeen:

df=pd.read_excel('http://taanila.fi/mokki.xlsx')
df

linreg4

Muodostan feature-matriisin selittävistä muuttujista ranta, pinta-ala ja sähkö. Selitettäväksi muuttujaksi (target) tulee hinta.

X=df[['ranta', 'pinta-ala','sähkö']]
y=df['hinta']

Mallin sovitus

Tuon lineaaristen mallien kirjastosta LinearRegression-mallin. Mukavuussyistä annan mallille nimeksi malli.

Sovitan mallin dataan fit-funktiolla.

from sklearn.linear_model import LinearRegression
malli=LinearRegression()
malli.fit(X,y)

Tuloksesta näen  mallin lähtötiedot, joita olisin halutessani voinut säätää:

LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)

Mallin vakiotermi:

malli.intercept_

-96.94145434036429

Selittävien muuttujien kertoimet:

malli.coef_

array([ 1.9750098 ,  2.77578415, 20.29877373])

Mallin sopivuuden arviointi

Mallin selityskerroin:

malli.score(X,y)

0.9819136190845801

Selityskertoimen mukaan 98,2 % hinnan varianssista voidaan selittää selittävien muuttujien avulla.

Mallin sopivuutta voin arvioida myös virhetermejä (ennusteen ero toteutuneeseen hintaan) tarkastelemalla:

plt.scatter(malli.predict(X), malli.predict(X)-y)
plt.hlines(y=0,xmin=50,xmax=250)
plt.xlabel('Ennuste')
plt.ylabel('Poikkeama todellisesta')

linreg5

Virhetermit ovat melko satunnaisesti jakautuneet, mikä on hyvä asia.

Seuraavassa tarkastelen vielä pistekuviona toteutunutta hintaa ja mallin ennustamaa hintaa:

plt.scatter(df['hinta'], malli.predict(X))
plt.xlabel('Todellinen hinta')
plt.ylabel('Ennuste')

linreg6

Ennustaminen

Mallin perusteella voin laskea hintaennusteita uudelle datalle, jota ei käytetty mallin laatimiseen:

Xuudet=pd.read_excel('http://taanila.fi/mokkinew.xlsx')
Xuudet['Hintaennuste']=malli.predict(Xuudet)
Xuudet

linreg7

Perinteisempi regressiotuloste

Halutessani saan perinteisemmän regressiotulosteen statsmodels-kirjaston toiminnoilla:

import statsmodels.api as sm
X = sm.add_constant(X)
malli_sm = sm.OLS(y, X)
results = malli_sm.fit()
print(results.summary())

linreg8

Lineaarinen regressio 1

Tämän artikkelin ohjelmakoodin ja tulosteet löydät GitHubista:

https://github.com/taanila/tilastoapu/blob/master/linreg1.ipynb

Jos kopioit koodia itsellesi, niin kannattaa käyttää GitHubia. Tästä artikkelista kopioidut koodit eivät välttämättä toimi oikein.

Tämän artikkelin esimerkeissä käytän dataa http://taanila.fi/linreg1.xlsx

Yleistä koneoppimisen malleista

Tästä artikkelista opit sklearn (scikit-learn) -ohjelmakirjaston koneoppimisen mallien käyttöliittymän pelkistetyn esimerkin avulla. Käyttöliittymä sklearn-kirjaston malleihin on yksinkertainen sisältäen seuraavat vaiheet:

Valmistele data

Ohjatun (supervised) oppimisen malleissa datasta täytyy erottaa selittävät muuttujat (feature-matriisi , x-muuttujat) ja selitettävä muuttuja (label, target, y-muuttuja).

Ohjaamattomissa (unsupervised) malleissa tarvitaan ainoastaan feature-matriisi.

Tuo malli ja säädä lähtötiedot

Esimerkiksi tässä artikkelissa käytettävä lineaarinen regressiomalli tuodaan seuraavasti:

from sklearn.linear_model import LinearRegression

Lineaaristen mallien kirjastosta siis tuodaan LinearRegression-malli. Mallin lähtötietojen säätäminen edellyttää käytettävän mallin tuntemusta. Jos et ole perehtynyt malliin, niin voit tyytyä lähtötietojen oletusarvoihin.

Sovita malli (fit)

Tässä vaiheessa suoritetaan varsinainen laskenta. Onneksi valmiit algoritmit hoitavat laskennan.

Arvioi mallin sopivuutta

Sopivuuden arviointiin on monia menetelmiä, esimerkiksi selityskertoimen laskeminen, visuaalinen tarkastelu tai mallin toimivuuden testaaminen testidatalla.

Ennusta (predict)

Ennakoivassa analytiikassa keskeisin vaihe on tietysti ennusteiden laskeminen uudelle datalle.

Lineaarinen regressio

Lineaarisella regressiomallilla voidaan ennustaa jatkuvaluonteisen muuttujan arvoja selittävien muuttujien avulla, jos selittävien muuttujien ja ennustettavan muuttujan välillä on likimain lineaarinen (suoraviivainen) riippuvuus.

Lineaarista regressiomallia voidaan pitää koneoppimisen mallina, jos kone määrittää (oppii) mallin parametrit olemassa olevan datan (training data) perusteella.

Ohjelmakirjastojen tuonti

Kuvailevasta analyysistä tutut peruskirjastot ovat tarpeen:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

Datan valmistelu

Tässä esimerkissä luen datan Excel-tiedostosta dataframeen:

df = pd.read_excel('linreg1.xlsx')
df

linreg1

Yritän selittää myyntiä mainoskuluilla, joten määritän mainoskulut selittäväksi muuttujaksi (x) ja myynnin selitettäväksi muuttujaksi (y). Feature-matriisin täytyy olla mallia sovitettaessa dataframe-muodossa, joten teen muunnoksen to_frame-funktiolla.

x=df['Mainoskulut 1000 €']
X=df['Mainoskulut 1000 €'].to_frame() #feature-matriisi
y=df['Myynti 1000 €'] #target
plt.scatter(x,y)

linreg2

Pistekaavion perusteella riippuvuus mainoskulujen ja myynnin välillä näyttää likimain lineaariselta (suoraviivaiselta).

Mallin sovitus

Tuon LinearRegression-mallin lineaaristen mallien kirjastosta ja nimeän sen yksinkertaisuuden vuoksi nimellä malli.

from sklearn.linear_model import LinearRegression
malli=LinearRegression()
malli.fit(X,y)

Tulosteena saan mallin lähtötiedot (joita olisin voinut halutessani säätää):

LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)

Mallin sovittamisen jälkeen voin katsoa mallin parametreja. Yksinkertaisen lineaarisen regression tapauksessa mallin parametrit ovat suoran kulmakerroin ja vakiotermi.

malli.coef_ #kulmakerroin

array([52.56756757])

Kulmakerroin tulee listamuodossa (array), koska mallissa voisi olla useampia selittäviä muuttujia ja näin ollen myös useampia kulmakertoimia.

malli.intercept_ #vakiotermi

46.486486486486505

Mallina on siis suora, jonka yhtälö: y = 52,568x + 46,486

Mallin sopivuuden arviointi

Mallin selityskertoimen saan:

malli.score(X,y)

0.7663982928521625

Voin siis todeta: 76,6 % myynnin varianssista voidaan selittää mainoskuluilla.

Voin tarkastella mallin sopivuutta myös graafisesti:

xfit=np.linspace(0.4,1.4) #50 arvoa tasavälein väliltä 0.4 - 1.4
Xfit=pd.DataFrame(xfit)
yfit=malli.predict(Xfit)
plt.scatter(x,y)
plt.plot(xfit,yfit)
plt.xlabel('Mainoskulut 1000 €')
plt.ylabel('Myynti 1000 €')

linreg3

Ennustaminen

Jos mainoskuluihin suunnitellaan käytettäväksi 700, 800 tai 900 euroa, niin mallin mukaiset myyntiennusteet:

malli.predict([0.7, 0.8, 0.9])

array([83.28378378, 88.54054054, 93.7972973 ])

Yhteenveto

Yksinkertaisimmillaan tuodaan ja määritellään malli, sovitetaan malli ja ennustetaan:

from sklearn.linear_model import LinearRegression 

malli=LinearRegression() 

malli.fit(X,y)

malli.predict([0.7, 0.8, 0.9])

 

Data-analytiikka Pythonilla

Päivitetty 4.5.2023

Data-analytiikka antaa vastauksia kysymyksiin

Data-analytiikka on tavoitteellista toimintaa: tavoitteena on etsiä vastauksia kysymyksiin. Data-analytiikan avulla vastataan monenlaisiin kysymyksiin:

  • Minkälainen ikäjakauma asiakkaillamme on?
  • Mihin toimintamme osa-alueisiin asiakkaamme ovat tyytymättömiä?
  • Onko asiakkaan iällä yhteyttä asiakastyytyväisyyteen?
  • Miten yrityksen työilmapiiri on muuttunut viime vuodesta?
  • Ketkä asiakkaistamme ovat vaarassa siirtyä kilpailijalle?
  • Keille tuotteen markkinointikampanja kannattaa suunnata?
  • Mikä mainosvaihtoehdoista tehoaa parhaiten kohderyhmään?
  • Mitä oheistuotteita verkkokaupasta ostaneella kannattaa tarjota?
  • Mikä on tuotteen ennustettu kysyntä ensi kuussa?
  • Liittyykö vakuutuskorvaushakemukseen vakuutuspetos?
  • Millä todennäköisyydellä laina-asiakas ei pysty maksamaan lainaansa takaisin?

Data

Tavoitteiden (kysymykset, joihin halutaan vastata) asettamisen jälkeen pitää selvittää minkälaista dataa tarvitaan. Data voi olla esimerkiksi:

  • Yrityksen tietokannoista löytyvää dataa (esimerkiksi CRM- ja ERP-järjestelmistä).
  • Erilaisten tiedontuottajien tarjoamaa ilmaista tai maksullista dataa.
  • Varta vasten kyselytutkimuksella tai kokeellisella tutkimuksella kerättyä dataa.
  • Erilaisten sensorien/mittalaitteiden automaattisesti tuottamaa dataa.

Blogissani rajoitun rakenteelliseen eli strukturoituun dataan. Rakenteellinen data on sellaista, joka voidaan tallentaa taulukkomuotoon. Yleisiä data-analytiikkaan sopivia tiedostomuotoja ovat pilkkueroteltu tekstimuoto (.csv) ja Excel-muoto (.xlsx). Tietokannoista data haetaan kyselyiden (SQL-kyselykieli) avulla. Nettikyselyohjelmista datan saa yleensä ulos pilkkuerotellussa tekstimuodossa tai Excel-muodossa.

Kun sopiva data on olemassa, niin datasta saadaan vastauksia kysymyksiin seuraavien vaiheiden kautta:

  • Datan valmistelu
  • Kuvaileva analytiikka
  • Selittävä analytiikka; selittävään analytiikkaan liittyy usein tilastollisen merkitsevyyden testaaminen: tilastollinen merkitsevyys kertoo, millä varmuudella otoksessa havaittuja eroja ja riippuvuuksia voidaan yleistää isompaan perusjoukkoon, josta otos on otettu.
  • Ennakoiva analytiikka; tähän käytetään usein koneoppimisen malleja.

Datan valmistelu

Datan valmistelulla tarkoitan datojen yhdistelyä, dataan tutustumista, datan siivoamista ja datan muunnoksia.

Datan valmistelu voi olla data-analytiikan aikaa vievin vaihe. Ensimmäiseksi kannattaa varmistaa datan taulukkomuotoisuus:

  • muuttujien nimet / kenttien nimet / sarakeotsikot ovat ensimmäisellä rivillä
  • datassa ei ole tarpeettomia tyhjiä rivejä tai sarakkeita
  • kuhunkin tilastoyksikköön/havaintoyksikköön liittyvät tiedot ovat yhdellä rivillä.

Datan valmistelu voi sisältää muiden muassa seuraavia:

  • Eri lähteistä peräisin olevien datojen yhdistely
  • Muuttujien uudelleen nimeäminen: jatkotoimet sujuvat sutjakkaammin, jos nimet ovat lyhyitä ja helposti tunnistettavia
  • Desimaalipilkkujen tarkistaminen: vaikka Suomessa desimaalipilkkuna käytetään pilkkua, niin Pythonissa täytyy käyttää pistettä
  • Päivämäärien muuntaminen päivämääriksi tunnistettavaan muotoon
  • Mittayksiköiden tarkistaminen ja tarvittavien muunnosten tekeminen
  • Puuttuvien arvojen käsittely: poistetaanko puuttuvia arvoja sisältävät rivit, korvataanko puuttuvat arvot jollain, miten puuttuvia arvoja merkitään
  • Uusien muuttujien laskeminen: esimerkiksi summamuuttuja useasta mielipidemuuttujasta, tilauksen hinta tilausmäärän ja yksikköhinnan avulla jne.
  • Arvojen luokittelu ja uudelleenkoodaaminen: esimerkiksi ikäluokat iän arvoista.

Kuvaileva analytiikka

Datan kuvailu voi sisältää seuraavia:

  • Lukumäärä- ja prosenttiyhteenvetojen laskeminen kategorisille muuttujille (frekvenssitaulukot)
  • Luokiteltujen jakaumien laskeminen määrällisille muuttujille
  • Tilastollisten tunnuslukujen laskeminen määrällisille muuttujille (keskiarvo, keskihajonta, viiden luvun yhteenveto)
  • Prosenttimuutosten laskeminen aikasarjoille
  • Aikasarjojen tarkastelu viivakaavioina
  • Liukuvien keskiarvojen esittäminen aikasarjojen yhteydessä.

Kuvailun tuloksia kannattaa visualisoida ja havainnollistaa hyvin viimeistellyillä taulukoilla ja kaavioilla.

Selittävä analytiikka ja tilastollinen merkitsevyys

Selittävä analytiikka voi sisältää seuraavia:

  • Tilastollisten tunnuslukujen vertailua eri ryhmissä
  • Kategoristen muuttujien riippuvuuden tarkastelua ristiintaulukoimalla
  • Määrällisten muuttujien välisten korrelaatioiden tarkastelua
  • Havaittujen erojen ja riippuvuuksien tilastollisen merkitsevyyden tarkastelua.

Jos käytetty data on otos isommasta perusjoukosta, niin tulokset kuvaavat otosta. Jos tarkoituksena on arvioida koko perusjoukkoa, niin otoksessa havaittujen erojen ja riippuvuuksien tilastollinen merkitsevyys kertoo, millä varmuudella eroja ja riippuvuuksia voidaan yleistää otoksesta perusjoukkoon.

Ennakoiva analytiikka ja koneoppiminen

Koneoppimisen malleilla voidaan luokitella (asiakkaat luottoriski-asiakkaisiin ja muihin, vakuutuskorvaushakemukset selviin tapauksiin ja petokselta haiskahtaviin, sähköpostiviestit roskapostiin ja kunnollisiin viesteihin jne.) ja ennakoida määrällisen muuttujan arvoja (käytetyn auton hinta, tuleva kysyntä jne.). Koneoppiminen perustuu siihen, että kone oppii käytettävän mallin parametrit olemassa olevasta datasta ja tämän jälkeen mallia voidaan soveltaa uuteen dataan.

Koneoppimisalgoritmit voidaan luokitella  seuraavasti:

  • Ohjattu oppiminen (supervised learning): Algoritmi opetetaan opetusdatalla (training data). Esimerkiksi roskapostisuodatin opetetaan sähköpostidatalla, jossa on erilaisia tietoja kustakin sähköpostiviestistä sekä tieto siitä oliko sähköpostiviesti roskapostia. Tämän datan perusteella muodostuu malli, jota käyttäen tulevista sähköpostiviesteistä voidaan tunnistaa roskapostiviestit.
  • Ohjaamaton oppiminen (Unsupervised learning): Esimerkiksi asiakkaiden jakaminen asiakassegmentteihin asiakastietojen perusteella.
  • Vahvistusoppiminen (Reinforcement learning): Algoritmi suorittaa toimia ja saa niistä palautetta palkkioiden ja rangaistusten muodossa. Algoritmi oppii saamistaan palkkioista ja rangaistuksista. Vahvistettua oppimista käytetään esimerkiksi robotiikassa.

Seuraavassa jaotellaan ohjattu ja ohjaamaton oppiminen edelleen alatyyppeihin:

mallit

Ohjattu oppiminen

Kohdemuuttuja kategorinen

Jos kohdemuuttuja (ennakoitava muuttuja) on kategorinen, niin kyseeseen tulevat luokittelua suorittavat algoritmit, esimerkiksi logistinen regressio tai päätöspuut.

Esimerkkejä, joissa on kategorinen kohdemuuttuja:

  • Roskapostisuodatin: kohdemuuttujana on tieto siitä, onko sähköpostiviesti roskapostia vai ei?
  • Lääketieteellinen diagnoosi: Kohdemuuttujana on tieto siitä, onko tutkitulla potilaalla tietty sairaus vai ei?
  • Vakuutuspetosten tunnistaminen: Kohdemuuttujana on tieto siitä, liittyykö korvaushakemukseen petos vai ei?

Kohdemuuttuja määrällinen

Jos kohdemuuttuja on määrällinen, niin kyseeseen tulevat regressiomallit ja aikasarjaennustamisen menetelmät. Esimerkkejä, joissa on määrällinen kohdemuuttuja:

  • Vanhan osakehuoneiston hinnan arviointi: Kohdemuuttujana on asunnon hinta.
  • Kysynnän ennustaminen aikaisemman kysynnän perusteella: Kohdemuuttujana on kysyntä.

Ohjaamaton oppiminen

Ohjaamattoman oppimisen algoritmi muodostaa mallin suoraan datasta (ei siis ole erillistä opetusdataa, jossa olisi valmiina kohdemuuttujan arvoja). Esimerkkinä asiakassegmenttien määrittäminen asiakasdatan pohjalta. Paljon käytetty algoritmi on k-means clustering.

Jos datassa on paljon muuttujia, jotka mittaavat osittain samoja asioita, niin datan rakennetta voidaan yksinkertaistaa yhdistämällä muuttujia uusiksi lasketuiksi muuttujiksi, joita on vähemmän kuin alkuperäisiä muuttujia. Tunnetuin algoritmi tähän tarkoitukseen on pääkomponenttianalyysi.

Aikasarjaennustaminen 3

Päivitetty 29.12.2020

Tämä artikkeli on jatkoa artikkeleille Aikasarjaennustaminen 1 ja Aikasarjaennustaminen 2.

Edellisen artikkelin Aikasarjaennustaminen 2 lopussa totesin, että esimerkkinä käyttämässäni aikasarjassa on neljän vuosineljänneksen välein toistuvaa kausivaihtelua, joka on syytä huomioida ennustamisessa. Tässä artikkelissa tarkastelen kausivaihtelun huomioivaa Holt-Winterin menetelmää.

Holt-Winterin tulomallissa aikasarjan tason L (level) hetkellä t määrittää lauseke

Lt = alfa * Yt/St-s + (1 – alfa)(Lt-1 + Tt-1)

Yllä Yt on viimeisin havainto, St-s on edellisen vastaavan periodin kausivaihtelu ja  Tt-1 on edellinen trendi.

Trendille T hetkellä t saadaan arvio lausekkeesta

Tt = beta * (Lt – Lt-1) + (1 – beta) * Tt-1

Kausivaihtelulle S hetkellä t saadaan arvio lausekkeesta

St = gamma * Yt/Lt + (1 – gamma) * St-s

Ennuste hetkelle t + p saadaan

(Lt + pTt)St-s

Yllä on kyse Holt-Winterin tulomallista, jossa kausivaihtelu huomioidaan kausivaihtelukertoimena. Holt-Winterin mallia voidaan soveltaa myös summamallina, jolloin kausivaihtelu huomioidaan lisättävänä kausivaihteluterminä. Tulomalli soveltuu paremmin tilanteisiin, joissa kausivaihtelukomponentin suuruus vaihtelee aikasarjan tason L mukaan. Summamalli soveltuu tilanteisiin, joissa kausivaihtelukomponentin suuruus ei riipu aikasarjan tasosta L.

Mallin parametrit alfa, beta ja gamma pyritään määrittämään siten että ennustevirheiden neliöiden keskiarvo saadaan mahdollisimman pieneksi.

Python toteutus

Esimerkkikoodin kolminkertaiseen eksponentiaaliseen tasoitukseen löydät GitHubista:

https://nbviewer.jupyter.org/github/taanila/aikasarjat/blob/main/forecast3.ipynb

Aikasarjaennustaminen 2

Päivitetty 29.12.2020

Tämä artikkeli on jatkoa yksinkertaista eksponentiaalista tasoitusta käsittelevälle artikkelille Aikasarjaennustaminen 1. Tässä artikkelissa käytän kaksinkertaista eksponentiaalista tasoitusta eli Holtin mallia, joka huomioi myös trendin.

Holtin mallissa aikasarjan tason L (level) hetkellä t määrittää lauseke

Lt = alfa * Yt + (1 – alfa) * (Lt-1 + Tt-1)

Yllä Yt on viimeisin havainto ja Tt-1 on edellinen trendi. Trendille hetkellä t saadaan arvio lausekkeesta

Tt = beta * (Lt – Lt-1) + (1 – beta) * Tt-1

Ennuste hetkelle t+p saadaan

Lt + pTt

Mallin parametrit alfa ja beta pyritään määrittämään siten että ennustevirheiden neliöiden keskiarvo saadaan mahdollisimman pieneksi.

Python toteutus

Esimerkkikoodin kaksinkertaisen eksponentiaalisen tasoituksen käytöstä löydät GitHubista:

https://nbviewer.jupyter.org/github/taanila/aikasarjat/blob/main/forecast2.ipynb

Aikasarjan lähempää tarkastelua

Löytääkseni paremman ennustemallin tarkastelen esimerkkikoodissa käyttämääni aikasarjaa hieman lähemmin purkamalla sen komponentteihin.

from statsmodels.tsa.api import seasonal_decompose
seasonal_decompose(data['Demand']).plot()

Tuloksena saan neljä kuviota:

  • alkuperäinen aikasarja
  • aikasarjasta erotettu trendi
  • aikasarjan kausivaihtelu
  • aikasarjan jäljelle jäänyt osa trendin ja kausivaihtelun poistamisen jälkeen.

holt4

Aikasarjassa on erotettavissa selkeä neljän vuosineljänneksen jaksoissa toistuva kausivaihtelu, jota kaksinkertainen eksponentiaalinen tasoitus ei huomioi ennusteessa. Asiaa voin tarkastella myös autokorrelaatioiden avulla. Autokorrelaatio tarkoittaa aikasarjan korrelaatiota viivästetyn aikasarjan kanssa, esimerkiksi aikasarjan korrelaatio neljän vuosineljänneksen takaisiin aikasarjan arvoihin. Autokorrelaatio voidaan laskea eri viiveille. Tämän voin tehdä pandas-kirjaston autocorrelation_plot-toiminnolla:

from pandas.plotting import autocorrelation_plot
autocorrelation_plot(data['Demand'])

holt5

Vaaka-akselilla on viive (lag) ja pystyakselilla autokorrelaatiokertoimen arvo. Huomaan, että viiveen 4 kohdalla on suurehko korrelaatio. Tämä viittaa neljän vuosineljänneksen mittaiseen kausivaihtelujaksoon. Kuvion katkoviivat edustavat tilastollisesti merkitsevän korrelaation rajoja. Viiveen 4 kohdalla korrelaatio on katkoviivan yläpuolella ja näin ollen tilastollisesti merkitsevä.

Seuraavassa artikkelissa Aikasarjaennustaminen 3 laadin ennustemallin, jossa myös neljän vuosineljänneksen jaksoissa toistuva kausivaihtelu on huomioitu.

Aikasarjaennustaminen 1

Päivitetty 29.12.2020

Aikasarjaennustamisessa oletan että toteutuneiden havaintojen muodostama aikasarja sisältää informaatiota, joka auttaa tulevien havaintojen ennustamisessa. Ennustusmenetelmä riippuu siitä, minkälaista systemaattista vaihtelua aikasarjassa esiintyy. Eksponentiaalisia tasoitusmenetelmiä käytettäessä on kolme päävaihtoehtoa:

  • Yksinkertainen eksponentiaalinen tasoitus aikasarjoille, joissa ei ole trendiä eikä kausivaihtelua.
  • Kaksinkertainen eksponentiaalinen tasoitus eli Holtin menetelmä aikasarjoille, joissa on trendi, mutta ei kausivaihtelua.
  • Kolminkertainen eksponentiaalinen tasoitus eli Holt-Winterin menetelmä aikasarjoille, joissa on sekä trendi että kausivaihtelu.

Tämä artikkeli käsittelee yksinkertaista eksponentiaalista tasoitusta. Yksinkertaisessa eksponentiaalisessa tasoituksessa ennuste lasketaan seuraavasti:

alfa*edellinen havainto + (1 – alfa)*edellinen ennuste

Ennuste saadaan viimeisimmän havainnon ja siihen liittyneen ennusteen painotettuna summana. Painokerroin alfa on välillä 0 – 1 oleva luku, joka ilmaisee, kuinka suurella painolla edellistä havaintoa painotetaan ennustetta laskettaessa:

    • Jos alfa on 0, niin ennuste on sama kuin edellinen ennuste.
    • Jos alfa on 1, niin ennuste on sama kuin edellinen havainto.
    • Suuret alfan arvot antavat ennusteita, jotka reagoivat herkästi aikasarjassa esiintyvään vaihteluun, koska viimeisimmillä havainnoilla on suuri paino.
    • Pienet alfan arvot tasoittavat voimakkaasti aikasarjan vaihtelua.

Alfan arvo valitaan yleensä siten että ennustevirheiden neliöiden keskiarvo saadaan mahdollisimman pieneksi. Voin kirjoittaa ennusteen laskentakaavan myös muotoon

edellinen ennuste + alfa*(edellinen havainto – edellinen ennuste)

Ennustetta siis korjataan jokaisen toteutuneen havainnon jälkeen korjaustermillä alfa*edellisen ennusteen virhe.

Python toteutus

Esimerkkikoodin yksinkertaisen eksponentiaalisen tasoituksen käyttöön löydät GitHubista:

https://nbviewer.jupyter.org/github/taanila/aikasarjat/blob/main/forecast1.ipynb

Seuraavaksi

Esimerkkinä käyttämässäni aikasarjassa on melko helppo erottaa alkupään laskeva trendi ja loppupään nouseva trendi. Seuraavassa artikkelissani Aikasarjaennustaminen 2 yritän sovittaa aikasarjaan mallin, joka huomioi trendin.