from sklearn.tree import DecisionTreeClassifier

from mlxtend.plotting import plot_decision_regions

def generated_entangled_clouds():
    X1, Y1 = make_blobs(n_features=2, centers=1)
    X2, Y2 = make_blobs(n_features=2, centers=1)
    Y2 = np.ones_like(Y2)
    X1 -= np.mean(X1, axis=0)
    X2 -= np.mean(X2, axis=0)
    X2 += 1
    X = np.vstack((X1, X2)); Y = np.hstack((Y1, Y2))
    return X, Y

X, Y = generated_entangled_clouds()

plt.scatter(X[:, 0], X[:, 1], marker='o', c=Y, cmap=plt.cm.jet_r);

"""
Explanation: Разделяющая граница
End of explanation
"""


from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score
clf = DecisionTreeClassifier(random_state=1234)
clf = clf.fit(X, Y)
scores = cross_val_score(clf, X, Y)
print('Mean score:', scores.mean())

from mlxtend.plotting import plot_decision_regions
plot_decision_regions(X,Y,clf)

"""
Explanation: <div class="panel panel-info" style="margin: 50px 0 0 0">
    <div class="panel-heading">
        <h3 class="panel-title">Задание 1</h3> 
    </div>
</div>

Постройте DecisionTree из пакета sklearn.tree на выборке X, Y, нарисуйте разделяющую границу с помощью mlxtend.plotting.plot_decision_regions.
Сравните с разделяющей границей других известных вам классификаторов.
Убедитесь, что вы переобучили дерево, и достигается нулевая ошибка на обучающей выборке.
DecisionTree
End of explanation
"""


from sklearn.linear_model import Lasso
clf2 = Lasso()
clf2.fit(X, Y);
plot_decision_regions(X,Y,clf2)

"""
Explanation: Lasso
End of explanation
"""


from sklearn.neighbors import KNeighborsClassifier
clf3 = KNeighborsClassifier()
clf3.fit(X, Y);
plot_decision_regions(X,Y,clf3)

"""
Explanation: KNeighborsClassifier
End of explanation
"""


from sklearn.ensemble import RandomForestClassifier
clf4 = RandomForestClassifier(random_state=1234)
clf4.fit(X, Y);
plot_decision_regions(X,Y,clf4)

"""
Explanation: RandomForestClassifier
End of explanation
"""


clf5 = DecisionTreeClassifier(random_state=1234)
clf5 = clf5.fit(X, Y)
scores = cross_val_score(clf5, X, Y)
plot_decision_regions(X,Y,clf5)

plot_decision_regions(X,Y,clf5)

"""
Explanation: <div class="panel panel-info" style="margin: 50px 0 0 0">
    <div class="panel-heading">
        <h3 class="panel-title">Задание 2</h3> 
    </div>
</div>

Создайте еще пару деревьев, повторите процедуру, нарисуйте разделяющую границу. Объясните, почему она выходит различной от раза к разу.
DecisionTree
End of explanation
"""


from sklearn.ensemble import ExtraTreesClassifier
clf6 = ExtraTreesClassifier(random_state=1234)
clf6 = clf6.fit(X, Y)
scores = cross_val_score(clf6, X, Y)
plot_decision_regions(X,Y,clf6)

"""
Explanation: ExtraTreesClassifier
End of explanation
"""


from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, ExtraTreesClassifier

def get_preprocessed_titanic():
    df = sns.load_dataset('titanic')

    X, y = df.drop(['survived'], axis=1), df.survived

    X["embarked"] = X["embarked"].fillna("S")
    X["fare"].fillna(X["fare"].median(), inplace=True)
    X["embark_town"] = X["embark_town"].fillna(X.embark_town.value_counts().index[0]) 
    
    average_age_titanic   = X["age"].mean()
    std_age_titanic       = X["age"].std()
    count_nan_age_titanic = X["age"].isnull().sum()
    rand_1 = np.random.randint(average_age_titanic - std_age_titanic, 
                               average_age_titanic + std_age_titanic, 
                               size=count_nan_age_titanic)
    
    X.loc[X.age.isnull(), 'age'] = rand_1
    X.drop(['deck', 'alive'], axis=1, inplace=True)
    return X, y

df = sns.load_dataset('titanic')

df.head()

X, y = get_preprocessed_titanic()

X.head()

y.head()

"""
Explanation: <div class="panel panel-info" style="margin: 50px 0 0 0">
    <div class="panel-heading">
        <h3 class="panel-title">Задание 3</h3> 
    </div>
</div>

Вооружитесь готовым кодом ниже. Это - данные о пассажирах Титаника: где они сидели, сколько им было лет, плыли ли они в одиночку или с родней и так далее. Требуется предсказать, выжил ли пассажир. Такую задачу вы решать уже, безусловно, умеете.
Возьмите validation_curve из sklearn.model_selection. С помощью этой функции постройте графики ошибок при различных значениях гиперпараметров:

n_estimators - один из самых важных параметров!
max_features - один из самых важных параметров!
min_samples_split 
min_samples_leaf
max_depth
End of explanation
"""


X = pd.get_dummies(X)

X.head()

X.shape

from sklearn.ensemble import ExtraTreesClassifier
clf7 = ExtraTreesClassifier(random_state=1234)
clf7 = clf7.fit(X, y)

from sklearn.model_selection import validation_curve

def plot_validation_curve(clf, X, y, param_name, param_range, cv):
    from sklearn.model_selection import validation_curve

    train_scores, valid_scores = validation_curve(clf, X, y, param_name, param_range, cv=cv)
    train_scores_mean = np.mean(train_scores, axis=1)
    train_scores_std = np.std(train_scores, axis=1)
    valid_scores_mean = np.mean(valid_scores, axis=1)
    valid_scores_std = np.std(valid_scores, axis=1)

    plt.plot(param_range, train_scores_mean, c='orange');
    plt.plot(param_range, valid_scores_mean, color='red');
    plt.fill_between(param_range, 
                     valid_scores_mean - valid_scores_std,
                     valid_scores_mean + valid_scores_std, 
                     alpha=0.2, color='red');
    plt.title(param_name);

"""
Explanation: Лайфхак: преврати все подряд в one-hot-закодированное все подряд с помощью pd.get_dummies!
End of explanation
"""


plot_validation_curve(clf7,X,y,'n_estimators',[1,200],5)

"""
Explanation: n_estimators
End of explanation
"""


plot_validation_curve(clf7,X,y,'max_features',[1,X.shape[1]],5)

"""
Explanation: max_features
End of explanation
"""


plot_validation_curve(clf7,X,y,'min_samples_split',[2,200],5)

"""
Explanation: min_samples_split
End of explanation
"""


plot_validation_curve(clf7,X,y,'min_samples_leaf',[2,200],5)

"""
Explanation: min_samples_leaf
End of explanation
"""


plot_validation_curve(clf7,X,y,'max_depth',[1,10],10)

"""
Explanation: max_depth
End of explanation
"""


