sábado, 18 de febrero de 2023

Cambiar una imagen dependiendo de una variable con JasperReport

Queremos que en función del valor de una variable que nos entra por base de datos, se muestre una imagen u otra diferente.

En este caso en nuestra query tenemos un campo llamado Marca, y dependiendo del valor de este campo, AS, LO, AK o TE deberemos mostrar una imagen diferente.

Para hacer esto colocamos un objeto imagen sobre nuestro informe y pulsamos sobre el icono Expresion de la pestaña Image (ver imagen inferior panel derecho abajo)

diferentes imágenes con JasperReport


Nos abre una pantalla donde le ponemos este código. En este caso MARCA es el campo de la query que traerá el valor a discriminar la imagen.

$F{MARCA}.equals("AS") ? "C:/LOGOS/logo_as.jpg" :  $F{MARCA}.equals("LO") ? "C:/LOGOS/Lo_logo.jpg" :  $F{MARCA}.equals("AK") ? "C:/LOGOS/logo_ak.png" :  $F{MARCA}.equals("TE") ? "C:/LOGOS/Te.jpg":"C:/LOGOS/logo_as.jpg"

imágenes variables en JasperReport
Hecho esto en función del valor que traiga el campo MARCA de la query se mostrará una imagen u otra.

sábado, 4 de febrero de 2023

Clasificador binario sencillo con Machine Learning

 Vamos a repetir este clasificador binario  pero en vez de con matrices de imágenes con un dataset sencillo numérico.

Dado un listado numérico (en este caso precipitaciones de una estación meteorológica) deberemos clasificarlas como año normal, si la precipitación está entre 300 mm anuales y 600 mm anuales y como extraordinario si la precipitación está por encima o por debajo de estos valores.

Si te gusta esta imagen

Hacer esto con Machine Learning es matar moscas a cañonazos, no tiene mucho sentido utilizar ML para clasificar esta serie numérica si supera o no cierto rango. Este tutorial tiene exclusivamente carácter didáctico pues para hacer esto bastaría un programa  tradicional con un simple if valor < 300 or valor > 600 then “extraordinario” else “normal”.



ML no trabaja con cadenas de texto, así que convertiremos ‘NORMAL’ en 0 y ‘EXTRAORDINARIO’ en 1.

El objetivo de hacer esto en ML es simplificar el dataset y utilizar uno simplemente numérico en vez de uno matricial como puede ser el dataset MNIST,  para centrarnos exclusivamente en el proceso de ML y no perdernos en tecnicismos de tratamiento de matrices.

Hay que asegurarse de que nuestro Excel genere los .csv con comas, pues puede estar configurado (sobre todo en castellano) con punto y coma ‘;‘ para no confundirlo con las comas ‘,’  decimales. Para evitar problemas, sustituiremos las comas decimales ‘,’ por puntos ‘.’ Y posteriormente sustituiremos los punto y coma ‘;’ por comas ‘,’ de este modo el intérprete de Jupyter ya leerá correctamente nuestro archivo .csv.

#Es necesaria una versión superior a Python 3.5

import sys

assert sys.version_info >= (3, 5)

 

# Es necesaria una versión de Scikit-Learn superior a ≥0.20

import sklearn

assert sklearn.__version__ >= "0.20"

 

# importaciones communes

import numpy as np

import os

 

# para hacer que la salida de este código sea estable en todas las ejecuciones

np.random.seed(42)

 

Ahora cargamos nuestrodataset, en este caso hemos creado un simple fichero .csv con un Excel en el que hemos puesto datos aleatorios y los hemos etiquetado como normal o extraordinario según los requisitos establecidos.

import warnings

warnings.filterwarnings('ignore')

Importamos la biblioteca pandas que utilizaremos para cargar los datos de un archivo CSV en un Dataset de pandas. Para que pueda leerlo el fichero debe colocarse en el raíz de nuestro proyecto, en este caso C:\Users\MI_NOMBRE\VE_TENSOR_FLOW. Para evitar errores no poner caracteres acentuados en los nombres de las columnas del csv.

import pandas as pd

caracter_precipitaciones = pd.read_csv(Caracter_Precipitaciones.csv)

caracter_precipitaciones.info

Esta última expresión debe devolvernos dos columnas, si no así es que el dataset no está bien creado.

Vamos a dividir el dataset en una parte de entrenamiento y otra de testeo, para entrenar nuestro algoritmo vamos utilizar el 90% de los datos que contiene como entrenamiento y lo testearemos con el 10% restante y despuñes con nuestro dataset aparte. Con el objetivo de aprender a utilizar nuestra red entrenada.

Antes de entrenar nuestra red neuronal, eliminamos la columna con las etiquetas, la que dice si es normal o extraordinario. De modo que nos quede la X con los datos y la Y con las etiquetas.

X = caracter_precipitaciones.drop('caracter', axis=1)

Y = caracter_precipitaciones['caracter']

Clasificadores binarios

Vamos a hacer un clasificador binario entre la etiqueta “Normal” (cero) y la etiqueta “Excepcional” (uno). Tomaremos sólo uno de los dos valores.

Elegiremos un clasificador binario y lo entrenamos. Para empezar comenzaremos con un clasificador de descenso de gradiente estocástico, utilizaremos SGDClassifier de Scikit-Learn, este clasificador de ser capaz de tratar datasets muy grandes de forma eficiente aunque no es este el caso.

Crearemos el clasificador y lo entrenaremos con el 90% del dataset.

from sklearn import preprocessing

X=preprocessing.scale(X)

from sklearn.model_selection import train_test_split

Dividimos e dataset en su parte de pruebas y entrenamiento, en este caso elegimos 90% para entrenamiento y 10% para pruebas, al ser un dataset tan pequeño, no lo barajamos para no perder el índice de cada valor.

x_train, x_test,y_train,y_test = train_test_split(X,Y,test_size=0.1,random_state=1,shuffle = False)

Y finalmente lo entrenamos con SVC

from sklearn.svm import SVC

svc_clf =SVC()

svc_clf.fit(x_train,y_train)

Utilizar la red para hacer “predicciones” con datos reales

Ya tenemos el modelo entrenado, ahora vamos a la parte que nunca se explica en Machine Learning, es decir, una vez tenemos la red entrenada vamos a cargarla con nuestro dataset de pruebas para ver como funciona.

Una vez entrenada la red neuronal cargamos el nuevo dataset que tendrá la misma estructura que el anterior pero con las etiquetas (datos de entrenamiento) a cero, Pues son los datos que la red debe predecir.

Lo primero que tenemos que hacer es cargar el nuevo dataset del que queremos predecir los resultados.

#Cargamos el dataset de pruebas

DATASET_PRUEBAS = pd.read_csv('DATASET_PRUEBAS.csv')

#DATASET_PRUEBAS.info

DATASET_PRUEBAS.head()

Tratamos el dataset de la misma forma que hicimos en el entrenamiento.

#asignamos a X_p los datos de nuestro dataset de pruebas

X_p = DATASET_PRUEBAS

X_p=preprocessing.scale(X_p)

 Y finalmente le pedimos que prediga un valor

#predecimos el valor del valor 3 del array

#x_ptrain, x_ptest,y_ptrain,y_ptest = train_test_split(X_p,Y_p,test_size=0.1,random_state=1)

svc_clf.predict([X_p[4]])

Si probamos, veremos que no es muy bueno prediciendo, comete algunos errores, sobre todo se elegimos valores no muy acordes con los que se entrenó, pero ese no era el objetivo de este post. Aquí lo que quería era entrenar y utilizar una red neuronal clasificadora con datasets creados por el usuario

Aquí el programa completo en Phyton.

# Es necesaria una versión superior a Python 3.5

import sys

assert sys.version_info >= (3, 5)

 

# Es necesaria una versión de Scikit-Learn superior a ≥0.20

import sklearn

assert sklearn.__version__ >= "0.20"

 

# importaciones communes

import numpy as np

import os

 

# para hacer que la salida de este código sea estable en todas las ejecuciones

np.random.seed(42)

 

import warnings

warnings.filterwarnings('ignore')

 

import pandas as pd

caracter_precipitaciones = pd.read_csv('Caracter_Precipitaciones.csv')

#debe devolver dos columnas para asegurarnos que el dataset está correctamente construido

#los decimales deben ir con punto y las comas representan la separación de campos

caracter_precipitaciones.info

#caracter_precipitaciones.head()

 

#eliminamos la columna de etiquetas 'caracter' de modo que la X contendrá solo los valores sin su etiqueta

#la variable Y contendrá las etiquetas

X = caracter_precipitaciones.drop('caracter', axis=1)

Y = caracter_precipitaciones['caracter']

 

#hacemos uso de su función de escala para escalar todas nuestras características de entrada.

from sklearn import preprocessing

X=preprocessing.scale(X)

from sklearn.model_selection import train_test_split

 

#dividimos nuestro conjunto de datos en conjuntos de prueba y de entrenamiento.Le ponemos shuffle a false para que no baraje los

#datos pues en este caso el orden es importante.

x_train, x_test,y_train,y_test = train_test_split(X,Y,test_size=0.1,random_state=1,shuffle = False)

 

#Para entrenar este clasificador le pasaremos nuestros datos de entrenamiento, las variables x_train e y_train.

from sklearn.svm import SVC

svc_clf =SVC()

svc_clf.fit(x_train,y_train)

#aqui podemos ver que el array no se baraja y los indices no pierden sus posiciones

y_train.head

 

#'Predecimos' un valor del dataset entrenado, ojo están barajados ya no coinciden con sus indices originales

svc_clf.predict([X[4]])

 

#podemos comprobar la precisión de las predicciones

accuracy= svc_clf.score(x_test,y_test)

print(accuracy)

 

#Cargamos el dataset de pruebas

DATASET_PRUEBAS = pd.read_csv('DATASET_PRUEBAS.csv')

#DATASET_PRUEBAS.info

DATASET_PRUEBAS.head()

 

#asignamos a X_p los datos de nuestro dataset de pruebas

X_p = DATASET_PRUEBAS

X_p=preprocessing.scale(X_p)

 

#predecimos el valor del valor 3 del array

#x_ptrain, x_ptest,y_ptrain,y_ptest = train_test_split(X_p,Y_p,test_size=0.1,random_state=1)

svc_clf.predict([X_p[4]])