Pop

Patrones de diseño software 5. Prototype superficial

5.Patrón de creación Prototype superficial

  • Hola a todos.Seguimos con  nuestro  curso dedicado a los patrones de diseño software.Los patrones de diseño son unas técnicas para resolver problemas comunes en el desarrollo de software y otros ámbitos  referentes al diseño de interacción o interfaces.
  • En esta ocasión veremos el patrón de diseño  Prototype superficial. El patrón de diseño prototipo tiene como finalidad crear nuevos objetos clonando una instancia creada previamente. 
  • Este patrón especifica la clase de objetos a crear mediante la clonación de un prototipo que es una instancia ya creada. La clase de los objetos que servirán de prototipo deberá incluir en su interfaz la manera de solicitar una copia, que será desarrollada luego por las clases concretas de prototipos.
  • En el siguiente  vídeo tenéis un ejemplo de este patrón de diseño.
  • Os dejo el código visto en el vídeo:
* Clase Mueble:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Prototype_superficial
{
    class Mueble:ICloneable
    {
        private int numAsientos;
        private string nombre;

        public int NumAsientos { get => numAsientos; set => numAsientos = value; }
        public string Nombre { get => nombre; set => nombre = value; }

        public object Clone()
        {
            return this.MemberwiseClone();
        }
 }
}

* Clase Program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Prototype_superficial
{
    class Program
    {
        static void Main(string[] args)
        {
            Mueble mueble = new Mueble();
            mueble.NumAsientos = 1;
            mueble.Nombre = "Silla";

            Console.WriteLine("num:" + mueble.NumAsientos.ToString());
            Console.WriteLine("nombre:" + mueble.Nombre);

            Mueble clonMueble = mueble.Clone() as Mueble;
            clonMueble.NumAsientos = 3;
            clonMueble.Nombre = "Sofa";


            Console.WriteLine("num:" + clonMueble.NumAsientos.ToString());
            Console.WriteLine("nombre:" + clonMueble.Nombre);

            Console.ReadLine();
        }
    }
}

    

Patrones de diseño software 4. Singleton

4.Patrón de creación Singleton

  • Hola a todos.Seguimos con  nuestro  curso dedicado a los patrones de diseño software.Los patrones de diseño son unas técnicas para resolver problemas comunes en el desarrollo de software y otros ámbitos  referentes al diseño de interacción o interfaces.
  • En esta ocasión veremos el patrón de diseño Singelton. Es un patrón de diseño que permite restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto.Su intención consiste en garantizar que una clase solo tenga una instancia y proporcionar un punto de acceso global a ella.
  • El patrón singleton se implementa creando en nuestra clase un método que crea una instancia del objeto solo si todavía no existe alguna. Para asegurar que la clase no puede ser instanciada nuevamente se regula el alcance del constructor.
  • En el siguiente  vídeo tenéis un ejemplo de este patrón de diseño.
  • Os dejo el código visto en el vídeo:
*Clase SingletonEjemplo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Singleton
{
    public class SingletonEjemplo
    {
        private static SingletonEjemplo singleton = null;
        public string texto = String.Empty;
        public int numerito = -1;

        SingletonEjemplo(string valor)
        {
            texto = valor;
            numerito = 2;
        }

        public static SingletonEjemplo Singleton
        {
            get
            {
                if (singleton == null)
                    singleton = new SingletonEjemplo("Creado");

                return singleton;
            }
            set => singleton = value;

        }
    }
}

*Clase Program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Singleton
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine(SingletonEjemplo.Singleton.texto);
            Console.WriteLine(SingletonEjemplo.Singleton.numerito.ToString());
            Console.ReadLine();
            SingletonEjemplo.Singleton.texto = "DSAfaadfasfasasfas";
            SingletonEjemplo.Singleton.numerito = 3;
            Console.WriteLine(SingletonEjemplo.Singleton.texto);
            Console.WriteLine(SingletonEjemplo.Singleton.numerito.ToString());
            Console.ReadLine();
        }
    }
}

Patrones de diseño software 3.Builder

3.Patrón de creación Builder

  • Hola a todos.Seguimos con  nuestro  curso dedicado a los patrones de diseño software.Los patrones de diseño son unas técnicas para resolver problemas comunes en el desarrollo de software y otros ámbitos  referentes al diseño de interacción o interfaces.
  • En esta ocasión veremos el patrón de diseño Builder, que separa la creación de un objeto complejo de su representación, de modo que el mismo proceso de construcción pueda crear representaciones diferentes. Básicamente significa que en lugar de implementar la creación de un objeto en el constructor de la clase, habrá otras clases encargadas de crear el objeto  y asignarles las propiedades iniciales. Cada una de estas "otras" clases será un builder. Y cada uno de estos builders será capaz de crear un objeto nuevo con ciertas características.
  • En nuestro caso la jerarquía de clase que hemos creado tiene el aspecto que veis en la imagen:

  • En el siguiente vídeo vemos con un ejemplo como construir esta estructura de clases basándonos en el patrón de diseño Builder. 


  • Os dejo el código de las diferentes clases vistas en el vídeo:
*Clase ConexionBuilder:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Builder
{
    // Builder
    public abstract class ConexionBuilder
    {

        protected CadenaConexion conexion;

        public CadenaConexion dameCadenaConexion() { return conexion; }

         public virtual void asignarServidor()
        {

        }

        public virtual void asignarBasedatos()
        {

        }

        public virtual void asignarUsuario()
        {

        }

        public virtual void asignarPasswor()
        {

        }

    }
}

*Clase MySQLBuilder:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Builder
{
    public class MySQLBuilder : ConexionBuilder
    {
        public MySQLBuilder()
        {
            conexion = new CadenaConexion();
        }
        public override void asignarServidor()
        {
            conexion.Servidor = "Servidor MySQl";
        }

        public override void asignarBasedatos()
        {
            conexion.NombreBaseDAtos = "Nombre instancia MySQl";
        }

        public override void asignarUsuario()
        {
            conexion.Usuario = "usuario MySQl";
        }

        public override void asignarPasswor()
        {
            conexion.Password = "pass usuario MySQl";
        }
    }
}

*Clase OracleBuilder :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Builder
{
    public class OracleBuilder : ConexionBuilder
    {
        public OracleBuilder()
        {
            conexion = new CadenaConexion();
        }
        public override void asignarServidor()
        {
            conexion.Servidor = "Servidor ORACLE";
        }

        public override void asignarBasedatos()
        {
            conexion.NombreBaseDAtos = "Nombre instancia ORACLE";
        }

        public override void asignarUsuario()
        {
            conexion.Usuario = "usuario ORACLE";
        }

        public override void asignarPasswor()
        {
            conexion.Password = "pass usuario ORACLE";
        }
    }
}

*Clase OracleBuilder :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Builder
{
    public class SqlServerBuilder : ConexionBuilder
    {
        public SqlServerBuilder()
        {
            conexion = new CadenaConexion();
        }
        public override void asignarServidor()
        {
            conexion.Servidor = "Servidor SQL SERVER";
        }

        public override void asignarBasedatos()
        {
            conexion.NombreBaseDAtos = "Nombre instancia SQL SERVER";
        }

        public override void asignarUsuario()
        {
            conexion.Usuario = "usuario SQL SERVER";
        }

        public override void asignarPasswor()
        {
            conexion.Password = "pass usuario SQL SERVER";
        }
    }
}

*Clase CadenaConexion:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Builder
{

    public class CadenaConexion
    {
        public string Servidor { get; set; }
        public string NombreBaseDAtos { get; set; }
        public string Usuario { get; set; }
        public string Password { get; set; }

        public CadenaConexion()
        {

        }

        public CadenaConexion(string servidor, string baseDatos, string usuario, string pass) : this()
        {
            Servidor = servidor;
            NombreBaseDAtos = baseDatos;
            Usuario = usuario;
            Password = pass;

        }
    }
}

*Clase Conexion:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Builder
{

    public class Conexion
    {
        private ConexionBuilder conexionBuilder;

        public void nuevaConexion(ConexionBuilder conBuilder)
        {
            conexionBuilder = conBuilder;
        }

        public void crearCadenaConexion()
        {
            conexionBuilder.asignarServidor();
            conexionBuilder.asignarBasedatos();
            conexionBuilder.asignarPasswor();
            conexionBuilder.asignarUsuario();
        }

        public CadenaConexion ConexionLista
        {
            get { return conexionBuilder.dameCadenaConexion(); }

        }
    }
}

*Clase Program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Builder
{
    class Program
    {
        static void Main(string[] args)
        {
            var conexion = new Conexion();

            // queremos crear cadena conexion a SQL SERVER
            conexion.nuevaConexion(new SqlServerBuilder());
            conexion.crearCadenaConexion();
            var conexionSQLServer = conexion.ConexionLista;


            // queremos crear cadena conexion a My SQL
            conexion.nuevaConexion(new MySQLBuilder());
            conexion.crearCadenaConexion();
            var conexionMySQl = conexion.ConexionLista;

            // queremos crear cadena conexion a oracle
            conexion.nuevaConexion(new OracleBuilder());
            conexion.crearCadenaConexion();
            var conexionOracle = conexion.ConexionLista;

        }
    }
  }



Curso Tensorflow con Anaconda -20 Creando nuestros propio clasificador de imágenes (2)

20 Nuestros propio clasificador de imágenes (2)

  • Hola a todos.Una vez finalizado el curso de google nos disponemos a crear nuestro propio clasificador de imágenes.En esta segunda entrada veremos en detalle el código implementado para poder entrenar nuestro modelo.
  • Os dejo un vídeo donde explico que hace el código implementado con el objetivo de clasificar nuestros conjuntos de imágenes de perros y de gatos que descargamos en el capítulo anterior:
  • Os dejo el código visto en el vídeo:
 
#importamos librerias necesarias
import sys
from PIL import Image
sys.modules['Image'] = Image 
import os
from tensorflow.python.keras import optimizers #libreria optimizadores para entrenar modelo
from tensorflow.python.keras.preprocessing.image import ImageDataGenerator # libreria prepocesa imagenes
from tensorflow.python.keras.layers import Dropout, Flatten, Dense, Activation # Libreria para las capas
from tensorflow.python.keras.layers import  Convolution2D, MaxPooling2D #capas donde hacemos convuliones
from tensorflow.python.keras.models import Sequential # libreria para redes neuronales secuenciales
from tensorflow.python.keras import backend as K 
from tensorflow.python.keras import applications


K.clear_session() # limpiamos por si hubiera algo corriendo
datosEntrenamiento = './imagenes/entrenamiento' #ruta imagenes enetrenamiento
datosValidacion = './imagenes/validacion' # ruta imagenes validacion

longitud, altura = 224, 224 
#longitud y altura de las imagenes.Le pongo 224 en el ancho y alto porque es lo que se espera el
 #el modelo preentrenado
    
#reescalamos las imágenes para que los valores en vez de ir de 1 a 255(posibles valores pixel) vayan de 0 a 1.
#shear_range--> inclina imágenes
#horizontal_flip --> invierte imágenes
entDatagen = ImageDataGenerator(rescale=1. / 255,shear_range=0.2,zoom_range=0.2,horizontal_flip=True)

#en el grupo de validación simplemente reescalamos
validacionDatagen = ImageDataGenerator(rescale=1. / 255)

#carga las imágenes de entrenammiento y las procesa según la altura pasada y las clasifica en modo el modo categorical
Entrenamiento = entDatagen.flow_from_directory(datosEntrenamiento,
                                                  target_size=(altura, longitud),batch_size=32,class_mode='categorical')

#carga las imágenes de validación y las procesa según la altura pasada y las clasifica en modo el modo categorical
Validacion = validacionDatagen.flow_from_directory(datosValidacion,
                                                             target_size=(altura, longitud),
                                                              batch_size=32, class_mode='categorical')
#cargamo el modelo preentrenado
vgg=applications.vgg16.VGG16()
#vgg=applications.vgg16.VGG16()# Ejemplo del modelo
cnn=Sequential()

#cargamos las capas del modelo preentrenado en nuestro modelo secuencial y quitamos la última capa
for capa in vgg.layers:
    cnn.add(capa)
cnn.layers.pop()

#queremos que solo se entrenna la capa que añadimos nosotros asi que le decimos  layer.trainable=False
for layer in cnn.layers:
    layer.trainable=False

#añadimos nuestra capa
cnn.add(Dense(2,activation='softmax'))

#compilamos nuestro modelo utilizando el optimizado de Adam
cnn.compile(loss='categorical_crossentropy',
            optimizer=optimizers.Adam(lr=0.0004),
            metrics=['accuracy'])

#utilizamos la función v para entrenar el algoritmo
cnn.fit_generator(Entrenamiento,steps_per_epoch=100,epochs=20,validation_data=Validacion,validation_steps=300)

#una vez entreando guardamos nuestro modelo
cnn.save('./modelo/modelo.h5')
cnn.save_weights('./modelo/pesos.h5')

    

import numpy as np
from tensorflow.keras.preprocessing.image import load_img, img_to_array
from tensorflow.python.keras.models import Sequential # libreria para redes neuronales secuenciales
from tensorflow.keras.models import load_model
from tensorflow.python.keras import applications
from tensorflow.python.keras.layers import  Dense

longitud, altura = 224, 224
weights_model='./modelo/pesos.h5'  
vgg=applications.vgg16.VGG16()
cnn=Sequential()
for capa in vgg.layers:
    cnn.add(capa)
cnn.layers.pop()
for layer in cnn.layers:
    layer.trainable=False
cnn.add(Dense(2,activation='softmax'))  

cnn.load_weights(weights_model)

def predict(file):
  x = load_img(file, target_size=(longitud, altura))
  x = img_to_array(x)
  x = np.expand_dims(x, axis=0)
  array = cnn.predict(x)
  result = array[0]
  answer = np.argmax(result)
  if answer == 0:
    print("Gato")
  elif answer == 1:
    print("Perro")

  return answer

Instalación y descarga nuevo Visual Studio 2019


Visual Studio community 2019

  • Hola a todos.Hoy os traigo información sobre como descargar e instalar el nuevo visual studio 2019. Podemos descargar este nuevo entorno de desarrollo desde la página oficial de microsoft. 
  • Existe un enlace de descarga gratuito que os dejo a continuación: 
  • Algunas de las novedades más destacadas que nos trae este Visual Studio 2019 es que mejora la navegación a través del código y  mejora la sección de plantillas para que sea más fácil iniciar un nuevo proyecto. También se ha mejorado la experiencia de depuración, y todas las novedades funcionan tanto con proyectos existentes como con los nuevos.Desde aplicaciones cross-plataforma escritas en C++, hasta aplicaciones móviles .NET para iOS y Android escritas en Xamarin, o aplicaciones basadas en la nube que usen los servicios de Azure.
  • En el siguiente vídeo podéis ver como descargarlo e instalarlo.También creamos nuestro primer proyecto:

Curso Tensorflow con Anaconda -19 Creando nuestro propio clasificador de imagenes (1)

19 Nuestro propio clasificador de imágenes (1)

  • Hola a todos.Una vez finalizado el curso de google nos disponemos a crear nuestro propio clasificador de imágenes.En esta primera entrada de las dos que  dedicaremos a este tema veremos como preparar nuestra máquina para poder realizar este ejercicio.
  • Para poder entrenar el modelo correctamente necesitaremos bastantes imágenes de los elementos  que queremos clasificar. Para este objetivo me he ayudado de un plugin de chrome que nos permite bajar todas la imágenes de una página de manera automática. El plugin es este. Además para facilitar el entrenamiento de nuestro modelo hemos utilizado un modelo preentrenado de google.
  • En el siguiente vídeo os cuento todo esto con mucho más detalle:

Patrones de diseño software 2.Factory

2.Patrón de creación Factory

  • Hola a todos.Seguimos con  nuestro  curso dedicado a los patrones de diseño software.Los patrones de diseño son unas técnicas para resolver problemas comunes en el desarrollo de software y otros ámbitos  referentes al diseño de interacción o interfaces.
  • En esta entrada veremos el patrón de diseño Factory, que consiste en utilizar una clase constructora abstracta con unos cuantos métodos definidos y otros abstractos. Es un patrón de diseño creacional y que sirve para construir una jerarquía de clases. En nuestro caso la jerarquía de clase que hemos creado tiene el aspecto que veis en la imagen:
  • En el siguiente vídeo vemos con un ejemplo como construir esta estructura de clases basándonos en el patrón de diseño factory. 


  • Os dejo el código de las diferentes clases vistas en el vídeo:
*Clase BaseDatosGenerica:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Factory
{
    public abstract  class BaseDatosGenerica
    {
        public abstract string dameCadenaConexion();

    }
}

*Clase Oracle:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Factory
{
    class Oracle:BaseDatosGenerica
    {
        public override string dameCadenaConexion()
        {
            return "CAdena conexión base de datos Oracle";
        }
    }
}

*Clase  SqlServer

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Factory
{
    class SqlServer:BaseDatosGenerica
    {
        public override string dameCadenaConexion()
        {
            return "Cadena conexión base de datos SQlServer";
        }
    }
}

*Clase MySql

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Factory
{
    class MySql:BaseDatosGenerica
    {
        public override string dameCadenaConexion()
        {
            return "Cadena conexión base de datos Mysql";
        }
    }
}

* Clase Configuracion:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Factory
{

    class Configuracion
    {
        public const int SqlServer = 1;
        public const int Oracle = 2;
        public const int MySql = 3;

        public BaseDatosGenerica CrearConexion(int BaseDatos)
        {
            BaseDatosGenerica baseDatos = null;

            if (BaseDatos == 1)
                baseDatos = new SqlServer();
            else if (BaseDatos == 2)
                baseDatos = new Oracle();
            else if (BaseDatos == 3)
                baseDatos = new MySql();
            else
                throw new Exception("Base de datos no soportada");

            return baseDatos;

        }
    }
}

*Clase Program: 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Factory
{
    class Program
    {
        static void Main(string[] args)
        {
            Configuracion conf = new Configuracion();
            BaseDatosGenerica bDatos = conf.CrearConexion(Configuracion.SqlServer);
            Console.WriteLine(bDatos.dameCadenaConexion());
            Console.ReadLine();
             bDatos = conf.CrearConexion(Configuracion.Oracle);
            Console.WriteLine(bDatos.dameCadenaConexion());
            Console.ReadLine();
            bDatos = conf.CrearConexion(Configuracion.MySql);
            Console.WriteLine(bDatos.dameCadenaConexion());
            Console.ReadLine();
        }
    }
}

Patrones de diseño software 1.Presentación

1.Presentación

  • Hola a todos.Hoy comenzamos un nuevo curso dedicado a los patrones de diseño software.Los patrones de diseño son unas técnicas para resolver problemas comunes en el desarrollo de software y otros ámbitos  referentes al diseño de interacción o interfaces.En definitiva un patrón de diseño es una forma reutilizable de resolver un problema común.
  • Algunos de lo motivos por lo que se usan son los siguientes: ahorran tiempo y nos ayudan a estar seguros de la validez de nuestros código.Además los patrones de diseño establecen un lenguaje común entre todos los miembros del equipo.
  • Quizás lo mas complicado es elegir que patrón de diseño se adapta mejor para resolver nuestro problema, para ello es necesario conocer qué tipo de problemas soluciona cada uno y descubrir cómo aplicarlo a casos concretos.
    • Patrones creación:  Son los que facilitan la tarea de creación de nuevos objetos, de tal forma que el proceso de creación pueda ser desacoplado de la implementación del resto del sistema.Los patrones creacionales están basados en la encapsulación, ya que nos facilitan la tarea de creación de nuevos objetos encapsulando el proceso.Los que veremos en este curso son: 
      • Factory 
      • Builder 
      • Singleton
      • Prototype superficial 
      • Prototype deep 
    • Patrones estrucuturales: Son patrones que nos facilitan la modelización de nuestros software especificando la forma en la que unas clases se relacionan con otras:
      • Adapter 
      •  Facade 
      •  Proxy  
      • Bridge 
    • Patrones comportamiento:
      • Memento
      • Strategy
      • Iterator 

  • En siguiente vídeo os cuento en consistirá el curso:

Curso Tensorflow con Anaconda -18 Incorporaciones

18 Incorporaciones

  • Una incorporación es un espacio de dimensiones relativamente bajas al que se pueden trasladar vectores de dimensiones altas. Las incorporaciones permiten llevar a cabo el aprendizaje automático con más facilidad en entradas de gran tamaño.
  • El filtrado colaborativo es la tarea de realizar predicciones acerca de los intereses de un usuario en función de los intereses de muchos otros usuarios.  Por ejemplo,observemos la tarea de recomendación de películas. Imagina que tenemos 1,000,000 usuarios y una lista de las películas que cada uno de ellos ha visto (de un catálogo de 500,000 películas). Nuestro objetivo es recomendar películas a los usuarios. Para resolver este problema, se necesita un método que determine qué películas son similares entre sí. En la imagen vemos como hemos agrupado las películas  similares cerca.


  • Si distribuimos las películas en una incorporación de dos dimensiones, definimos una distancia entre las películas de manera tal que las películas estén cerca entre sí  (y por lo tanto se infiere que son similares). En términos más generales, lo que hicimos es asignar estas películas a un espacio de incorporación, donde se describe cada palabra mediante un conjunto de coordenadas en dos dimensiones. Por ejemplo, en este espacio, "Shrek" se asigna a (-1.0, 0.95) y "Bleu" se asigna a (0.65, -0.2). 




  • En general, al aprender una incorporación de d dimensiones, cada película se representa con d números de valores reales y cada uno de ellos proporciona la coordenada en cada dimensión. Los datos categóricos hacen referencia a atributos de entrada que representan uno o más elementos discretos de un conjunto de opciones finito.Se representan de manera más eficaz a través de tensores dispersos, que son tensores con muy pocos elementos distintos de cero. Por ejemplo, si queremos crear un modelo de recomendaciones de películas, podemos asignar un ID único a cada película posible y, luego, representar al usuario como un tensor disperso de las películas que ha mirado, tal como se muestra en la Figura.


    • Cada fila de la matriz en la Figura 3 corresponde a un usuario y puede ser representado con un tensor disperso, ya que cada usuario solo mira una pequeña fracción de las películas posibles. La última fila corresponde al tensor disperso [1, 3, 999999]
    • Os dejo el vídeo con la explicación:
    • Os dejo el código visto en el vídeo:
    """Objetivos:
    - En este ejercicio, exploraremos datos dispersos y trabajaremos con incrustaciones utilizando datos de texto de reseñas 
    de películas (del conjunto de datos de la ACL 2011 IMDB). Estos datos ya han sido procesados en formato tf.Example.
    - Convertir datos de cadena de revisión de películas en un vector de características.
    - Implementar un modelo lineal de análisis.
    - Implementar un modelo neuronal utilizando una incorporación que proyecte datos en dos dimensiones.
    - Visualicar la inserción para ver lo que el modelo ha aprendido sobre las relaciones entre las palabras.
    """

    #Importemos nuestras dependencias y descarguemos los datos de entrenamiento y prueba

    from __future__ import print_function

    import collections
    import io
    import math

    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    import tensorflow as tf
    from IPython import display
    from sklearn import metrics

    tf.logging.set_verbosity(tf.logging.ERROR)
    train_url = 'https://download.mlcc.google.com/mledu-datasets/sparse-data-embedding/train.tfrecord'
    train_path = tf.keras.utils.get_file(train_url.split('/')[-1], train_url)
    test_url = 'https://download.mlcc.google.com/mledu-datasets/sparse-data-embedding/test.tfrecord'
    test_path = tf.keras.utils.get_file(test_url.split('/')[-1], test_url)

    #Primero, configuremos el canal de entrada para importar nuestros datos en un modelo TensorFlow. 
    #Podemos usar la siguiente función para analizar los datos de entrenamiento y prueba (formato TFRecord) y devolver un dictado 
    #de las características y las etiquetas correspondientes.

    def _parse_function(record):
      """Extracts features and labels.
      
      Args:
        record: Ruta  a un archivo TFRecord   
      Returns:
        A `tuple` `(labels, features)`:
          features: Una de tensores que representan las características.
          labels: Un tensor con las etiquetas correspondientes.
      """
      features = {
        "terms": tf.VarLenFeature(dtype=tf.string), # terms are strings of varying lengths
        "labels": tf.FixedLenFeature(shape=[1], dtype=tf.float32) # labels are 0 or 1
      }
      
      parsed_features = tf.parse_single_example(record, features)
      
      terms = parsed_features['terms'].values
      labels = parsed_features['labels']

      return  {'terms':terms}, labels
      
    #Para confirmar que nuestra función está funcionando como se espera, construyamos un TFRecordDataset para los datos 
    #de entrenamiento, y asignemos los datos a características y etiquetas utilizando la función anterior.

    ds = tf.data.TFRecordDataset(train_path)
    # Map features and labels with the parse function.
    ds = ds.map(_parse_function)

    ds

    #Ejecute el siguiente código recuperamos el primer ejemplo del conjunto de datos de entrenamiento.

    n = ds.make_one_shot_iterator().get_next()
    sess = tf.Session()# Create an input_fn that parses the tf.Examples from the given files,
    # and split them into features and targets.
    def _input_fn(input_filenames, num_epochs=None, shuffle=True):
      
      # Same code as above; create a dataset and map features and labels.
      ds = tf.data.TFRecordDataset(input_filenames)
      ds = ds.map(_parse_function)

      if shuffle:
        ds = ds.shuffle(10000)

      # Our feature data is variable-length, so we pad and batch
      # each field of the dataset structure to whatever size is necessary.
      ds = ds.padded_batch(25, ds.output_shapes)
      
      ds = ds.repeat(num_epochs)

      
      # Return the next batch of data.
      features, labels = ds.make_one_shot_iterator().get_next()
      return features, labels
    sess.run(n)

    #Ahora, construyamos una función de entrada  que podamos pasar al método train () de un objeto TensorFlow Estimator.
    # Create an input_fn that parses the tf.Examples from the given files,
    # and split them into features and targets.
    def _input_fn(input_filenames, num_epochs=None, shuffle=True):
      
      # Same code as above; create a dataset and map features and labels.
      ds = tf.data.TFRecordDataset(input_filenames)
      ds = ds.map(_parse_function)

      if shuffle:
        ds = ds.shuffle(10000)

      # Our feature data is variable-length, so we pad and batch
      # each field of the dataset structure to whatever size is necessary.
      ds = ds.padded_batch(25, ds.output_shapes)
      
      ds = ds.repeat(num_epochs)

      
      # Return the next batch of data.
      features, labels = ds.make_one_shot_iterator().get_next()
      return features, labels

    #Tarea 1: usar un modelo lineal con entradas dispersas y un vocabulario explícito

    #Para nuestro primer modelo, construiremos un modelo LinearClassifier usando 50 términos informativos

    # 50 informative terms that compose our model vocabulary 
    informative_terms = ("bad", "great", "best", "worst", "fun", "beautiful",
                         "excellent", "poor", "boring", "awful", "terrible",
                         "definitely", "perfect", "liked", "worse", "waste",
                         "entertaining", "loved", "unfortunately", "amazing",
                         "enjoyed", "favorite", "horrible", "brilliant", "highly",
                         "simple", "annoying", "today", "hilarious", "enjoyable",
                         "dull", "fantastic", "poorly", "fails", "disappointing",
                         "disappointment", "not", "him", "her", "good", "time",
                         "?", ".", "!", "movie", "film", "action", "comedy",
                         "drama", "family")

    terms_feature_column = tf.feature_column.categorical_column_with_vocabulary_list(key="terms", vocabulary_list=informative_terms)

    #A continuación, construiremos el LinearClassifier, lo entrenaremos en el conjunto de entrenamiento y lo evaluaremos en el 
    #conjunto de evaluación. 

    my_optimizer = tf.train.AdagradOptimizer(learning_rate=0.1)
    my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)

    feature_columns = [ terms_feature_column ]


    classifier = tf.estimator.LinearClassifier(
      feature_columns=feature_columns,
      optimizer=my_optimizer,
    )

    classifier.train(
      input_fn=lambda: _input_fn([train_path]),
      steps=1000)

    evaluation_metrics = classifier.evaluate(
      input_fn=lambda: _input_fn([train_path]),
      steps=1000)
    print("Valores conjunto entrenamiento:")
    for m in evaluation_metrics:
      print(m, evaluation_metrics[m])
    print("---")

    evaluation_metrics = classifier.evaluate(
      input_fn=lambda: _input_fn([test_path]),
      steps=1000)

    print("Valores conjunto validación:")
    for m in evaluation_metrics:
      print(m, evaluation_metrics[m])
    print("---")


    #Tarea 2: usar un modelo de red neuronal profunda (DNN)

    ##################### Here's what we changed ##################################
    classifier = tf.estimator.DNNClassifier(                                      #
      feature_columns=[tf.feature_column.indicator_column(terms_feature_column)], #
      hidden_units=[20,20],                                                       #
      optimizer=my_optimizer,                                                     #
    )                                                                             #
    ###############################################################################

    try:
      classifier.train(
        input_fn=lambda: _input_fn([train_path]),
        steps=1000)

      evaluation_metrics = classifier.evaluate(
        input_fn=lambda: _input_fn([train_path]),
        steps=1)
      print("Valores conjunto entrenamiento:")
      for m in evaluation_metrics:
        print(m, evaluation_metrics[m])
      print("---")

      evaluation_metrics = classifier.evaluate(
        input_fn=lambda: _input_fn([test_path]),
        steps=1)

      print("Valores conjunto validación:")
      for m in evaluation_metrics:
        print(m, evaluation_metrics[m])
      print("---")
    except ValueError as err:
      print(err)
      

    #Tarea 3: usar una incrustación con un modelo DNN
    #Una columna incrustada toma datos escasos como entrada y devuelve un vector denso de dimensión inferior como salida.
    #En el siguiente código, haga lo siguiente:
        #Defina las columnas de características para el modelo utilizando una columna de incrustación que proyecta los datos en 
        #2 dimensiones.
        #Defina un DNNClassifier con las siguientes especificaciones:
            #Dos capas ocultas de 20 unidades cada una.
            #Optimización de Adagrad con una tasa de aprendizaje de 0,1.
            #Un gradient_clip_norm de 5.0
            
    ########################## SOLUTION CODE ########################################
    terms_embedding_column = tf.feature_column.embedding_column(terms_feature_column, dimension=2)
    feature_columns = [ terms_embedding_column ]

    my_optimizer = tf.train.AdagradOptimizer(learning_rate=0.1)
    my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)

    classifier = tf.estimator.DNNClassifier(
      feature_columns=feature_columns,
      hidden_units=[20,20],
      optimizer=my_optimizer
    )
    #################################################################################

    classifier.train(
      input_fn=lambda: _input_fn([train_path]),
      steps=1000)

    evaluation_metrics = classifier.evaluate(
      input_fn=lambda: _input_fn([train_path]),
      steps=1000)
    print("Valores conjunto entrenamiento:")
    for m in evaluation_metrics:
      print(m, evaluation_metrics[m])
    print("---")

    evaluation_metrics = classifier.evaluate(
      input_fn=lambda: _input_fn([test_path]),
      steps=1000)

    print("Valores conjunto validación:")
    for m in evaluation_metrics:
      print(m, evaluation_metrics[m])
    print("---")

    #Tarea 5: Examinar la incrustación
    # 1 Ejecute el siguiente código para ver la inserción que entrenamos en la Tarea 3. 
    # 2 Vuelva a entrenar el modelo volviendo a ejecutar el código en la Tarea 3, y luego vuelva a ejecutar 
    # 3 Finalmente, vuelva a entrenar el modelo nuevamente usando solo 10 pasos 

    import numpy as np
    import matplotlib.pyplot as plt

    embedding_matrix = classifier.get_variable_value('dnn/input_from_feature_columns/input_layer/terms_embedding/embedding_weights')

    for term_index in range(len(informative_terms)):
      # Create a one-hot encoding for our term. It has 0s everywhere, except for
      # a single 1 in the coordinate that corresponds to that term.
      term_vector = np.zeros(len(informative_terms))
      term_vector[term_index] = 1
      # We'll now project that one-hot vector into the embedding space.
      embedding_xy = np.matmul(term_vector, embedding_matrix)
      plt.text(embedding_xy[0],
               embedding_xy[1],
               informative_terms[term_index])

    # Do a little setup to make sure the plot displays nicely.
    plt.rcParams["figure.figsize"] = (15, 15)
    plt.xlim(1.2 * embedding_matrix.min(), 1.2 * embedding_matrix.max())
    plt.ylim(1.2 * embedding_matrix.min(), 1.2 * embedding_matrix.max())
    plt.show() 

    #Tarea 6: tratar de mejorar el rendimiento del modelo
    # Download the vocabulary file.
    terms_url = 'https://download.mlcc.google.com/mledu-datasets/sparse-data-embedding/terms.txt'
    terms_path = tf.keras.utils.get_file(terms_url.split('/')[-1], terms_url)

    # Create a feature column from "terms", using a full vocabulary file.
    informative_terms = None
    with io.open(terms_path, 'r', encoding='utf8') as f:
      # Convert it to a set first to remove duplicates.
      informative_terms = list(set(f.read().split()))
      
    terms_feature_column = tf.feature_column.categorical_column_with_vocabulary_list(key="terms", 
                                                                                     vocabulary_list=informative_terms)

    terms_embedding_column = tf.feature_column.embedding_column(terms_feature_column, dimension=2)
    feature_columns = [ terms_embedding_column ]

    my_optimizer = tf.train.AdagradOptimizer(learning_rate=0.1)
    my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)

    classifier = tf.estimator.DNNClassifier(
      feature_columns=feature_columns,
      hidden_units=[10,10],
      optimizer=my_optimizer
    )

    classifier.train(
      input_fn=lambda: _input_fn([train_path]),
      steps=1000)

    evaluation_metrics = classifier.evaluate(
      input_fn=lambda: _input_fn([train_path]),
      steps=1000)
    print("Training set metrics:")
    for m in evaluation_metrics:
      print(m, evaluation_metrics[m])
    print("---")

    evaluation_metrics = classifier.evaluate(
      input_fn=lambda: _input_fn([test_path]),
      steps=1000)

    print("Test set metrics:")
    for m in evaluation_metrics:
      print(m, evaluation_metrics[m])
    print("---")

    Curso Tensorflow con Anaconda -17 Redes neuronales de clases múltiples

    17 Redes neuronales de clases múltiples

    • En vídeos anteriores, presentamos modelos de clasificación binaria que podían elegir una de dos opciones posibles, como el caso en el que distinguimos si un correo electrónico dado "es spam" o "no es spam". En este vídeo, investigaremos la clasificación de clases múltiples, que puedes elegir entre posibilidades múltiples. Por ejemplo:
      • ¿Este perro es un beagle, un basset hound o un sabueso?
      • ¿Esta flor es una iris sibirica, hollandica, versicolor o setosa?
      • Algunos problemas de clases múltiples del mundo real implican elegir entre millones de clases individuales.Por ejemplo, supongamos un modelo de clasificación de clases múltiples que pueda identificar la imagen de lo que fuera.
    • En la imagen vemos un ejemplo de "uno frente a todos", que es un enfoque que nos proporciona una mane
    • ra de aprovechar la clasificación binaria. En un problema de clasificación dado con N soluciones posibles, una solución de uno frente a todos consiste en N clasificadores binarios independientes.


    • Otro posible enfoque es utilizar Softmax. La regresión logística genera un decimal entre 0 y 1.0. Por ejemplo, si un clasificador de correo electrónico tiene un resultado de  regresión logística de 0.8, hay un 80% de posibilidad de que un correo electrónico sea spam y un 20% de que no lo sea. La suma de las probabilidades de que un correo electrónico sea spam o no es 1.0.
    • Softmax lleva esta idea al plano de las clases múltiples. Es decir, softmax asigna probabilidades decimales a cada clase en un caso de clases múltiples. Esas probabilidades decimales deben sumar 1.0. Esta restricción adicional permite que el entrenamiento converja más rápido.
    • Os dejo un vídeo donde os cuento todo esto:



    • Os dejo el código visto en el vídeo:
    #Capacitar a un modelo lineal y una red neuronal para clasificar los dígitos escritos a mano.
    """
    Primero, descargamos el conjunto de datos, importemos TensorFlow y otras utilidades, y carguemos los datos en un dataframe. """

    from __future__ import print_function

    import glob
    import math
    import os

    from IPython import display
    from matplotlib import cm
    from matplotlib import gridspec
    from matplotlib import pyplot as plt
    import numpy as np
    import pandas as pd
    import seaborn as sns
    from sklearn import metrics
    import tensorflow as tf
    from tensorflow.python.data import Dataset

    tf.logging.set_verbosity(tf.logging.ERROR)
    pd.options.display.max_rows = 10
    pd.options.display.float_format = '{:.1f}'.format

    mnist_dataframe = pd.read_csv(
      "https://download.mlcc.google.com/mledu-datasets/mnist_train_small.csv",
      sep=",",
      header=None)

    # Usamos los primeros 10,000 registros de entrenamiento y validación.
    mnist_dataframe = mnist_dataframe.head(10000)

    mnist_dataframe = mnist_dataframe.reindex(np.random.permutation(mnist_dataframe.index))
    mnist_dataframe.head()

    """Las columnas 1 a 784 contienen los valores de características, uno por píxel para los valores de 28 × 28 = 784 píxeles.
    Los valores de los píxeles están en una escala de grises en la que 0 representa blanco, 255 representa negro y 
    los valores entre 0 y 255 representan tonos de gris. 
    La mayoría de los valores de píxeles son 0 pero no todos son cero"""
    mnist_dataframe.loc[:, 120:130]

    # Ahora, analicemos las etiquetas y características y veamos algunos ejemplos
    def parse_labels_and_features(dataset):
      """Extraemos de etiquetas y características.
      Función para escalar o transformar las funciones si es necesario.
      
      Args:
        dataset: `Dataframe`, que contiene la etiqueta en la primera columna y
           valores de píxeles monocromos en las columnas restantes, en orden mayor de fila.
      Returns:
        Una `tupla` `(labels, features)`:
          labels: Devuelve una serie panda
          características: Devuelve un dataframe
      """
      labels = dataset[0]
      features = dataset.loc[:,1:784]
      # Escalamos para que los valores esten entre 0 y 1
      features = features / 255

      return labels, features

    training_targets, training_examples = parse_labels_and_features(mnist_dataframe[:7500])
    training_examples.describe()
    validation_targets, validation_examples = parse_labels_and_features(mnist_dataframe[7500:10000])
    validation_examples.describe()

    #Ejemplo aleatorio y su etiqueta correspondiente.
    rand_example = np.random.choice(training_examples.index)
    _, ax = plt.subplots()
    ax.matshow(training_examples.loc[rand_example].values.reshape(28, 28))
    ax.set_title("Label: %i" % training_targets.loc[rand_example])
    ax.grid(False)

    """Tarea 1: construir un modelo lineal para MNIST
    Primero, vamos a crear un modelo de línea base para comparar.
    El LinearClassifier proporciona un conjunto de k clasificadores de uno contra todos, uno para cada una de las k clases.
    Mostramos una matriz de confusión. La matriz de confusión muestra qué clases se clasificaron erróneamente. 
    También tenga en cuenta que rastreamos el error del modelo usando la función log_loss.
    Esto no debe confundirse con la función de pérdida interna de LinearClassifier que se utiliza para el entrenamiento."""

    def construct_feature_columns():
      """Construye las columnas de la característica TensorFlow.

      Returns:
       Una columna de características de 784 pixeles
      """ 
      
      return set([tf.feature_column.numeric_column('pixels', shape=784)])


    #Creamos funciones de entrada separadas para entrenamiento y para predicción: create_training_input_fn () y 
    #create_predict_input_fn ().Podemos invocar estas funciones para devolver las _input_fns correspondientes para 
    #que pasen a nuestras llamadas .train () y .predict ().

    def create_training_input_fn(features, labels, batch_size, num_epochs=None, shuffle=True):
      """Un input_fn personalizado para enviar datos.
      Args:
        features: Características de entrenamiento.
        labels: Etiquetas de entrenamiento.
        batch_size: Tamaño de lote para usar durante el entrenamiento.

      Returns:
       Una función que devuelve lotes de características de entrenamiento y etiquetas durante el entrenamiento
      """
      def _input_fn(num_epochs=None, shuffle=True):
        # Las entradas son reseteadas en cada llamada a to .train(). Para asegurar el modelo
        # obtiene una buena muestra de datos, incluso cuando el número de pasos es pequeño,
        # mezcla todos los datos antes de crear el objeto Dataset
        idx = np.random.permutation(features.index)
        raw_features = {"pixels":features.reindex(idx)}
        raw_targets = np.array(labels[idx])
       
        ds = Dataset.from_tensor_slices((raw_features,raw_targets)) # warning: 2GB limit
        ds = ds.batch(batch_size).repeat(num_epochs)
        
        if shuffle:
          ds = ds.shuffle(10000)
        
        # Devuelve el siguiente lote de datos.
        feature_batch, label_batch = ds.make_one_shot_iterator().get_next()
        return feature_batch, label_batch

      return _input_fn

    def create_predict_input_fn(features, labels, batch_size):
      """Un input_fn personalizado para enviar datos mnist al estimador para predicciones.

      Args:
        features: Características para predicciones
        labels: Las etiquetas de los ejemplos de predicción.

      Returns:
        Una función que devuelve características y etiquetas para predicciones.
      """
      def _input_fn():
        raw_features = {"pixels": features.values}
        raw_targets = np.array(labels)
        
        ds = Dataset.from_tensor_slices((raw_features, raw_targets)) # warning: 2GB limit
        ds = ds.batch(batch_size)
        
            
        # Devolvemos el siguiente lote de datos
        feature_batch, label_batch = ds.make_one_shot_iterator().get_next()
        return feature_batch, label_batch

      return _input_fn

    def train_linear_classification_model(
        learning_rate,
        steps,
        batch_size,
        training_examples,
        training_targets,
        validation_examples,
        validation_targets):
      """Entrena un modelo de clasificación lineal para el conjunto de datos de dígitos MNIST.
      
        Además del enrenamiento, esta función también imprime información sobre el progreso de dicho entrenamiento,
       Un gráfico de la pérdida de entrenamiento y validación en el tiempo, y una matriz de confuciónn.
      
      Args:
        learning_rate: A `float`, the learning rate to use.
        steps: A non-zero `int`, the total number of training steps. A training step
          consists of a forward and backward pass using a single batch.
        batch_size: A non-zero `int`, the batch size.
        training_examples: A `DataFrame` containing the training features.
        training_targets: A `DataFrame` containing the training labels.
        validation_examples: A `DataFrame` containing the validation features.
        validation_targets: A `DataFrame` containing the validation labels.
          
      Returns:
        El objeto `LinearClassifier` entrenado.
      """

      periods = 10

      steps_per_period = steps / periods  
      # Creamos las funciones de entrada
      predict_training_input_fn = create_predict_input_fn(
        training_examples, training_targets, batch_size)
      predict_validation_input_fn = create_predict_input_fn(
        validation_examples, validation_targets, batch_size)
      training_input_fn = create_training_input_fn(
        training_examples, training_targets, batch_size)
      
      # Creamos el objeto LinearClassifier.
      my_optimizer = tf.train.AdagradOptimizer(learning_rate=learning_rate)
      my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)
      classifier = tf.estimator.LinearClassifier(
          feature_columns=construct_feature_columns(),
          n_classes=10,
          optimizer=my_optimizer,
          config=tf.estimator.RunConfig(keep_checkpoint_max=1)
      )

      # Entrene al modelo, pero hágalo dentro de un bucle para que podamos evaluar periódicamente
      print("Entrenando el modelo...")
      print("LogLoss error en datos de valdación:")
      training_errors = []
      validation_errors = []
      for period in range (0, periods):
        # Entrenamos al modelo desde el estado anterior
        classifier.train(
            input_fn=training_input_fn,
            steps=steps_per_period
        )
      
        #Calculamos probabilidades
        training_predictions = list(classifier.predict(input_fn=predict_training_input_fn))
        training_probabilities = np.array([item['probabilities'] for item in training_predictions])
        training_pred_class_id = np.array([item['class_ids'][0] for item in training_predictions])
        training_pred_one_hot = tf.keras.utils.to_categorical(training_pred_class_id,10)
            
        validation_predictions = list(classifier.predict(input_fn=predict_validation_input_fn))
        validation_probabilities = np.array([item['probabilities'] for item in validation_predictions])    
        validation_pred_class_id = np.array([item['class_ids'][0] for item in validation_predictions])
        validation_pred_one_hot = tf.keras.utils.to_categorical(validation_pred_class_id,10)    
        
        # Calcular los errores de entrenamiento y validación.
        training_log_loss = metrics.log_loss(training_targets, training_pred_one_hot)
        validation_log_loss = metrics.log_loss(validation_targets, validation_pred_one_hot)
        # De vez en cuando imprimir la pérdida actual.
        print("  period %02d : %0.2f" % (period, validation_log_loss))
        # Agrega las métricas de pérdida de este período a nuestra lista.
        training_errors.append(training_log_loss)
        validation_errors.append(validation_log_loss)
      print("Entrenamiento del modelo finalizazo.")
      # Eliminar archivos de eventos para ahorrar espacio en disco.
      _ = map(os.remove, glob.glob(os.path.join(classifier.model_dir, 'events.out.tfevents*')))
      
      # Calcule las predicciones finales
      final_predictions = classifier.predict(input_fn=predict_validation_input_fn)
      final_predictions = np.array([item['class_ids'][0] for item in final_predictions])
      
      
      accuracy = metrics.accuracy_score(validation_targets, final_predictions)
      print("Exactitud final (on validation data): %0.2f" % accuracy)

      # Genera una gráfica de métricas de pérdida en periodos.
      plt.ylabel("LogLoss")
      plt.xlabel("Periodos")
      plt.title("LogLoss vs. Periodos")
      plt.plot(training_errors, label="training")
      plt.plot(validation_errors, label="validation")
      plt.legend()
      plt.show()
      
      # Pintamos la matriz de confusión
      cm = metrics.confusion_matrix(validation_targets, final_predictions)
      # Normalizamos la matriz de confusión por fila.
      cm_normalized = cm.astype("float") / cm.sum(axis=1)[:, np.newaxis]
      ax = sns.heatmap(cm_normalized, cmap="bone_r")
      ax.set_aspect(1)
      plt.title("Confusion matriz")
      plt.ylabel("Etiqueta verdadera")
      plt.xlabel("Etiqueta predicción")
      plt.show()

      return classifier

    _ = train_linear_classification_model(
        learning_rate=0.03,
        steps=1000,
        batch_size=30,
        training_examples=training_examples,
        training_targets=training_targets,
        validation_examples=validation_examples,
        validation_targets=validation_targets)

    """Tarea 2: reemplazar el clasificador lineal con una red neuronal
    Reemplace el LinearClassifier de arriba con un DNNClassifier y encuentre una combinación de parámetros que 
    dé una precisión de 0.95 o más."""

    def train_nn_classification_model(
        learning_rate,
        steps,
        batch_size,
        hidden_units,
        training_examples,
        training_targets,
        validation_examples,
        validation_targets):
      """Entrena un modelo de clasificación de red neuronal para el conjunto de datos de dígitos MNIST.
      
        Además del enrenamiento, esta función también imprime información sobre el progreso 
        de dicho entrenamiento,
       Un gráfico de la pérdida de entrenamiento y validación en el tiempo, y una matriz de confusiónn.
      
      Args:
        learning_rate: A `float`, the learning rate to use.
        steps: A non-zero `int`, the total number of training steps. A training step
          consists of a forward and backward pass using a single batch.
        batch_size: A non-zero `int`, the batch size.
        hidden_units: A `list` of int values, specifying the number of neurons in each layer.
        training_examples: A `DataFrame` containing the training features.
        training_targets: A `DataFrame` containing the training labels.
        validation_examples: A `DataFrame` containing the validation features.
        validation_targets: A `DataFrame` containing the validation labels.
          
      Returns:
        El objeto  `DNNClassifier` .
      """

      periods = 10
      # Precaución: las entradasse restablecen con cada llamada.
      # Si el número de pasos es pequeño, es posible que su modelo nunca vea la mayoría de los datos. 
      # Así que con múltiples llamadas `.train`  es posible que desee controlar la longitud

      steps_per_period = steps / periods  
      
        # Creamos las funciones de entrada
      predict_training_input_fn = create_predict_input_fn(
        training_examples, training_targets, batch_size)
      predict_validation_input_fn = create_predict_input_fn(
        validation_examples, validation_targets, batch_size)
      training_input_fn = create_training_input_fn(
        training_examples, training_targets, batch_size)
      
      # Creamos las funciones de entrada
      predict_training_input_fn = create_predict_input_fn(
        training_examples, training_targets, batch_size)
      predict_validation_input_fn = create_predict_input_fn(
        validation_examples, validation_targets, batch_size)
      training_input_fn = create_training_input_fn(
        training_examples, training_targets, batch_size)
      
      # Creamos las columnas
      feature_columns = [tf.feature_column.numeric_column('pixels', shape=784)]

      #objeto DNNClassifier.
      my_optimizer = tf.train.AdagradOptimizer(learning_rate=learning_rate)
      my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)
      classifier = tf.estimator.DNNClassifier(
          feature_columns=feature_columns,
          n_classes=10,
          hidden_units=hidden_units,
          optimizer=my_optimizer,
          config=tf.contrib.learn.RunConfig(keep_checkpoint_max=1)
      )

      # Entrene al modelo, pero hágalo dentro de un bucle para que podamos evaluar periódicamente
      print("Training model...")
      print("LogLoss error (on validation data):")
      training_errors = []
      validation_errors = []
      for period in range (0, periods):
        #Entrena el modelo, partiendo del estado anterior.
        classifier.train(
            input_fn=training_input_fn,
            steps=steps_per_period
        )
      
          #Calculamos probabilidades
        training_predictions = list(classifier.predict(input_fn=predict_training_input_fn))
        training_probabilities = np.array([item['probabilities'] for item in training_predictions])
        training_pred_class_id = np.array([item['class_ids'][0] for item in training_predictions])
        training_pred_one_hot = tf.keras.utils.to_categorical(training_pred_class_id,10)
            
        validation_predictions = list(classifier.predict(input_fn=predict_validation_input_fn))
        validation_probabilities = np.array([item['probabilities'] for item in validation_predictions])    
        validation_pred_class_id = np.array([item['class_ids'][0] for item in validation_predictions])
        validation_pred_one_hot = tf.keras.utils.to_categorical(validation_pred_class_id,10)    
        
         # Calcular los errores de entrenamiento y validación.
        training_log_loss = metrics.log_loss(training_targets, training_pred_one_hot)
        validation_log_loss = metrics.log_loss(validation_targets, validation_pred_one_hot)
         # De vez en cuando imprimir la pérdida actual.
        print("  period %02d : %0.2f" % (period, validation_log_loss))
         # Agrega las métricas de pérdida de este período a nuestra lista.
        training_errors.append(training_log_loss)
        validation_errors.append(validation_log_loss)
      print("Entrenamiento del modelo finalizado.")
     # Eliminar archivos de eventos para ahorrar espacio en disco.
      _ = map(os.remove, glob.glob(os.path.join(classifier.model_dir, 'events.out.tfevents*')))
      
      # Calculamos las predicciones finales
      final_predictions = classifier.predict(input_fn=predict_validation_input_fn)
      final_predictions = np.array([item['class_ids'][0] for item in final_predictions])
      
      
      accuracy = metrics.accuracy_score(validation_targets, final_predictions)
      print("Exactitud final (on validation data): %0.2f" % accuracy)

      # Genera una gráfica de métricas de pérdida en periodos.
      plt.ylabel("LogLoss")
      plt.xlabel("Periodos")
      plt.title("LogLoss vs. Periodos")
      plt.plot(training_errors, label="training")
      plt.plot(validation_errors, label="validation")
      plt.legend()
      plt.show()
      
       # Pintamos la matriz de confusión# Pintamos la matriz de confusión
      cm = metrics.confusion_matrix(validation_targets, final_predictions)

        #Normalizamos
      cm_normalized = cm.astype("float") / cm.sum(axis=1)[:, np.newaxis]
      ax = sns.heatmap(cm_normalized, cmap="bone_r")
      ax.set_aspect(1)
      plt.title("Confusion matriz")
      plt.ylabel("Etiqueta verdadera")
      plt.xlabel("Etiqueta predicción")
      plt.show()

      return classifier
    classifier = train_nn_classification_model(
        learning_rate=0.05,
        steps=1000,
        batch_size=30,
        hidden_units=[100, 100],
        training_examples=training_examples,
        training_targets=training_targets,
        validation_examples=validation_examples,
        validation_targets=validation_targets)

    predict_test_input_fn = create_predict_input_fn(
        test_examples, test_targets, batch_size=100)

    test_predictions = classifier.predict(input_fn=predict_test_input_fn)
    test_predictions = np.array([item['class_ids'][0] for item in test_predictions])
      
    accuracy = metrics.accuracy_score(test_targets, test_predictions)
    print("Accuracy on test data: %0.2f" % accuracy)

    """Tarea 3: Visualizar los pesos de la primera capa oculta.
    Tomemos unos minutos para profundizar en nuestra red neuronal
    y ver lo que ha aprendido al acceder al atributo de peso_ de
    nuestro modelo.
    La capa de entrada de nuestro modelo tiene 784 pesos correspondientes a las imágenes de entrada de 28 × 28 píxeles. 
    La primera capa oculta tendrá 784 × N pesos, donde N es el número de nodos en esa capa. 
    Podemos volver a convertir esos pesos en imágenes 28 × 28 cambiando cada una de las matrices N 1 × 784 de pesos 
    en matrices N de tamaño 28 × 28."""

    print(classifier.get_variable_names())

    weights0 = classifier.get_variable_value("dnn/hiddenlayer_0/kernel")

    print("weights0 shape:", weights0.shape)

    num_nodes = weights0.shape[1]
    num_rows = int(math.ceil(num_nodes / 10.0))
    fig, axes = plt.subplots(num_rows, 10, figsize=(20, 2 * num_rows))
    for coef, ax in zip(weights0.T, axes.ravel()):
        # Weights in coef is reshaped from 1x784 to 28x28.
        ax.matshow(coef.reshape(28, 28), cmap=plt.cm.pink)
        ax.set_xticks(())
        ax.set_yticks(())

    plt.show()

    Curso .NET Core en C# - 34.Creamos nuestro propio log

    34.Creamos nuestro propio log Hola a todos. En este curso, analizaremos todos los conceptos básicos, intermedios y avanzados de  ASP.NET...