2023-programowanie-w-pythonie/zajecia3/sklearn cz. 1.ipynb

30 KiB

Kkolejna część zajęć będzie wprowadzeniem do drugiej, szeroko używanej biblioteki w Pythonie: sklearn. Zajęcia będą miały charaktere case-study poprzeplatane zadaniami do wykonania. Zacznijmy od załadowania odpowiednich bibliotek.

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

%matplotlib inline

Zacznijmy od załadowania danych. Na dzisiejszych zajęciach będziemy korzystać z danych z portalu gapminder.org.

df = pd.read_csv('gapminder.csv', index_col=0)

Dane zawierają różne informacje z większość państw świata (z roku 2008). Poniżej znajduje się opis kolumn:

  • female_BMI - średnie BMI u kobiet
  • male_BMI - średnie BMI u mężczyzn
  • gdp - PKB na obywatela
  • population - wielkość populacji
  • under5mortality - wskaźnik śmiertelności dzieni pon. 5 roku życia (na 1000 urodzonych dzieci)
  • life_expectancy - średnia długość życia
  • fertility - wskaźnik dzietności

zad. 1 Na podstawie danych zawartych w df odpowiedz na następujące pytania:

  • Jaki był współczynniki dzietności w Polsce w 2018?
  • W którym kraju ludzie żyją najdłużej?
  • Z ilu krajów zostały zebrane dane?

zad. 2 Stwórz kolumnę gdp_log, która powstanie z kolumny gdp poprzez zastowanie funkcji log (logarytm).

Hint 1: Wykorzystaj funkcję apply (https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.apply.html#pandas.Series.apply).

Hint 2: Wykorzystaj fukcję log z pakietu np.

Naszym zadaniem będzie oszacowanie długości życia (kolumna life_expectancy) na podstawie pozostałych zmiennych. Na samym początku, zastosujemy regresje jednowymiarową na fertility.

y = df['life_expectancy'].values
X = df['fertility'].values

print("Y shape:", y.shape)
print("X shape:", X.shape)
Y shape: (175,)
X shape: (175,)

Będziemy korzystać z gotowej implementacji regreji liniowej z pakietu sklearn. Żeby móc wykorzystać, musimy napierw zmienić shape na dwuwymiarowy.

y = y.reshape(-1, 1)
X = X.reshape(-1, 1)

print("Y shape:", y.shape)
print("X shape:", X.shape)
Y shape: (175, 1)
X shape: (175, 1)

Jeszcze przed właściwą analizą, narysujmy wykres i zobaczny czy istnieje "wizualny" związek pomiędzy kolumnami.

df.plot.scatter('fertility', 'life_expectancy')
<matplotlib.axes._subplots.AxesSubplot at 0x7fc2c92991f0>

zad. 3 Zaimportuj LinearRegression z pakietu sklearn.linear_model.

Tworzymy obiekt modelu regresji liniowej.

model = LinearRegression()

Trening modelu ogranicza się do wywołania metodu fit, która przyjmuje dwa argumenty:

model.fit(X, y)
LinearRegression()

Współczynniki modelu:

print("Wyraz wolny (bias):", model.intercept_)
print("Współczynniki cech:", model.coef_)
Wyraz wolny (bias): [83.2025629]
Współczynniki cech: [[-4.41400624]]

zad. 4 Wytrenuj nowy model model2, który będzie jako X przyjmie kolumnę gdp_log. Wyświetl parametry nowego modelu.

Mając wytrenowany model możemy wykorzystać go do predykcji. Wystarczy wywołać metodę predict.

X_test = X[:5,:]
y_test = y[:5,:]
output = model.predict(X_test)

for i in range(5):
    print("input: {}\t predicted: {}\t expected: {}".format(X_test[i,0], output[i,0], y_test[i,0]))
input: 6.2	 predicted: 55.835724214829476	 expected: 52.8
input: 1.76	 predicted: 75.43391191760767	 expected: 76.8
input: 2.73	 predicted: 71.15232586542415	 expected: 75.5
input: 6.43	 predicted: 54.82050277977565	 expected: 56.7
input: 2.16	 predicted: 73.66830942186188	 expected: 75.5

Sprawdzenie jakości modelu - metryki: $R^2$ i $MSE$

Istnieją 3 metryki, które określają jak dobry jest nasz model:

from sklearn.metrics import mean_squared_error

print("R^2: {}".format(model.score(X, y)))
rmse = np.sqrt(mean_squared_error(y, model.predict(X)))
print("Root Mean Squared Error: {}".format(rmse))
R^2: 0.5955222955385271
Root Mean Squared Error: 5.682032704570357
# Import necessary modules
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split

# Create training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.30, random_state=42)

# Create the regressor: reg_all
reg_all = LinearRegression()

# Fit the regressor to the training data
reg_all.fit(X_train, y_train)

# Predict on the test data: y_pred
y_pred = reg_all.predict(X_test)

# Compute and print R^2 and RMSE
print("R^2: {}".format(reg_all.score(X_test, y_test)))
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
print("Root Mean Squared Error: {}".format(rmse))
R^2: 0.6742169953190864
Root Mean Squared Error: 4.874062378427941

Regresja wielu zmiennych

Model regresji liniowej wielu zmiennych nie różni się istotnie od modelu jednej zmiennej. Np. chcąc zbudować model oparty o dwie kolumny: fertility i gdp wystarczy zmienić X (cechy wejściowe):

X = df[['fertility', 'gdp']]
print(df['fertility'].shape)
print(df[['fertility']].shape)

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

model_mv.score(X, y)
(175,)
(175, 1)
0.6566838211706549

zad. 6 Która kombinacja dwóch kolumn daje najlepszy wynik w metryce $R^2$? Tak jak poprzednio, próbujemy przewidzieć zawartosć kolumny life_expectancy.

Uwaga: Należy wyłączyć kolumnę life_expectancy spośród szukanych.

zad. 7

  • Zbuduj model regresji liniowej, która oszacuje wartność kolumny life_expectancy na podstawie pozostałych kolumn.
  • Wyświetl współczynniki modelu? Dla jakich cech współczynniki modelu są bliskie 0? Dlaczego?
  • Oblicz wartości obu metryk na zbiorze trenującym.

zad. 6 Wykonaj jedno z zadań 6.1 lub 6.2.

zad. 6.1 Zaimplementuj metrykę $R^2$ jako fukcję r2 (szablon poniżej). Fukcja r2 przyjmuje dwa parametry typu _list i ma zwrócić wartość metryki $R^2$.

def r2(expected, predicted):
    """
    argumenty:
    expected (type: list): poprawne wartości
    predicted (type: list): oszacowanie z modelu
    """
    pass

y = df['life_expectancy'].values
X = df[['fertility', 'gdp']].values

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

print("Real R2:", test_model.score(X, y))

predicted = list(test_model.predict(X))
expected = list(y)

print("Calculated:", r2(expected, predicted))
Real R2: 0.6566838211706549
Calculated: None

Zaimplementuj metrykę $RMSE$ jako fukcję rmse (szablon poniżej). Fukcja rmse przyjmuje dwa parametry typu list i ma zwrócić wartość metryki $RMSE$ .

def rmse(expected, predicted):
    """
    argumenty:
    expected (type: list): poprawne wartości
    predicted (type: list): oszacowanie z modelu
    """
    pass

y = df['life_expectancy'].values
X = df[['fertility', 'gdp']].values

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

print("Real R2:", np.sqrt(mean_squared_error(y, test_model.predict(X))))

predicted = list(test_model.predict(X))
expected = list(y)

print("Calculated:", r2(expected, predicted))
Real R2: 5.234841906276239
Calculated: None