Hola! Bienvenida al libro 🌸
Antes de empezar quiero que te pares un segundo y pienses una cosa: ¿cuántas decisiones tomaste hoy que en realidad te sugirió un modelo?
Piénsalo de verdad, no sigas leyendo de corrido. Yo te ayudo con la lista 🐣
- 📱 El orden de tu feed de TikTok. No es cronológico desde hace años.
- ⌨️ La palabra que te propone el teclado del celular antes de que la escribas.
- 🎬 Las tres series que Netflix te puso arriba del todo.
- 📧 Los correos que ni viste porque cayeron en spam.
- 💸 Ese Yape que te pidió confirmar dos veces porque le pareció raro.
Los cinco son lo mismo por dentro, y ese "lo mismo" es lo que vas a aprender a construir en este libro.
La idea que le da la vuelta a todo
Voy a empezar por la frase que más me costó entender, y que cuando la entiendes se te acomoda todo lo demás:
En programación normal tú escribes las reglas. En machine learning das los ejemplos y la máquina escribe las reglas.
Piénsalo con algo que ya sabes hacer. Si quisieras marcar los pedidos sospechosos con Python, escribirías algo así:
if (monto > 5000 and cliente_nuevo and hora > 23): marcar_como_sospechoso()
Y funciona hasta que el fraude cambia de forma, que es la semana que viene 🙃
Entonces alguien añade otra condición, y otra, y a los seis meses hay
cuatrocientas líneas de if que nadie se atreve a tocar.
Machine learning le da la vuelta: le das mil pedidos etiquetados como buenos o sospechosos, y el modelo saca las reglas solo. Cuando el fraude cambie, le das ejemplos nuevos y vuelve a aprender.
Y esto no es de ahora. En 1959, Arthur Samuel puso a una computadora a jugar damas contra sí misma hasta que le ganó a él, que era quien la había programado 🕰️
Los tres tipos, en una frase cada uno
El tipo de machine learning no lo eliges tú por gusto: lo eligen los datos que tengas encima de la mesa. Con dos preguntas queda decidido 🔀
- 🎯 Supervisado. Tienes ejemplos con la respuesta correcta y quieres predecir esa respuesta en casos nuevos. "Estos 3.000 clientes compraron o no compraron; dime qué va a hacer el 3.001". Es con diferencia lo que más se usa en empresa, y es lo que hace este libro.
- 🧩 No supervisado. No tienes respuesta y quieres que salgan grupos. "Aquí están mis clientes, dime en cuántos grupos se parecen entre ellos". A eso se le llama clustering o análisis de conglomerados, y su algoritmo más conocido es k-means. No sale en este libro, que va entero de supervisado, y te lo digo aquí para que no lo busques en vano durante los veinticinco.
- 🎮 Por refuerzo. Un sistema que prueba, se equivoca y recibe premio o castigo. Es lo de los robots y los juegos. No sale en este libro porque en empresa peruana casi no aparece, y prefiero decírtelo que hacerte perder el tiempo.
Dentro del supervisado hay dos sabores, y la diferencia es solo qué tipo de respuesta quieres:
- 🔢 Regresión cuando la respuesta es un número: cuántos soles va a facturar este cliente.
- 🏷️ Clasificación cuando la respuesta es una etiqueta: va a comprar o no va a comprar.
La pregunta que lo decide es una sola y te la vas a hacer en cada proyecto: ¿lo que quiero de vuelta es una etiqueta o un número?
Este libro va casi todo sobre clasificación, porque es lo que más te van a pedir y porque ahí están los errores más interesantes 💛
Dónde estamos parados, en un solo dibujo
Todo lo de arriba cabe en una escalera, y quiero que la tengas a mano porque la vas a necesitar cada vez que alguien suelte una sigla en una reunión 🪜
La casilla rosa es este libro entero: de las 25 paradas que vienen, ninguna se sale de ahí.
Y ahora el uso práctico de la escalera, que es lo que quiero que te lleves de esta sección. Cuando en una reunión alguien diga "necesitamos IA", esa frase no significa nada todavía. La pregunta que la convierte en algo accionable es en qué casilla cae lo que están pidiendo, y para contestarla hacen falta dos datos que casi nunca están sobre la mesa: qué se quiere predecir, y si existen ejemplos pasados con la respuesta ya puesta.
Si los hay, estás en supervisado y este libro te sirve entero. Si no los hay, lo que te están pidiendo o es no supervisado, o es un proyecto de recolectar datos disfrazado de proyecto de modelos, que es lo que pasa la mayoría de las veces. Distinguir esas dos cosas antes de firmar te ahorra meses 🧭
Fíjate además en la casilla de arriba del todo. Inteligencia artificial es el paraguas grande y machine learning es una de sus ramas, así que "compramos IA" puede significar cinco cosas distintas y solo una de ellas es lo que vas a aprender aquí. Esa precisión no es pedantería: es la diferencia entre pagar por lo que necesitas y pagar por la palabra 💸
Cuándo NO usar machine learning
Esta sección va antes que el código a propósito, porque es la que más plata ahorra.
- 📏 Si la regla se puede escribir. "Avisar cuando el stock
baje de 10" es un
if. Meterle un modelo es cobrar de más y entregar algo peor. - 🔍 Si necesitas explicar cada decisión con certeza. Un modelo da probabilidades, no razones. Si el área legal necesita el porqué exacto de cada rechazo, hay que pensarlo distinto desde el principio.
- 📉 Si tienes cien filas. Con cien filas no se aprende nada que no se vea mirando el Excel un rato.
- 🤷♀️ Si nadie va a hacer nada con la predicción. El caso más común y el más caro: un modelo precioso que nadie usa porque no había una decisión esperándolo. Antes de modelar, pregunta qué se va a hacer distinto con el resultado.
De hecho, ese último punto es el capítulo 2 entero 🌟
Los datos con los que vamos a trabajar
Todo este libro corre sobre el mismo archivo, y viene sucio a propósito.
import pandas as pd URL = 'https://missyera.com/static/datasets/ventas-miss-yera.csv' ventas = pd.read_csv(URL) print(ventas.shape) print(ventas['compro'].value_counts())
(3037, 14) compro 1 1753 0 1284 Name: count, dtype: int64
3.037 ventas y 14 columnas. Y la columna que vamos a predecir es
compro: 1 si la venta se cerró, 0 si no.
print(ventas[['ciudad', 'segmento', 'canal', 'unidades', 'satisfaccion', 'compro']].head(5).to_string(index=False))
ciudad segmento canal unidades satisfaccion compro
Trujillo Horeca Marketplace 10 4.0 1
lima Minimarket Web 10 3.0 1
Cusco Minimarket Web 13 1.0 1
Arequipa Mayorista Marketplace 3 4.0 1
Cusco Minimarket Marketplace 1 1.0 0
Cada fila es una venta: dónde, a qué tipo de cliente, por qué canal, cuántas unidades, qué satisfacción tenía ese cliente y si compró o no.
Si te fijas en la segunda fila ya vas a ver el primer problema: la ciudad dice
lima en minúscula. Hay más, muchos más, y son el capítulo 4 🧽
El número que hay que saber antes que ningún otro
print(round(ventas['compro'].mean(), 4))
0.5772
El 57,7% de las ventas se cerraron.
Guárdate ese número, porque es el listón. Si yo digo "todas las ventas se cierran" sin mirar nada, acierto el 57,7% de las veces. Cualquier modelo que no le gane a eso no vale nada, por muy elegante que sea 📏
La cantidad de proyectos que se presentan con un "77% de exactitud" sin decir que el listón estaba en 75... muchos. Vamos a volver sobre esto en el capítulo 14, que va entero de eso.
Tu primer modelo, en seis líneas
Vamos a hacer el equivalente del "hola mundo": un modelo de verdad, con dos columnas y sin limpiar nada.
from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier d = ventas[['unidades', 'satisfaccion', 'compro']].dropna() X, y = d[['unidades', 'satisfaccion']], d['compro'] X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.25, random_state=42, stratify=y) arbol = DecisionTreeClassifier(max_depth=2, random_state=42).fit(X_tr, y_tr) print(round(arbol.score(X_te, y_te), 4))
0.582
0,582. O sea que acierta el 58,2% de las veces 🎉
Los porqués de esas seis líneas
Ninguna de esas decisiones es de adorno, y las cuatro te las van a preguntar en una entrevista:
- ✂️
test_size=0.25. Le escondo una cuarta parte de las filas al modelo para tomarle examen con datos que no vio. Si le tomara el examen con lo que ya estudió, aprobaría siempre. - ⚖️
stratify=y. Obliga a que el trozo escondido tenga el mismo porcentaje de ventas cerradas que el original. Sin esto, el azar puede dejarte un examen con muchos más "sí" que la realidad, y la nota deja de significar nada. - 🎲
random_state=42. El reparto es al azar, y esto fija ese azar. Sin él, cada corrida te da un número distinto y no puedes comparar el modelo de hoy con el de ayer. El 42 no tiene nada de especial, lo que importa es que sea siempre el mismo. - 🌳
max_depth=2. Le prohíbo al árbol hacer más de dos preguntas seguidas. Es una decisión mía, no algo que el modelo aprenda, y a eso se le llama hiperparámetro. En el ejercicio 5 vas a ver qué pasa cuando se lo suelto.
Y ahora la ducha fría, que es la parte importante de este capítulo.
print(round(y_te.mean(), 4))
0.5735
El listón en ese mismo trozo de datos era 0,5735. Nuestro modelo saca 0,582. Le ganamos por menos de un punto porcentual.
Eso no es un fracaso, es información. Y se puede averiguar por qué en una línea:
print(ventas.groupby('compro')['unidades'].mean().round(2))
compro 0 11.47 1 11.69 Name: unidades, dtype: float64
11,47 unidades en las ventas que no se cerraron y 11,69 en las que sí. Prácticamente lo mismo. Esa columna no sabe nada sobre el resultado, así que el modelo estaba trabajando con una sola señal de verdad, la satisfacción, y con un ruido al lado.
Yo elegí esas dos columnas porque eran las dos numéricas que tenía a mano, y esa es exactamente la trampa: las columnas que sí separan en este archivo son de texto, y scikit-learn no come texto. Lo vas a ver en los ejercicios y es lo que justifica los veinticuatro capítulos que vienen 🐣
Qué aprendió, exactamente
Un árbol tiene una gracia enorme y es que se puede leer.
from sklearn.tree import export_text print(export_text(arbol, feature_names=['unidades', 'satisfaccion']))
|--- satisfaccion <= 3.50 | |--- satisfaccion <= 1.50 | | |--- class: 0 | |--- satisfaccion > 1.50 | | |--- class: 1 |--- satisfaccion > 3.50 | |--- satisfaccion <= 4.50 | | |--- class: 1 | |--- satisfaccion > 4.50 | | |--- class: 1
Ahí está: aprendió que si la satisfacción es 1 (o sea, malísima) la venta no se cierra, y en todo lo demás dice que sí. Eso son cuatro reglas que nadie escribió, salidas solas de mirar 2.100 ejemplos.
Fíjate también que las ramas de abajo a la derecha dicen las dos
class: 1, o sea que ese corte no separaba nada. Un árbol se parte
aunque la partición no sirva, y eso es exactamente el tipo de cosa que hay que
saber mirar 🔍
Y una cosa que voy a repetir todo el libro: ese
random_state=42 no es decoración. Sin él, cada vez que
corras esto te sale un número distinto y no puedes comparar nada.
Contra qué hay que comparar tu primer modelo
El árbol de arriba acierta el 58,2%. Suena a aprobado, y no se puede saber si es bueno hasta compararlo con dos cosas 📏
from sklearn.metrics import accuracy_score print('decir que todos compran :', round(y_te.mean(), 4)) print('el árbol :', round(arbol.score(X_te, y_te), 4)) print() for col, umbral in [('satisfaccion', 4), ('unidades', 12)]: regla = (X_te[col] >= umbral).astype(int) print(f'regla "{col} >= {umbral}"'.ljust(30), round(accuracy_score(y_te, regla), 4))
decir que todos compran : 0.5735 el árbol : 0.582 regla "satisfaccion >= 4" 0.5692 regla "unidades >= 12" 0.505
Y aquí está el balde de agua fría del capítulo 🪣
Decir que todos compran acierta el 57,35%. Sin modelo, sin datos, sin nada: solo porque la mayoría compra. El árbol acierta el 58,2%, o sea que todo el trabajo vale ocho décimas de punto porcentual.
Y las reglas escritas a mano lo hacen peor todavía. "Compra si la satisfacción es 4 o más" acierta el 56,9%, por debajo de no hacer nada. "Compra si lleva 12 unidades o más" acierta el 50,5%, que es tirar una moneda.
Qué se hace con un resultado así
Lo primero, no esconderlo. Un modelo que gana ocho décimas al listón no está listo para nada, y decirlo el primer día es mucho más barato que descubrirlo cuando ya lo prometiste 💬
Lo segundo, entender que esto es lo normal al empezar. El árbol de arriba usa dos columnas y ninguna preparación. Con el libro entero por delante, ese número va a subir bastante, y va a subir por cosas concretas que se pueden explicar.
Y lo tercero, que es lo que quiero que te lleves: el listón se calcula antes que el modelo, no después. Si primero entrenas y luego buscas con qué compararlo, vas a encontrar la comparación que te deje bien. Es humano y pasa siempre 🙈
Las dos reglas de arriba también valen la pena por otro motivo. Muchas veces llegas a un proyecto donde ya hay una regla de negocio escrita en un Excel, y la pregunta no es "¿mi modelo es bueno?" sino "¿mi modelo es mejor que lo que ya hacen?". Si no lo es, el proyecto es cambiar el Excel, no montar un modelo 📋
Y ahora al revés: el número que se ve precioso
Acabas de ver un modelo honesto que gana ocho décimas. Ahora mira uno que presume de acertar el 100%, porque de estos vas a ver muchos más 👀
La trampa
Alguien de tu equipo te manda esto un viernes con un "ya está, sale 100%". Léelo antes de responder: el código corre, no da ningún error y el número es de verdad. Hay dos cosas mal y las dos caben en dos líneas.
cols = ['id_venta', 'unidades', 'satisfaccion'] d = ventas[cols + ['compro']].dropna() X, y = d[cols], d['compro'] arbol = DecisionTreeClassifier( random_state=42).fit(X, y) print(round(arbol.score(X, y), 4))
Qué está mal
La primera: entrena y toma el examen con las mismas filas. La segunda, y es la que hace el destrozo: metió id_venta como columna para predecir. Cada venta tiene un id único, así que al árbol le basta con aprenderse "el id 1842 compró" para acertar el 100%. No aprendió nada del negocio, se aprendió la lista de memoria 📋
Lo que pasa cuando ese mismo modelo ve filas nuevas es lo que quiero que te quede: acierta el 52,6%. El listón era 57,4%, o sea que el modelo del 100% rinde peor que decir que sí a todo. Una columna que identifica la fila en vez de describirla se llama fuga de información, y tiene el capítulo 12 entero para ella sola.
Cómo se ve un proyecto entero, para que tengas el mapa
Casi todos los cursos te enseñan el paso 6 y te dejan sola con los otros siete. Estos son los ocho, y este libro los recorre en orden:
- 1️⃣ La pregunta. Qué se va a decidir distinto con la predicción. Sin esto no se empieza. (Capítulo 2)
- 2️⃣ Mirar los datos. Cuántas filas, cuántos huecos, qué está sucio. (Capítulo 4)
- 3️⃣ Construir las columnas. Convertir lo que hay en algo que un modelo pueda usar. Es donde más se gana. (Capítulos 9 y 11)
- 4️⃣ El listón. Lo tonto que hay que ganar. (Capítulo 14)
- 5️⃣ Comprobar que no hay trampa. Que ninguna columna esté contando el futuro. (Capítulo 12)
- 6️⃣ Los modelos. Probar varios y quedarse con uno. (Capítulos 13 y 18)
- 7️⃣ Medir bien. Elegir la métrica que corresponde al problema, no la que se ve mejor. (Capítulos 14 a 16)
- 8️⃣ Explicarlo y vigilarlo. Porque un modelo que nadie entiende no se usa, y todos se pudren con el tiempo. (Capítulos 20 a 27)
Y fíjate dónde está el paso de los modelos: en el sexto de ocho. Cuando alguien dice que el 80% del trabajo es limpiar y preparar datos no está exagerando ni quejándose, está describiendo el oficio 🧹
El vocabulario, para que no te agarre desprevenida
| Palabra | Qué es en cristiano |
|---|---|
| Feature o variable | Una columna que usas para predecir. unidades, ciudad |
| Target u objetivo | La columna que quieres predecir. Aquí, compro |
| Entrenar | Mostrarle los ejemplos al modelo para que saque sus reglas |
| Train y test | Los datos partidos en dos: con unos aprende y con los otros se le toma examen |
| Predecir | Pedirle la respuesta para filas que no vio |
| Hiperparámetro | Una decisión tuya sobre el modelo, no algo que aprenda. El max_depth=2 de arriba |
| Baseline o listón | Lo tonto que hay que ganarle. Aquí, decir siempre que sí |
Si en algún capítulo te sale una palabra que no está en esta tabla, la tengo definida en dos líneas en el glosario de IA 📖
Y si el código de arriba te resultó cuesta arriba más que los conceptos, eso no es de machine learning: es de Python, y se arregla con el libro de Python desde cero. No hace falta terminarlo para seguir aquí, tranqui 🐣
Ejercicios
Siete sobre el mismo archivo. Intenta antes de abrir 💛
1. Cuánto se cierra por canal
Qué porcentaje de ventas se cierra en cada canal.
print(ventas.groupby('canal')['compro'].mean().round(4).sort_values(ascending=False))
canal WhatsApp 0.6524 Tienda 0.6190 Web 0.5830 Marketplace 0.4613 Name: compro, dtype: float64
Diecinueve puntos entre WhatsApp (65%) y Marketplace (46%). Eso es muchísimo: el canal solo ya separa mejor que nuestro modelo entero, que ganaba menos de un punto 😳
Y es una columna de texto, o sea de las que scikit-learn no come. Ahí está el resumen de por qué este libro tiene veinticinco capítulos.
2. Y por segmento de cliente
Lo mismo con segmento, y de paso cuántas filas
tiene cada uno.
print(ventas.groupby('segmento')['compro'].agg(['count', 'mean']).round(4))
count mean segmento Bodega 719 0.3755 Horeca 750 0.6320 Mayorista 758 0.7230 Minimarket 810 0.5691
Y esta es todavía más fuerte: Bodega cierra el 37,6% y Mayorista el 72,3%. Treinta y cinco puntos de diferencia.
Si tuvieras que apostar con un solo dato, apostarías con este y le ganarías a nuestro árbol sin despeinarte. Lo que hace un modelo, cuando está bien hecho, es combinar estas señales en vez de elegir una 🔧
3. La satisfacción sí separa
Tasa de cierre por nivel de satisfacción.
print(ventas.groupby('satisfaccion')['compro'].agg(['count', 'mean']).round(4))
count mean satisfaccion 1.0 568 0.4472 2.0 542 0.5351 3.0 557 0.5404 4.0 567 0.6279 5.0 569 0.7135
De 44,7% con satisfacción 1 a 71,4% con satisfacción 5: veintisiete puntos, y
además ordenaditos de menos a más. Por eso el árbol de arriba eligió justo esta
columna para su primer corte, y no unidades 🌟
Fíjate también en la columna count: los cinco niveles tienen
entre 542 y 569 filas. Cuando un nivel tiene veinte filas, su tasa no significa
nada por mucho que se vea distinta, y eso hay que mirarlo siempre.
4. Un árbol un poco más profundo
El mismo modelo con max_depth=4. ¿Mejora?
arbol4 = DecisionTreeClassifier(max_depth=4, random_state=42).fit(X_tr, y_tr) print(round(arbol4.score(X_te, y_te), 4))
0.5892
0,5892. Subió un punto respecto al de profundidad 2. Poquísimo, y con dos columnas flojas es lo que hay.
Lo interesante viene en el ejercicio siguiente, porque ese "mejoró" hay que mirarlo con lupa.
5. Cuánto acierta en los datos que ya vio
Compara la nota del árbol de profundidad 4 en train y en test.
print('en train:', round(arbol4.score(X_tr, y_tr), 4)) print('en test :', round(arbol4.score(X_te, y_te), 4))
en train: 0.6047 en test : 0.5892
0,6047 en los datos que ya vio contra 0,5892 en los que no. Kilómetro y medio de diferencia, todavía poco. Pero mira qué pasa si le damos más profundidad todavía:
for prof in (2, 4, 6, 10): a = DecisionTreeClassifier(max_depth=prof, random_state=42).fit(X_tr, y_tr) print(prof, round(a.score(X_tr, y_tr), 4), round(a.score(X_te, y_te), 4))
2 0.599 0.582 4 0.6047 0.5892 6 0.6132 0.582 10 0.6318 0.582
Ahí está clarísimo: la columna del medio (train) sube y sube, de 0,599 a 0,6318. La de la derecha (test) se queda clavada. El modelo está memorizando, y eso se llama sobreajuste, o overfitting, que es como te lo vas a encontrar escrito casi siempre.
Es de los problemas más traicioneros del oficio, porque el número que ves mientras trabajas sube mientras el que importa no se mueve. La nota de entrenamiento no se reporta nunca: sirve solo para compararla con la otra y cazar esto. Capítulo 16 entero 🫠
6. El error que vas a cometer el primer día
Entrena con una columna de texto sin convertirla.
X_malo = ventas[['ciudad', 'unidades']] DecisionTreeClassifier().fit(X_malo, ventas['compro'])
ValueError: could not convert string to float: 'Trujillo'
could not convert string to float. Y es de los mensajes más honestos que hay: scikit-learn solo entiende números. Ni una letra.
Convertir ciudad en algo que el modelo entienda tiene nombre,
OneHotEncoder, y está en el capítulo 11. Por ahora quédate con el
mensaje, porque lo vas a ver muchas veces 💛
7. El listón, escrito como se debe
Calcula el baseline con la herramienta que trae scikit-learn para eso, en vez de a mano.
from sklearn.dummy import DummyClassifier tonto = DummyClassifier(strategy='most_frequent').fit(X_tr, y_tr) print(round(tonto.score(X_te, y_te), 4))
0.5735
0,5735, el mismo número que sacamos a mano. DummyClassifier
existe justo para esto y merece estar en tu primer cuaderno de cada proyecto:
te da el listón sin que tengas que pensarlo, y sin listón no hay forma de saber
si tu modelo sirve 📏
Comprueba que lo tienes
El 57,7% de las ventas se cierra y tu modelo acierta el 58%. ¿Qué tienes?
- Nada todavía: eso es lo mismo que decir que sí a todo
- Un modelo que acierta más de la mitad, que es un buen empiece
- Un modelo que hay que ajustar un poco
- Un modelo mal entrenado
Lo que te llevas
- 🔄 En programación tú escribes las reglas; en ML das ejemplos y salen las reglas.
- 🎯 Supervisado es predecir con ejemplos etiquetados, y es lo que más se usa en empresa. Dentro, regresión para números y clasificación para etiquetas.
- 🚫 No uses ML si la regla se puede escribir, si tienes cien filas, o si nadie va a hacer nada con la predicción.
- 📏 El listón primero. Aquí es 57,7% y todo se compara contra eso.
- 🌳 Tu primer modelo sacó 0,582 contra un listón de 0,5735. Menos de un punto, y eso también es un resultado.
- 🎲
random_stateen todo lo que reparta o baraje, o no puedes comparar nada. - 🔢 scikit-learn solo entiende números.
- 🧾 Una columna que identifica la fila en vez de describirla te regala un 100% que no existe.
Y si de todo el capítulo te llevas una sola frase, que sea esta:
Un modelo no se mide contra cero. Se mide contra lo que ya funciona sin él.
En el capítulo 2 vamos a lo que va antes del código y que casi nadie enseña: el contrato de datos, o sea qué se acuerda con el cliente antes de tocar una sola fila.
Que tengas lindo día! 🌸
Practica este capítulo 📓
Todo el código de arriba en un cuaderno que corre de principio a fin, y los ejercicios con una celda vacía para que los hagas tú. Se abre en Google Colab de un clic y no hay que instalar nada. Donde veas %%revisa, escribe tu respuesta y el cuaderno te dice si te salió.
¿Prefieres trabajar en tu máquina? Bájate el cuaderno de práctica o el de soluciones. Todos están también en github.com/soymissyera/MissYeraEjercicios.
Los términos que salen en este capítulo
- Generative AI vs Predictive AI
- Machine Learning vs Generative AI
- Machine learning
- Analitica predictiva
- Algoritmo
Están todos en el glosario de IA, con su definición corta.