# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     name: python3
# ---

# + [markdown] id="_ImNextglJ6g"
# # Taller Entendiendo Jupyter Lab, Github, Python y Regresión Lineal
#
# ---
#
# **Nombre**: <NAME>
#
# **Feha**: 22 de marzo de 2021
#
# **Obetivo**: Conocer las herramientas básicas de trabajo de entorno de trabajo de Jupyter con Google Collaboration, Github y desarrollo con Python para generar un modelo de ajuste de aprendizaje de máquina 
#
# ---
# -

# ## Parte 1 - Introducción a la regresión lineal

# ### Introducción
# Representa un ajuste o relación lineal entre dos o mas variables en un modelo matemático usado para aproximar la relación de dependencia, entre una variable dependiente $y$, y una variable independiente $x$.
#
# Entendiendo que lo que llamamos predicción o pronóstico (Probabilidad en el futuro que algo suceda) en las situaciones que nos compete estudiar la basaremos en conocimiento que aplicaremos para el desarrollo de nuestro estudio en temas de Inteligencia Artificial. Y podemos partir de una relación como la que se describe a continuación:
#
# $Variable Dependiente = Constante + Pendiente * Variable Independiente + Error$

# ### 2. Breve historia
#
# La regresión lineal es un campo de estudio el cual se centra en la relación estadística entre dos variables continuas, cuando ya se involucran más de una variable predictora, se establece una relación lineal Múltiple, se puede llevar el estudio de relación de $variables$.
#
# ![Image](https://i.imgur.com/HW2MoNP.png)
#

# ### Fundamento teórico
#
# La regresión lineal se puede decir que es una técnica basada en parámetros, para ejemplificar conocemos que una línea necesita 2 parámetros. cuya formula es $y=wx +b$
#
# Lo que denominamos aprendizaje se basa en encontrar los mejores parámetros (coeficientes -- $w$) que minimicen la medida del error.
#
# $y= b + wx$
# es así, que cuando tengamos un dato con N variables, llamaremos al dato $x$. Se debe tener en cuenta que se expanden también los parámetros $w$.
#
# ![Image](https://i.imgur.com/4p09QuC.png)
#

# + [markdown] id="FkEmGBQOl6td"
# ## Regresión lineal con Datos de muestras de suelo 
#
# El siguiente conjunto de datos corresponde a las muestras de suelo toamdas en un ejemplo académico por parte del ITC de Holanda, en el municipio de Chinchiná (Caldas) [ver documento](https://github.com/DiplomadoAI-DL-UNAL2021/samuelmesa/blob/main/taller_regresion_lineal/documento_base.pdf). 
#
# ### Descripción de los datos 
#
# Los datos corresponden a barrenos o muestras tomadas en terreno (203) y en la cual trae información de:
#
# * Ubicación (logitud y latitud) 
# * Descripción (DESCRIPTIO)
# * Litología (GEOL)
# * Espesor en metros de la capas enterradas (Thickness)
# * Porcentaje de arcillas (PERCLAY)
# * Permeabilidad metros/dia (PERMEABILI).

# + id="DOkinIHvlGWF"
## Importar librerias y módulos

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# %matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
plt.rcParams['figure.figsize'] = (128, 54)
plt.style.use('ggplot')
from sklearn import linear_model
from sklearn.metrics import mean_squared_error, r2_score

# + colab={"base_uri": "https://localhost:8080/"} id="RD83FRyPmOPf" outputId="9a0e7d4c-4262-4829-fd5e-af44bcdfa06c"
# Importamos el archivo CSV
# Carga de los datos de barrenos 
barrenos = pd.read_csv("https://raw.githubusercontent.com/DiplomadoAI-DL-UNAL2021/samuelmesa/main/taller_regresion_lineal/barrenos.csv")

# imprimir dimensiones, número e filas y registros
barrenos.shape

# + colab={"base_uri": "https://localhost:8080/", "height": 195} id="pSMPWWwcmoNx" outputId="4ea104c4-c976-42ce-8fea-640b5705bea2"
# Explorar los registros con una muestra 

barrenos.head()

# + colab={"base_uri": "https://localhost:8080/", "height": 284} id="eLA4eBehmqPl" outputId="382ef5cf-111e-4d7b-b4d2-3c5e29619d0a"
# Despliegue de estadísticas de los datos de entrada

barrenos.describe()

# + colab={"base_uri": "https://localhost:8080/", "height": 717} id="RJn2A0j8m_nO" outputId="8b4efc00-6d41-42d8-b946-4d4628b60bb8"
# Despliegue de los datos en histogramas 
fig, axs = plt.subplots(3, figsize=(12, 12))
sns.histplot(data=barrenos, x="THICKNESS", kde=True, ax=axs[0])
sns.histplot(data=barrenos, x="PERCCLAY", kde=True, ax=axs[1])
sns.histplot(data=barrenos, x="PERMEABILI", kde=True, ax=axs[2])
plt.show()

# + colab={"base_uri": "https://localhost:8080/", "height": 515} id="IZDaI_dKngKH" outputId="4f75fbae-e418-464c-ad03-654acf7e8657"
## Realizamos el gráfico de dispersión

sns.pairplot(barrenos,x_vars=['THICKNESS','PERCCLAY'],y_vars='PERMEABILI',height=7,aspect=0.7,kind='reg')
sns.despine()

# + [markdown] id="jAKLb0ntpWOQ"
#
# ## Regresión lineal con Python
#
#
# Realizar el entrenamiento con la regresión lineal simple usando las varible independiente de **PERCCLAY** y variable dependiente **PERMEABILI**
#

# + colab={"base_uri": "https://localhost:8080/"} id="18Oz2mNooxo-" outputId="f56e0683-8fce-4cee-bbc9-9625b1e96759"
## En este caso definirmos las variables dependientes e independienets como vectores de entrada de entrenamiento 

data_x = barrenos[["PERCCLAY"]]
X_train = np.array(data_x)
Y_train = barrenos[["PERMEABILI"]]

# Crear el modelo Regresión Lineal simple
regr = linear_model.LinearRegression()

# Entrenar el modelo de regresión lineal simple
regr.fit(X_train, Y_train)

# Hacemos las predicciones que en definitiva una línea (en este caso, al ser 2D)
Y_pred = regr.predict(X_train)

# Imprimir los coeficienetes obtenidos, En nuestro caso, serán la Tangente
print('Coefficients: \n', regr.coef_)
# Este es el valor donde corta el eje Y (en X=0)
print('Independent term: \n', regr.intercept_)
# Error Cuadrado Medio
print("Mean squared error: %.2f" % mean_squared_error(Y_train, Y_pred))
# Puntaje de Varianza. El mejor puntaje es un 1.0
print('Variance score: %.2f' % r2_score(Y_train, Y_pred))

# + [markdown] id="uCTuZT_Yrayb"
# ## Visualizamos la recta en el diagrama de dispersión

# + colab={"base_uri": "https://localhost:8080/", "height": 386} id="SFOv0muQrfcE" outputId="e74045d7-a144-4d4b-e8c5-eb92d54248d7"
# Predicción de m, b

sns.lmplot(x='PERCCLAY',y='PERMEABILI',data=barrenos)
sns.despine()

# + colab={"base_uri": "https://localhost:8080/", "height": 374} id="stluApbUDIPr" outputId="9375c20a-590d-4a2d-cdcb-6c8fa3437b56"
fig, axs = plt.subplots(figsize=(10, 6))
sns.histplot((Y_pred-Y_train), kde=True, ax=axs)
fig.show()

# + [markdown] id="UahpKgI3uPGR"
# ## Regresión Lineal Múltiple en Python
#
# La regresión lineal múltiple se realiza entre las variables independientes **THICKNESS**,	**PERCCLAY** y variable dependiente	**PERMEABILI**

# + id="5nkGtSexs2NX"
# Vamos a intentar mejorar el Modelo, con una dimensión más: 
# Para poder graficar en 3D se agrega un nuevo dataframe las variables de THICKNESS y PERCCLAY
dataX2 =  pd.DataFrame()
dataX2["PERCCLAY"] =  barrenos["PERCCLAY"]
dataX2["THICKNESS"] = barrenos["THICKNESS"]

XY_train = np.array(dataX2)
z_train = barrenos["PERMEABILI"].values

# + colab={"base_uri": "https://localhost:8080/"} id="pNRrhOVFvq66" outputId="ac5b88ac-5136-4741-facc-a0c6de4365ac"
## Entrenamiento con SKLearn
# Crear el modelo de Regresión Lineal
regr2 = linear_model.LinearRegression()

# Entrenamos el modelo, esta vez, con 2 dimensiones
# obtendremos 2 coeficientes, para graficar un plano
regr2.fit(XY_train, z_train)

# Reaizar la predicción con la que tendremos puntos sobre el plano hallado
z_pred = regr2.predict(XY_train)

# Los coeficientes
print('Coefficients: \n', regr2.coef_)
# Error cuadrático medio
print("Mean squared error: %.2f" % mean_squared_error(z_train, z_pred))
# Evaluamos el puntaje de varianza (siendo 1.0 el mejor posible)
print('Variance score: %.2f' % r2_score(z_train, z_pred))

# + colab={"base_uri": "https://localhost:8080/", "height": 575} id="hn91j8k1GKI5" outputId="d2dd0607-554f-4664-bfcd-52e9b06e7b4f"
## Visualizar diagrama de dispersión en 3D
fig = plt.figure(figsize=(12, 10))
ax = fig.add_subplot(111, projection = '3d')

# Creamos una malla, sobre la cual graficaremos el plano
xx, yy = np.meshgrid(np.linspace(0, 100, num=10), np.linspace(0, 50, num=10))

# calculamos los valores del plano para los puntos x e y
nuevoX = (regr2.coef_[0] * xx)
nuevoY = (regr2.coef_[1] * yy) 
# calculamos los correspondientes valores para z. Debemos sumar el punto de intercepción
z = (nuevoX + nuevoY + regr2.intercept_)

ax.set_xlabel('% arcillas')
ax.set_ylabel('Espesor en m')
ax.set_zlabel('Permeabilidad m/dia')
ax.set_title('Regresión Lineal con Múltiples Variables') 

ax.scatter(XY_train[:, 0], XY_train[:, 1], z_train)
ax.plot_surface(xx, yy, z, alpha=0.4, cmap='hot')
ax.scatter(XY_train[:, 0], XY_train[:, 1], z_pred)
ax.view_init(elev=10, azim=25)

plt.show()

# + [markdown] id="wsYDQoDVFIR5"
# ## Conclusiones
#
# Se observa el desarrollo e implementación de la regresión lineal en los cuadernos de Python con Scikit Learn

StarcoderdataJupyterScriptsDedupFiltered