<jupyter_start><jupyter_text>Nombre: <NAME> (418127029) Materia: Machine Learning Semestre: 4°  **Tarea: RF** (evaluada en la categoría _Otras evaluaciones_)<jupyter_code># Common imports
import numpy as np

# to make this notebook's output stable across runs
np.random.seed(42)

# To plot pretty figures
%matplotlib inline

import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.rc('axes', labelsize=14)
mpl.rc('xtick', labelsize=12)
mpl.rc('ytick', labelsize=12)<jupyter_output><empty_output><jupyter_text>a) Entrenar y ajustar un árbol de decisión para el conjunto de datos _Moon_<jupyter_code>from sklearn.datasets import make_moons

X, y = make_moons(n_samples=10000, noise=0.4, random_state=42)<jupyter_output><empty_output><jupyter_text>b) Dividir en conjunto de entrenamiento y de prueba utilizando ```train_test_split()``` **Importante**: _Todas las pruebas_ se realizarán prediciendo sobre ```X_test``` y comparando dichas predicciones contra ```y_test```<jupyter_code>from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)<jupyter_output><empty_output><jupyter_text>c) Utilizar la búsqueda en malla con validación cruzada (con ayuda de la clase ```GridSearchCV```) para encontrar valores aceptables para los metaparámetros del ```DecisionTreeClassifier```:<jupyter_code>from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV

params = {'max_leaf_nodes': list(range(2, 100)), 'min_samples_split': [2, 3, 4]}
grid_search_cv = GridSearchCV(DecisionTreeClassifier(random_state=42), params, n_jobs=-1, verbose=1, cv=3)

grid_search_cv.fit(X_train, y_train)<jupyter_output>Fitting 3 folds for each of 294 candidates, totalling 882 fits<jupyter_text>d) Mostrar el mejor estimador encontrado:<jupyter_code>grid_search_cv.best_estimator_
grid_search_cv.best_params_<jupyter_output><empty_output><jupyter_text>e) Por omisión, ```GridSearchCV``` entrena el mejor modelo encontrado con todo el conjunto de datos (entrenamiento + prueba) al terminar la búsqueda (esto se puede cambiar pasándole a ```GridSearchCV``` el parámetro ```refit=False```). Con lo anterior, evaluamos la exactitud del modelo directamente:<jupyter_code>from sklearn.metrics import accuracy_score

y_pred = grid_search_cv.predict(X_test)
accuracy_score(y_test, y_pred)<jupyter_output><empty_output><jupyter_text>*** **Trabajo a realizar*****  En este trabajo haremos la comparación de los resultados obtenidos al realizar GridSearchCV con la predicción que se logra obtener de entrenar arboles con los mejores parametros encontrados y posteriormente encontrando la predicción mas común.  1.- Generar 1,000 subconjuntos del conjunto de entrenamiento ```X_train```, cada uno con 100 instancias seleccionadas aleatoriamente. La selección es con reemplazo, es decir, no _sacan_ de ```X_train``` las instancias que vayan seleccionando (y no olviden copiar también de ```y_train``` las etiquetas correspondientes). Pueden utilizar la clase ```ShuffleSplit``` de Scikit-Learn para esto. **Nota**.- No hay subconjuntos de validación aquí, todas las pruebas se harán contra ```X_test``` y ```y_test```, como se indicó más arriba. se hace uso de ShuffleSplit para obtener los conjuntos de indices para generar nuestros arboles<jupyter_code>from sklearn.model_selection import ShuffleSplit

random_split = ShuffleSplit(n_splits=1000, test_size=0, train_size=100, random_state=42)
random_split.get_n_splits(X_train)<jupyter_output><empty_output><jupyter_text>se crea una lista de "arboles" donde almacenamos cada uno de los subconjuntos de indices que genero nuestro ShuffleSplit<jupyter_code>arboles = []
for train in random_split.split(X_train, y = None, groups = None):
    arboles.append(train[0])
print(len(arboles))<jupyter_output>1000<jupyter_text>2.- Entrenar un árbol de decisión en cada subconjunto de 100 instancias, usando los mejores valores de los metaparámetros encontrados por la búsqueda en malla, es decir, el estimador devuelto por ```grid_search_cv.best_estimator_```. Creamos los arboles y sus conjuntos de soluciones a partir de un ciclo for,  posteriormente haciendo uso del best_estimator_ y best_params_ entrenamos cada uno de los arboles creados<jupyter_code>from sklearn.tree import DecisionTreeClassifier
arbol_shuffle = []
arbol_entrenado = []
y_train_2_electricbogaloo = []
for i in range(len(arboles)):
    arbol_actual = []
    y_actual = []
    for j in range(100):
        indice = arboles[i][j]
        arbol_actual.append(X_train[indice])
        y_actual.append(y_train[indice])
    arbol_shuffle.append(arbol_actual)
    y_train_2_electricbogaloo.append(y_actual)
        
for i in range(len(arboles)):
    tree_sk = DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
                max_features=None,
                min_impurity_decrease=0.0, min_impurity_split=None,
                min_samples_leaf=1,
                min_weight_fraction_leaf=0.0, presort=False, random_state=42,
                splitter='best', max_leaf_nodes = 17, min_samples_split = 2)
    arbol_entrenado.append(tree_sk.fit(arbol_shuffle[i], y_train_2_electricbogaloo[i]))<jupyter_output><empty_output><jupyter_text>4.- Llega la magia: generar las predicciones de cada uno de los 1,000 árboles de decisión para cada instancia en el conjunto de prueba.  3.- Evaluar cada uno de estos 1,000 árboles de decisión sobre el conjunto de prueba (```X_test``` y ```y_test```). Sólo deben calcular los 1,000 ```accuracy_score``` y promediarlos. Dado que los árboles se entrenarán con conjuntos de datos más pequeños que con el árbol de decisión determinado por la búsqueda en malla, la exactitud promedio de estos mil árboles será muy probablemente más baja (resultará un 80% de exactitud, aproximadamente):<jupyter_code>pred = []
scores = []
avg = 0
for j in range(len(arbol_entrenado)):  
    y_predict = arbol_entrenado[j].predict(X_test)
    pred.append(y_predict)
    score = accuracy_score(y_test, y_predict)
    avg += score
    scores.append(score)
    
avg /= 1000
print(avg)<jupyter_output>0.8062925000000005<jupyter_text>El promedio de las predicciones termina siendo menor que nuestra predicción por GridSearch (0.8695)  5.- Conservar solamente la predicción más frecuente (se puede utilizar la función ```mode()``` de SciPy para esto). Esto corresponde a una predicción por mayoría de votos sobre el conjunto de prueba.<jupyter_code>from scipy import stats
moda = stats.mode(pred)<jupyter_output><empty_output><jupyter_text>6.- Evaluar las predicciones conservadas ```y_pred_majority_votes``` contra el conjunto de prueba ```y_test```: se debe obtener un  ```accuracy_score``` ligeramente más alto que el del árbol de decisión de la búsqueda en malla (entre el 0.5 y el 1.5%).<jupyter_code>moda_score = accuracy_score(y_test, moda[0][0])
print(moda_score)<jupyter_output>0.875
{'fraction_non_alphanumeric': 0.09080393290919607, 'fraction_numerical': 0.021399652978600348, 'mean_word_length': 6.087090163934426, 'pattern_counts': {'":': 0, '<': 46, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '178505', 'license': 'MIT', 'n_tokens_mistral': 2523, 'n_tokens_neox': 2383, 'n_words': 679, 'path': 'random_forest.ipynb', 'repo_name': 'ktsb3/random_forest_implementation_example', 'size': '6942'}