Categorizando textos con inteligencia artificial en NodeJS

Aprende cómo categorizar textos de forma muy fácil con inteligencia artificial usando NodeJS

En esta publicación vamos a aprender cómo crear un sistema de categorización que nos permita acomodar textos respecto a ciertas categorías de forma automatizada.

Antes de entrar de lleno a la publicación, como de costumbre voy a contextualizar el motivo de la misma.

Aquí donde me encuentro laborando manejan miles y miles de servidores, switches, firewalls, vpns, máquinas virtuales y demás cosas que deben ser monitoreadas y revisadas constantemente para evitar fallas, es por ello que se tiene un NOC bastante grande que permite al equipo encargado estar al pendiente de cualquier situación en la infraestructura. Sin embargo, había una buena oportunidad de mejora ya que los registros aunque se guardaban en Elastic y toda su paquetería nos ayudaba a acomodar, no se sabía a ciencia cierta cuáles eran las fallas críticas, los tipos de mensaje y todo eso y al haber cientos de miles de registros no es tan fácil encontrar cierta información para dar constante mejoría a los servicios, por lo que se optó por montar un servicio con machine learning que categorice todos estos registros.

Entendiendo esto entonces, vamos a hacer un pequeño tutorial para categorizar pequeños pedazos de textos con inteligencia artificial.

Primeros pasos…

Para seguir este tutorial realmente no ocupas mucho conocimiento de inteligencia artificial o machine learning o lo que gustes y mandes, trataré de hacerlo lo más sencillo posible.

Primero que nada, vamos a crear un nuevo proyecto en NodeJS, con el comando: npm init , vamos a dejar casi todo lo que sale por default y cambiar únicamente nuestro entry point de index.js a app.js.

Ya que tengamos esto, ocuparemos una librería llamada natural (más información https://github.com/NaturalNode/natural) por lo que para instalarla ejecutamos el comando:

npm install natural

Usaremos el clasificador bayesiano ingenuo o “Bayesian” que básicamente nos permite saber si la probabilidad de que una característica o evento en A se encuentre contenida en B. Es bastante complicado de explicar así que usaré un excelente ejemplo que encontré en un blog:

Ya que más o menos tenemos una base de esto, vamos a generar un par de textos dummy que usaremos:

Advertencia: Hubo una falla en el servidor 45
Error en la VPN 45
El usuario root intentó loguear con error
Se conectó un usuario a la red interna
Precaución en el servidor 560, el uso de CPU está al 80%
Se detectó alta latencia en el servidor 893, revisar la conexión con fallas
Guardado el registro de la última hora de accesos a la VPN
La máquina virtual 431 fue apagada exitosamente
El usuario mi_empresa accedió por SSH exitosamente al servidor 33
Error crítico en el servidor HTTP principal, cantidad de errores 500 excedido a lo permitido

Y vamos a clasificarlos en informativo, advertencia y error (en el orden):

advertencia
error
error
informativo
advertencia
advertencia
informativo
informativo
informativo
error

Ahora sí, a programar…

Ya que tenemos nuestros textos disponibles vamos a nuestro código, dentro del archivo app.js vamos a importar nuestra librería y a llamar el clasificador bayesiano:

const natural = require('natural'); 
const classifier = new natural.BayesClassifier();

Después de esto hay que entrenar el clasificador, para ello usamos el método .addDocument() con el siguiente formato:

classifier.addDocument(textoDeEntrenamiento, categoria);

Entonces, tomando nuestros ejemplos anteriores quedaría de la siguiente forma:

classifier.addDocument('Advertencia: Hubo una falla en el servidor 45', 'advertencia');
classifier.addDocument('Error en la VPN 45', 'error');
classifier.addDocument('El usuario root intentó loguear con error', 'error');
classifier.addDocument('Se conectó un usuario a la red interna', 'informativo');
classifier.addDocument('Precaución en el servidor 560, el uso de CPU está al 80%', 'advertencia');
classifier.addDocument('Se detectó alta latencia en el servidor 893, revisar la conexión con fallas', 'advertencia');
classifier.addDocument('Guardado el registro de la última hora de accesos a la VPN', 'informativo');
classifier.addDocument('La máquina virtual 431 fue apagada exitosamente', 'informativo');
classifier.addDocument('El usuario mi_empresa accedió por SSH exitosamente al servidor 33', 'informativo');
classifier.addDocument('Error crítico en el servidor HTTP principal, cantidad de errores 500 excedido a lo permitido', 'error');

Y listo, ahora solo llamamos el método .train() en el objeto classifierejecutar el script y empezará a aprender.

Ahora bien, en este punto nosotros ya tenemos más o menos el entrenamiento, no veremos salida a consola, no veremos nada, ¿cómo sabemos que funcionó?. Para ello vamos a hacer una prueba:

console.log(classifier.classify('La máquina virtual 510 tiene el uso de disco duro al 90%'));

Si agregamos este texto, nos deberá arrojar en consola advertencia y como podemos ver es una advertencia, si agregamos otra prueba:

console.log(classifier.classify('El servidor 15 presentó un error en el sistema operativo y se apagó inesperadamente.'));

En este caso podemos ver que es un error, pero la consola nos arrojará que es una advertencia, ¿por qué sucede esto?, bueno, en este caso entre mayores ejemplos tengamos, la máquina aprenderá mejor. Agregaremos en la parte superior este mensaje para entrenar a la máquina y haremos el cambio a otro número y con otro mensaje intermedio quedando arriba:

classifier.addDocument('El servidor 15 presentó un error en el sistema operativo y se apagó inesperadamente.', 'error');

Y en la prueba:

console.log(classifier.classify('El servidor 333 presentó un error en hardware terminando con BSOD'));

Y ahora sí, aparece error en la consola.

Como podemos ver, entre mejor entrenemos al sistema mejor nos responderá.

Ahora bien, ¿qué pasa si por ejemplo ya que entrenamos a la máquina queremos recargar las pruebas?.

Bueno, para ello debemos guardar nuestros resultados en un archivo para ello usamos .save() de la siguiente forma:

classifier.save('clasificaciones.json');

Y después, si por ejemplo queremos re-entrenar la máquina podemos volver a guardar las clasificaciones en este archivo y reusarlo, por ejemplo pensemos en la siguiente situación:

Después de 1 semana vemos que el clasificador ha ido mejorando gracias a la información proveída pero, aún falla bastante, por lo que re-entrenamos el clasificador mejorando nosotros la información de entrada y categorizando a mano, después, re-entrenamos y podemos reusar el nuevo archivo para posteriores ocasiones, por ejemplo:

natural.BayesClassifier.load('clasificaciones.json', null, function(err, classifier) {
  console.log(classifier.classify('El usuario 615 se desconectó del SSH correctamente'));
  console.log(classifier.classify('La VPN 116 fue agregada con éxito'));
  console.log(classifier.classify('Servidores del rack 15 con alta latencia'));
});

Y en este caso, podemos ver que nos muestra en los primeros casos como informativo y en el tercero como advertencia quedando correctamente ordenados.

Por último, ¿qué pasa si por ejemplo no estamos seguros de cuáles son las opciones?.

Para ello podemos usar .getClassifications() el cual nos arrojará un array con las posibles opciones por ejemplo:

console.log(classifier.getClassifications('La máquina virtual 612 falló inesperadamente'));

Este nos arroja el resultado de:

[ { label: 'informativo', value: 0.01066666666666667 },
  { label: 'error', value: 0.0026666666666666683 },
  { label: 'advertencia', value: 0.002604166666666667 } ]

Y como podemos ver tiene más orientación hacia un mensaje informativo ya que el puntaje más alto es informativo. De esta forma podemos ir revisando qué cantidad de puntos nos arroja cada resultado para ir mejorando nuestra clasificación.

Conclusión:

Este sistema como podrán ver es súper sencillo, pero requiere que nosotros entrenemos a la máquina, por lo que pueden aprovechar sus bases de datos actuales o registros para empezar a entrenarla y cada cierto tiempo hacer un nuevo entrenamiento para ir mejorando la clasificación, sin embargo también es recomendable no usar una grandísima cantidad de datos para el entrenamiento porque puede que la misma máquina se maree y entonces empiece también a clasificar mal.

Les dejo el código demo final:

const natural = require('natural'); 
const classifier = new natural.BayesClassifier();

console.log('Creando registros...');
classifier.addDocument('Advertencia: Hubo una falla en el servidor 45', 'advertencia');
classifier.addDocument('Error en la VPN 45', 'error');
classifier.addDocument('El usuario root intentó loguear con error', 'error');
classifier.addDocument('Se conectó un usuario a la red interna', 'informativo');
classifier.addDocument('Precaución en el servidor 560, el uso de CPU está al 80%', 'advertencia');
classifier.addDocument('Se detectó alta latencia en el servidor 893, revisar la conexión con fallas', 'advertencia');
classifier.addDocument('Guardado el registro de la última hora de accesos a la VPN', 'informativo');
classifier.addDocument('La máquina virtual 431 fue apagada exitosamente', 'informativo');
classifier.addDocument('El usuario mi_empresa accedió por SSH exitosamente al servidor 33', 'informativo');
classifier.addDocument('Error crítico en el servidor HTTP principal, cantidad de errores 500 excedido a lo permitido', 'error');
classifier.addDocument('El servidor 15 presentó un error en el sistema operativo y se apagó inesperadamente.', 'error');

console.log('Entrenando...');
classifier.train();

console.log('Realizando prueba de clasificación...');
console.log(classifier.classify('La máquina virtual 510 tiene el uso de disco duro al 90%'));
console.log(classifier.classify('El servidor 333 presentó un error en hardware terminando con BSOD'));

console.log('Guardando clasificaciones...');
classifier.save('clasificaciones.json');

console.log('Cargando clasificaciones...');
natural.BayesClassifier.load('clasificaciones.json', null, function(err, classifier) {
  console.log(classifier.classify('El usuario 615 se desconectó del SSH correctamente'));
  console.log(classifier.classify('La VPN 116 fue agregada con éxito'));
  console.log(classifier.classify('Servidores del rack 15 con alta latencia'));
  console.log(classifier.getClassifications('La máquina virtual 612 falló inesperadamente'));
});
¿Cuál es tu reacción?
+1
0
+1
0
+1
0
+1
0
+1
1
Total
0
Shares
Publicación anterior

Creando un Proxy en Angular para conectarte a un API local y de producción

Siguiente Publicación

Exportando un JSON a CSV con JavaScript.

Publicaciones Relacionadas