sábado, 17 de septiembre de 2022

Archivos externos de recursos resx en .NET

Para no tener que recompilar un proyecto cuando cambian ciertas condiciones (rutas, ubicaciones, etc) conviene almacenar algunas variables en un archivo externo de recursos .resx donde podremos modificar manualmente dichas variables sin tener que recompilar de nuevo el proyecto.

1ª Opción

En nuestro proyecto, elegimos proyecto -> propiedades

 

Archivos externos de recursos resx en .NET

Vamos a la última pestaña de recursos y pulsamos sobre “Este proyecto no contiene un archivo de recursos predeterminado….”

 

Este proyecto no contiene un archivo de recursos predeterminado

Esta acción, nos abre una pantalla de recursos donde podemos introducir la declaración de variables y sus valores correspondientes

 

declaración de variables y sus valores correspondientes

Hecho esto, no es necesario que declaremos dichas variables en el código, podemos referirnos a ellas desde nuestro código tecleando My.Resources.[Nombre_Variable]

Estas definiciones se encuentran en la carpeta My Project del explorador de soluciones

 

carpeta My Project del explorador de soluciones

Podemos ir al directorio de nuestro proyecto y en la carpeta My Project encontraremos un archivo llamado Resources.resx donde se encuentran definidas nuestras variables, podemos modificar sus valore directamente en el archivo abriéndolo con un editor, por ejemplo notepad++


notepad++


Y al final del archivo aparecen nuestras definiciones donde podemos cambiar los valores sin necesidad de recompilar el proyecto

 

definiciones donde podemos cambiar los valores

En este ejemplo hemos utilizado rutas, pero si no escribimos bien la ruta puede dar error, porque en realidad leerá C:\Ruta_Aplicacion\C:\PRUEBAS Hay que estar atentos a ver que parte de la ruta ponemos, podemos poner por ejemplo en vez de C:\PRUEBAS poner sólo pruebas, y el programa lo añadirá a la ruta de la aplicación, pero si queremos una ruta diferente de la aplicación podemos utilizar la segunda opción.

2ª Opción

Otra solución consiste en añadir un archivo de configuración app.config o settings. En el explorador de soluciones con el botón derecho del ratón pulsamos Agregar -> Nuevo elemento

app.config o settings


Sobre la pestaña General de Elementos comunes, elegimos Archivo de configuración 


Pestaña General de Elementos comunes

Ahora nos sale una pantalla donde podemos elegir el nombre de la variable y su valor

 

Archivo de configuración

Si el código creado automáticamente no funciona, podemos editarlo manualmente y dejarlo de este modo:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

     <configSections>

          <sectionGroup name="applicationSettings"

                      type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >

 

                <section name="Nombre_de_tu_Proyecto.Properties.Settings"

                     type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

                     requirePermission="false" />

 

          </sectionGroup>

     </configSections>

   

     <appSettings>

          <!--Directorio de entrada de los ficheros-->

          <add key="dirEntrada" value="C:\Pruebas" />

          <!--Directorio de salida para el fichero una vez unido-->

          <add key="dirSalida" value="C:\Pruebas\Out" />

          <!--Directorio donde se deja la copia del original-->

          <add key="dirCopiaOriginal" value="C:\Pruebas\Original" />

          <add key="dirTemporal" value="C:\Pruebas\TEMPORAL" />

          <!--Posicion final e inicial de coincidencia de archivos-->

          <add key="posInicial" value= "1" />

          <add key="posFinal" value= "1" />

     </appSettings>

</configuration>


Luego en el código le llamamos así a las variables definidas.

Dim dirEntrada As String = ConfigurationManager.AppSettings("dirEntrada").ToString()

Para que el código nos reconozca las instrucciones de llamada a ConfigurationManage, es importante importar antes la librería System.Configuration

Imports System.Configuration

Si aun así no funciona, es posible que tengamos que instalar el paquete System.Configuration desde nuget, para ello sobre el error pulsamos en Mostrar posibles correcciones del error.

Mostrar posibles correcciones del error.


Esto nos despliega un combo con las diferentes opciones, elegimos Instalar Paquete “System.ConfigurationManager” -> Buscar e instalar la última versión

 

Instalar Paquete “System.ConfigurationManager” -> Buscar e instalar la última versión

Ahora ya podemos editar el archivo app.config o settings para cambiar los valores de las variables definidas, sin necesidad de recompilar el proyecto cada vez.


sábado, 10 de septiembre de 2022

Programación de la tasa de aprendizaje (redes neuronales profundas)

Ya vimos algo de teoría sobre este temaPodemos encontrar una buena tasa de aprendizaje entrenando nuestro modelo durante unos pocos cientos de iteraciones aumentando exponencialmente la tasa de aprendizaje desde un valor pequeño a uno muy grande y observando la tasa de aprendizaje mientras tomamos cada vez una tasa de aprendizaje ligeramente más pequeña y lo entrenamos de nuevo.

Pero podemos hacerlo mejor que con una tasa de aprendizaje constante: si comenzamos con una tasa de aprendizaje grande y la reducimos en cada iteración, tendremos un progreso más rápido. 

Podemos ver diferentes técnicas y sus ejecuciones comparadas en este paperY también podemos consultar la técnica de programación de un ciclo ( 1 cycle Scheduling).

A continuación vamos a implementar algunas de estas técnicas con Keras.

Se muestra el proyecto completo igual que en entrada anterior , en gris el código y en color la parte necesaria para este ejemplo.

En el caso de la programación potente (Power scheduling) se puede implementar fácilmente con Keras simplemente con la línea 

optimizer = keras.optimizers.SGD(lr=0.01, decay=1e-4)

Esta línea inicializa el valor del hiperparámetro decay cuando creamos el optimizador. El hiperparámetro decay es la inversa de s (el número de pasos que resulta de dividir la tasa de aprendizaje por más de una unidad)

# Python ≥3.5

import sys

assert sys.version_info >= (3, 5)

 

# Scikit-Learn ≥0.20

import sklearn

assert sklearn.__version__ >= "0.20"

 

try:

    # %tensorflow_version solo existe en Colab.

    %tensorflow_version 2.x

except Exception:

    pass

 

# TensorFlow ≥2.0

import tensorflow as tf

assert tf.__version__ >= "2.0"

 

# importaciones comunes

import numpy as np

import os

 

# para hacer este cuaderno estable

np.random.seed(42)

 

import tensorflow as tf

from tensorflow import keras

 

#importamos nuestro dataset

import pandas as pd

quinielas = pd.read_csv('Completo_Etiquetado_Puntuado_3.csv') #tiene goles quiniela y quinigol

quinielas.head()

 

#las X contienen los datos relevantes para hacer predicciones quitamos todas las etiquetas

#dejamos división, jornada, EquipoLocal, EquipoVisitante, PuntosLocal, PuntosVisitante, Puntos_Normalizados

X = tf.cast(quinielas.drop(columns=['idPartido','temporada','golesLocal','golesVisitante','fecha','timestamp','Q1','QX','Q2','QGC0','QGC1','QGC2','QGCM','QGF0','QGF1','QGF2','QGFM']), tf.float64)

#las Y son las etiquetas a predecir, en este caso quitamos todo excepto 'Q1','QX','Q2'

y = tf.cast(quinielas.drop(columns=['division','jornada','idPartido','temporada','PuntosLocal','PuntosVisitante','EquipoLocal','Puntos_Normalizados','EquipoVisitante','QGC0','QGC1','QGC2','QGCM','QGF0','QGF1','QGF2','QGFM','timestamp','golesLocal','golesVisitante','fecha','timestamp']), tf.float64)

 

x_data = np.array(X)

y_data = np.array(y)

 

#dividimos el dataset en una parte de entrenamiento y otra de testeo

train_data = x_data[:29718]

test_data = x_data[29718:]

train_labels = y_data [:29718]

test_labels = y_data [29718:]

 

optimizer = keras.optimizers.SGD(lr=0.01, decay=1e-4)

                          

 

# Normalización por lotes antes de la función de activación

model = keras.models.Sequential([

    keras.layers.BatchNormalization(),

    keras.layers.Dense(300, use_bias=False),

    keras.layers.BatchNormalization(),

    keras.layers.Activation("relu"),

    keras.layers.Dense(100, use_bias=False),

    keras.layers.BatchNormalization(),

    keras.layers.Activation("relu"),

    keras.layers.Dense(3, activation="softmax")

])

 

model.compile(loss="categorical_crossentropy",

              optimizer="sgd",

              metrics=["accuracy"])

             

#entrenamos y evaluamos el modelo

n_epochs = 25

history = model.fit(train_data, train_labels, epochs=25,

                    validation_data=(test_data , test_labels))

                   

# Para mostrar graficos

%matplotlib inline

import matplotlib as mpl

import matplotlib.pyplot as plt

mpl.rc('axes', labelsize=14)

mpl.rc('xtick', labelsize=12)

mpl.rc('ytick', labelsize=12)

 

learning_rate = 0.01

decay = 1e-4

batch_size = 32

n_steps_per_epoch = len(train_data) // batch_size

epochs = np.arange(n_epochs)

lrs = learning_rate / (1 + decay * epochs * n_steps_per_epoch)

 

plt.plot(epochs, lrs,  "o-")

plt.axis([0, n_epochs - 1, 0, 0.01])

plt.xlabel("Epoch")

plt.ylabel("Learning Rate")

plt.title("Power Scheduling", fontsize=14)

plt.grid(True)

plt.show()

 

         

Programación de la tasa de aprendizaje (redes neuronales profundas)

 
             

Para la programación exponencial (Exponential scheduling) es igual pero  donde poníamos

optimizer = keras.optimizers.SGD(lr=0.01, decay=1e-4)

ponemos:

def exponential_decay_fn(epoch):

    return 0.01 * 0.1**(epoch / 20)

   

def exponential_decay(lr0, s):

    def exponential_decay_fn(epoch):

        return lr0 * 0.1**(epoch / s)

    return exponential_decay_fn

 

exponential_decay_fn = exponential_decay(lr0=0.01, s=20)

Programación de la tasa de aprendizaje (redes neuronales profundas)
Evitando el sobre-entrenamiento a través de la regularización

Las redes neuronales profundas pueden tener miles o incluso millones de parámetros, lo que nos brinda una increíble cantidad de libertad para entrenar una vasta variedad de conjuntos de datos. Pero esta gran cantidad de flexibilidad también convierte la red en propensa al sobre-entrenamiento. Necesitamos regularización.

Dropout

Dropout (Abandono) es una de la técnicas más populares de regularización para redes profundas explicada en este paper de 2012  y este de 2014

El dropout aumenta en un 1-2% la precisión de la red profunda. Puede que un 1 o 2% no nos parezca una mejora muy grande, pero si nuestra red ya tiene un 95% de precisión, aumentar al 97% implica una disminución del error  cercana al 40% (del 5% al 3%).

Se trata de un algoritmo bastante sencillo, en cada paso de entrenamiento, cada neurona, incluyendo las neuronas de entrada, pero siempre excluyendo las neuronas de salida) tiene una probabilidad p de ser temporalmente “abandonada” lo que significa que es ignorada durante el paso de entrenamiento, pero debe ser activada en el siguiente paso. El parámetro p se llama tasa de abandono y está típicamente entre el 10 y el 50% siendo más cercana al 20-30% en las redes neuronales recurrentes y en torno al 40-50% en redes neuronales convolucionales. Después del entrenamiento las neurona no se abandonan más. En principio la técnica parece contraintuitiva, pero esta técnica hace que las neuronas no pueden adaptarse a lo que hagan sus neuronas vecinas, lo que las convierte en lo más útiles posible por si mismas, tampoco pueden confiar excesivamente en las neuronas de entrada por lo que deben poner atención en todas las neuronas de entrada en su conjunto. Al final, la red se hace menos sensible a cambios sutiles en las entradas y al final tenemos una red más robusta y que generaliza mejor.

Para implementar el dropout con Keras podemos utilizar la capa keras.layers.Dropout durante el entrenamiento elimina neuronas de la red de forma aleatoria (las pone a 0) y divide las entradas entre las neuronas restantes. Después del entrenamiento las entradas pasan a la siguiente capa. En este caso hemos tomado un dropout del 20%.        

# Python ≥3.5

import sys

assert sys.version_info >= (3, 5)

 

# Scikit-Learn ≥0.20

import sklearn

assert sklearn.__version__ >= "0.20"

 

try:

    # %tensorflow_version solo existe en Colab.

    %tensorflow_version 2.x

except Exception:

    pass

 

# TensorFlow ≥2.0

import tensorflow as tf

assert tf.__version__ >= "2.0"

 

# importaciones comunes

import numpy as np

import os

 

# para hacer este cuaderno estable

np.random.seed(42)

 

import tensorflow as tf

from tensorflow import keras

 

#utilizamos la inicialización He normal

keras.layers.Dense(10, activation="relu", kernel_initializer="he_normal")

 

init = keras.initializers.VarianceScaling(scale=2., mode='fan_avg',

                                          distribution='uniform')

keras.layers.Dense(10, activation="relu", kernel_initializer=init)

 

#importamos nuestro dataset

import pandas as pd

quinielas = pd.read_csv('Completo_Etiquetado_Puntuado_3.csv') #tiene goles quiniela y quinigol

quinielas.head()

 

#las X contienen los datos relevantes para hacer predicciones quitamos todas las etiquetas

#dejamos división, jornada, EquipoLocal, EquipoVisitante, PuntosLocal, PuntosVisitante, Puntos_Normalizados

X = tf.cast(quinielas.drop(columns=['idPartido','temporada','golesLocal','golesVisitante','fecha','timestamp','Q1','QX','Q2','QGC0','QGC1','QGC2','QGCM','QGF0','QGF1','QGF2','QGFM']), tf.float64)

#las Y son las etiquetas a predecir, en este caso quitamos todo excepto 'Q1','QX','Q2'

y = tf.cast(quinielas.drop(columns=['division','jornada','idPartido','temporada','PuntosLocal','PuntosVisitante','EquipoLocal','Puntos_Normalizados','EquipoVisitante','QGC0','QGC1','QGC2','QGCM','QGF0','QGF1','QGF2','QGFM','timestamp','golesLocal','golesVisitante','fecha','timestamp']), tf.float64)

 

x_data = np.array(X)

y_data = np.array(y)

 

#dividimos el dataset en una parte de entrenamiento y otra de testeo

train_data = x_data[:29718]

test_data = x_data[29718:]

train_labels = y_data [:29718]

test_labels = y_data [29718:]

 

# Dropout

model = keras.models.Sequential([

    keras.layers.Dropout(rate=0.2),

    keras.layers.Dense(300, activation="elu", kernel_initializer="he_normal"),

    keras.layers.Dropout(rate=0.2),

    keras.layers.Dense(100, activation="elu", kernel_initializer="he_normal"),

    keras.layers.Dropout(rate=0.2),

    keras.layers.Dense(3, activation="softmax")

])

 

model.compile(loss="categorical_crossentropy",

              optimizer="sgd",

              metrics=["accuracy"])

             

              #entrenamos y evaluamos el modelo para DROPOUT

n_epochs = 2

history = model.fit(train_data, train_labels, epochs=2,

                    validation_data=(test_data , test_labels))

Si observamos que el modelo sigue sobre-entrenado podemos incrementar la tasa de dropout (abandono) y a la inversa, si vemos que el modelo está sub-entrenado, podemos disminuir la tasa de dropout. También nos puede ser de utilidad aumentar las tasas de dropout en capas con muchas neuronas, y disminuirla en capas con pocas neuronas