rellenar los valores vac\u00edos<\/strong>. Ya sea obteniendo valores de registros con las mismas caracter\u00edsticas o calculando una media. En el caso de que los valores no sean num\u00e9ricos podemos llenarlos con una nueva categor\u00eda que indique que es un campo con valor desconocido. <\/li><\/ul>\n\n\n\nLa decisi\u00f3n de qu\u00e9 t\u00e9cnica usar depende de nosotros, de c\u00f3mo valoremos los datos, y no pocas veces tendremos que dar marcha atr\u00e1s o probar m\u00e1s de una opci\u00f3n para ver si afecta o no a las predicciones del modelo. <\/p>\n\n\n\n
Para encontrar los valores v\u00e1cios de una forma r\u00e1pida se hace usando el comando dataset.isna().sum(). <\/p>\n\n\n\n
cars.isna().sum()<\/pre>\n\n\n\nurl 0\ncompany 0\nmake 2\nmodel 5\nversion 0\nprice 0\nprice_financed 26437\nfuel 46\nyear 2<\/pre>\n\n\n\nNos devuelve la lista de columnas indicando cu\u00e1ntos valores vac\u00edos hay en ellas. <\/p>\n\n\n\n
En nuestro ejemplo se ha decidido eliminar totalmente la columna price_financed<\/strong>, junto con otras m\u00e1s, ya que no se prev\u00e9 que tenga ninguna importancia en la predicci\u00f3n de la columna price, y tiene m\u00e1s de un 50% de registros sin valor. Adem\u00e1s dejarla podr\u00eda ser perjudicial, por que seguro que hay una dependencia lineal entre esta columna y price<\/strong>, pero la direcci\u00f3n contraria a la que queremos. Es decir, posiblemente sea una columna dependiente de nuestra columna dependiente. <\/p>\n\n\n\nPara eliminar las columnas se usa la funci\u00f3n drops de pandas y se recoge el resultado en un nuevo dataset. <\/p>\n\n\n\n
cars_ready = cars.drop([\"price_financed\", \"url\", \"version\"], axis=1)\ncars_ready<\/pre>\n\n\n\nPara la columna power en el v\u00eddeo, por cuesti\u00f3n de mantenerlo lo m\u00e1s simple posible, se rellena con la media de la columna. Pero podr\u00eda sacarse una media de potencia por marca, o buscar por el dataset si hay alg\u00fan modelo parecido y sustituir la potencia. <\/p>\n\n\n\n
cars_ready[\"power\"].fillna(cars_ready[\"power\"].mean(), inplace=True)<\/pre>\n\n\n\nSe usa la opci\u00f3n inplace=True<\/strong>, para indicar que queremos modificar el dataframe donde se ejecuta, por lo que no debe recogerse el resultado en un nuevo dataframe. <\/p>\n\n\n\nLa columna de color la rellenamos con un valor indicando que no ten\u00eda valor. <\/p>\n\n\n\n
cars_ready[\"color\"].fillna(\"desc\", inplace=True)<\/pre>\n\n\n\nAl rellenarlo con un valor espec\u00edfico conseguimos aislarlo ya que cuando convirtamos los campos de texto en categor\u00edas. Se crear\u00e1 una categor\u00eda de nombre desc y no tendr\u00e1 una gran relaci\u00f3n con el precio, mas que nada por que los registros que forman parte de ella han sido escogidos al “azar”. <\/p>\n\n\n\n
Cuando ya se han tratado todos los campos vac\u00edos, llega el momento de ver c\u00f3mo podemos transformar los campos de texto en categor\u00edas. La mayor\u00eda de modelos no se llevan bien con los campos de texto y suelen dar error en caso de que les pasemos un campo texto como feature. Para evitarlo tenemos que decidir qu\u00e9 hacer con ellos. Podemos eliminarlos en caso de que no sean \u00fatiles, o podemos convertirlos en categor\u00edas. Hay varias formas de hacerlo, pero en el ejemplo hemos usado la m\u00e1s sencilla y directa. Hemos usado la funci\u00f3n dummies de pandas. <\/p>\n\n\n\n
dummies = pd.get_dummies(cars_ready[[\"make\", \"model\", \"fuel\", \"shift\"]])\ndummies<\/pre>\n\n\n\nLe hemos pasado 4 columnas que queremos convertir en categor\u00edas. <\/p>\n\n\n\n <\/figure>\n\n\n\nComo podemos ver en la imagen, ha convertido cada uno de los valores en las columnas indicadas en nuevas columnas, indicando con un 0 o u 1 la pertenencia, o no, del registro a esa categoria. <\/p>\n\n\n\n
Las categor\u00edas nuevas se guardan en un dataframe que he llamado dummie. Este data frame debe concatenarse con el de origen, pero debemos eliminar tambi\u00e9n las columnas que se han utilizado para crear las categor\u00edas. <\/p>\n\n\n\n
cars_ready = cars_ready.drop([\"company\", \"color\", \"dealer\", \"province\", \"country\", \"publish_date\", \"insert_date\"], axis=1)\nconcat_cars = pd.concat([cars_ready, dummies], axis=1)<\/pre>\n\n\n\nCuando ya hemos trabajado con los datos eliminando los espacios en blanco y convietiendo en categorias los campos de tipo texto, podemos crear los juegos de datos necesarios para realizar el entreno. <\/p>\n\n\n\n
Se necesita separar las features del target, es decir las variables independientes de la dependiente, y al mismo tiempo se necesitan dos juegos de datos, uno para entrenar el modelo y otro para testearlo. <\/p>\n\n\n\n
X = concat_cars.drop(\"price\", axis=1)\ny= concat_cars[\"price\"]\nfrom sklearn.model_selection import train_test_split\nX_entreno, X_test, y_entreno, y_test = train_test_split(X, y, test_size=0.2)<\/pre>\n\n\n\nEn la X <\/em><\/strong>tenemos las variables independientes y en y<\/em><\/strong> la variable dependiente, es decir, la variable de la que queremos encontrar en valor en nuestras predicciones. <\/p>\n\n\n\nUsamos train_test_split<\/strong> para que divida los datos con el porcentaje que le indicamos, que en este caso ser\u00e1 un 20% de datos para test y un 80% de datos para entrenar el modelo. <\/p>\n\n\n\nUna vez ya tenemos nuestro juego de datos preparado hay que escoger que estimator de scikit vamos a usar. Aunque yo tengo tendencia a usar siempre un estimator basado en RandomForest, tanto sea para regresi\u00f3n como clasificaci\u00f3n, hay veces que otros algoritmos pueden dar mejor resultado. Aparte tenemos que aprovechar dos ventajas que nos da scikit-learn: <\/p>\n\n\n\n
Su gr\u00e1fico para escoger un estimator. Actua como guia r\u00e1pida, bastante sencilla de usar. <\/li> La facilidad en probar diferentes modelos.<\/li><\/ul>\n\n\n\nalgoritmos scikit-learn <\/figcaption><\/figure>\n\n\n\nSiguiendo este gr\u00e1fico podemos decidir que estimator se adapta mejor al problema que queremos resolver y a los datos que disponemos. <\/p>\n\n\n\n
Bueno pues con nuestros datos he probado tres estimators diferentes:<\/p>\n\n\n\n
Ridge Regression. <\/strong><\/p>\n\n\n\nfrom sklearn import linear_model \nmodelo = linear_model.Ridge()\nmodelo.fit(X_entreno, y_entreno)<\/pre>\n\n\n\nUn estimator basado en Ridge Regression suele usarse cuando el n\u00famero de variables independientes es muy grande, puede llegar a ser mayor que el n\u00famero de registros disponibles. Parece bastante claro que no es nuestro caso. Aunque el n\u00famero de columnas que nos han quedado despu\u00e9s de la transformaci\u00f3n de los datos de texto en categor\u00edas usando dummies es mucho mayor que el que ten\u00edamos al principio. <\/p>\n\n\n\n
Hemos llegado a el, por que en la fat\u00eddica pregunta “few features should be important” que nos encontramos en el diagrama que nos ofrecen la gente de scikit… hemos respondido que NO. <\/p>\n\n\n\n
A\u00fan as\u00ed su score nos ha dado un resultado de 0.78. Nada mal por ser un primer intento, con un tratamiento de los datos no del todo “profesional” y sin tocar nada del modelo. <\/p>\n\n\n\n
LASSO Model<\/strong>. <\/p>\n\n\n\nfrom sklearn import linear_model \nmodelo = linear_model.Lasso()\nmodelo.fit(X_entreno, y_entreno)<\/pre>\n\n\n\nSe usa cuando, aunque tengamos muchos features, tan solo unos pocos de ellos son realmente importantes. En nuestro modelo la respuesta a esta pregunta ser\u00eda diferente si la tenemos que responder con los datos de origen a los datos ya tratados. Se ha aumentado en mucho el n\u00famero de columnas y por lo tanto se ha reducido su peso. No creo que Lasso sea el modelo que m\u00e1s se adapte a la nueva forma de los datos. Pero….. \u00bfy si hubi\u00e9ramos transformado de una forma diferente las columnas? <\/p>\n\n\n\n
La estrategia que hemos seguido es la de crear columnas nuevas por cada marca, y asignar un 0 o un 1 dependiendo de si el coche pertenece o no a esa marca. Otra estrategia podr\u00eda haber sido convertir los valores texto en numericos. Seat = 3, Volkswagen = 5, Volvo = 1….. y dejar todos los valores en la misma columna. As\u00ed tendr\u00edamos una columna con todos los datos de marca y con un peso bastante grande sobre la variable dependiente. <\/p>\n\n\n\n
\u00bfOs fijais? Una decisi\u00f3n en c\u00f3mo tratar los datos nos puede llevar a escoger un estimator u otro. <\/p>\n\n\n\n
Bueno, con LASSO hemos obtenido un 0.76. Ni tan mal. <\/p>\n\n\n\n
RandomForestRegressor<\/strong><\/p>\n\n\n\nfrom sklearn.ensemble import RandomForestRegressor\nmodelo = RandomForestRegressor()\nmodelo.fit(X_entreno, y_entreno)<\/pre>\n\n\n\nUn algoritmo basado en Random Forest sirve para casi todo y lo hace casi todo bien. Tenemos el RandomForestClassifier para clasificar y el RandomForestRegressor para problemas de regresi\u00f3n. En el v\u00eddeo me confundo y intento usar el Classifier en un problema de regresi\u00f3n \ud83d\ude42 <\/p>\n\n\n\n
Funciona bien casi siempre, pero si tienes muchos datos mejor! <\/p>\n\n\n\n
En nuestro modelo hemos conseguido un score del 0.92. Espectacular!!!!<\/p>\n\n\n\n
\u00bfQue hemos aprendido solucionando nuestro problema de regresi\u00f3n? <\/h3>\n\n\n\n Lo m\u00e1s importante ha sido la transformaci\u00f3n de los datos, y las decisiones que se han ido tomando para modelar los datos para que sean aptas para un Modelo de Machine Learning. <\/p>\n\n\n\n
Hay dos transformaciones que se deben hacer: Eliminar los campos sin valor y transformar textos, o campos sin estructurar, en categorias. <\/p>\n\n\n\n
Los campos vac\u00edos pueden eliminarse de varias formas: <\/p>\n\n\n\n
Eliminando las columnas. Como en el caso de Price_financed<\/strong>. Una columna con el 50% de sus valores vac\u00edos no tiene sentido, a no ser de que seamos capaces de rellenarlos de una forma coherente. Eliminar los registros en este caso tampoco ser\u00eda una opci\u00f3n ya que el n\u00famero de datos que perderiamos har\u00eda perder mucho valor a nuestro modelo. <\/li>Eliminar los registros. En el caso de que sean unas pocas filas y los datos a vac\u00edos no son muy importantes para nuestro modelo se pueden eliminar los registros. Se debe tener en cuenta que perdemos el peso de las otras columnas, pero si el n\u00famero de registros a eliminar es muy peque\u00f1o es la mejor opci\u00f3n. <\/li> Sustituir los valores vac\u00edos. En este caso nos encontramos con dos casos toalmente diferentes. Sustituci\u00f3n de valores num\u00e9ricos. Lo mejor es calcular una media del grupo m\u00e1s acotado posible. Es decir, si podemos sacar una media del precio del modelo ser\u00e1 mejor que la media del precio de la marca y mucho mejor que una media general de todos los precios. <\/li> Sustituci\u00f3n de categor\u00edas. Si no podemos adivinar a qu\u00e9 categor\u00eda pertenece, cosa que muchas veces puede hacerse mirando datos del mismo dataset, lo mejor es crear como m\u00ednimo una categor\u00eda nueva. La intenci\u00f3n es intentar que esta nueva categor\u00eda no influya en el c\u00e1lculo de la variable dependiente. <\/li><\/ul><\/li><\/ul>\n\n\n\nLa sustituci\u00f3n de campos texto en categor\u00edas tamb\u00eden hay varias formas de atacar, solo hemos visto una, pero voy a indicar dos. <\/p>\n\n\n\n
Creaci\u00f3n de categor\u00edas en columnas. Usando la funci\u00f3n get_dummies<\/strong> de pandas se convierte autom\u00e1ticamente el contenido de la columna en nuevas columnas num\u00e9ricas donde se indica la pertinencia o no del registro a esa columa. Por ejemplo, en nuestro modelo se ha creado una columna SEAT<\/strong>, que ha sido sacada del contenido de la columna Marca<\/strong>. Todos los coches que ten\u00edan el valor “SEAT” en la columna Marca<\/strong>, ahora tienen un “1” en la columna SEAT<\/strong>. <\/li>Sustituci\u00f3n de los textos por valores num\u00e9ricos. Mediante pandas decidimos sustituir todos los SEAT por 5’s los Volvo por 2… etc… Con lo que acabamos teniendo una columna num\u00e9rica. <\/li><\/ul>\n\n\n\nLa decisi\u00f3n de c\u00f3mo realizar la transformaci\u00f3n a categor\u00edas puede, y debe, influir en el algoritmo que despu\u00e9s usaremos. <\/strong>Podemos acabar con una columna que tenga mucho peso en el modelo, si hemos decidido no crear columnas nuevas por cada categor\u00eda. En este caso nos funcionar\u00e1 mejor un algoritmo basado en Lasso. En cambio si hemos decidido transformar en columnas nuevas todas las categor\u00edas podemos acabar con un dataset que se adapte mejor a un algoritmo de tipo Ridge Regression. En ambos caso… siempre hay que probar el RandomForest \ud83d\ude42 <\/p>\n\n\n\nFinalmente le hemos dado un vistazo al gr\u00e1fico de SciKit-learn que nos ayuda a escoger un estimator y hemos probado tres de ellos. Ya hemos visto que hay que perderle el miedo a probar, no nos quita demasiado tiempo. Si podemos seleccionar el algoritmo con un poco de conocimiento mucho mejor, pero si tenemos dudas…. adelante! Probemos! <\/p>\n\n\n\n
Continuaremos aprendiendo IA y ML. <\/h3>\n\n\n\n Lo que nos queda!!!!! Esta es la segunda lecci\u00f3n, y hemos visto un mont\u00f3n de cosas, pero estamos rascando….. y continuaremos rascando. Prefiero que demos un vistazo amplio por todas las ramas de la IA, antes de que estemos 4 horas hablando de c\u00f3mo debemos evaluar el funcionamiento de un algoritmo LASSO. <\/p>\n\n\n\n
Ya entraremos, si nos interesa mas adelante. Pero veamos todas las ramas de la IA, no tan solo el Machine Learning. Que seamos capaces de escoger que nos gusta y que nos apasiona. <\/p>\n\n\n\n
Pero por ahora…. no tengo claro c\u00f3mo voy a continuar. Pero que en alg\u00fan momento veremos cosas de reinforcement learnig y deep learning esta m\u00e1s que claro! <\/p>\n\n\n\n
<\/p>\n\n\n\n
<\/p>\n\n\n\n
<\/p>\n\n\n\n
<\/p>\n\n\n\n
<\/p>\n\n\n\n
<\/p>\n\n\n\n
<\/p>\n