{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Sumar y escalar, que ya es media predicción\n",
    "\n",
    "Las dos únicas operaciones que necesitas para entender qué hace un modelo lineal por dentro, con la tabla de ventas de siempre.\n",
    "\n",
    "Cuaderno de práctica del capítulo 3 de **Matemática para machine learning**, de Miss Yera.\n",
    "\n",
    "Corre de arriba abajo. Si lo abres en Google Colab no necesitas instalar nada.\n",
    "\n",
    "Capítulo completo: https://missyera.com/guias/matematica-para-machine-learning/suma-y-escalado-de-vectores/\n",
    "\n",
    "Los ejercicios están al final y traen una celda vacía debajo de cada uno. Las\n",
    "respuestas viven en el cuaderno de soluciones, y merece la pena pelearse un\n",
    "rato antes de abrirlo 💛"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Antes de empezar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import urllib.request\n",
    "\n",
    "# Este capitulo abre el archivo por su nombre, sin URL, que es lo que se hace\n",
    "# cuando lo tienes al lado. Aqui se baja primero para que exista.\n",
    "for nombre in ['ventas-miss-yera.csv']:\n",
    "    urllib.request.urlretrieve(f\"https://missyera.com/static/datasets/{nombre}\", nombre)\n",
    "    print(nombre, \"lista\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Antes de empezar\n",
    "\n",
    "Esta celda baja el ayudante que corrige tus ejercicios. Después, en cada\n",
    "ejercicio que se pueda corregir solo, vas a ver `%%revisa` arriba de la celda:\n",
    "escribe tu respuesta debajo, ejecuta, y te digo si te salió 💛"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import urllib.request\n",
    "\n",
    "# El ayudante de los cuadernos. Trae la corrección de los ejercicios y, en los\n",
    "# capítulos de consola, la celda mágica que ejecuta los comandos. Se baja en\n",
    "# vez de venir pegado aquí para que siempre sea el último.\n",
    "urllib.request.urlretrieve(\n",
    "    \"https://missyera.com/static/cuadernos/revisa.py\", \"revisa.py\")\n",
    "import revisa\n",
    "revisa.carga({\n",
    "    1: \"YSBtYW5vIDogWyAxMS42OCA4MDMuMzkgICAzLjAyXQptZWFuICAgOiBbIDExLjY4IDgwMy4zOSAgIDMuMDJd\",\n",
    "    2: \"Y29uIG1vbnRvIDogNDQ4LjEzCnNpbiBtb250byA6IDI4MC4w\",\n",
    "    3: \"ZGlmZXJlbmNpYSA6IFsgIC0xLjY4IC0zMjMuMDIgICAgMC45OF0=\",\n",
    "}, lenguaje=\"python\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dos operaciones y ya está 🌸"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Este capítulo es corto porque los vectores solo saben hacer dos cosas:\n",
    "sumarse entre ellos y estirarse. Con eso se construye todo lo demás."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Volvemos a abrir el archivo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cada capítulo arranca de cero, así que estas líneas se repiten. Son las\n",
    "mismas del capítulo 1 y las vas a ver en todos."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "df = pd.read_csv('ventas-miss-yera.csv')\n",
    "for c in ('unidades', 'monto', 'satisfaccion'):\n",
    "    df[c] = pd.to_numeric(df[c], errors='coerce')\n",
    "X = df[['unidades', 'monto', 'satisfaccion']].dropna().to_numpy()\n",
    "print('X.shape:', X.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sumar es componente con componente"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a, b = X[0], X[1]\n",
    "print('a     :', np.round(a, 2))\n",
    "print('b     :', np.round(b, 2))\n",
    "print('a + b :', np.round(a + b, 2))\n",
    "print('a - b :', np.round(a - b, 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Las unidades con las unidades, los soles con los soles. Nunca se cruzan."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "𝐚+𝐛=(a1+b1,a2+b2,…,ad+bd)\n",
    "\n",
    "sumar dos vectores es sumar componente con componente, cada una con la que le toca y con ninguna otra"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y mira la resta, que es la que de verdad se usa: `[0, -44.53, 1]`\n",
    "te dice que las dos ventas tuvieron las mismas unidades, que la segunda facturó\n",
    "44.53 soles más, y que la primera tuvo un punto más de satisfacción.\n",
    "\n",
    "Guárdate eso, porque **restar dos vectores es cómo se mide una\n",
    "diferencia**, y medir diferencias es lo que hace un modelo cuando calcula\n",
    "cuánto se equivocó. Eso es el capítulo de norma y distancia."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Escalar es estirar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('a * 2 :', np.round(a * 2, 2))\n",
    "print('a / 2 :', np.round(a / 2, 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "α𝐯=(αv1,αv2,…,αvd)\n",
    "\n",
    "multiplicar por un número escala todas las componentes por igual, sin cambiar la proporción entre ellas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese número que multiplica se llama **escalar**, y el nombre no\n",
    "es casual: escala el vector sin cambiar la proporción entre sus componentes.\n",
    "\n",
    "Fíjate en `a * 2`: la satisfacción pasó a 8. Matemáticamente\n",
    "correcto y comercialmente absurdo, porque la escala llega a 5. Las operaciones\n",
    "no saben qué significan tus columnas: eso lo pones tú."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y aquí está la predicción"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahora júntalas. Supón que quieres estimar cuánto vale una venta, y decides\n",
    "que cada unidad vale 12, cada sol facturado vale 0.35 y cada punto de\n",
    "satisfacción vale 40."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pesos = np.array([12.0, 0.35, 40.0])\n",
    "print('a       :', np.round(a, 2))\n",
    "print('pesos   :', pesos)\n",
    "print('a*pesos :', np.round(a * pesos, 2))\n",
    "print('suma    :', round(float((a * pesos).sum()), 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Multiplicar cada característica por su peso y sumarlo todo. **Eso es\n",
    "una predicción lineal.** Ese 448.13 es exactamente la forma que tiene la\n",
    "salida de una regresión lineal, de una regresión logística antes de la sigmoide,\n",
    "y de una sola neurona.\n",
    "\n",
    "La única diferencia entre esto y un modelo de verdad es de dónde salen los\n",
    "pesos. Yo me los inventé; un modelo los aprende. Cómo los aprende es la parte de\n",
    "optimización de este libro, y lo que hace en cada paso es el capítulo del\n",
    "descenso de gradiente.\n",
    "\n",
    "Y esa operación de \"multiplicar componente a componente y sumar\" es tan\n",
    "importante que tiene nombre propio y capítulo propio: el producto punto 🐣"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Sumar vectores es componente con componente. Nunca se cruzan.\n",
    "\n",
    "- Restar es cómo se mide una diferencia, y de ahí sale el error de un modelo.\n",
    "\n",
    "- Escalar es multiplicar todo por un número, sin cambiar las proporciones.\n",
    "\n",
    "- Pesar y sumar es literalmente lo que hace un modelo lineal.\n",
    "\n",
    "- Las operaciones no saben qué significan tus columnas."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comprueba que se entendió"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Multiplicas cada característica de una venta por su peso y sumas todo. ¿Qué acabas de calcular?\n",
    "\n",
    "a) Una predicción lineal, que es lo que hace por dentro una regresión\n",
    "\n",
    "b) El promedio ponderado de la venta\n",
    "\n",
    "c) La distancia de esa venta al origen\n",
    "\n",
    "d) Nada útil, porque los pesos me los inventé yo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. El promedio es sumar y escalar\n",
    "\n",
    "Calcula la venta media a mano, sin usar mean."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 1\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Cambia los pesos y mira qué manda\n",
    "\n",
    "Pon a cero el peso del monto y compara."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 2\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. La resta como error\n",
    "\n",
    "Compara la primera venta contra la venta media."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 3\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preguntas frecuentes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "¿Cómo se hace la suma de vectores?Se suman componente a componente y sale otro vector del mismo largo. Si los largos no coinciden, la operación no existe.\n",
    "\n",
    "¿Y la resta de vectores?Igual, componente a componente. La resta de dos vectores es la flecha que va de uno al otro, y por eso mide la distancia entre dos clientes.\n",
    "\n",
    "¿Qué es multiplicar un vector por un escalar?Multiplicar cada componente por el mismo número. Estira el vector si el número es mayor que uno, lo encoge si es menor, y lo da vuelta si es negativo.\n",
    "\n",
    "¿Qué son las operaciones con vectores?Sumar, restar, escalar y el producto punto. Con esas cuatro está hecho casi todo lo que un modelo lineal calcula."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 3 de **Matemática para machine learning**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/matematica-para-machine-learning/suma-y-escalado-de-vectores/\n",
    "\n",
    "Que tengas lindo día! 🌸"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
