
#!/usr/bin/env python
# coding: utf-8

# Kody źródłowe do książki: Python. Uczenie maszynowe w przykładach
#  
# Rozdział 9.: Rozpoznawanie twarzy przy użyciu maszyny wektorów nośnych
#  
# Autor: Yuxi (Hayden) Liu (yuxi.liu.ece@gmail.com)

# # Klasyfikowanie zdjęć twarzy za pomocą maszyny wektorów nośnych

# ## Badanie zbioru zdjęć twarzy

from sklearn.datasets import fetch_lfw_people

# Wykonaj pierwszy wiersz kodu podczas pierwszego uruchamiania przykładu, w celu pobrania zbioru danych.
# face_data = fetch_lfw_people(min_faces_per_person=80)
face_data = fetch_lfw_people(data_home='./', min_faces_per_person=80, download_if_missing=False)


X = face_data.data
Y = face_data.target

print('Wielkość zbioru wejściowego:', X.shape)
print('Wielkość zbioru wyjściowego:', Y.shape)
print('Etykiety:', face_data.target_names)


for i in range(5):
    print(f'Klasa {i}, liczba próbek:{(Y == i).sum()}.')


import matplotlib.pyplot as plt

fig, ax = plt.subplots(3, 4)
for i, axi in enumerate(ax.flat):
    axi.imshow(face_data.images[i], cmap='bone')
    axi.set(xticks=[], yticks=[],
            xlabel=face_data.target_names[face_data.target[i]])

plt.show()


# ## Tworzenie klasyfikatora obrazów opartego na maszynie wektorów nośnych

from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, random_state=42)


from sklearn.svm import SVC
clf = SVC(class_weight='balanced', random_state=42)


from sklearn.model_selection import GridSearchCV
parameters = {'C': [10, 100, 300],
              'gamma': [0.0001,  0.0003, 0.001],
              'kernel' : ['rbf', 'linear'] }

grid_search = GridSearchCV(clf, parameters, n_jobs=-1, cv=5)


grid_search.fit(X_train, Y_train)


print('Najlepszy model:\n', grid_search.best_params_)


print('Najlepsza średnia skuteczność:', grid_search.best_score_)

clf_best = grid_search.best_estimator_

print(f'Dokładność: {clf_best.score(X_test, Y_test)*100:.1f}%')


pred = clf_best.predict(X_test)

from sklearn.metrics import classification_report
print(classification_report(Y_test, pred, target_names=face_data.target_names))


# ## Zwiększanie skuteczności klasyfikatora obrazów za pomocą analizy głównych składowych

from sklearn.decomposition import PCA
pca = PCA(n_components=100, whiten=True, random_state=42)
svc = SVC(class_weight='balanced', kernel='rbf', random_state=42)

from sklearn.pipeline import Pipeline
model = Pipeline([('pca', pca),
                  ('svc', svc)])


parameters_pipeline = {'svc__C': [1, 3, 10],
                       'svc__gamma': [0.01,  0.03, 0.003]}
grid_search = GridSearchCV(model, parameters_pipeline, n_jobs=-1, cv=5)

grid_search.fit(X_train, Y_train)


print('Najlepszy model:\n', grid_search.best_params_)
print('Najlepsza średnia skuteczność:', grid_search.best_score_)

model_best = grid_search.best_estimator_
print(f'Dokładność: {model_best.score(X_test, Y_test)*100:.1f}%')
pred = model_best.predict(X_test)
print(classification_report(Y_test, pred, target_names=face_data.target_names))


# # Szacowanie z użyciem regresji wektorów nośnych

# ## Implementacja regresji wektorów nośnych 

from sklearn import datasets
diabetes = datasets.load_diabetes()

X = diabetes.data
Y = diabetes.target

print('Rozmiar danych wejściowych: ', X.shape)
print('Rozmiar danych wyjściowych: ', Y.shape)


num_test = 30    # 30 ostatnich próbek używamy jako zbioru testowego
X_train = diabetes.data[:-num_test, :]
y_train = diabetes.target[:-num_test]
X_test = diabetes.data[-num_test:, :]
y_test = diabetes.target[-num_test:]


from sklearn.svm import SVR
regressor = SVR(C=100, kernel='linear')
regressor.fit(X_train, y_train)


from sklearn.metrics import r2_score
predictions = regressor.predict(X_test)
print(r2_score(y_test, predictions))


parameters = {'C': [300, 500, 700],
              'gamma': [0.3, 0.6, 1],
              'kernel' : ['rbf', 'linear']}

regressor = SVR()
grid_search = GridSearchCV(regressor, parameters, n_jobs=-1, cv=5)


grid_search.fit(X_train, y_train)


print('Najlepszy model:\n', grid_search.best_params_)


model_best = grid_search.best_estimator_
predictions = model_best.predict(X_test)

print(r2_score(y_test, predictions))


# ---

# Czytelnicy mogą pominąć następną komórkę.

get_ipython().system('jupyter nbconvert --to python ch9_part2.ipynb --TemplateExporter.exclude_input_prompt=True')

