• No se han encontrado resultados

Evaluación de Modelos para Predicción Meteorológica

N/A
N/A
Protected

Academic year: 2021

Share "Evaluación de Modelos para Predicción Meteorológica"

Copied!
33
0
0

Texto completo

(1)

Trabajo de Inteligencia en redes de

comunicaciones

Evaluación de Modelos

para Predicción

Meteorológica

5º I. Telecomunicación

Autores: Aurora Agudo de Carlos

Juan

Carlos

Alonso

Bayal

(2)

ÍNDICE

1. Introducción

... 3

2. Métodos empleados

... 4

2.1 Decisión Table

... 4

2.2. REPTree

... 4

2.3. KStar

... 5

2.4. LMS

... 5

2.5. MultilayerPerceptron

... 5

2.6. SMOreg

...5

2.7. SMO

... 5

2.8. J481

... 5

3. Preprocesado de los datos

... 6

4. Resultados obtenidos

... 12

4.1. Predicción de temperatura a 1 hora.

... 12

4.2. Predicción de temperatura a 24 horas.

... 13

4.3. Predicción de las condiciones meteorológicas

... 14

5. Conclusiones

... 16

6. Bibliografía

... 16

Anexo I

... 17

(3)

1. Introducción

El objetivo es desarrollar un sistema real de predicción meteorológica para la

ciudad de Madrid, utilizando técnicas de aprendizaje automático para obtener modelos

de caracterización y predicción, empleando como herramienta la plataforma Weka. En

concreto hay que desarrollar tres modelos de predicción:

Predicción de temperatura a 1 hora

Predicción de temperatura a 24 horas

Predicción de condiciones meteorológicas (Despejado, Parcialmente

Nublado, etc) a 24 horas

Es decir, con la información disponible hasta el momento (valores de las

variables de entrada en la hora H, H-1, H-2, etc.) hay que predecir el valor de la variable

de salida (temperatura o condiciones meteorológicas) en H+1 y H+24. Los modelos

pueden basarse en cualquier técnica entre las disponibles en Weka, incorporando las

variables que se estimen oportunas entre las proporcionadas y haciendo uso de toda la

información histórica que se crea conveniente.

El punto de partida es la información METAR (Meteorological Actual Report)

disponible en Internet. El código METAR, que fue establecido por la World

Meteorological Organization (WMO) y adoptado por todas las naciones del mundo,

sirve para representar condiciones meteorológicas en aeropuertos o estaciones

meteorológicas, habitualmente con medidas horarias.

Se partirá de un conjunto de datos meteorológicos en dos localizaciones (Barajas

y Cuatro Vientos) desde el año 1996 a la actualidad, con las siguientes medidas cada

media hora (pueden faltar medidas):

HoraCET

Temperatura (grados Farenheit)

Punto de rocío (grados Farenheit)

Humedad

Presión (pulgadas)

Visibilidad

Dirección del viento

Velocidad del viento (millas por hora)

Velocidad de ráfagas de viento (millas por hora)

Precipitación

Eventos

Condiciones

El formato de los datos es el siguiente (extracto de un día cualquiera):

HoraCET,TemperaturaF,Nivel de RocíoF,Humedad,PresiónIn,Visibilidad MPH,Wind

Direction,Velocidad del vientoMPH,RáfagaMPH,Precipitación In,Hechos,Conditions

(4)

En los datos no se ha realizado ningún tipo de procesado ni limpieza de datos,

por lo que como primer paso es necesario un trabajo de limpieza y preprocesado de

datos, previo al estudio de variables que conducirá a la obtención de la matriz (o

matrices) de minería de datos. En particular hay que tener en cuenta el hecho de que

faltan medidas para algunas horas, por lo que la matriz de minería tendrá huecos

(valores incorrectos o inexistentes) en esos instantes de tiempo, que habrá que tratar

apropiadamente (eliminar esos registros, rellenarlos con valores medios o

extrapolaciones, etc.).

Como conjunto de entrenamiento se utilizará la información hasta el 31/12/2003

(incluida) y los modelos se evaluarán con la información de 2004.

El criterio de evaluación de sistemas será:

en temperatura: el error relativo medio, calculado como:

ERROR = media( abs(Tpredicha-Treal)/Treal )

en condiciones meteorológicas: en proporción de aciertos:

ERROR = cuenta(aciertos)/ (cuenta(aciertos) + cuenta(fallos))

Además puede resultar muy útil establecer un primer modelo de segmentación

para distinguir situaciones meteorológicas particulares (invierno/verano, "tiempo

bueno"/"tiempo malo", "tiempo mejorando"/"tiempo estable"/"tiempo empeorando",

etc.) para después desarrollar modelos de predicción más ajustados a cada una de esas

situaciones, y, por tanto, con menos error.

2. Métodos empleados

2.1. Decisión Table

La tabla de decisión es un instrumento para decidir la mejor alternativa en un

proceso de decisión. Para ello se utiliza el concepto de regla de decisión, que es una

aplicación que asocia a cada alternativa un número, que expresa las preferencias del

decisor por los resultados asociados a dicha alternativa. Una tabla de decisión se

compone de una matriz en la que se almacenan una serie de condiciones y sus

correspondientes acciones. El problema de este algoritmo es decidir qué atributos

introducir en la tabla.

2.2. REPTree

Es un método de aprendizaje rápido mediante árboles de decisión. Construye un

árbol de decisión usando la información de varianza y lo poda usando como criterio la

reducción del error. Solamente clasifica valores para atributos numéricos una vez. Los

valores que faltan se obtienen partiendo las correspondientes instancias.

(5)

2.3. KStar

K* es un clasificado basado en instancias, esto significa que la clasificación de

una instancia está basada en la clasificación de instancias de entrenamiento similares,

determinadas por alguna función de similitud. Se diferencia de otros aprendizajes

basados en lo mismo en que usa una función de distancia basada en entropía.

2.4. LMS

Implementa una regresión lineal LMS utilizando la clasificación por regresión

lineal disponible en el WEKA para formar predicciones. Las funciones LMS se generan

a partir de un muestreo de datos aleatorio. La regresión ajustada con el error cuadrático

medio más bajo se elige como el modelo final.

2.5. MultilayerPerceptron

Es un clasificador que usa retropropagación para clasificar instancias. Esta red

puede construirse a mano, mediante un algoritmo o mediante ambos. Además puede ser

monitorizada y modificada durante el tiempo de entrenamiento. Los nodos en esta red

son todo sigmoides, excepto cuando la clase es numérica, en cuyo caso los nodos de

salida son unidades lineales.

2.6. SMOreg

Implementa el algoritmo de optimización de secuencia mínima desarrollado por

John C. Platts pra entrenar una SVM (máquina de vectores soporte) con kernel

polinomiales o funciones de base radial (RBF) Esta implementación substituye todos los

valores que faltan y transforma atributos nominales en otros binarios. También

normaliza todos los atributos por defecto. (los coeficientes a la salida están basados en

los datos normalizados, no en los originales.)

2.7. SMO

Es similar al anterior pero soluciona problemas multiclase usando clasificación

por parejas. En los casos multi-clase las probabilidades predichas se juntaran usando

los métodos de emparejamiento Hastie y Tibshirani.

2.8. J48

Se trata de una implementación propia de WEKA para el algoritmo C4.5, un

algoritmo basado en clasificación por árbol de decisión. El algoritmo ofrece la

posibilidad de poder parar antes de alcanzar las hojas en cada subárbol; esto dará lugar a

árboles menos refinados, por decirlo de alguna forma, y ayudará a evitar el overfitting.

(6)

3. Preprocesado de los datos

Datos de Partida

El preprocesado de datos en un problema de datamining engloba la recolección

la información, extrayendo lo que en realidad es relevante para poder enfrentarnos a

nuestro problema. Hay que limpiar la información quitando ruidos, redundancias;

analizando cuál es la información de la que disponemos y qué pretendemos obtener a

partir de ella. En nuestro caso, la información de partida estaba constituida por las

medidas tomadas en dos estaciones meteorológicas de Madrid durante el mismo

intervalo de tiempo, desde 1994 hasta 2004.

Observando los ficheros proporcionados, pudimos comprobar que en realidad no

todos los ficheros contenían datos; exactamente, los ficheros desde 1994 hasta el 30 de

Junio de 1996 estaban vacíos (para ambas estaciones meteorológicas). Por lo que, para

el desarrollo de nuestro problema tuvimos en cuenta los ficheros desde el 1 de Julio de

1996 hasta el 31 de Octubre de 2004, un total de 6090 ficheros. Estos ficheros estaban

escritos en HTML, formato que Weka no es capaz de procesar.

HoraCEST,TemperaturaF,Nivel de

RocíoF,Humedad,PresiónIn,VisibilidadMPH,Wind

Direction,Velocidad del

vientoMPH,R&aacute;fagaMPH,Precipitaci&oacute;nIn,Hechos,Conditions<BR>

2:00 AM,75.2,50.0,41,30.01,-9999.0,Calm,Calm,-,N/A,,Despejado<BR>2:30

AM,75.2,50.0,41,30.01,-9999.0,Calm,Calm,-,N/A,,Despejado<BR>3:00

AM,73.4,48.2,41,30.01,-9999.0,Este,1.2,-,N/A,,Despejado<BR>3:30

AM,73.4,48.2,41,30.01,-9999.0,Este,1.2,-,N/A,,Despejado<BR>4:00

AM,69.8,48.2,46,29.98,-9999.0,Norte,3.5,-Figura 1.- Datos en formato HTML disponibles (fichero 08221-1996-07-01)

Datos legibles en Weka

Para poder leer los datos en Weka y comprobar qué era de lo que partíamos,

usamos un programa en Java que nos permitiera sustituir las etiquetas <BR> por un

retorno de carro (“\n”). Transformamos los datos a un formato que Weka sí era capaz de

interpretar; teníamos que guardar cada fichero con la extensión .csv. Fue en esta fase

donde verificamos que disponíamos de un fichero para cada día del calendario

correspondiente al intervalo de tiempo anteriormente señalado.

Automatizando el proceso de preprocesado

Tras eso, al observar los datos que contenía cada fichero, comprobamos que

tenía medidas de temperatura, rocío, humedad, presión, visibilidad, dirección del viento,

velocidad del viento, ráfaga, nivel de precipitación, eventos acontecidos y condiciones

meteorológicas tomadas aproximadamente cada 30 minutos.

(7)

Hora,Temperatura,Nivel de Rocio,Humedad,Presión,Visibilidad,Dirección del

Viento,Velocidad del Viento,Ráfaga,Precipitación,Eventos,Condiciones

2:00 AM,75.2,50.0,41,30.01,-9999.0,Calm,Calm,-,N/A,,Despejado

2:30 AM,75.2,50.0,41,30.01,-9999.0,Calm,Calm,-,N/A,,Despejado

3:00 AM,73.4,48.2,41,30.01,-9999.0,Este,1.2,-,N/A,,Despejado

3:30 AM,73.4,48.2,41,30.01,-9999.0,Este,1.2,-,N/A,,Despejado

4:00 AM,69.8,48.2,46,29.98,-9999.0,Norte,3.5,-,N/A,,Despejado

Figura 2.- Datos transformados al formato CSV (fichero 08221-1996-07-01.csv)

En el ejemplo mostrado anteriormente se comprueba que no todos los ficheros

disponían de datos en toda la franja horaria de un día de 0:00 a 23:30. Para poder

preprocesar de forma automática los datos, decidimos registrar las medidas de un día

de 30 en 30 minutos. Para ello tuvimos que añadir líneas con las horas que faltaban,

eliminar medidas redundantes tomadas a la misma hora, el mismo día y en la misma

estación meteorológica, así como las medidas tomadas en instantes de tiempo no

correspondientes a los instantes que queríamos almacenar.

Para eliminar la redundancia, tan sólo tuvimos en cuenta la primera medida que

aparecía para dicho intervalo. Las medidas en franjas horarias distintas a las previstas no

se tuvieron en cuenta. Todo esto fue posible a un array de control como el que se

muestra en la siguiente figura que almacenaba qué horas eran las que ya se habían leído.

Suponiendo que los datos estaban ordenados cronológicamente, al leer una línea, leer

los datos de un intervalo de tiempo determinado, si en el array de control existían

elementos previos marcados como no leídos, se interpretaba que el fichero no contenía

dichos datos y había que añadir una línea vacía (atributos desconocidos). En esta fase de

preprocesado fue cuando añadimos un nuevo atributo, la fecha del fichero que

estábamos leyendo en ese momento. La importancia de este parámetro se explicará

posteriormente en este documento.

Algunas de las medidas que contenía el fichero indicaban que era un valor

desconocido. El formato general de dicho valor era a través de un guión bajo “_”,

aunque el parámetro rocío tenía un valor “-9999.0” cuando no se conocía su valor, así

como en eventos producidos cuando no había nada que escribir podía aparecer la

00:00 00:30 01:00 01:30 02:00 02:30 23:00 23:30

Línea leída

Líneas

(8)

Para poder crear la matriz de minería de datos debíamos tener los datos de todos

los días en un mismo fichero. Este fue el siguiente paso a llevar a cabo y para poder

distinguir entre todos los datos de los que disponíamos fue por lo que añadimos el

campo fecha, de tal modo que para cada estación meteorológica teníamos un fichero con

todos las medidas tomadas, donde cada una se identificaba a partir del par < fecha, hora

>. Cada fichero contenía 3045*48 = 146 160 líneas.

Mezclado e Interpolación

A fin de obtener una mejor aproximación a nuestro problema, predecir la

temperatura y las condiciones meteorológicas en Madrid, decidimos mezclar los datos

del siguiente modo:

- para las medidas de temperatura, rocío, humedad, presión, visibilidad,

velocidad del viento, ráfaga y nivel de precipitación, parámetros numéricos:

tomamos la media de ambos datos; en caso de que uno de los valores fuera

desconocido se tomaba el valor conocido.

- para las medidas de dirección del viento, eventos acontecidos y condiciones

meteorológicas, constituidos por cadenas, tomamos uno de los valores

escogido aleatoriamente.

Una vez realizada la mezcla de ambos ficheros, usamos un filtro interpolador

para sustituir datos desconocidos por datos aproximados. Cuando un dato era

desconocido, comprobamos si el registro anterior y el registro posterior de dicho

parámetros no eran desconocidos; en tal caso, sustituíamos el valor desconocido usando

medias en caso de datos numéricos o escogiendo aleatoriamente si el parámetro era una

cadena, como en el caso de la mezcla, a partir del dato anterior y el dato posterior.

Vector de Parámetros

El vector de parámetros escogido para formar la matriz de minería es, para cada

uno los problemas a predecir, distinto. Para su elección se han considerado los

siguientes puntos:

• A mayor número de parámetros, obtenemos una selección más precisa.

Según [1] , los parámetros importantes para predecir temperatura y

condiciones meteorológicas son la temperatura, la presión, las condiciones

meteorológicas y el nivel de precipitación.

• Es conveniente tener un registro temporal para valorar la evolución de los

parámetros.

• Un número elevado de parámetros produce un elevado coste computacional,

a veces inabordable por ordenadores personales. Buscando una situación de

compromiso entre el registro temporal y el número de parámetros, decidimos

usar valores medios que nos permitieran tener en cuenta la evolución de los

registros anteriores.

(9)

• Parámetros que se mantienen constantes no influyen en nuestra decisión, este

es el caso de la presión atmosférica, aunque en un principio es un parámetro

importante a tener en cuenta como ya hemos comentado anteriormente, en

nuestros datos siempre se mantiene constante: las estaciones base están

situadas aproximadamente a la misma altura.

• Parámetros cuyo valor en la mayoría de los registros es desconocido no es

útil para predecir, tan sólo proporcionan excepciones que en muchos casos

inducen a aumentar el error obtenido. De este modo, teniendo en cuenta los

valores que obtuvimos descartamos las medidas de visibilidad, ráfaga, nivel

de precipitación y eventos acontecidos.

• Parámetros que toman valores incongruentes no son válidos. Esto ocurre en

la medida de dirección del viento, donde a veces se introducen valores

numéricos en vez de una cadena indicando la dirección, algo que carece de

interpretación.

Vector de parámetros para predecir la temperatura con un margen de 1h.

Para predecir la temperatura con un margen de una hora hemos usado los

parámetros de temperatura, rocío, velocidad del viento y condiciones meteorológicas de

los tres registros anteriores, es decir de la hora y media anterior, así como los valores

medios de temperatura de las últimas 12 horas tomados de 3 en 3 horas. Hemos de

añadir también la temperatura a predecir y la fecha. Este último parámetro nos servirá

para una fase posterior de preprocesado que explicaremos a continuación.

Vector de parámetros para predecir la temperatura con un margen de 24 h.

Predecir la temperatura con un margen de 24 horas parece en un principio un

ejercicio más complicado de abordar, por ello hemos usado un vector de parámetros

algo más complejo. Hemos utilizado las siguientes medidas de los cinco registros

anteriores: temperatura, rocío y velocidad del viento. También hemos añadido los

valores medios de temperatura de las 36 horas anteriores tomadas de 12 en 12 horas. Al

igual que en el caso anterior hemos añadido la temperatura a predecir y la fecha.

Vector de parámetros para predecir las condiciones meteorológicas con un

margen de 24 h.

Predecir las condiciones meteorológicas con un margen de 24 horas es un

problema de complejidad mayor, ya que el uso de cadenas de caracteres tanto en los

parámetros como en el dato a predecir induce a algoritmos de clasificación más costosos

y complejos computacionalmente. Por eso a parte de los parámetros tomados

anteriormente para el problema de la temperatura con un margen de 24 horas hemos

añadido también las condiciones meteorológicas de esos cinco registros anteriores.

(10)

Segmentación

En los requisitos de este trabajo se imponía que para evaluar los distintos

algoritmos de clasificación había que dividir los datos en un conjunto de entrenamiento

y un conjunto de validación. El conjunto de validación debía corresponder a la

predicción de la temperatura o de las condiciones meteorológicas del año 2004; por lo

que el conjunto de entrenamiento debe estar constituido por los datos anteriores. Para

crear estos dos conjuntos usamos el campo fecha en cada una de las matrices de minería

creadas, una para cada problema de predicción.

Por problemas de memoria de nuestros ordenadores, nos vimos obligados a

segmentar los datos en función de las estaciones del año: primavera, verano, otoño e

invierno, especializando de este modo aún más los clasificadores a evaluar. Para hacer

esta división usamos el mes del año del parámetro fecha de cada fila de la matriz de

minería. La segmentación fue según se muestra en la siguiente tabla:

Grupo asignado

Mes

Invierno

‘-01-’; ‘-02-’; ‘-03-’

Primavera

‘-04-’; ‘-05-’; ‘-06-’

Verano

‘-07-’; ‘-08-’; ‘-09-’

Otoño

‘-10-’; ‘-11-’; ‘-12-’

Escribir matriz en fichero

A la hora de almacenar en fichero, ya no tuvimos en cuenta el parámetro fecha

porque no nos era útil. Además, tampoco tuvimos en cuenta las filas cuyo valor predecir

era desconocido (‘?’) porque carecía de sentido. Debido a problemas de memoria, nos

vimos también obligados a eliminar todos los datos que tuvieran algún parámetro

desconocido. Aún con esas, los ficheros de entrenamiento, seguían siendo demasiado

grandes por lo que escogimos filas alternadas para reducir el tamaño de este. Teniendo

en cuenta esto, mostramos el número de datos que en un principio procesaríamos y los

que al final procesamos:

Fichero de entrenamiento:

Invierno

Primavera

Verano

Otoño

Líneas

Iniciales

Líneas

Finales

Líneas

Iniciales

Líneas

Finales

Líneas

Iniciales

Líneas

Finales

Líneas

Iniciales

Líneas

Finales

Entrenamiento 30 288 17 735 30 576 13 576 35 304 16 686 35 328 16 988

Temperatura

con un

margen de

1h.

Validación

4 368

2 790

4 368

4 285

4 416

4 370

1 488

1 463

(11)

Entrenamiento 30 288 13 587

30 576

13 645

35 256

16 533 35 328 16 802

Temperatura

con un

margen de

24 h.

Validación

4 368

2 766

4 368

4 259

4 416

4 259

1 488

1 457

Entrenamiento 30 288 13 589

30 576

13 647

35 256

16 538 35 328 16 804

Condiciones

con un

margen de

24 h.

Validación

4 368

2 766

4 368

4 256

4 416

4 356

1 488

1 457

Cabe comentar que se cumple que aproximadamente que los datos de validación

son aproximadamente un 20 % del conjunto de datos total y los datos de entrenamiento

constituyen el 80 %, división que se realiza habitualmente en estos problemas de

predicción.

Un comentario de lo que a procesado de información se refiere, es que la mitad

de él se ha realizado en Java y la otra mitad en MatLab debido a que JVM no poseía

memoria suficiente como para mezclar ambos ficheros. A partir del filtro mezclador se

realizó todo el preprocesado con MatLab. Al final de la memoria incluimos un anexo

con todo el código utilizado.

(12)

4. Resultados obtenidos

4.1. Predicción de temperatura a 1 hora.

Estación del

año

Método de

predicción

Tiempo en

generar el

modelo (s)

Root mean

squared error

Relative

absolute error

DecisionTable 77.77

4.983 25.9095

%

REPTree 8.34

2.2975 11.7486

%

Primavera

Kstar

0.01

3.394 15.9975

%

DecisionTable 50.36

5.7027 48.3812

%

REPTree 10.16

1.5553 13.0578

%

Verano

Kstar

0.02

2.1856 17.8961

%

DecisionTable 58.55

6.6486 38.5205

%

REPTree 9.89

1.7933 12.7607

%

Otoño

Kstar

0.02

3.9377 23.8489

%

DecisionTable 53.44

3.3794 36.8439

%

REPTree 7.91

1.4777 15.3538

%

Invierno

Kstar

0.02

3.979 23.0944

%

Tabla 1: Resultados obtenidos para la predicción de temperatura en 1 hora.

Observando la tabla anterior se deduce rápidamente cual es el método mas

exacto de los tres que se han empleado para predecir la temperatura en el plazo de 1h, es

claramente el REPTree tanto por las tasas de error que presenta como por el reducido

tiempo que tarde en generar el modelo de predicción a partir de los datos de

entrenamiento. En las cuatro estaciones del año genera los mejores resultados que

oscilan entre un 11-15% de error, un resultado que a nuestro modo de ver está bastante

bien siendo hasta tres veces menor que para el método de DecisionTable y la mitad que

para el método Kstar. Cabe también destacar que a pesar de que el algoritmo Kstar es

más rápido, este factor no compensa los errores cometidos.

Una cuestión que hay que subrayar aquí y que se comprobará mas adelante es

que algoritmos mas complejos (MultilayerPerceptron , LMS o SOMreg) llegan a

obtener resultados para predecir temperatura a 24h pero no a 1h porque en este caso se

utilizan parámetros tanto numéricos como nominales por lo que el entrenamiento y la

validación tiene un coste computacional mayor. Esto es debido a que Weka trata los

atributos nominales parametrizándolos a un valor numérico, lo cual requiere mayor

coste computacional. Es por esto que estos algoritmos no convergen para predicciones

de temperatura de 1h (con los atributos que se han utilizado).

(13)

4.2. Predicción de temperatura a 24 horas.

Estación del

año

Método de

predicción

Tiempo en

generar el

modelo (s)

Root mean

squared

error

Relative

absolute

error

DecisionTable 45.92

4.8182

27.0841

%

REPTree 8.35

1.8247

11.3032

%

MultilayerPerceptron 682.37

1.4923 9.6094

%

SOMreg 27778.19

1.4136 9.0747

%

Kstar

0.02

3.5218 16.3087

%

Primavera

LMS 2005.6

3.861

12.7196

%

DecisionTable 58.88

8.6631

78.8826

%

REPTree 9.78

1.6857

13.2711

%

MultilayerPerceptron 898.98

1.5786 13.5301

%

SOMreg 25224.79

1.4158 11.7167

%

Kstar

0

3.3958 19.0927

%

Verano

LMS 2291.61

6.5093

15.3199

%

DecisionTable

71.96

7.8964

53.422 %

REPTree 9.89

1.7481

12.1553

%

MultilayerPerceptron 823.27

2.0494 15.7151

%

SOMreg 39172.23

1.3353 9.5033

%

Kstar

0

3.8634 23.0722

%

Otoño

LMS 2312.12

4.4913

14.0865

%

DecisionTable 40.81

4.5624

50.0695

%

REPTree 7.14

1.4576

15.6465

%

MultilayerPerceptron 709.21

1.4018 15.2719

%

SOMreg 27355.76

3.4703

16.3177

%

Kstar

0

2.1081 22.3372

%

Invierno

LMS

2066.1

3.3846

16.74 %

(14)

Si se atiende solo al porcentaje de error que proporciona cada algoritmo de

predicción, es lógico pensar que los resultados son mejores en este caso que en la

predicción a 1 hora. Esto es debido a que los atributos que se utilizan son solo

numéricos y se pueden emplear complejos algoritmos de predicción como LMS o

MultilayerPerceptron. Debido a esto se llegan a realizar predicciones con un error

inferior al 10% en función de la estación del año que se analice pero esta mejora se

realiza a costa de un mayor tiempo de procesado de datos de entrenamiento para obtener

el modelo de predicción, basta con ver el tiempo que necesita el SOMreg que es

superior a 7 horas. Quizás tan solo el algoritmo que utiliza el MultilayerPerceptron sea

el único que realmente mejora los anteriores en la relación precisión/tiempo ya que

mejora los resultados obtenidos por el REPTree y el tiempo que tarda en crear el

modelo es de 10-20 minutos.

Otro cuestión que se puede ver es que los resultados obtenidos por los métodos

que se usaron para predecir la temperatura a 1 hora son similares (en función de la

estación) a los que se obtienen para la predicción a 24 horas, a pesar de que se usan

parámetros distintos, ya que ahora sólo son numéricos y antes también se empleaban

nominales.

4.3. Predicción de las condiciones meteorológicas.

En la siguiente tabla se observan los resultados de las predicciones realizadas

para cada algoritmo utilizado. Al contrario que en las predicciones anteriores, el mejor

algoritmo es el DecisionTable, aunque cualquiera de los otros métodos presentan

resultados similares excepto el Kstar.

(15)

Estación del

año

Método de

predicción

Tiempo en

generar el

modelo (s)

Instancias mal

clasificadas

Decisión Table

62.94

12.6116 %

REPTree 21.58

12.9873

%

SMO 15955.78

12.8229

%

J48 7.81

13.0343

%

Primavera

Kstar

0

31.3293 %

Decisión Table

63.17

7.0478 %

REPTree 22.57

7.4839

%

SMO 20517.52

7.0707

%

J48 9.28

7.2773

%

Verano

Kstar

0.02

19.9954 %

Decisión Table

78.33

16.2663 %

REPTree 26.25

17.0213

%

SMO 15955.78

16.6781

%

J48 10.81

17.0899

%

Otoño

Kstar

0

31.7776 %

Decisión Table

61.25

12.3327 %

REPTree 18.57

12.9114

%

SMO 23106.51

12.9837

%

J48 7.84

13.9241

%

Invierno

Kstar

0.02

30.7776 %

Tabla 3: Resultados obtenidos para la predicción las condiciones meteorológicas en 24 horas.

En definitiva, para los tres tipos de predicciones realizadas podemos concluir

que el mejor método en nuestra opinión es el REPTree, porque proporciona buenos

resultados (aunque no siempre los mejores) en todos los casos. Además se ha

comprobado que los algoritmos complejos no trabajan muy bien con atributos

(16)

5. Conclusiones

En este trabajo hemos desarrollado un completo estudio en la medida de nuestras

posibilidades de diferentes métodos que se pueden utilizar para predecir parámetros

meteorológicos: la temperatura y las condiciones meteorológicas. En este estudio hemos

conseguido errores inferiores al 10% tanto con algoritmos más bien sencillos

computacionalmente como las tablas o árboles de decisión, y con algoritmos más bien

complejos como las redes SOM o las redes neuronales MLP.

Estos algoritmos son los que comúnmente se utilizan para predecir los

parámetros meteorológicos, pero requieren de un exhaustivo periodo de entrenamiento

como hemos podido verificar a lo largo de este trabajo. Los resultados obtenidos con

estos algoritmos suelen ser bastante mejores que los que hemos obtenido no sólo porque

el número de parámetros utilizados es mayor o el preprocesado es más complejo, sino

porque actualmente las matrices de minería de datos que se utilizan son matrices

espacio-temporales [1,3], contienen datos de varias estaciones de medida

(aproximadamente 10) y la evolución de estos a lo largo del tiempo. Además estos

algoritmos se caracterizan por conseguir disminuir el número de parámetros a medida

que aumentan el número de estaciones.

En nuestro trabajo hemos desarrollado tan sólo predicciones a corto plazo, sólo

hemos tenido en cuenta datos con 24 h. de antelación. Las predicciones a corto plazo, a

día de hoy, suelen conducir a peores resultados que las predicciones a largo plazo, esto

se debe principalmente a que se considera que los datos meteorológicos siguen una

periodicidad estacional, por lo que tener en cuenta datos de años anteriores en la misma

estación del año permite mejorar el comportamiento de estos clasificadores. Cabe

destacar que éstos son los que más tiempo llevan investigándose.

6. Bibliografía

[1]

http://grupos.unican.es/ai/meteo/articulos/TesisCofino2004.pdf

[2] “WEKA. Machine Learning Algorithms in Java.” Chapter 8 from the book “Data

Mining: Practical Machine Learning Tools and Techniques with Java Implementations”

Ian H. Witten.

[3]

http://grupos.unican.es/ai/meteo/index.html

[4] Manual incorporado en el programa WEKA

[5]

http://galahad.plg.inf.uc3m.es/~docweb/ia-sup/software.html

[6]

http://www.cs.waikato.ac.nz/ml/weka/

(17)

Anexo I. Ficheros en Java utilizados para el

preprocesado

Datos legibles en Weka

prueba1.java

import java.io.File; public class prueba_1 {

/** Creates a new instance of prueba_1 */ public prueba_1() {

} /**

* @param args the command line arguments */

public static void main(String[] args) { FileList f = new FileList("D:/LEVS/"); File lista_f[]=f.getFich_list();

f.checkFileList(1,7,1996,31,10,2004);

for (int i=0;i < lista_f.length; i++) {

ModificarFichero mf = new ModificarFichero(lista_f[i]); mf.obtenerTexto(); mf.parsearTexto(); mf.escribirFichero(); System.out.println(i); }

System.out.println("Fin del directorio"); } }

FileList.java

import java.util.ArrayList; import java.io.File; import java.util.GregorianCalendar; import java.lang.Integer; import java.util.StringTokenizer; public class FileList {

String directory; // directorio donde extraemos la lista de ficheros a modificar public String getDirectory(){

return directory; }

File dir_file; // objeto File que contiene el directorio. public File getDir_file(){

return dir_file; };

File[] fich_list;// lista de ficheros;

public File[] getFich_list(){ return fich_list;

}

/** Creates a new instance of FileList */ public FileList(String d) {

(18)

}

public void checkFileList(int day_ini, int mes_ini, int ano_ini, int day_fin, int mes_fin, int ano_fin){

/*

1.- Deberíamos comprobar si existen ficheros para todos los días.. --.-.-.-.-.-.-.-.---.--.-.-.-.-.-.-.-.-.-.-.-....--.-.-.--.-.-.-.*/

GregorianCalendar fecha_ini = new GregorianCalendar(ano_ini,mes_ini,day_ini); GregorianCalendar fecha_fin = new GregorianCalendar(ano_fin,mes_fin,day_fin); GregorianCalendar fecha_file = new GregorianCalendar();

String parser1 = "-"; String parser2 = "."; int i, dia, mes, ano;

StringTokenizer fecha, file_name;

i = 0;

System.out.println("IO "+fich_list.length);

while ((i < fich_list.length)|| ((fecha_ini.DATE != fecha_fin.DATE) && (fecha_ini.MONTH != fecha_fin.MONTH) &&(fecha_ini.YEAR != fecha_fin.YEAR))){

// 1. Obtener la fecha del nombre del fichero

file_name = new StringTokenizer(fich_list[i].getName(),parser2); fecha = new StringTokenizer(file_name.nextToken(),parser1);

/* sabemos que el nombre del fichero es como sigue: 08223-2004-10-31.csv */ /* obtenemos los campos que necesitamos realmente*/

fecha.nextToken(); ano = Integer.parseInt(fecha.nextToken()); mes = Integer.parseInt(fecha.nextToken()); dia = Integer.parseInt(fecha.nextToken());

// 2. Contrastar si corresponde a la fecha del calendario.

// suponemos que el directorio está ordenado por fechas desde la más temprana a la más tardía

// en caso de que no corresponda mostramos un mensaje de información por pantalla

fecha_file.set(ano,mes,dia);

if ((fecha_file.DATE != fecha_ini.DATE) || (fecha_file.MONTH != fecha_ini.MONTH) || (fecha_file.YEAR != fecha_ini.YEAR))

System.out.println("El fichero correspondiente a la fecha

"+fecha_ini.DATE+"-"+fecha_ini.MONTH+"-"+fecha_ini.YEAR+"no está en el directorio");

// aumentar la fecha de inicio del calendario. fecha_ini.roll(fecha_ini.DATE, true); i++; } } }

ModificarFichero.java

import java.io.File; import java.io.FileWriter; import java.io.BufferedWriter; import java.io.FileReader; import java.io.BufferedReader; import java.util.ArrayList; import java.util.StringTokenizer; public class ModificarFichero {

(19)

File fich_escritura; String texto_leido;

public String getTexto_leido(){ return texto_leido;

}

String cadena_escrita;

public String getCadena_escrita(){ return cadena_escrita;

}

String[] lista_cadenas;

final static String parametros = "Hora,Temperatura,Nivel de Rocio,Humedad,Presión,Visibilidad,Dirección del Viento,Velocidad del Viento,Ráfaga,Precipitación,Eventos,Condiciones";

final static String parser = "<BR>";

/** Creates a new instance of ModificarFichero */ public ModificarFichero(File fich_lect) { this.fich_lectura=fich_lect;

fich_escritura = new File((fich_lect.getPath()).concat(".csv")); //fich_escritura = new File((fich_lect.getPath()).concat(".csv")); texto_leido= new String();

cadena_escrita= new String(); lista_cadenas = null;

}

public void obtenerTexto(){ try{

BufferedReader stdin = new BufferedReader(new FileReader(fich_lectura)); stdin.readLine();

stdin.readLine();

// Hemos comprobado que tan sólo necesitamos la tercera linea del fichero de lectura texto_leido=stdin.readLine(); stdin.close(); } catch(Exception e){ System.out.println("Exception capturada"); } }

public void parsearTexto(){

// El texto leido se transforma en una array de longitud indeterminada y no fija de líneas

// Para parsear el texto, detectaremos las líneas encontrando la cadena <BR>; lista_cadenas = (this.getTexto_leido()).split(parser); }

public void escribirFichero(){ try{

BufferedWriter stdout = new BufferedWriter(new FileWriter(fich_escritura)); stdout.write(parametros);

stdout.newLine(); // Parsear texto

for (int x=0; x<lista_cadenas.length; x++){ stdout.write(lista_cadenas[x]); stdout.newLine(); } stdout.close(); } catch(Exception e){ System.out.println("Exception capturada");

(20)

Automatizando el proceso de preprocesado

prueba2.java

import java.io.File; public class prueba_2 {

/** Creates a new instance of prueba_2 */ public prueba_2() {

}

public static void main(String[] args) {

FileList f1 = new FileList("D:/prediccion_meteo/meteo/LEVS/"); File lista_f1[]=f1.getFich_list();

for (int i=0;i < lista_f1.length; i++) {

FormatearFichero ff1 = new FormatearFichero(lista_f1[i]); ff1.leerFicheroaFormatear(); ff1.escribirFicheroFormateado(); System.out.println(i); }

System.out.println("Fin del directorio LEMD"); } }

FormatearFichero.java

import java.io.File; import java.io.FileWriter; import java.io.BufferedWriter; import java.io.FileReader; import java.io.BufferedReader; import java.util.ArrayList; import java.util.StringTokenizer; import java.util.Vector;

public class FormatearFichero {

static final int TOTAL_LINEAS = 48;

static final String LINEA_VACIA = ",,,,,,,,,"; File fich_lectura;

File fich_escritura; String file_name; String texto_leido;

public String getTexto_leido(){ return texto_leido;

}

String cadena_escrita;

public String getCadena_escrita(){ return cadena_escrita;

}

Vector lista_cadenas;

final static String parametros = "Fecha,Hora,Temperatura,Nivel de Rocio,Humedad,Presión,Visibilidad,Dirección del Viento,Velocidad del Viento,Ráfaga,Precipitación,Eventos,Condiciones";

//final static String parser = "<BR>";

/** Creates a new instance of FormatearFichero */ public FormatearFichero(File fich_lect) {

this.fich_lectura=fich_lect; file_name = fich_lect.getPath();

file_name = file_name.substring(0,file_name.lastIndexOf(".csv"));

(21)

//fich_escritura = new File((fich_lect.getPath()).concat(".csv")); texto_leido= new String();

cadena_escrita= new String(); lista_cadenas = new Vector(); lista_cadenas.add(parametros); }

public void escribirFicheroFormateado(){ try{

BufferedWriter stdout = new BufferedWriter(new FileWriter(fich_escritura)); int i=0; for (i=0;i<lista_cadenas.size();i++){ stdout.write((String) lista_cadenas.get(i)); stdout.newLine(); } stdout.close(); } catch(Exception e){

System.out.println("Exception capturada "+e); }

}

public void leerFicheroaFormatear(){ int linea_leida = 0;

FormatLinea fline = new FormatLinea(); String lista[]=null; int j = 0; int indice = 0; FormatLinea.inicializarControlHorario(); try{

BufferedReader stdin = new BufferedReader(new FileReader(fich_lectura)); /* la primera linea del fichero es la linea de parameros, no nos interesa, vamos a trabajar con los datos que vienen definidios a partir de la segunda linea */

try{

texto_leido = stdin.readLine();

while ( texto_leido != null){

texto_leido = stdin.readLine(); if (texto_leido != null){

fline = new FormatLinea(texto_leido, this.obtenerFecha(),linea_leida); if (! texto_leido.startsWith(LINEA_VACIA)){ indice = fline.obtenerIndice(); if (indice != -1){ if (! FormatLinea.comprobarHoraActualizada(indice)){ if (fline.comprobarSiNuevasLineas()){ lista=fline.crearLineas(); for (j=0;j<lista.length;j++){ lista_cadenas.add(lista[j]); } linea_leida = linea_leida+lista.length; } lista_cadenas.add(fline.formatearLinea()); linea_leida++; } }

(22)

if (linea_leida < TOTAL_LINEAS){

for (int l=linea_leida;l<TOTAL_LINEAS;l++){ lista_cadenas.add(fline.crearLineaVacia(l)); linea_leida++; } } }

catch (Exception e){

System.out.println("Exception 1 capturada "+e); } stdin.close(); } catch(Exception e){ System.out.println("Exception 2 capturada"); } }

public String obtenerFecha(){

StringTokenizer s = new StringTokenizer(file_name,"-"); s.nextToken();

String year = s.nextToken(); String mes = s.nextToken(); String dia = s.nextToken();

String fecha = dia +"-"+mes+"-"+year; return fecha; } }

FormatLinea.java

import java.util.ArrayList; import java.util.StringTokenizer; import java.util.Hashtable; public class FormatLinea {

final static String HORARIO_INICIAL[] = {"12:00 AM","12:30 AM","1:00 AM","1:30 AM","2:00 AM","2:30 AM","3:00 AM","3:30 AM","4:00 AM","4:30 AM","5:00 AM","5:30 AM","6:00 AM","6:30 AM","7:00 AM","7:30 AM","8:00 AM","8:30 AM","9:00 AM","9:30 AM","10:00 AM","10:30 AM","11:00 AM","11:30 AM","12:00 PM","12:30 PM","1:00 PM","1:30 PM","2:00 PM","2:30 PM","3:00 PM","3:30 PM","4:00 PM","4:30 PM","5:00 PM","5:30 PM","6:00 PM","6:30 PM","7:00 PM","7:30 PM","8:00 PM","8:30 PM","9:00 PM","9:30 PM","10:00 PM","10:30 PM","11:00 PM","11:30 PM"};

final static String HORARIO_FINAL[] =

{"0:00","0:30","1:00","1:30","2:00","2:30","3:00","3:30","4:00","4:30","5:00","5:30",

"6:00","6:30","7:00","7:30","8:00","8:30","9:00","9:30","10:00","10:30","11:00","11:30","12:00", "12:30","13:00","13:30","14:00","14:30","15:00","15:30","16:00","16:30","17:00","17:30",

"18:00","18:30","19:00","19:30","20:00","20:30","21:00","21:30","22:00","22:30","23:00","23:30"}; final static int NUM_PARAMS = 13;

final static int HORA_FIELD = 1; final static int PRESION_FIELD = 5; final static int FECHA_FIELD = 0; final static int EVENTOS_FIELD = 11; final static String DEFAULT = "?";

static Hashtable control_horario = new Hashtable();

ArrayList horas; /* utilizado para facilitar el proceso de busqueda */ ArrayList parametros; /* vector de parametros leido */

int puntero; int index;

static void inicializarControlHorario(){ for (int i=0;i<HORARIO_INICIAL.length;i++){

control_horario.put(HORARIO_INICIAL[i],new Integer(0)); // indicar que todavía no se ha formateado dicha linea

} }

(23)

if (control_horario.containsKey(HORARIO_INICIAL[hora_key])){ control_horario.put(HORARIO_INICIAL[hora_key],new Integer(1)); }

}

static boolean comprobarHoraActualizada(int hora_key){

// devolverá 1 cuando ya se haya leido la linea correspondiente a dicha hora

if( control_horario.containsKey(HORARIO_INICIAL[hora_key])){

Integer ni = (Integer) control_horario.get(HORARIO_INICIAL[hora_key]); if (ni.intValue()==1) { return true; } } return false; }

static boolean comprobarHorarioIncompleto(){ // comprobar si hay una linea que no se ha formateado o no está leida.

return control_horario.containsValue(new Integer(0)); }

/** Creates a new instance of FormatLinea */

public FormatLinea(String s,String fecha_fich,int linea_leida) {

horas = new ArrayList();

for (int i = 0;i<HORARIO_INICIAL.length;i++){ horas.add(HORARIO_INICIAL[i]); } puntero = linea_leida; /* Vector de parametros */ /*fecha,hora,temperatura,rocio,humedad,presion,visibilidad,dir_viento,vel_viento,rafaga, precipitacion,eventos,condiciones;*/

String linea[] = s.split(","); parametros = new ArrayList(); parametros.add(fecha_fich);

for (int x=0; x<linea.length; x++){ if (linea[x].equals("-")) linea[x] = DEFAULT; parametros.add(linea[x]); } if ((parametros.size()<NUM_PARAMS)){

for (int b = parametros.size();b<NUM_PARAMS;b++){ parametros.add(DEFAULT); } } index = 0; }

/* usado para comprobar si el dato leido corresponde a uno de los datos que queremos utilizar en el preprocesado*/

/* ver HORARIO_INICIAL, valores permitidos en el campo horas */

public int obtenerIndice(){

index = horas.indexOf(parametros.get(HORA_FIELD)); return index;

}

public boolean comprobarSiNuevasLineas(){

return (index!=puntero); }

(24)

for (int j=0;j<num_lineas;j++){ nuevas_lineas[j]=this.crearLineaVacia(puntero+j); } return nuevas_lineas; }

public String crearLineaVacia(int index){

String linea_vacia = parametros.get(FECHA_FIELD)+","+HORARIO_FINAL[index]+",";

for (int i=HORA_FIELD+1;i<NUM_PARAMS-1;i++){ linea_vacia=linea_vacia.concat(DEFAULT+","); } linea_vacia=linea_vacia.concat(DEFAULT); return linea_vacia; }

public String formatearLinea(){

String linea_final = new String(); int i = 0;

// 1.- Modificar el formato de las horas: 12:00 AM -> 0:00, y 11'30 PM -> 23:00 parametros.set(HORA_FIELD,HORARIO_FINAL[index]); if (parametros.get(8).equals("Calm")){ parametros.set(8,"0.0"); }

// 3.-Crear la linea a devolver

/* Cuando el campo eventos está vacio, al realizar la segmentación con StringTokenizer, no ha parece un Token

*asociado a dicho campo. El tamaño del vector de parametros es menor a la longitud verdadera de dicho vector.

Vamos a añadir el caracter - para indicar que está vacio */ for (i = 0;i<NUM_PARAMS;i++){ linea_final=linea_final.concat((String) parametros.get(i)); if (i<NUM_PARAMS-1) linea_final=linea_final.concat(","); }

// 4.- Reemplazar la cadena ",," por ",?," linea_final = linea_final.replaceAll(",,", ",?,"); // 5.- Quitar el simbolo % linea_final = linea_final.replaceAll("%", "");

// 2.- Comprobar si la humedad tiene como valor -9999 y en tal caso sustituir por -

linea_final = linea_final.replaceAll("-9999.0", DEFAULT); linea_final = linea_final.replaceAll("-9999", DEFAULT);

// Sustituir N/A por el valor por defecto.

linea_final = linea_final.replaceAll("N/A", DEFAULT);

// 5.- Actualizar control de lineas formateadas actualizarControlHorario(index); return linea_final; } public FormatLinea(){ } }

(25)

Anexo II. Ficheros en MatLab utilizados para el

preprocesado

Mezclado e Interpolación

filtro_mezclador.m

num_lineas=48*3045+1; % n= num_lineas;;

% convertir el fichero LEMD.arff a matriz

[fecha_lemd,hora_lemd,temperatura_lemd,rocio_lemd,humedad_lemd,presion_lemd,visibilidad_lemd, dir_viento_lemd,vel_viento_lemd,rafaga_lemd,lluvia_lemd,eventos_lemd,condiciones_lemd] = textread('LEMD.arff', '%s %s %s %s %s %s %s %s %s %s %s %s %s',num_lineas,'delimiter',','); matriz_lemd = [fecha_lemd hora_lemd temperatura_lemd rocio_lemd humedad_lemd presion_lemd visibilidad_lemd dir_viento_lemd vel_viento_lemd rafaga_lemd lluvia_lemd eventos_lemd condiciones_lemd];

[num_filas_lemd,num_columnas_lemd]=size(matriz_lemd); A=matriz_lemd(2:num_filas_lemd,:);

[num_filas_lemd,num_columnas_lemd]=size(A); % convertir el fichero LEVS.arff a matriz

[fecha_levs,hora_levs,temperatura_levs,rocio_levs,humedad_levs,presion_levs,visibilidad_levs, dir_viento_levs,vel_viento_levs,rafaga_levs,lluvia_levs,eventos_levs,condiciones_levs] = textread('LEMD.arff', '%s %s %s %s %s %s %s %s %s %s %s %s %s',num_lineas,'delimiter',','); matriz_levs = [fecha_levs hora_levs temperatura_levs rocio_levs humedad_levs presion_levs visibilidad_levs dir_viento_levs vel_viento_levs rafaga_levs lluvia_levs eventos_levs condiciones_levs];

[num_filas_levs,num_columnas_levs]=size(matriz_levs); B=matriz_levs(2:num_filas_levs,:);

[num_filas_levs,num_columnas_levs]=size(B);

% Crear una matriz donde los elemntos no vacios si son numericos son la % media de ambos y si son alfanumericos un valor de ambos escogido

% aleatoriamente. En caso de ausencia de un elemento, se usara el otro. Si % ambos elementos son elementos vacios, dicho elemento en la nueva matriz % tambien sera un elemento vacio

% sabemos que ambas matrices tienen el mismo tamaño if (size(matriz_lemd)==size(matriz_levs)) C = cellstr(char(zeros(num_filas_lemd,num_columnas_lemd))); C(:,1:2)=A(:,1:2); for i=1:num_filas_lemd for j=3:num_columnas_lemd

if (strcmp(A(i,j),'?')& strcmp(B(i,j),'?')) % Ambos elementos estan vacios C(i,j)=A(i,j);

elseif ((strcmp(B(i,j),'?'))& (~ strcmp(A(i,j),'?'))) % Elemento B vacio C(i,j)=A(i,j);

elseif ((strcmp(A(i,j),'?'))& (~ strcmp(B(i,j),'?'))) % Elemento A vacio C(i,j)=B(i,j);

else % ambos elementos no vacios

switch (j)

case {3,4,7,9}

% tomamos valores medios b = (str2num(char(A(i,j)))+str2num(char(B(i,j))))/2; C(i,j)=cellstr(num2str(b)); % FALTA case{5} b = (str2num(char(A(i,j)))+str2num(char(B(i,j))))/2; C(i,j)=cellstr(num2str(b)); % FALTA

(26)

% escogemos valor aleatorio if (mod(round(10*rand(1)),2)==1) C(i,j)=A(i,j); else C(i,j)=B(i,j); end end end end end end

filtro_interpolador.m

function [A] = filtro_interpolador(B) % num_lineas=48*3045+1; % % [a b c d e f g]=textread('LEMD.arff','%s %s %s %s %s %s %s',5,'delimiter',',') % % fid = fopen('LEMD.arff'); % [fecha,hora,temperatura,rocio,humedad,presion,visibilidad,dir_viento,vel_viento,rafaga,lluvia, eventos,condiciones] = textread('LEMD.arff', '%s %s %s %s %s %s %s %s %s %s %s %s %s',num_lineas,'delimiter',','); % % fclose(fid);

% interpolador = [fecha hora temperatura rocio humedad presion visibilidad dir_viento vel_viento rafaga lluvia eventos condiciones];

% [num_filas,num_columnas]=size(interpolador); % A=interpolador(2:num_filas,:); A = B; [num_filas,num_columnas]=size(A); for i=1:num_filas for j=3:num_columnas

% comprobar si el parametro es una '?' en tal caso siempre que la % instancia anterior y la posterior (sin salirnos de los limites) % tengan valores, tomaremos el valor medio exceptuando para los % campos que son cadenas de texto: condiciones(13) y dir_viento(8) % donde tomaremos aleatoriamente uno de los dos resultados.

% No interpolamos ni rafaga(10), ni lluvia(11) ni eventos(12) % porque disponemos de pocos datos y no los vamos a usar para % predecir. if ((i==1)&(strcmp(A(i,j),'?'))&(~ strcmp(A(i+1,j),'?'))&((j<10)|(j==8)|(j==13))) % primer elemento A(i,j)=A(i+1,j); elseif ((i==num_filas)&(strcmp(A(i,j),'?'))&(~strcmp(A(i-1,j),'?'))&((j<10)|(j==8)|(j==13))) % ultimo elemento A(i,j)=A(i-1,j);

else % resto de elementos

if ((i~=1)&(i~=num_filas)&(strcmp(A(i,j),'?'))&(~ strcmp(A(i-1,j),'?'))&(~ strcmp(A(i+1,j),'?')))

% podemos modificar switch (j)

case {3,4,7,9}

% tomamos valores medios b = (str2num(char(A(i-1,j)))+str2num(char(A(i+1,j))))/2; A(i,j)=cellstr(num2str(b)); % FALTA case{5} b = (str2num(char(A(i-1,j)))+str2num(char(A(i+1,j))))/2; A(i,j)=cellstr(num2str(b)); % FALTA case{6} b = (str2num(char(A(i-1,j)))+str2num(char(A(i+1,j))))/2; A(i,j)=cellstr(num2str(b)); % FALTA case {8,13}

% escogemos valor aleatorio if (mod(round(10*rand(1)),2)==1) A(i,j)=A(i+1,j);

else

(27)

end end end end end end

Vector de Parámetros

Mineria_temperatura_1h.m

function [minero] = mineria_temperatura_1h(D) %

% Creacion de la matriz de mineria para el fichero de training para predecir la temperatura con un

% margen de precision de una hora. %

% El vector de parametros que vamos a utilizar es el que sigue:

% [temperatura,rocio,vel_viento,condiciones] = [3,4,9,13] de las muestras 3 % muestras anteriores, asi como la media de la temperatura y el rocio de % las 24 instancias anterirores segmentadas de 6 en 6.

% Segmentaremos los datos por la fecha de estos....

% Esto implica un vector de 42 parametros, posteriormente usaremos el % selector de parametros para obtener cuales son los parametros utiles. % En la matriz de mineria incluiremos tambien tres columnas mas

% correspondientes al vector que queremos predecir: [fecha,hora,temperatura] W = 24; param = [3 4 9 13]; [nrow,ncol]=size(D); % for i=1:nrow; % if(strcmp(D(i,1),'01-01-2004')) % nrow_train=i-1 % break; % end % end minero = cell(nrow-W,18); [mr,mc]=size(minero); media1 = cellstr('?'); media2 = cellstr('?'); media3 = cellstr('?'); media4 = cellstr('?'); for i=1:mr

if( 1,3),'?')) & 2,3),'?')) & 3,3),'?')) & 4,3),'?')) & 5,3),'?')) & (~strcmp(D(W+i-6,3),'?')))

media1 = mean([str2num(char(D(W+i-1,3))) str2num(char(D(W+i-2,3))) str2num(char(D(W+i-3,3))) str2num(char(D(W+i-4,3))) str2num(char(D(W+i-5,3))) str2num(char(D(W+i-6,3)))]);

media1 = cellstr(num2str(media1)); end

if( 7,3),'?')) & 8,3),'?')) & 9,3),'?')) & 10,3),'?')) & 11,3),'?')) & (~strcmp(D(W+i-12,3),'?')))

media2 = mean([str2num(char(D(W+i-7,3))) str2num(char(D(W+i-8,3))) str2num(char(D(W+i-9,3))) str2num(char(D(W+i-10,3))) str2num(char(D(W+i-11,3))) str2num(char(D(W+i-12,3)))]);

media2 = cellstr(num2str(media2)); end

if( 13,3),'?')) & 14,3),'?')) & 15,3),'?')) & 16,3),'?')) & 17,3),'?')) & (~strcmp(D(W+i-18,3),'?')))

(28)

if( 19,3),'?')) & 20,3),'?')) & 21,3),'?')) & 22,3),'?')) & 23,3),'?')) & (~strcmp(D(W+i-24,3),'?')))

media4 = mean([str2num(char(D(W+i-19,3))) str2num(char(D(W+i-20,3))) str2num(char(D(W+i-21,3))) str2num(char(D(W+i-22,3))) str2num(char(D(W+i-23,3))) str2num(char(D(W+i-24,3)))]);

media4 = cellstr(num2str(media4)); end

minero(i,:)=[D(i+W-1,param) D(i+W-2,param) D(i+W-3,param) media1 media2 media3 media4 D(i+W,[1 3])];

% _matrix(i,:)=[D(i-1,param) D(i-2,param) D(i-3,param) D(i-4,param) D(i-5,param) D(i-6,param) D(i,[1 2 3])];

end

% Segmentar en entrenamiento y evaluacion % [rowmin,colmin]=size(minero);

Mineria_temperatura_24h.m

function [minero] = mineria_temperatura_24h(D) %

% Creacion de la matriz de mineria para el fichero de training para predecir la temperatura con un

% margen de precision de 24 hora. %

% El vector de parametros que vamos a utilizar es el que sigue: % [temperatura,rocio,vel_viento] = [3,4,9] de las muestras 5

% muestras anteriores, asi como la media de la temperatura y el rocio de la % media de las 72 horas anteriores: escogemos 12 muestras por dia.

% Segmentaremos los datos por la fecha de estos.... W = 72; param = [3 4 9]; [nrow,ncol]=size(D); % for i=1:nrow; % if(strcmp(D(i,1),'01-01-2004')) % nrow_train=i-1 % break; % end % end minero = cell(nrow-W,20); [mr,mc]=size(minero); media1 = cellstr('?'); media2 = cellstr('?'); media3 = cellstr('?'); for i=1:mr

if (2,3),'?')) & 4,3),'?')) & 6,3),'?')) & 8,3),'?')) & 10,3),'?')) & 12,3),'?')) & 14,3),'?')) & 16,3),'?')) & 18,3),'?')) & 20,3),'?')) & 22,3),'?')) & (~strcmp(D(W+i-24,3),'?')))

media1 = mean([str2num(char(D(W+i-2,3))) str2num(char(D(W+i-4,3))) str2num(char(D(W+i-6,3))) str2num(char(D(W+i-8,3))) str2num(char(D(W+i-10,3))) str2num(char(D(W+i-12,3))) str2num(char(D(W+i-14,3))) str2num(char(D(W+i-16,3))) str2num(char(D(W+i-18,3))) str2num(char(D(W+i-20,3))) str2num(char(D(W+i-22,3))) str2num(char(D(W+i-24,3)))]);

media1 = cellstr(num2str(media1)); end

if (26,3),'?')) & 28,3),'?')) & 30,3),'?')) & 32,3),'?')) & 34,3),'?')) & 36,3),'?')) & 38,3),'?')) & 40,3),'?')) & 42,3),'?')) & 44,3),'?')) & 46,3),'?')) &

(29)

(~strcmp(D(W+i-48,3),'?')))

% if( 7,3),'?')) & 8,3),'?')) & 9,3),'?')) & 10,3),'?')) & 11,3),'?')) & (~strcmp(D(W+i-12,3),'?')))

media2 = mean([str2num(char(D(W+i-26,3))) str2num(char(D(W+i-28,3))) str2num(char(D(W+i-30,3))) str2num(char(D(W+i-32,3))) str2num(char(D(W+i-34,3))) str2num(char(D(W+i-36,3))) str2num(char(D(W+i-38,3))) str2num(char(D(W+i-40,3))) str2num(char(D(W+i-42,3))) str2num(char(D(W+i-44,3))) str2num(char(D(W+i-46,3))) str2num(char(D(W+i-48,3)))]);

% media2 = mean([str2num(char(D(W+i-7,3))) str2num(char(D(W+i-8,3))) str2num(char(D(W+i-9,3))) str2num(char(D(W+i-10,3))) str2num(char(D(W+i-11,3))) str2num(char(D(W+i-12,3)))]);

media2 = cellstr(num2str(media2)); end

if (50,3),'?')) & 52,3),'?')) & 54,3),'?')) & 56,3),'?')) & 58,3),'?')) & 60,3),'?')) & 62,3),'?')) & 64,3),'?')) & 66,3),'?')) & 68,3),'?')) & 70,3),'?')) & (~strcmp(D(W+i-72,3),'?')))

media3 = mean([str2num(char(D(W+i-50,3))) str2num(char(D(W+i-52,3))) str2num(char(D(W+i-54,3))) str2num(char(D(W+i-56,3))) str2num(char(D(W+i-58,3))) str2num(char(D(W+i-60,3))) str2num(char(D(W+i-62,3))) str2num(char(D(W+i-64,3))) str2num(char(D(W+i-66,3))) str2num(char(D(W+i-68,3))) str2num(char(D(W+i-70,3))) str2num(char(D(W+i-72,3)))]);

% if( 13,3),'?')) & 14,3),'?')) & 15,3),'?')) & 16,3),'?')) & 17,3),'?')) & (~strcmp(D(W+i-18,3),'?')))

% media3 = mean([str2num(char(D(W+i-13,3))) str2num(char(D(W+i-14,3))) str2num(char(D(W+i-15,3))) str2num(char(D(W+i-16,3))) str2num(char(D(W+i-17,3))) str2num(char(D(W+i-18,3)))]);

media3 = cellstr(num2str(media3)); end

% if( 19,3),'?')) & 20,3),'?')) & 21,3),'?')) & 22,3),'?')) & 23,3),'?')) & (~strcmp(D(W+i-24,3),'?')))

% media4 = mean([str2num(char(D(W+i-19,3))) str2num(char(D(W+i-20,3))) str2num(char(D(W+i-21,3))) str2num(char(D(W+i-22,3))) str2num(char(D(W+i-23,3))) str2num(char(D(W+i-24,3)))]);

% media4 = cellstr(num2str(media4)); % end

minero(i,:)=[1,param) 2,param) 3,param) 4,param) D(i+W-5,param) media1 media2 media3 D(i+W,[1 3])];

% _matrix(i,:)=[D(i-1,param) D(i-2,param) D(i-3,param) D(i-4,param) D(i-5,param) D(i-6,param) D(i,[1 2 3])];

end

% Segmentar en entrenamiento y evaluacion % [rowmin,colmin]=size(minero);

Mineria_condiciones_24h.m

function [minero] = mineria_condiciones_24h(D) %

% Creacion de la matriz de mineria para el fichero de training para predecir la temperatura con un

% margen de precision de 24 hora. %

% El vector de parametros que vamos a utilizar es el que sigue:

% [temperatura,rocio,vel_viento,condiciones] = [3,4,9,13] de las muestras 5 % muestras anteriores, asi como la media de la temperatura de

(30)

[nrow,ncol]=size(D); % for i=1:nrow; % if(strcmp(D(i,1),'01-01-2004')) % nrow_train=i-1 % break; % end % end minero = cell(nrow-W,25); [mr,mc]=size(minero); media1 = cellstr('?'); media2 = cellstr('?'); media3 = cellstr('?'); for i=1:mr

if (2,3),'?')) & 4,3),'?')) & 6,3),'?')) & 8,3),'?')) & 10,3),'?')) & 12,3),'?')) & 14,3),'?')) & 16,3),'?')) & 18,3),'?')) & 20,3),'?')) & 22,3),'?')) & (~strcmp(D(W+i-24,3),'?')))

media1 = mean([str2num(char(D(W+i-2,3))) str2num(char(D(W+i-4,3))) str2num(char(D(W+i-6,3))) str2num(char(D(W+i-8,3))) str2num(char(D(W+i-10,3))) str2num(char(D(W+i-12,3))) str2num(char(D(W+i-14,3))) str2num(char(D(W+i-16,3))) str2num(char(D(W+i-18,3))) str2num(char(D(W+i-20,3))) str2num(char(D(W+i-22,3))) str2num(char(D(W+i-24,3)))]);

media1 = cellstr(num2str(media1)); end

if (26,3),'?')) & 28,3),'?')) & 30,3),'?')) & 32,3),'?')) & 34,3),'?')) & 36,3),'?')) & 38,3),'?')) & 40,3),'?')) & 42,3),'?')) & 44,3),'?')) & 46,3),'?')) & (~strcmp(D(W+i-48,3),'?')))

% if( 7,3),'?')) & 8,3),'?')) & 9,3),'?')) & 10,3),'?')) & 11,3),'?')) & (~strcmp(D(W+i-12,3),'?')))

media2 = mean([str2num(char(D(W+i-26,3))) str2num(char(D(W+i-28,3))) str2num(char(D(W+i-30,3))) str2num(char(D(W+i-32,3))) str2num(char(D(W+i-34,3))) str2num(char(D(W+i-36,3))) str2num(char(D(W+i-38,3))) str2num(char(D(W+i-40,3))) str2num(char(D(W+i-42,3))) str2num(char(D(W+i-44,3))) str2num(char(D(W+i-46,3))) str2num(char(D(W+i-48,3)))]);

% media2 = mean([str2num(char(D(W+i-7,3))) str2num(char(D(W+i-8,3))) str2num(char(D(W+i-9,3))) str2num(char(D(W+i-10,3))) str2num(char(D(W+i-11,3))) str2num(char(D(W+i-12,3)))]);

media2 = cellstr(num2str(media2)); end

if (50,3),'?')) & 52,3),'?')) & 54,3),'?')) & 56,3),'?')) & 58,3),'?')) & 60,3),'?')) & 62,3),'?')) & 64,3),'?')) & 66,3),'?')) & 68,3),'?')) & 70,3),'?')) & (~strcmp(D(W+i-72,3),'?')))

media3 = mean([str2num(char(D(W+i-50,3))) str2num(char(D(W+i-52,3))) str2num(char(D(W+i-54,3))) str2num(char(D(W+i-56,3))) str2num(char(D(W+i-58,3))) str2num(char(D(W+i-60,3))) str2num(char(D(W+i-62,3))) str2num(char(D(W+i-64,3))) str2num(char(D(W+i-66,3))) str2num(char(D(W+i-68,3))) str2num(char(D(W+i-70,3))) str2num(char(D(W+i-72,3)))]);

% if( 13,3),'?')) & 14,3),'?')) & 15,3),'?')) & 16,3),'?')) & 17,3),'?')) & (~strcmp(D(W+i-18,3),'?')))

% media3 = mean([str2num(char(D(W+i-13,3))) str2num(char(D(W+i-14,3))) str2num(char(D(W+i-15,3))) str2num(char(D(W+i-16,3))) str2num(char(D(W+i-17,3))) str2num(char(D(W+i-18,3)))]);

media3 = cellstr(num2str(media3)); end

% if( 19,3),'?')) & 20,3),'?')) & 21,3),'?')) & 22,3),'?')) & 23,3),'?')) & (~strcmp(D(W+i-24,3),'?')))

% media4 = mean([str2num(char(D(W+i-19,3))) str2num(char(D(W+i-20,3))) str2num(char(D(W+i-21,3))) str2num(char(D(W+i-22,3))) str2num(char(D(W+i-23,3))) str2num(char(D(W+i-24,3)))]);

% media4 = cellstr(num2str(media4)); % end

minero(i,:)=[1,param) 2,param) 3,param) 4,param) D(i+W-5,param) media1 media2 media3 D(i+W,[1 13])];

Referencias

Documento similar

¿Cómo el sector veterinario en la ciudad de Tijuana Baja California pude desarrollar su competitividad en base al crecimiento de tenencia de mascotas no convencionales?.

Unha das principais razóns esgrimidas pola literatura para xustificar a introdu- ción de regras fiscais nunha unión monetaria era precisamente esa: que a súa ine- xistencia podía

El presente estudio fue realizado para determinar la longevidad y el ciclo gonotrófico en 594 mosquitos de la especie Aedes aegypti en el municipio de Girardot en condiciones

“somos nosotros mismos los que vamos a reconstruir a Puerto Rico y tenemos que tener paciencia, que a lo mejor quisiéramos resolverlo todo con una varita mágica de hoy para mañana,

Esta corriente dentro de la arquitectura, registra al Diseño como herramienta fundamental para mejorar la sustentabilidad en el hábitat.. Es más abarcativa que la corriente

Este libro intenta aportar al lector una mirada cuestiona- dora al ambiente que se desarrolló en las redes sociales digitales en un escenario de guerra mediática mantenido por

- Un curso formativo para los técnicos de laboratorio de la UPV sobre la prevención de los residuos en los laboratorios, que se llevará a cabo los días 23, 24, 25, 26 y 27

En tales circunstancias, una forma de proceder posible sería iniciar una fase preconstitucional de diálogo nacional, como sucedió en Sudáfrica, para reunir a