martes, 15 de noviembre de 2022

Tipos de inteligencia artificial (mapa)

version en video:




Voy a empezar con el mapa completo por que posiblemente si suena conocido no va tener nada nuevo este articulo(y se puede saltar + rápido :D)




La idea es entonces ir colocando las explicación los conceptos y bajar por el árbol agregando nuevos conceptos de manera de queden relacionados.



Es una disciplina que estudia las máquinas con comportamientos inteligentes.



El machine learning es como se consigue esta inteligencia artificial usando generalmente tecnicas que tiene su fundamento en las matematicas y en la estadistica(este articulo tiene una buena explicacion de la diferencia https://azure.microsoft.com/en-us/solutions/ai/artificial-intelligence-vs-machine-learning/#process)



Aprendizaje supervisado. Es una de las 3 divisiones del machine learning que estudia problemas donde ya sabemos que queremos encontrar, de hecho tenemos etiquetas que nos indican el valor a predecir. ejemplos de esto pueden ser una tabla donde tenemos información de viejos clientes y ex-clientes donde marcamos cuales se fueron y queremos generar un modelo para saber que un cliente se va ir(para tal vez ofrecerle un descuento y/o evitar perderlo)



Aprendizaje no supervisado. en este como su nombre lo dice no se tiene una supervisión o una etiqueta con ejemplos previos de lo que queremos encontrar. Aqui un dato curioso que escuche hay grupos dentro de la ia que creen mucho en este tipo de machine learning por que se considera un aprendizaje más real al ser casi espontáneo



Aprendizaje por refuerzo: Esta es la tercera categoria, donde los modelos son premiados o castigados basado en que tan bien son capaces de conseguir una actividad. una de las areas grande de uso de estos modelos es en los videojuegos un ejemplo pueden ser modelos que juegan juegos como ajedrez o league of legends donde se le deja al modelo realizar acciones con las entradas(los controles del juego) y se le da el info del input(lo que se muestra en pantalla/sonidos/posiciones de las fichas) y el modelo es premiado/reforzados cuando hacen cosas que aumente el puntaje en el juego.



Clasificación y regresión: son los 2 tipos de divisiones que se le dan a los algoritmos de aprendizaje supervisado en la clasificación los algoritmos buscan encontrar a qué grupo pertenecen los datos por ejemplo (comprar,vender)(manzanas,peras,sandias). mientras que en la regresion el objetivo es una variable con valores infinitos algunos ejemplos pueden ser la temperatura global, ingresos anuales (se usa para valores numéricos)



Reducción de dimensionalidad, agrupación o detección de anomalías: son los 3 grupos donde esta el aprendizaje no supervisado.

  • La reducción de la dimensionalidad se usa especialmente para poder visualizar los datos reducidos a 2 o 3 dimensiones que son la que podemos ver los humanos. básicamente consiste en que se tienen datos con n dimensiones y llevamos esos datos a otro donde la dimensión sea menor a n
  • Agrupación: a mi se me hace muy parecido a la clasificación del aprendizaje supervisado, lo que la diferencia con la clasificación es que no sabemos que grupos espontáneos se van a generar en el algoritmo (y no deberíamos tener grupos previamente catalogados). como dato curioso nos mostraron un método que llaman el método del codo(https://en.wikipedia.org/wiki/Elbow_method_(clustering)) para escoger el número correcto de clusters(o grupos dentro de la agrupación)
  • Detección de anomalías: en este tipo de algoritmos tenemos una serie de información y queremos que el algoritmo, nos diga cuando algo anormal esta pasando en los datos. por ejemplo el uso de memoria de una base de datos y queremos detectar anomalías para saber si las operaciones bajaron de manera drástica o subieron de manera drástica (y entrar a revisar por que se presenta la anomalía en el momento de que se presenta donde se pueden capturar evidencias más fácilmente)



El aprendizaje por refuerzo no se ha explicado(creo que no se explica) pero igual se mencionó en la clasificación global, conocer estas clasificaciones puede ser valioso para por ejemplo si se tiene un problema de tipo regresión, saber que se pueden buscar algoritmos de aprendizaje supervisado de tipo regresión(que hay mucho) y así para cada uno. tambien para ubicar los conceptos de manera conectada pues nos permite recordar mejor la informacion

 

fuentes:

 

jueves, 25 de agosto de 2022

Mejorar la velocidad de equipos de desarrollo

version en video:


 

 

hace poco lei un articulo que me pareció muy poderoso titulado “teams that finish early accelerate faster” traducido los equipos que terminan temprano se aceleran más rápido, me pareció bacano por que nos presenta algunas estrategias para equipos de desarrollo que trabajan con scrum para que estos generan más valor.

Empieza poniendo unos criterios para aplicar estas estrategias entre ellos que los equipos sigan buenas prácticas y que sean estables, después de esto empiezan a comentar unas estrategias que pueden ayudar a generar equipos de alto desempeño.

El buffer comenta que si el equipo espera soporte o tareas inesperadas se debe tener un buffer(no mayor al 30% de la capacidad del equipo) que le permita atacar estas tareas si aparecen. para la implementación de este buffer es común que se asigne y rote una persona que está en soporte encargada de estos inesperados.
VInculado a este buffer comentan la necesidad de un procedimiento de emergencia si estas tareas inesperadas(y mas importantes que las tareas del sprint actual por que sino no entrarían) superan el 30%, se deben seguir unos pasos (no necesariamente todos).
cambiar la forma como se trabaja para que esto no sea un 30% extra(intentar encontrar innovación)
buscar alternativas aka intentar entregar este trabajo a otros.
cancelar el sprint y re planearlo informando las nuevas fechas a los jefes.

yesterday weather(el clima de ayer) consiste en determinar la capacidad que el equipo tiene basado en los 3 o mas ultimos sprint, se promedia la velocidad de estos como base para determinar los compromisos de los próximos sprints(rolling average)

Swarming esta nunca la he visto ni de cerca implementada, consiste en que se trabaje 1 historia de usuario a la vez, donde una persona hace de capitán y el resto del equipo lo ayuda en todo los que necesita.

Mantener un equipo estable sin gente que deje el equipo, e incluyendo una persona cada 6 meses a un año para traer ideas nuevas (un equipo de entre 4 y 6 personas). esto ciertamente es dificil de conseguir una recomendación que hacen el artículo es rastrear la felicidad del equipo( con algunas preguntas por escala numerica ) y se disminuye la felicida mucho investigar a fondo hablando con las personas del equipo que esta pasando.

Con estas estrategias el articulo reporta que hubo mejoras drasticas en los equipos del x40 o mas de la velocidad previa, ante esto supongo que habra que ver para creer.

Del lado de la implementacion de estas estrategias en http://scrumbook.org/ se habla de kaizen-pulse como un meta patron para hacer mejora continua (por ejemplo para ir implementando alguna de las estrategias anteriores) la idea es reunir data de como se comporta el equipo antes del cambio su velocidad y la varianza en esta velocidad, teniendo esto se procede a realizar un cambio (esto no lo dicen pero es mas probable que se acepte un cambio si se presenta de manera que parezca una propuesta del equipo mismo y no una descision unilateral) se procede entonces a medir como cambia la velocidad y la varianza(en la velocidad) del equipo a lo largo de varios sprints ( por que la apdatacion a cualquier cambio toma tiempo) posiblemente realizando pequeñas adaptaciones segun las discuciones del equipo. un cambio fue bueno si disminuye la varianza del equipo o si aumenta la velocida del mismo(sin aumentar drasticamente la varianza). en kaizen pulse este proceso se repite por cada cambio.


jueves, 30 de junio de 2022

Types, Covarianza y Contravarianza


 

Los tipos (types)


empezando por los tipos son una definición del grupo de propiedades que algo tiene por ejemplo si tenemos un String este tiene algunas propiedades como su tamaño y tal vez un método substring que nos permite tomar parte del string etc. mediante el tipo se define esto, cuando usamos tipos en lenguajes tipados lo que buscamos es que sepamos con que estamos interactuando y que operaciones son válidas/qué valores tiene algo.

Estos los vemos por ejemplo cuando declaramos una variable como String, Int, Boolean o cuando creamos una instancia de una interfaz o de una clase.

tipos genéricos (Generic types)


en algunos casos queremos garantizar que algo tenga un tipo pero no nos importa cuál sea este por ejemplo para las lista queremos que las listas solo contengan un tipo de elementos, pero no queremos decir especificamente cual, o queremos crear una funcion que nos permita aplicar validaciones pero no sabemos cuáles van a ser los campos, aquí vienen los Generic types que usualmente se definen en algo como esto.


public static <A> List<A> createListWithTwoElements(A element, A element2){
   return List.of(element,element2);
}

usarlos estos generic types tiene varias ventajas entre ellas:

  • que podemos reusar mas el codigo: por ejemplo el método anterior nos sirve para crear una lista de 2 elementos de varios typo llamándola con diferentes A’s
  • que el compilador nos va a chequear si hacemos algo mal si de repente quiero crear una lista con el primer elemento de un tipo, pero el segundo de otro se va generar un error que queremos que pase para estar seguros de que tenemos en esa lista que crea ese método que tipo

 

Covarianza y ContraVarianza.

Existen 2 tipos de herencia que me parecieron interesantes la covarianza y la contravarianza pero antes de eso vamos definir un árbol de herencias para poder explicar mejor :p

open class LivingThing

open class Animal(val name:String):LivingThing(){
    fun yell(){}
    fun eat(){}
}

data class Sloth(val slothName: String, val isTwoFingered: Boolean):Animal(slothName) {

    fun sleep(){}
}

data class Panda(val pandaName:String):Animal(pandaName){

    fun sleep(){}
}

con esto tenemos más o menos una estructura asi.

 

Donde tenemos a LivingThing(cosa viva) como supertipo de Animal, y Animal como supertipo de Sloth(oso peresozo) y Panda.
Al mismo tiempo Sloth y panda son subtipos de Animal, y Animal es un subtipo de LivinThing.

Covarianza.

en la covarianza decimos que recibimos un tipo o sus subtipos por ejemplo:

  • si recibimos un animal también recibió un Sloth o un Panda en ese parametro.
  • si recibimos un Sloth solo recibimos el Sloth porque este no tiene subtipos.
  • Si recibimos un LIvingThing podemos recibir cualquier cosa en el grafo.


la covarianza es la más natural y sencilla de entender desde mi punto de vista, por que se ve también cuando se castea de un tipo mas especifico a uno mas generico.

en kotlin la covarianza se establece por defecto sin que le pongamos nada simplemente un tipo es covariante por defecto, pero si queremos podemos usar la palabra clave out
<out Animal>.
en el caso de java para obtener covarianza se usa extends
<? extends Animal>
 

Contravarianza.

la contravarianza implica que algo puede recibir un tipo o sus supertipos, ejemplos:

  • si se define contravarianza de Sloth, el parámetro puede tener tipo de un Sloth, un Animal o un LIvingThing
  • si es Animal, puede ser de tipo Animal o LivingThing
  • si es un LivingThing puede solo ser un LivingThing


en kotlin la contravarianza se define así
<in A>
y en java
<? super A>

este es para mi fue mas dificil de entender principalmente por que parece contrario a la intuición, lo pude entender cuando vi un ejemplo de uso.

un árbol de herencias para poder explicar mejor :p
 
fun copy(src: List<out Animal>,dest: MutableList<in Animal>){
    for(a in src){
        dest.add(a)
    }
}


en este podemos ver un método que se encarga de copiar lo que está en input(parámetro src) al output(parámetro dest), en el input recibe una lista de Animales out o covarianza esto nos indica que la lista puede ser una lista de Animales con Sloths y Pandas, por el contrario en la salida tenemos un in de Animal o contravarianza lo que quiere decir que en esta lista vamos a tener Animales o LivingThing

y ahora sí todo empieza a tener sentido recibimos algo específico o su hijo, y generamos ese algo o algo más general

la regla para usar covarianza es para definir productores o get( en el ejemplo anterior estamos sacando de src y por eso lo definimos como covarianza).
y la regla para usar contravarianza es para definir consumidores o put( en el ejemplo anterior estamos guarda o consumiendo en dest).

Esto me lleva a creer más que la herencia es complicada :D .

referencias:


  • https://www.youtube.com/watch?v=yqB8u9higoI&t=2s
  • https://www.youtube.com/watch?v=A7oPKEj1-Fg
  • https://docs.microsoft.com/en-us/archive/blogs/csharpfaq/covariance-and-contravariance-faq
  • https://medium.com/kotlin-thursdays/introduction-to-kotlin-generics-9d18d3719e1d
  • https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)

 

jueves, 19 de mayo de 2022

ordenamiento bubble sort, quicksort y sin implementar en java.

version en video.


 

ordenar es poner las cosas siguiendo un orden(que viva la redundancia) por ejemplo podemos ordenar un numero de mayor a menor (5,4,3,2,1) o de menor a mayor (1,2,3,4,5) y en programacion existen muchos metodos de ordenamiento siendo uno de los mas sencillos de implementar bubble sort.

Bubble Sort.

es un método de ordenamiento donde iterativa mente vamos por toda la lista de elementos comparando el valor actual con el anterior (y rotandolos cuando no estan en orden) esto se hace cuantas veces como se necesite hasta que ido por todo el arreglo sin tener que rotar nada (significando esto que ya esta en orden).

es un algoritmo muy sencillo y tambien muy ineficiente en promedio toma O(n*n)  *1

en java se puede implementar de la siguiente manera.


 public static void main(String args[]) {
      int[] array = {13, 14, 42, 54, 56, 38, 97, 24, 57};
      bubbleSort(array);
      printArray(array);
  }

  public static boolean printArray(int[] input) {
      if (input.length == 0) {
          return false;
      }
      for (int i = 0; i < input.length; i++) {
          System.out.println(" " + input[i]);
      }
      return true;
  }

  public static boolean bubbleSort(int[] input) {
      if (input.length < 2) return false;
      boolean isInOrder;
      do {
          isInOrder = true;
          for (int i = 1; i < input.length; i++) {
              if (input[i - 1] < input[i]) {
                  int temporal = input[i - 1];
                  input[i - 1] = input[i];
                  input[i] = temporal;
                  isInOrder = false;
              }
          }
      } while (!isInOrder);
      return true;
  }


otro algoritmo muy conocido y que es creo de los que mas se usa es 

 

Quick Sort 


quicksort(ordenamiento rápido) y gusta bastante por que:

  • es rápido en promedio toma O(nlogn)
  • toma menos tiempo si los registros estan parcialmente ordenados(es verda en muchos casos)
  • optimiza bien el uso de cache *3

yo para entender  este algoritmo tuve que ver este video donde se explica muy bien *3.

el algoritmo es mas o menos asi.

  • usted empieza con un array (posiblemente desordenado)
  • tiene un metodo para ordernarlo(quicksort) que recibe este array, un minimo que es 0 el inicio del array y el tamaño del array(el intervalo que va ordenar)
  • este metodo despues de revisar que el min sea menor que el maximo llama a otro metodo que se encarga de encontrar una "particion" y mientras lo hace organiza los mas pequeño que la particion a la izquierda y lo mas grandes a la derecha (ordena no todo sino simplemente lo mayor y menor que donde esta la particion)
  • luego teniendo el index de esa particion se vuelve a llamar el metodo inicial dos veces una del inicio a la particion, y otra de la particion(el index de la misma hasta el tamaño original)
  • esto se sigue repitiendo recursivamente hasta que se acaba organizando todo.

entrando mas en detalle en el metodo que hace la particion se encarga de lo siguiente.

  • setea una variable i con el inicio/minimo y una variable j con el maximo/final
  • determina un pivote o elemento en el array para comparar(al inicio o al final del array generamente por facilidad, pero tambien se puede en en cualquier punto.
  • empieza a aumentar el i mientras lo que se encuentre sea menor que el pivote(osea que ya esta organizado con respecto al pivote), y a disminuir j mientras lo que se encuentre sea mayor que el pivote(osea que ya esta organizado en relacion al pivote)
  • si i es menor que j, es decir encontraron uno mayor y uno menor donde no debian estar estos se intercambian.
  • esto se repite y al final el pivote se pone en el "medio"(cambiando la variable en la poscision del pivote y la j) de manera de que queden menores a la izquierda y mayores a derecha del mismo
  • se retorna j, ya que en la poscision de j esta el pivote solo queda organizar las otras dos mitades usandolo.

en java una forma de implementar quicksort seria la siguiente.


public class mainClass {

    public static void main(String[] args) {
        int[] input = {1, 10, 10, 8, 6, 10, 1};
        quickSort(input, 0, input.length);
        printArray(input);
    }

    public static boolean printArray(int[] input) {
        if (input.length == 0) return false;
        System.out.println("");
        for (int i = 0; i < input.length; i++) {
            System.out.print(input[i] + " ");
        }
        return true;
    }

    public static void quickSort(int[] input, int min, int max) {
        if (min < max) {
            int j = partition(input, min, max);

            quickSort(input, min, j);
            quickSort(input, j + 1, max);
        }
    }

    public static int partition(int[] input, int min, int max) {
        int i = min;
        int j = max;
        int pivot = input[min];

        while (i < j) {
            do {
                i++;
            } while (i < input.length && input[i] < pivot);
            do {
                j--;
            } while (input[j] > pivot);
            if (i < j) {
                switchTheVariables(input, i, j);
            }
        }
        switchTheVariables(input, min, j);
        return j;
    }

    public static void switchTheVariables(int[] input, int a, int b) {
        int temporal = input[a];
        input[a] = input[b];
        input[b] = temporal;
    }

}

 implementar quicksort o bubble sort tan literal es interesante como ejercisio pero creo que tiene mas sentido utilizar el ordenamiento que ofrece el lenguaje, para ordenar en java podemos hacerlo asi

 


import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;

public class runjava {
    public static void main(String []args){
        Integer[] arrayInt={1,3,2,1,5,3,1};
        Arrays.sort(arrayInt);
        printArray(arrayInt);

        List<Integer> listInt=new ArrayList<Integer>();
        listInt.add(1);
        listInt.add(3);
        listInt.add(2);
        listInt.add(1);
        listInt.add(5);
        Collections.sort(listInt);
        System.out.print(listInt);

    }

    public static <A> boolean printArray(A[] array){
        if(array.length==0) return false;
        for(int i=0;i< array.length;i++){
            System.out.print(" "+array[i]);
        }
        return true;
    }
}

y si tuvieramos que implementar basados en un criterio propio x(por ejemplo ordenar un arreglo de string que sabemos son entero) o usando un campo especifico de una clase, o cualquier logica que quisieramos podriamos crear un comparator para informarle a java como queremos que ordene y hacerlo asi.


 import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class runJava{
    public static void main(String[] args) {

        Comparator<String> customComparator = ((a, b) -> {
            Integer aInt = Integer.valueOf(a);
            Integer bInt = Integer.valueOf(b);
            return aInt > bInt ? 1 : aInt < bInt ? -1 : 0;
        });
        List<String> listInt = new ArrayList<String>();
        listInt.add("1");
        listInt.add("3");
        listInt.add("2");
        listInt.add("1");
        listInt.add("5");
        Collections.sort(listInt);
        System.out.print(listInt);

    }

}

 

Referencias.

1. bubble sort https://www.geeksforgeeks.org/bubble-sort/

2. quicksort explicacion. https://www.youtube.com/watch?v=7h1s2SojIRw

3. por que gusta quicksort https://cs.stackexchange.com/questions/3/why-is-quicksort-better-than-other-sorting-algorithms-in-practice 

4. https://www.opinionatedgeek.com/codecs/htmlencoder