<jupyter_start><jupyter_text>Algoritmo KNNEl algoritmo KNN (K Nearest Neighbors) trata de buscar los K puntos más cercanos a un punto concreto para poder inferir su valor.<jupyter_code>import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from sklearn.neighbors import KNeighborsClassifier<jupyter_output><empty_output><jupyter_text>EjemploImaginemos que seleccionamos 5 personas aleatorias y apuntamos su altura, peso y género (Hombre o mujer). Apuntamos sus datos en una libreta que tengamos a mano (o notebook) y los analizamos (creamos un DataFrame):<jupyter_code>data = {'Masa': [50, 80, 90, 45, 60, 40, 30],
        'Altura': [1.48, 1.82, 1.85, 1.55, 1.60, 2.00, 2.10],
        'Genero': ['m', 'h', 'h', 'm', 'm', 'z', 'z']}

df = pd.DataFrame(data)<jupyter_output><empty_output><jupyter_text>Ahora, veamos los datos de la mejor forma posible, con un gráfico de dispersión:<jupyter_code>ax = plt.axes()

ax.scatter(df.loc[df['Genero'] == 'h', 'Masa'],
           df.loc[df['Genero'] == 'h', 'Altura'],
           c="red",
           label="Hombre")
ax.scatter(df.loc[df['Genero'] == 'm', 'Masa'],
           df.loc[df['Genero'] == 'm', 'Altura'],
           c="blue",
           label="Mujer")
ax.scatter(df.loc[df['Genero'] == 'z', 'Masa'],
           df.loc[df['Genero'] == 'z', 'Altura'],
           c="green",
           label="??")

plt.xlabel("Masa")
plt.ylabel("Altura")
ax.legend()
plt.grid()
plt.show()<jupyter_output><empty_output><jupyter_text>Si nos dieran datos de una sexta persona, pero no nos dieran su género, ¿Podríamos adivinarlo de alguna forma? Pintemos los datos:<jupyter_code>punto_nuevo = {'Masa': [70],
               'Altura': [1.82]}


punto_nuevo = pd.DataFrame(punto_nuevo)

ax = plt.axes()

ax.scatter(df.loc[df['Genero'] == 'h', 'Masa'],
           df.loc[df['Genero'] == 'h', 'Altura'],
           c="red",
           label="Hombre")

ax.scatter(df.loc[df['Genero'] == 'm', 'Masa'],
           df.loc[df['Genero'] == 'm', 'Altura'],
           c="blue",
           label="Mujer")

ax.scatter(punto_nuevo['Masa'],
           punto_nuevo['Altura'],
           c="black",
          label='?')
plt.xlabel("Masa")
plt.ylabel("Altura")
ax.legend()
plt.grid()<jupyter_output><empty_output><jupyter_text>Dirías que es 'Hombre', ¿verdad? ¿Cómo lo has racionado?Si tu pensamiento es como el de la mayoría, habrás hecho (aunque sea de manera inconsciente) la diferencia entre ambos grupos. Al estar más cerca del grupo formado por los puntos que sabemos que son 'Hombres', decidimos que es 'Hombre'. Pues esto es lo que hace el algoritmo KNN, calcula la distancia de los puntos entre sí y decide a qué grupo pertenece, solo que en vez de utilizar todos los datos posibles, utiliza los K vecinos más próximos.<jupyter_code>from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=5)
X = df[['Masa', 'Altura']]
y = df[['Genero']]

knn.fit(X, y)

print(y.shape)

prediccion = knn.predict(punto_nuevo)
print(prediccion)<jupyter_output>(7, 1)
['m']<jupyter_text>Si quieres más información, puedes verlo en [documentación](https://scikit-learn.org/stable/modules/neighbors.htmlnearest-neighbors-classification). EJERCICIOVamos a practicar un poco más. Lee el dataset de Anuncios en redes sociales y crea un modelo de predicción con los diferentes algortimos que hemos visto, sabiendo que nuestro objetivo será predecir si el usuario compra (``Purchased = 1``) o no.1. ¿Se trata de un problema de regresión o de clasificación?2. Adapta todas las variables que tengan que se adaptadas.3. Divide el dataset en train y test, con un 30% de datos para test, y utilizando una semilla = 42.3. Prueba el modelo lineal que hemos visto para ese tipo de problemas (LinearRegression o LogisticRegression)4. Ahora, utiliza el modelo acorde basado en árboles de decisión5. Finalmente, utiliza el modelo que acabamos de estudiar y compara los resultados<jupyter_code>df = pd.read_csv("Social_Network_Ads.csv")
df['Gender'] = (df['Gender']=='Female').astype(int)
df
X_cols = ['Gender', 'Age', 'EstimatedSalary']
Y_cols = 'Purchased'
df['Sal_Age'] = df['EstimatedSalary']/df['Age']
mean_sal_age = df.groupby(['Age'])['EstimatedSalary'].mean()
mean_sal_g = df.groupby(['Gender'])['EstimatedSalary'].mean()
# df.merge(mean_sal_age, on='Age')
import sklearn
from sklearn.tree import DecisionTreeClassifier

clf = DecisionTreeClassifier(max_depth=3)
clf.fit(X_)

# linear_model.LogisticRegression
linear_model.LogisticRegression<jupyter_output><empty_output><jupyter_text>6. Imagina que en lugar de los datos que hemos visto, nos dieran los datos sin la edad. Elimina las variables 'Age' y 'User ID', y vuelve a probar los modelos, ¿cuál es el mejor algoritmo ahora?<jupyter_code>import numpy as np

df = pd.read_csv("Social_Network_Ads.csv")
df_2 = pd.get_dummies(df.copy())

knn = KNeighborsClassifier(n_neighbors=3)
y =df_2['Purchased']
X = df_2[['Age', 'EstimatedSalary','Gender_Female']]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state = 42)

# REGRESIÓN LOGÍSTICA
print("reglog")
log_model = linear_model.LogisticRegression(multi_class='ovr')
# Lo entrenamos:
log_model.fit(X_train, y_train)
predict_probab = log_model.predict_proba(X)
np.round(predict_probab, 2)
print(f" accuracy_train:" , log_model.score(X_train, y_train))
print(f" accuracy_test:" , log_model.score(X_test, y_test))# accuracy

# ARBOL DE DECISIÓN
print("tree")
from sklearn.tree import DecisionTreeClassifier
tree_clf = DecisionTreeClassifier(max_depth=3, random_state=42)
tree_clf.fit(X_train, y_train)
print(f" accuracy_train:" , tree_clf.score(X_test,y_test))
print(f" accuracy_train:" , tree_clf.score(X_train,y_train))

# KNN
print("knn")
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=30)
knn_model = knn.fit(X_train, y_train)
print(f" accuracy_train:" , knn_model.score(X_train, y_train))
print(f" accuracy_test:" , knn_model.score(X_test, y_test))# accuracy<jupyter_output>reglog
 accuracy_train: 0.6571428571428571
 accuracy_test: 0.6083333333333333
tree
 accuracy_train: 0.9333333333333333
 accuracy_train: 0.9071428571428571
knn
 accuracy_train: 0.8
 accuracy_test: 0.75<jupyter_text>7. ¿Y si las columnas que tuviera fueran 'Gender' y 'Age', que parece que serán las más fáciles de conseguir en un entorno real? Finalmente, también podríamos crearnos un iterador para encontrar la mejor K:<jupyter_code>best_k = 1
best_score = 0

for k in range(1, 281):
    knn = KNeighborsClassifier(n_neighbors=k)
    knn_model = knn.fit(X_train, y_train)
    knn_score = knn_model.score(X_test, y_test)
    if knn_score > best_score:
        best_score = knn_score
        best_k = k
best_k, best_score
df = pd.DataFrame(columns=['k', 'score'])

for k in range(1, 281):
    knn = KNeighborsClassifier(n_neighbors=k)
    knn_model = knn.fit(X_train, y_train)
#     print(f" accuracy_test:" , knn_model.score(X_test, y_test))
    df_aux = pd.DataFrame({'k': k, 'score': knn_model.score(X_test, y_test)}, index=[k-1])
    df = df.append(df_aux)
    
df.sort_values(by='score', ascending=False)
list_k = []
list_score = []

for k in range(1, 281):
    knn = KNeighborsClassifier(n_neighbors=k)
    knn_model = knn.fit(X_train, y_train)
#     print(f" accuracy_test:" , knn_model.score(X_test, y_test))
    list_k.append(k)
    list_score.append(knn_model.score(X_test, y_test))
    
pd.DataFrame({'k': list_k, 'score': list_score})<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13244944422124014, 'fraction_numerical': 0.021427614838623276, 'mean_word_length': 5.046963562753036, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 32, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '249974', 'license': 'MIT', 'n_tokens_mistral': 3014, 'n_tokens_neox': 2858, 'n_words': 694, 'path': 'Bloque 3 - Machine Learning/01_Supervisado/5-KNN/01_KNN_teoría.ipynb', 'repo_name': 'franciscocanon-thebridge/bootcamp_thebridge_PTSep20', 'size': '7467'}