Luokittelu - logistinen regressio

Klassinen esimerkki luokittelusta on kurjenmiekkojen (iris) luokittelu kolmeen lajiin (setosa, versicolor, virginica) terä- (petal) ja verholehtien (sepal) koon mukaan. Seuraavassa käytän luokitteluun logistista regressiota.

Logistisen regression idea

Logistinen regressio on luokittelumenetelmä eikä sitä pidä sekoittaa tavalliseen regressioon.

Logistinen regressio antaa myös todennäköisyydet luokkiin kuulumisille.

Logistisen regression perusideaa vaikea selittää lyhyesti. Lue aihetta koskeva artikkelini: https://tilastoapu.wordpress.com/2014/04/25/logistinen-regressio/

In [1]:
import numpy as np
import pandas as pd
import matplotlib as plt
import seaborn as sns
%matplotlib inline

#Vaikuttaa kaavioiden ulkoasuun:
sns.set()
In [2]:
#Esimerkkiaineisto löytyy seaborn-kirjastosta:
iris=sns.load_dataset('iris')
iris.head()
Out[2]:
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
In [3]:
#Seaborn-kirjaston pairplot havainnollistaa hyvin lajin (species) riippuvuutta petal- ja sepal-mitoista:
sns.pairplot(iris, hue='species')
C:\Users\Aki\Anaconda3\lib\site-packages\scipy\stats\stats.py:1713: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.
  return np.add.reduce(sorted[indexer] * weights, axis=axis) / sumval
Out[3]:
<seaborn.axisgrid.PairGrid at 0x1fa05a92a20>
In [4]:
#Feature-matriisi on iris-data ilman species-muuttujaa:
X = iris.drop('species', axis=1)

#Target on species (laji):
y = iris['species']
In [5]:
#train_test_split jakaa datan opetusdataan ja testidataan (25 % datasta, jolloin toisin määrätä).
#random_state määrittää satunnaislukugeneraattorin siemenluvun. Sama siemenluku takaa saman jaottelun
#eri suorituskerroilla.
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test=train_test_split(X, y, random_state=5)
In [6]:
#Logistisen regressiomallin tuonti:
from sklearn.linear_model import LogisticRegression

#Mallin sovitus:
malli = LogisticRegression()
malli.fit(X_train, y_train)

#Mallin mukaisten ennusteiden laskeminen opetusdatalle ja testidatalle:
y_train_malli = malli.predict(X_train)
y_test_malli = malli.predict(X_test)
C:\Users\Aki\Anaconda3\lib\site-packages\sklearn\linear_model\logistic.py:433: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.
  FutureWarning)
C:\Users\Aki\Anaconda3\lib\site-packages\sklearn\linear_model\logistic.py:460: FutureWarning: Default multi_class will be changed to 'auto' in 0.22. Specify the multi_class option to silence this warning.
  "this warning.", FutureWarning)
In [7]:
#Oikeaan osuneiden ennusteiden osuus opetusdatassa:

from sklearn.metrics import accuracy_score

accuracy_score(y_train, y_train_malli)
Out[7]:
0.9553571428571429
In [8]:
#Oikeaan osuneiden ennusteiden osuus testidatassa:

accuracy_score(y_test, y_test_malli)
Out[8]:
0.9210526315789473
In [9]:
#Confusion-matriisi opetusdatalle:

from sklearn.metrics import confusion_matrix

print(confusion_matrix(y_train, y_train_malli))
[[38  0  0]
 [ 0 32  4]
 [ 0  1 37]]

Kaikki Setosa-lajiin kuuluvat ennustetaan oikein, neljä Versicoloria ennustetaan virheellisesti Virginica-lajiin kuuluviksi, yksi Virginica-lajiin kuuluvaa ennustetaan virheellisesti Versicolor-lajiin kuuluvaksi.

In [10]:
#Confusion-matriisi testidatalle:

from sklearn.metrics import confusion_matrix

print(confusion_matrix(y_test, y_test_malli))
[[12  0  0]
 [ 0 11  3]
 [ 0  0 12]]

Kaikki Setosa-lajiin kuuluvat ennustetaan oikein, kolme Versicoloria ennustetaan virheellisesti Virginica-lajiin kuuluviksi, kaikki Virginica-lajiin kuuluvat ennustetaan oikein.

In [11]:
#Uusi data, jota ei ole valmiiksi luokiteltu:
Xnew = pd.read_excel('http://taanila.fi/irisnew.xlsx')
Xnew
Out[11]:
sepal_length sepal_width petal_length petal_width
0 5.0 3.5 1.5 0.3
1 8.1 3.3 6.5 1.9
2 6.0 3.0 3.0 0.5
In [12]:
#Luokittelu:
malli.predict(Xnew)
Out[12]:
array(['setosa', 'virginica', 'versicolor'], dtype=object)
In [13]:
#Todennäköisyydet:
malli.predict_proba(Xnew)
Out[13]:
array([[8.93301567e-01, 1.06602497e-01, 9.59362225e-05],
       [3.84074383e-04, 4.77002244e-01, 5.22613681e-01],
       [4.91342480e-01, 5.07162173e-01, 1.49534737e-03]])

Ensimmäinen 89,330 % todennäköisyydellä setosa, 10,660 % todennäköisyydellä versicolor ja 0,0096 % todennäköisyydellä virginica.