2023-programowanie-w-pythonie/zajecia3/sklearn cz. 1.ipynb
Maksymilian Stachowiak d506707eb8 update
2023-11-26 11:14:05 +01:00

50 KiB
Raw Blame History

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.

# ! pip install matplotlib
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?
df.head(10)

df.loc['Poland', 'fertility']
df[df['life_expectancy'].max() == df['life_expectancy']]
len(df.index)
175

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.

df['gdp_log'] = df['gdp'].apply(np.log)

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('gdp_log', 'gdp')
<Axes: xlabel='gdp_log', ylabel='gdp'>

zad. 3 Zaimportuj LinearRegression z pakietu sklearn.linear_model.

Tworzymy obiekt modelu regresji liniowej.

from sklearn.linear_model import LinearRegression
model = LinearRegression()

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

model.fit(X, y)
LinearRegression()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
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.

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

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

model.fit(X, y)

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

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: 7.1785454837637	 predicted: 59.56349361537759	 expected: 52.8
input: 9.064620717626777	 predicted: 69.89389316839483	 expected: 76.8
input: 9.418492105471156	 predicted: 71.83211533534711	 expected: 75.5
input: 8.86827250899781	 predicted: 68.81845597997369	 expected: 56.7
input: 10.155646068918863	 predicted: 75.86965044411781	 expected: 75.5

Sprawdzenie jakości modelu - metryki: $MSE$

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

from sklearn.metrics import mean_squared_error

rmse = np.sqrt(mean_squared_error(y, model.predict(X)))
print("Root Mean Squared Error: {}".format(rmse))
Root Mean Squared Error: 5.542126033117308
# 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.768485708231896
Root Mean Squared Error: 4.108807300711791

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']]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.30, random_state=42)

print(X.shape)

model_mv = LinearRegression()
model_mv.fit(X_train, y_train)

print("Wyraz wolny (bias):", model_mv.intercept_)
print("Współczynniki cech:", model_mv.coef_)

y_pred = model_mv.predict(X_test)

rmse = np.sqrt(mean_squared_error(y_test, y_pred))
print("Root Mean Squared Error: {}".format(rmse))
(175, 2)
Wyraz wolny (bias): [78.39388437]
Współczynniki cech: [[-3.68816683e+00  1.38298454e-04]]
Root Mean Squared Error: 4.347105512793037

zad. 7

  • Zbuduj model regresji liniowej, która oszacuje wartność kolumny life_expectancy na podstawie pozostałych kolumn.
  • Wyświetl współczynniki modelu.
  • Oblicz wartości metryki rmse na zbiorze trenującym.
from sklearn.linear_model import LogisticRegression, LinearRegression, LogisticRegressionCV
from sklearn.model_selection import train_test_split

X = df.drop('life_expectancy', axis='columns')
y = df['life_expectancy']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3)

model = LinearRegression()
model.fit(X_train, y_train)

print("Wyraz wolny (bias):", model.intercept_)
print("Współczynniki cech:", model.coef_)

y_pred = model.predict(X_test)

rmse = np.sqrt(mean_squared_error(y_test, y_pred))
print(f"Root Mean Sqared Error: {rmse}")
Wyraz wolny (bias): 51.77966340645703
Współczynniki cech: [-1.26558913e+00  1.58457647e+00 -1.19465585e-05  8.99682207e-10
 -1.32027358e-01  3.09413223e-01  1.74214537e+00]
Root Mean Sqared Error: 3.42188778846474

zad. 6

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
    """

    if len(expected) != len(predicted):
        raise ValueError("Lists have to be equal length, can't proceed.")

    mse = 0
    for i in range(len(expected)):
        mse += pow((expected[i] - predicted[i]),2)
    return np.sqrt(mse/len(expected))
    
    

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

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

predicted = list(test_model.predict(X))
expected = list(y)
# expected.append(1)

print(rmse(predicted,expected))
print(np.sqrt(mean_squared_error(predicted, expected)))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
j:\Python\2023-programowanie-w-pythonie\zajecia3\sklearn cz. 1.ipynb Cell 39 line 2
     <a href='vscode-notebook-cell:/j%3A/Python/2023-programowanie-w-pythonie/zajecia3/sklearn%20cz.%201.ipynb#X53sZmlsZQ%3D%3D?line=25'>26</a> expected.append(1)
     <a href='vscode-notebook-cell:/j%3A/Python/2023-programowanie-w-pythonie/zajecia3/sklearn%20cz.%201.ipynb#X53sZmlsZQ%3D%3D?line=27'>28</a> # print(rmse(predicted,expected))
---> <a href='vscode-notebook-cell:/j%3A/Python/2023-programowanie-w-pythonie/zajecia3/sklearn%20cz.%201.ipynb#X53sZmlsZQ%3D%3D?line=28'>29</a> print(np.sqrt(mean_squared_error(predicted, expected)))

File c:\software\python3\lib\site-packages\sklearn\utils\_param_validation.py:211, in validate_params.<locals>.decorator.<locals>.wrapper(*args, **kwargs)
    205 try:
    206     with config_context(
    207         skip_parameter_validation=(
    208             prefer_skip_nested_validation or global_skip_validation
    209         )
    210     ):
--> 211         return func(*args, **kwargs)
    212 except InvalidParameterError as e:
    213     # When the function is just a wrapper around an estimator, we allow
    214     # the function to delegate validation to the estimator, but we replace
    215     # the name of the estimator by the name of the function in the error
    216     # message to avoid confusion.
    217     msg = re.sub(
    218         r"parameter of \w+ must be",
    219         f"parameter of {func.__qualname__} must be",
    220         str(e),
    221     )

File c:\software\python3\lib\site-packages\sklearn\metrics\_regression.py:474, in mean_squared_error(y_true, y_pred, sample_weight, multioutput, squared)
    404 @validate_params(
    405     {
    406         "y_true": ["array-like"],
   (...)
    415     y_true, y_pred, *, sample_weight=None, multioutput="uniform_average", squared=True
    416 ):
    417     """Mean squared error regression loss.
    418 
    419     Read more in the :ref:`User Guide <mean_squared_error>`.
   (...)
    472     0.825...
    473     """
--> 474     y_type, y_true, y_pred, multioutput = _check_reg_targets(
    475         y_true, y_pred, multioutput
    476     )
    477     check_consistent_length(y_true, y_pred, sample_weight)
    478     output_errors = np.average((y_true - y_pred) ** 2, axis=0, weights=sample_weight)

File c:\software\python3\lib\site-packages\sklearn\metrics\_regression.py:99, in _check_reg_targets(y_true, y_pred, multioutput, dtype)
     65 def _check_reg_targets(y_true, y_pred, multioutput, dtype="numeric"):
     66     """Check that y_true and y_pred belong to the same regression task.
     67 
     68     Parameters
   (...)
     97         correct keyword.
     98     """
---> 99     check_consistent_length(y_true, y_pred)
    100     y_true = check_array(y_true, ensure_2d=False, dtype=dtype)
    101     y_pred = check_array(y_pred, ensure_2d=False, dtype=dtype)

File c:\software\python3\lib\site-packages\sklearn\utils\validation.py:409, in check_consistent_length(*arrays)
    407 uniques = np.unique(lengths)
    408 if len(uniques) > 1:
--> 409     raise ValueError(
    410         "Found input variables with inconsistent numbers of samples: %r"
    411         % [int(l) for l in lengths]
    412     )

ValueError: Found input variables with inconsistent numbers of samples: [175, 176]