Kirjoittajan arkistot: Aki Taanila

Koneoppimisen käsitteitä

Data-analytiikan tasot

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

dataportaat

Kahdella alimmalla tasolla selvitään yleensä kuvailevilla menetelmillä ja tilastollisten merkitsevyyksien laskemisella. Kahdella ylimmällä tasolla tarvitaan koneoppimisen malleja.

Koneoppimisen menetelmien jaottelu

Koneoppimisalgoritmit voidaan luokitella  seuraavasti (suomennokset eivät ole vakiintuneita):

  • Supervised learning (ohjattu oppiminen): 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.
  • Unsupervised learning (ohjaamaton oppiminen): Esimerkiksi asiakkaiden jakaminen asiakassegmentteihin.
  • Reinforcement learning (vahvistusoppiminen): 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:

kone1

Ohjattu oppiminen

Ohjatussa oppimisessa:

  • Kone muodostaa (oppii) mallin opetusdatan (training set) avulla.
  • Opetusdata koostuu selittävistä muuttujista (feature matrix) ja selitettävästä eli ennustettavasta muuttujasta (target).
  • Opetusdatassa ennustettavan muuttujan arvot (labels) ovat tiedossa.
  • Opitun mallin avulla kone osaa ennustaa ennustettavan muuttujan arvoja (labels) uudelle datalle.

ohjattu1

Ohjatun oppisen prosessi etenee seuraavan kaavion mukaisesti:

ohjattu2

Ohjattua oppimista, jossa ennustettava muuttuja on kategorinen (discrete label) 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) ja käytettäviä malleja ovat esimerkiksi:

  • Naiivi Bayes
  • Logistinen regressio
  • Päätöspuut (decision trees)
  • K lähintä naapuria (K nearest neighbor)

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

luokittelu1

Ohjattua oppimista, jossa ennustettava muuttuja on määrällinen (continuous label) käytetään esimerkiksi seuraavissa:

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

Tällaisissa tilanteissa käytetään eniten erilaisia regressiomalleja, esimerkiksi lineaarista regressiota.

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ä mentelmä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 (feature matrix) 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.).

Koneoppiminen ja scikit-learn -kirjasto

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.

Ohjatun (supervised) oppimisen malleissa tarvitset kaksi dataframea:

  • Selittävien muuttujien arvot (feature-matriisi , x-muuttujat). Selittävien muuttujien dataframen nimeksi voit antaa esimerkiksi X.
  • Selitettävän/ennustettavan muuttujan arvot (target, labels, y-muuttuja). Selitettävän muuttujan dataframen nimeksi voit antaa esimerksi y.

Ohjaamattomissa (unsupervised) malleissa tarvitset ainoastaan feature-matriisin.

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 erilaisilla lisäparametreilla. Mahdolliset lisäparametrit kirjoitetaan sulkujen sisään. Esimerkiksi seuraavassa muodostetaan lineaarinen regressiomalli, johon ei otetan mukaan lainkaan vakiotermiä (intercept).

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

Mallien tuunaus lisäparametreilla edellyttää mallien hyvää tuntemusta.

Arvioi mallin sopivuutta

Sopivuuden arviointiin on monia menetelmiä. 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/

Miksi Python?

Miksi vaivautua koodaamaan, koska datojen analysointiin sopivia valmisohjelmia (Excel, SPSS jne.) on olemassa? Seuraavassa muutamia Pythonin vahvuuksia:

  • Jos sinulla ei ole aiempaa kokemusta koodauksesta, niin opit samalla koodaamaan yhdellä suosituimmista ohjelmointikielistä.
  • Python on nopea ja toimii hyvin isojenkin datojen kanssa.
  • Perusasiat hoituvat helposti. Esimerkiksi komennolla data.describe() saat datan kaikkien muuttujien keskeisimmät tilastolliset tunnusluvut ja komennolla data.corr() saat datan muuttujien väliset korrelaatiot.
  • Kerran kirjoitettu koodi on aina suoritettavissa uudelleen. Voit analysoida rakenteeltaan samanlaisia aineistoja ilman koodin uudelleen kirjoittamista. Voit pienin muutoksin hyödyntää kerran kirjoitettua koodia uusien datojen kanssa.
  • Koodi toimii dokumentaationa tehdyistä analyyseistä. Voit milloin tahansa tehdä muutoksia koodiin ja suorittaa analyysit uudelleen.
  • Python tarjoaa monipuoliset mahdollisuudet tulosten graafiseen havainnollistamiseen.
  • Python on yleiskäyttöinen ohjelmointikieli ja sillä laskettuja tuloksia voit käyttää Pythonilla kirjoitetuissa ohjelmissa (esimerkiksi erilaiset tekoälysovellukset).
  • Ohjemateriaalia ja esimerkkejä löytyy helposti netistä. Jos kohtaat ongelman, niin kirjoittamalla Googleen englanninkielisen kysymyksen, löydät yleensä myös vastauksen (usein miten stackoverflow-sivustolta).
  • Python toimii samalla tavoin Windows-, Linux– ja MacOS-käyttäjärjestelmissä.
  • Python on ilmainen.

Kuviot ja kaaviot Pythonilla

Päivitetty 31.7.2019.

Kuvioiden ja kaavioiden peruskirjasto on matplotlib. Vakiintuneen tavan mukaan käytän plt-lyhennettä:

import matplotlib.pyplot as plt
%matplotlib inline

Jupyteria käyttäessäni lisään rivin %matplotlib inline, jonka ansiosta laaditut kaaviot tulostuvat Jupyter-notebookiin ilman erillistä tulostuskomentoa (plt.show()).

Kaavioiden luomiseen ja muotoiluun on erilaisia tapoja. Tarkastelen seuraavassa kahta tapaa, jotka sopivat kaavioiden luomiseen pandas dataframesta. Ensimmäinen tapa on yksinkertaisempi, mutta toinenkin tapa kannattaa opetella.

Tapa1

Pystypylväskaavion (bar) voin luoda dataframesta df:

df.plot.bar()

Muita paljon käytettyjä kaaviolajeja ovat barh (vaakapylväs), pie (piirakka), hist (histogrammi), line (viiva), scatter (piste) ja box (ruutu- ja janakaavio).

Kaavion luonnin yhteydessä voin tehdä kaavioon liittyviä asetuksia lisäparametreilla, esimerkiksi:

  • legend arvoksi voin asettaa False tai ’reverse’. Oletusarvona on True. legend=’reverse’ kääntää selitteen arvojen järjestyksen.
  • width arvoksi voin asettaa luvun väliltä 0-1. Oletusarvona on 0.5. Mitä suurempi arvo, sitä lähempänä toisiaan ja sitä paksumpia pylväät ovat. Jos width=1, niin pylväät ovat kiinni toisissaan.
  • rot kääntää luokka-akselin jakoviivojen (ticks) nimiöt annetun asteluvun mukaan. Esimerkiksi rot=45 kääntää nimiöt 45 asteen kulmaan.
  • stacked=True luo pinotun pylväskaavion
  • color määrittää pylväiden värin. Esimerkiksi color=’C0′ asettaa väriksi käytössä olevan väripaletin ensimmäisen värin. Voin käyttää värien nimiä tai koodeja (katso https://htmlcolorcodes.com/)
  • style määrittää viivakaavion viivan ja havaintopisteiden tyylin. Esimerkiksi style=’ro-’ tekee punaisen (r) viivan (), jossa havaintopisteet ovat ympyröitä (o). Lisätietoa https://matplotlib.org/3.1.0/api/_as_gen/matplotlib.axes.Axes.plot.html
  • edgecolor määrittää pylväiden reunan värin.

Lisätietoa ominaisuuksista, jotka voit asettaa lisäparametreilla:

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.plot.html

Lisäparametrien lisäksi voin muotoilla kaaviota matplotlib.pyplot-funktioilla. Esimerkiksi plt.title(’Kaavion otsikko’). Funktiot kohdistuvat aina viimeksi luotuun kaavioon. Funktiot tarjoavat Matlab-matematiikkaohjelmiston käyttäjille tutun käyttöliittymän kaavioihin. Lisätietoa:

https://matplotlib.org/3.1.0/tutorials/introductory/pyplot.html

Esimerkeissäni en yleensä käytä matplotlib.pyplot-funktioita, vaan muotoilen kaaviot kaavion luonnin palauttaman olion kautta. Tätä varten sijoitan kaavion luonnin palauttaman olion muuttujan arvoksi:

ax = df.plot.bar()

Tämän Axes-luokan olion kautta pääsen käsiksi kaavion elementteihin, esimerkiksi:

  • ax.set_title(’Kaavion otsikko’)
  • ax.set_xlabel(’x-akselin otsikko’)
  • ax.set_ylabel(’y-akselin otsikko’)

Koodiesimerkeistäni löydät malleja useimmin tarvittavista muotoilu-komennoista. Lisätietoa Axes-luokan oliosta:

https://matplotlib.org/3.1.0/api/axes_api.html

Tapa 2

Toinen tapa kaavion luontiin vaatii hieman enemmän koodia (vertaa ax = df.plot.bar()):

fig, ax = plt.subplots()
df.plot.bar(ax = ax)

Tämän hankalamman tuntuisen tavan perusteluksi kannattaa perehtyä kaavion luonnin yhteydessä syntyviin olioihin.

Kaavio itsessään on Axes-luokan olio.

Kaavio sijoittuu aina kuvion sisään. Kuvio puolestaan on Figure-luokan olio. Jos kuvioon pitää viitata, niin kannattaa käyttää kaavion luontiin plt.subplots()-funktiota, joka palauttaa sekä kuvion että ”tyhjän” kaavion. plt.subplots()-funktion palauttaman kuvion ja kaavion sijoitan muuttujien arvoiksi (esimerkiksi fig, ax = plt.subplots()).

Kaavion sisällön määritän plot-funktiolla. Lisäparametrilla ax kerron, minkä nimiseen Axes-luokan olioon kaavio piirretään (esimerkiksi df.plt.bar(ax = ax)) .

Oliohierarkian hahmottamista auttaa oheinen osoitteesta https://realpython.com/python-matplotlib-guide/ lainattu havainnollistus:

matplotlib1

Uloimpana on kuvio (Figure) ja sen sisällä kaavio (Axes). Kaavion sisällä on useita olioita, esimerkiksi kaavion otsikko, akselit, akselien otsikot, jne.

Ensimmäinen, yksinkertaisempi tapa kaavion luontiin, tuottaa saman olioiden hierarkian, mutta ei palauta Figure-luokan olioita siten että voisin sijoittaa sen suoraan muuttujan arvoksi. Saan tosin selville Figure-luokan olion jälkikäteen funktiolla plt.gcf(). Figure-luokan olioita tarvitsen ainakin seuraavissa tilanteissa:

  • Kuvion tallentaminen: jos haluan tallentaa kaavion, niin minun pitää tallentaa kuvio.
  • Useita kaavioita samassa kuviossa: voin sijoittaa saman kuvion sisään useita kaavioita vierekkäin ja allekkain.

Seuraavaksi

Pääset hyvään alkuun tutustumalla esimerkkikokoelmani koodeihin:

https://github.com/taanila/kaaviot

Samalla kannattaa alkaa kokeilla omien kaavioiden luomista ja muotoilua.

Perusasiat ja useimmin tarvitut muotoilukomennot oppii nopeasti ulkoa, mutta harvemmin tarvittavia temppuja täytyy selvitellä googlaamalla. Hämmennystä aiheuttaa netistä löytyvien esimerkkien moninaisuus ja vaihtelevat käytännöt. Monissa koodeissa käytetään sekaisin Axes-olion kautta tehtyjä muotoiluja ja matplotlib.pyplot-funktioilla tehtyjä muotoiluja. Kaavioiden luonnissa käytetään tässä esitettyjen tapojen lisäksi myös kaavion luomista suoraan Axes-olioon (ax.bar()).

Artikkelista jupyter: taulukot ja kaaviot raporttiin selviää, miten tallennat ja siirrät kaavioita raporttiin.

Jupyter: Taulukot ja kaaviot raporttiin

Päivitetty 1.7.2019.

Tässä artikkelissa kerron, miten voit siirtää Pythonilla Jupyter-notebookiin lasketut taulukot ja kaaviot Word-raporttiin.

Taulukot

Jupyter-notebook toimii oletusselaimessa. Laskettujen (html-muotoisten) taulukoiden ulkoasu riippuu käytetystä selaimesta.

Ennen Wordiin kopiointia taulukon lukumuotoilut kannattaa laittaa kuntoon (desimaalien määrä, mahdolliset prosenttimuotoilut).

Valitse taulukko ja kopioi-liitä se Word-dokumenttiin. Näin saat Word-taulukon, jonka ulkoasua voit  muuttaa Wordin taulukkotyökaluilla:

  • Valitse solu taulukon alueelta.
  • Valitse Table Tools – Design -työkaluista haluamasi tyyli.

taulukko

Vieressä on kuvakaappaus Jupyter-notebookista.

Kopioi-liitä liittää sen Wordiin karun näköisenä taulukkona (keskimmäinen taulukko).

Tämän jälkeen valitsin Table Tools – Design (Taulukkotyökalut – Rakenne) -työkaluista mieleiseni tyylin. Tästä voisin vielä jatkaa esimerkiksi tasaamalla koulutuksia kuvaavat tekstit vasempaan reunaan, korvaamalla desimaalipisteet pilkuilla ja vaihtamalla fonttia.

Taulukon sisältöä, tekstejä ja lukuja, voin tarvittaessa muokata.

Kaaviot

Samassa Jupyter-notebookin solussa luodun kaavion voit tallentaa komennolla

plt.savefig('nimi.png', bbox_inches='tight')

Tärkeitä huomioita:

  • Jos tiedostonimeen ei liity polkua, niin kaavio tallentuu samaan kansioon kuin Jypyter-notebook.
  • Ilman bbox_inches=’tight’-parametria kaavion reunoilla olevat tekstit jäävät usein osittain tallennetun kaavion ulkopuolelle.
  • Tiedostoformaatti määräytyy tiedostonimen tarkentimesta (edellä .png).

Järjestelmäsi tukemat kuvaformaatit saat selville komennolla

plt.figure().canvas.get_supported_filetypes()

Tuloksena saat listauksen kuvaformaateista, esimerkiksi:

{'ps': 'Postscript',
 'eps': 'Encapsulated Postscript',
 'pdf': 'Portable Document Format',
 'pgf': 'PGF code for LaTeX',
 'png': 'Portable Network Graphics',
 'raw': 'Raw RGBA bitmap',
 'rgba': 'Raw RGBA bitmap',
 'svg': 'Scalable Vector Graphics',
 'svgz': 'Scalable Vector Graphics',
 'jpg': 'Joint Photographic Experts Group',
 'jpeg': 'Joint Photographic Experts Group',
 'tif': 'Tagged Image File Format',
 'tiff': 'Tagged Image File Format'}

Kaavion voit myös kopioida Jupyter-notebookista suoraan Wordiin kopioi-liitä-toiminnolla (löydät kopioi-komennon napsauttamalla hiiren kakkospainiketta kaavion päällä).

Kaavioiden fontti

Kaavion  fonttia et voi vaihtaa enää raportissa. Pythonilla fontin vaihto onnistuu, mutta se pitää tehdä ennen kaavioiden luontia. Voit antaa seuraavat komennot heti ohjelmakirjaston tuonnin (import  matplotlib.pyplot as plt) jälkeen. Komennot vaikuttavat näin kaikkiin samassa notebookissa laadittaviin kaavioihin.

plt.rcParams['font.sans-serif'] = "Arial"
plt.rcParams['font.family'] = "sans-serif"

Ensimmäisellä komennolla määrität fonttilajin. Yllä on määritelty ’sans-serif’-fontiksi ’Arial’. Sen jälkeen on määritelty, että kaavioissa käytetään ’sans-serif’-fonttia. ’sans-serif’ tarkoittaa fontteja ilman pääteviivaa (groteski). Voit myös määrittää käytettäväksi ’serif’-fontin eli pääteviivallisen fontin.

Voit halutessasi säätää myös fonttikoot, esimerkiksi:

plt.rcParams['font.size'] = 12 #oletusfontti
plt.rcParams['axes.titlesize'] = 14 #kaavion otsikko
plt.rcParams['axes.labelsize'] = 12 #akselien otsikot
plt.rcParams['xtick.labelsize'] = 10 #x-akselin jaotuksen nimiöt
plt.rcParams['ytick.labelsize'] = 10 #y-akselin jaotuksen nimiöt
plt.rcParams['legend.fontsize'] = 12 #selite
plt.rcParams['figure.titlesize'] = 14 #kuvion otsikko

 

Github – esimerkit omalle koneelle

Olen tallentanut esimerkkikoodit Jypyter-notebook -muotoisina githubiin. Esimerkit aukeavat selaimeen, josta voit halutessasi kopioida koodin pätkiä (solu kerrallaan) itsellesi. Kokonaisen Jupyter-notebookin tallentaminen omalle koneelle ei välttämättä onnistu (riippuu selaimesta ja monesta muustakin asiasta). Voit kuitenkin kloonata kaikki esimerkkini kerralla omalle koneellesi seuraavasti:

  • Siirry osoitteeseen https://github.com/taanila/tilastoapu
  • Napsauta vihreää Clone or download -painiketta ja valitse Download ZIP
  • Tallenna omaan kotihakemistoosi (sinne, missä säilytät Python-koodejasi)
  • Pura (Extract all) tallentamasi paketti (tilastoapu-master)

Kaikki esimerkit ovat tämän jälkeen avattavissa ja käytettävissä Jupyterissä.

Päivitän esimerkkejä aika ajoin. Tuoreimmat versiot saat käyttöösi suorittamalla yllä kuvatun kloonauksen uudelleen.

Kloonaa myös esimerkkikokoelmani kaavioista http://github.com/taanila/kaaviot

 

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.