<jupyter_start><jupyter_text>Primer ejercicio [Pag 75] Crearemos una función para extraer los datos desde una URL. Los datos pretenecen a los precios de las casas de California tomados en 1990.  1 DESCARGAR LA DATA<jupyter_code>import os
import tarfile
import urllib.request

DOWNLOAD_ROOT="https://raw.githubusercontent.com/ageron/handson-ml2/master/"
HOUSING_PATH= os.path.join("datasets","housing")
HOUSING_URL= DOWNLOAD_ROOT + "datasets/housing/housing.tgz"

def fetch_housing_data(housing_url=HOUSING_URL, housing_path=HOUSING_PATH):
    
    """ función para descargar data de una URL, para luego extraerla a un directorio
    Args:
        housing_url: la URL del archivo a descargar
        housing_path: la ruta donde se descargar el archivo y posteriormente se extraera la información.
    
    return: Ninguno
    
    """
    
    if not os.path.isdir(housing_path):
        os.makedirs(housing_path)

    tgz_path = os.path.join(housing_path, "housing.tgz")
    urllib.request.urlretrieve(housing_url, tgz_path) 
    housing_tgz = tarfile.open(tgz_path)
    housing_tgz.extractall(path=housing_path)
    housing_tgz.close()<jupyter_output><empty_output><jupyter_text>Ejecutamos la función para descargar el archivo y crear las carpetas de destino<jupyter_code>fetch_housing_data()<jupyter_output><empty_output><jupyter_text>Lectura de datos en un dataframe de pandas<jupyter_code>import pandas as pd

def load_housing_data(housing_path=HOUSING_PATH):
    """
    Creamos un función que devuelve un DataFrame de pandas con los datos de la dirección
    seleccionada.
    """

    csv_path = os.path.join(housing_path, "housing.csv")
    return pd.read_csv(csv_path)


#Leemos la data en un dataframe
housing=load_housing_data()
housing.head()
housing.info()
housing["ocean_proximity"].value_counts() #mostramos los valores posibles de la variable categorica "ocean_proximity"

housing.describe()<jupyter_output><empty_output><jupyter_text>Grafica de histogramas<jupyter_code>%matplotlib inline
# %matplotlib inline solo posible en un notebook de jupiter. Indica a Jupiter que configure matplotlib para que utilice
#el propio back-end de Jupiter.

import matplotlib.pyplot as plt

housing.hist(bins=50, figsize=(20,15))
plt.show()<jupyter_output><empty_output><jupyter_text>2 CREAR UN CONJUNTO DE PRUEBAS  2.1 Primera forma (Muestreo aleatorio)<jupyter_code>import numpy as np   

np.random.seed(42) #para que la salida de la permutación aleatoria sea idéntica en cada ejecución

def split_train_test(data, test_ratio):
    shuffled_indices = np.random.permutation(len(data))
    test_set_size = int(len(data) * test_ratio)
    test_indices = shuffled_indices[:test_set_size]
    train_indices = shuffled_indices[test_set_size:]
    return data.iloc[train_indices], data.iloc[test_indices]
train_set, test_set =split_train_test(housing,0.2)
print('len train set:',len(train_set))
print('len test set:',len(test_set))<jupyter_output>len train set: 16512
len test set: 4128<jupyter_text>2.2 Segunda forma (Muestreo aleatorio-con Robustes ante actualizaciones, mayor eficiencia) La necesidad de actualizar los datos periodicamente hacen que los algoritmos esten preparados para hacerlos de manera eficiente. Considerando que los datos de prueba, antes elegidos, no deben hacer parte en los datos de entrenemaiento despues de cualquier actualización de datos, se opta por algun algoritmo que nos permita siempre tener como DATOS DE PRUEBAS el 20% (ratio de test) de datos de prueba "antiguos" + un 20% de datos de prueba de los datos agregados en la actualización.La forma más eficiente para lograr lo anterior es utilizar el hash crc32, que explicados en terminos simples para nuestro uso, realiza una transformación de los datos de manera casi univoca, y cuyo resultado es una distribución aleatoria cerca de ser homogenea para datos con una gran cantidad de instancias. A continuación crearemos una lista "Data" de 1000 instancias, y aplicaremos la transformación crc32 a cada instanciapara guardarla en otra lista de nombre "Data_crc32".<jupyter_code>from zlib import crc32

Data=[]
Data_crc32=[]
for i in range(1000):
    Data.append(i)
    Data_crc32.append(crc32(np.int64(i))/5000000) 
    ''' dividimos la trasformada entre 5000000, 
    porque su mangitud es muy grande para nuestro apreciar nuestro ejemplo '''<jupyter_output><empty_output><jupyter_text>Graficaremos los datos transformados para observar su aleatoriedad casi homogenea<jupyter_code>Max=[2**32/5000000]*1000
Value_ratio=[0.2*(2**32/5000000)]*1000


plt.figure(figsize=(16,4))
X = np.linspace(0, 100,1000)
plt.plot(X,Data_crc32,".")
plt.plot(X,Data,linewidth=0.5)
plt.plot(X,Max)
plt.plot(X,Value_ratio)
plt.legend(['Data crc32', 'Data','Max_value: 2^32', 'ratio: 20%'])
plt.title('fig 01');
plt.show()<jupyter_output><empty_output><jupyter_text>Como se puede observar en la fig 01, la linea naranja genera mediante la transformación crc32 un mapa homogeneo de puntos azules. En esta distribución cuyo valor máximo es 2^32 (para nuestro ejemplo divido entre 5000000) puede ser separa facilmenteel conjunto de datos de prueva (Set_test) mediante una linea horizontal con el valor de: ratio*2^32 (para nuestro ejemplo divido entre 5000000).Los datos debajo de la linea roja seran los datos de prueba los que unca seran utilizados como datos de entrenamiento.<jupyter_code>#El histograma a continuación muestra lo uniforme que es la distribución de los datos transformados
plt.hist(Data_crc32)
plt.show()<jupyter_output><empty_output><jupyter_text>Para terminar, agregaremos más datos y observaremos como en la atualización de datos se respeta la integridad de los datos deprueba anteriormente seleccionados.<jupyter_code>Data=[]
Data_crc32=[]
for i in range(1200):
    Data.append(i)
    Data_crc32.append(crc32(np.int64(i))/5000000) 

Data_crc32_1=Data_crc32[:1000]+[0]*200
Data_crc32_2=[0]*1000+Data_crc32[1000:1200]  

    
Max=[2**32/5000000]*1200
Value_ratio=[0.2*(2**32/5000000)]*1200


plt.figure(figsize=(16,4))
X = np.linspace(0, 100,1200)
plt.plot(X,Data_crc32_1,".")
plt.plot(X,Data,linewidth=0.5)
plt.plot(X,Max)
plt.plot(X,Value_ratio)
plt.plot(X,Data_crc32_2,".")
plt.legend(['Data crc32 original', 'Data','Max_value: 2^32', 'ratio: 20%','Data crc32 nueva'])
plt.title('fig 02');
plt.show()<jupyter_output><empty_output><jupyter_text>Como se puede apreciar en la fig 02, la actualización que agrego nuevos datos (puntos morados), no altera la selección de los datos de prueba anteriores y considera un 20 por cientos de la nueva data como datos de prueba nuevos. Creamos la funciones para definir  los datos de prueva con crc32<jupyter_code>#Definimos la función test_set_check
def test_set_check(identifier, test_ratio):
    return crc32(np.int64(identifier)) & 0xffffffff < test_ratio*2**32


def split_train_test_by_id(data, test_ratio, id_column):
    ids = data[id_column]
    in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio))
    return data.loc[~in_test_set], data.loc[in_test_set]<jupyter_output><empty_output><jupyter_text>Añadimos la columna identificador: 2.1.1 Identificador enteros desde 0 hasta n<jupyter_code>housing_with_id=housing.reset_index() #añade una columna index

housing_with_id
train_set, test_set=split_train_test_by_id(housing_with_id,0.2,"index")
train_set.head()<jupyter_output><empty_output><jupyter_text>2.1.2 utilizando indicadores como función de latitud y longitud<jupyter_code>housing_with_id["id"] = housing["longitude"] * 1000 + housing["latitude"]
train_set, test_set = split_train_test_by_id(housing_with_id, 0.2, "id")
test_set.head()<jupyter_output><empty_output><jupyter_text>2.3 Utilizando Scikit learn  (Muestreo aleatorio)<jupyter_code>from sklearn.model_selection import train_test_split

train_set, test_set = train_test_split(housing, test_size=0.2, random_state=42)
test_set.head()<jupyter_output><empty_output><jupyter_text>2.4 Muestreo Estratificado (2da mejor opción) El muestreo estratificado nos permite tener una mayor posibilidad de obtener un conjunto de datos de prueba representativos del  conjunto de datos total a diferencia del muestreo aleatorio que depende de que su tamaño sea considerablemente grande respecto del número de caracteristicas de los datos para evitar un sesgo muestral. POr ejemplo, si tubieramos que hacer una encuesta a una población con un porcentaje de varones iagual 48.7% y mujeres 51.3 %, si decidimos extramer una muestra aleatoria, tendriamos alrededor de 12% de posibilidad de muestrar un conjunto de prueba sesgado que tendria o menos de 49 % de hombres o mas de 54% de mujeres. En cualquier caso, los resultados de la encuesta estarian totalmente distorisionadosobservemos primero el histograma de ingresos medios<jupyter_code>housing["median_income"].hist()<jupyter_output><empty_output><jupyter_text>Categorización de median_income en 5 categorias<jupyter_code>housing["income_cat"] = pd.cut(housing["median_income"],
                               bins=[0., 1.5, 3.0, 4.5, 6., np.inf],
                               labels=[1, 2, 3, 4, 5])<jupyter_output><empty_output><jupyter_text>Categorizarlo en pocas categorias no permite aseguramos que cada categoria tenga suficiente cantidad de datos para extraer muestras representativas, de lo contrario la importnacia de una u otra categoria podria distorsionarse.<jupyter_code>housing["income_cat"].value_counts()
housing["income_cat"].hist()
from sklearn.model_selection import StratifiedShuffleSplit

split = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)

for train_index, test_index in split.split(housing, housing["income_cat"]):
    strat_train_set = housing.loc[train_index]
    strat_test_set = housing.loc[test_index]<jupyter_output><empty_output><jupyter_text>Evaluamos la proporción de de los datos categoricos<jupyter_code>strat_test_set["income_cat"].value_counts() / len(strat_test_set)
housing["income_cat"].value_counts() / len(housing)<jupyter_output><empty_output><jupyter_text>Mostramos un cuadro comprativo con los porcentajes de error entre el muestre estratificado y el aleatorio<jupyter_code>def income_cat_proportions(data):
    return data["income_cat"].value_counts() / len(data)

train_set, test_set = train_test_split(housing, test_size=0.2, random_state=42)

compare_props = pd.DataFrame({
    "Overall": income_cat_proportions(housing),
    "Stratified": income_cat_proportions(strat_test_set),
    "Random": income_cat_proportions(test_set),
}).sort_index()
compare_props["Rand. %error"] = 100 * compare_props["Random"] / compare_props["Overall"] - 100
compare_props["Strat. %error"] = 100 * compare_props["Stratified"] / compare_props["Overall"] - 100
compare_props<jupyter_output><empty_output><jupyter_text>Eliminamos el atributo income_cat para volver al estado original los datos<jupyter_code>for set_ in (strat_train_set, strat_test_set):
    set_.drop("income_cat", axis=1, inplace=True)<jupyter_output><empty_output><jupyter_text>3 Descubra y visualice los datos para obtener conocimientos<jupyter_code>%run functions.ipynb # llamamos al módulo creado en jupiter
housing = strat_train_set.copy()
housing.plot(kind="scatter", x="longitude", y="latitude")
save_fig("bad_visualization_plot")
housing.plot(kind="scatter", x="longitude", y="latitude", alpha=0.1)
save_fig("better_visualization_plot")
housing.plot(kind="scatter", x="longitude", y="latitude", alpha=0.4,
             s=housing["population"]/100, label="population", figsize=(10,7),
             c="median_house_value", cmap=plt.get_cmap("jet"), colorbar=True,
             sharex=False)
plt.legend()
save_fig("housing_prices_scatterplot")
# Download the California image
images_path = os.path.join(PROJECT_ROOT_DIR, "images", "end_to_end_project")
os.makedirs(images_path, exist_ok=True)
DOWNLOAD_ROOT = "https://raw.githubusercontent.com/ageron/handson-ml2/master/"
filename = "california.png"
print("Downloading", filename)
url = DOWNLOAD_ROOT + "images/end_to_end_project/" + filename
urllib.request.urlretrieve(url, os.path.join(images_path, filename))
import matplotlib.image as mpimg
california_img=mpimg.imread(os.path.join(images_path, filename))
ax = housing.plot(kind="scatter", x="longitude", y="latitude", figsize=(10,7),
                  s=housing['population']/100, label="Population",
                  c="median_house_value", cmap=plt.get_cmap("jet"),
                  colorbar=False, alpha=0.4)
plt.imshow(california_img, extent=[-124.55, -113.80, 32.45, 42.05], alpha=0.5,
           cmap=plt.get_cmap("jet"))
plt.ylabel("Latitude", fontsize=14)
plt.xlabel("Longitude", fontsize=14)

prices = housing["median_house_value"]
tick_values = np.linspace(prices.min(), prices.max(), 11)
cbar = plt.colorbar(ticks=tick_values/prices.max())
cbar.ax.set_yticklabels(["$%dk"%(round(v/1000)) for v in tick_values], fontsize=14)
cbar.set_label('Median House Value', fontsize=16)

plt.legend(fontsize=16)
save_fig("california_housing_prices_plot")
plt.show()<jupyter_output>Saving figure california_housing_prices_plot
{'fraction_non_alphanumeric': 0.10099223136681794, 'fraction_numerical': 0.031228367048688564, 'mean_word_length': 6.203324099722992, 'pattern_counts': {'":': 3, '<': 80, '<?xml version=': 0, '>': 79, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '20', 'dir': 'jupyter-structured-clean-dedup', 'id': '596920', 'license': 'Apache-2.0', 'n_tokens_mistral': 4921, 'n_tokens_neox': 4583, 'n_words': 1119, 'path': 'Desarrollo libro/Cap02-proyecto-machine-learning.ipynb', 'repo_name': 'ugarteg/handson-ml2', 'size': '13001'}