dimarts, 14 de maig del 2013

GHAP-BI: OLAP project with only open source tools

At this time, we are finishing the second course that GHAP is running. GHAP is an attendance control software and plus.

Previous GHAP feature was the ability to predict students attendance, a mix of Knime decision tree model and python lxml module to read resulting PMML. 


The new GHAP big feature is the Business Intelligence module. GHAP is for public schools, for this (and other) reason  only free software tools should be included. I'm used to develop BI projects but this is my first one with open software tools. In this post I explain GHAP-BI software components and experience.

As any BI solution GHAP-BI incorporates ETL and Data Analysis and visualization software.  

ETL is splitted as E+TL. The Extraction phase is made directly by GHAP application (django) and Transform and Load is made with pygrametl. This tool, pygrametl is praiseworthy: it is easy, fast and powerful and also clear documentation is available. 

I prefer OLAP solutions over Reporting solutions, I appreciate metadata layer with measures and dimensions, for this reason I have included Saiku software as viz software. I found Saiku through a post in stackoverflow.



ETL development: GHAP generates each night a 91MB text file (>500K lines), it takes over 4 hours to complete export. This file contains 1 course attendance controls full detailed. Then, a little python code load this data into Warehouse database. In 2 minutes all data is imported over 5 tables in snow-flock design. pygrametl is the piece that makes this possible combining dimension cache with bulk facts import. Notice that pygrametl could reduce drastically also export time avoiding database lookups, but I prefer to generate first text file.

Viz: Saiku is the front end for the users. You can learn about Saiku Pros and Cons reading @twn08 post, but this is my experience: I send GHAP-BI url, user and passwd to manager, 20 minutes later I move to manager's office to know if connection was successful and my surprise was to see Saiku page with a combination on filters, dimensions and measures and also with some sorted data! When user see me the question was: "how can I export this viz?" I realized than Saiku is a very friendly tool. Install Saiku is easy, I have apt-get installed tomcat6 and copy Saiku "binary" files into tomcat webapps folder, then change connections and schema.

DataWarehouse backend: Saiku perform MDX queries to Mondrian and Mondrian translate it to Relational Database. I have test with both MySQL and Postgres, this one, Postgres, is definitely the option adopted. Postgres serves in seconds queries that run forever in MySQL.

Cubes: I have wrote cube schema initially with Pentaho Schema Workbench, but I have left it when I have transformed dimensions to shared dimensions.



Summarizing, In 20 hours my open software BI solution was successfully running, thanks to: python, django, Saiku, Postgres and pygrametl.








dissabte, 6 d’abril del 2013

Em sento afortunat - Arbres de decisió

484mil controls d'assistència fins a l'abril
Amb data abril de 2013 es porten realitzats més de 484mil controls d'assistència a l'Institut mitjançant el programa GHAP. Un control d'assistència és determinar si un alumne assisteix a una hora de classe. És a dir, a un mateix alumne se li realitzen uns 6 controls d'assistència diari.

 Per facilitar la tasca del professor a l'hora de passar llista l'aplicatiu disposa de l'opció 'copiar assistència de l'hora anterior'. Aquesta opció funciona molt bé però depen de que el professor anterior hagi passat llista.

Amb l'esperit de facilitar la tasca del professorat, i d'entretenir-me jo mateix, he afegit la opció 'Em sento afortunat'. Triant aquesta opció l'aplicatiu fa una proposta de passar llista (a partir de la seva predicció).
Nova opció per passar llista: 'Em sento afortunat'

Però, quina lògica hi ha d'arrera d'aquesta opció?


Per a formular una predicció de control d'assistència l'aplicatiu utilitza una tècnica de mineria de dades, bé realment d' 'Aprenentatge Automàtic'. En concret, la tècnica que fa servir és la de predicció mitjançant  'arbre de decisió'. 

Per construir l'arbre de decisions he fet servir el programari Knime. I una exportació de dades dissociades de la base de dades del programari GHAP.

Les dades que he triat i que serveixen per a construir el model són les següents:


I en aquesta captura de pantalla es veu el procés de construcció del model:


El sistema de predicció utilitza tècnica de mineria de dades.
Un cop processat tenim un model informàtic en un format estandaritzat anomenat PMML (Predictive Model Markup Language). És un fitxer en XML d'un pes de mig mega. No he trobat cap utilitat python que a partir dels valors i el model em calculi la predicció, per això he escrit el meu propi algorisme, que he anomenat lightPMMLpredictor, i l'he integrat al GHAP. Si teniu interès podeu trobar una mostra de les dades utilitzades dins el propi projecte.

La representació gràfica d'aquest model és aquesta:


El factor principal determinat pel sistema és l'assistència a l'hora anterior.
La lectura d'aquest model seria: un 85.4% dels controls els marquem a 'Present', per tant, si haguès de fer una previsió diria 'Present'. Però, si tenim en compte l'assistència a l'hora anterior ens trobem que, si l'alumne era absent l'hora anterior el % de presencia a la següent hora es redueix fins un 14%. L'arbre no finalitza en aquest nivell sino que segueix afegint paràmetres a la decisió:


Tot i estar present l'hora anterior, el sistema prediu que faltarà un alumne de GS Admin. si ha faltat a la mateixa hora les tres setmana anteriors i és l'hora següent al pati.
Aquest esquema ens diu que un alumne que l'hora anterior hagi estat present, però, hagi faltat a la mateixa hora les tres setmana anterior, l'hora sigui les 18:05 (després del pati) i l'alumne sigui del grau superior d'administratiu, llavors el model aposta per que aquest alumne sigui absent ( 9 casos sobre 19).


Els models cal contrastar-los per saber si estan funcionant correctament. Normalment es reserva un 20% de les mostres per, en comptes de donar de menjar al programa que apren, s'utilitzin per contrastar el model. Jo aquest pas no l'he fet, però procuraré, d'aquí tres setmanes, comprovar la bondat del model amb els nous controls que es realitzin. Mentrestant animo als companys a sentir-se afortunats.

dilluns, 28 de gener del 2013

Corva epidèmica de la grip v.s. assistència a l'Institut


Corba epidèmica
Fa dos cursos tenim en marxa a l'Institut Cendrassos el programa de control d'assistència d'alumnes anomenat GHAP.

Ara que estem a 3 setmanes del pic màxim de grip, he volgut mirar com ens afectarà l'epidèmia en relació a l'assistència dels alumnes a les aules tot comparant-ho amb pics històrics.

Utilitzant les dades obertes i les dades tencades he elaborat el següent gràfic. En blau representat el número de faltes per setmana i en vermell les taxes setmanals de grip. Les puntes d'absència en blau segurament són vagues.

Obviament una sèrie de un curs acadèmic no ens aporta gran informació,


La sorpresa ha estat observar com les absències dels alumnes són inversament proporcionals a les taxes de grip.

Aquesta priàmide de taxa de grip per edats ens pot argumentar en part els resultats observats:


La segona explicació a la correlació inversa és que els professors de guardia no passen llista.

Per últim un gràfic incloent la temporada 2010-2011 en la que vam fer servir el programari de l'Institut Brugulat per a dur el control de presència. En aquella temporada el pic de grip va caure a la setmana 2.






dilluns, 31 de desembre del 2012

Exercicis de Primària amb Python V

Aquest és un exercici de Grafs extret del llibre Nou i Mig 8 de l'editorial Teide:


Plantejament


  • Identifiquem cada vertex amb una lletra.
  • Construim un diccionari python amb una 'cassella' per a cada vertex.
  • Fem una 'llista' (és una tupla en realitat) amb els parells de nodes adjacents.
  • Provem totes les permutacions de digits tot imprimint les que compleixen amb els requeriments de l'enunciat.

El codi del programa


from itertools import permutations, combinations_with_replacement

vertex = {}
for identificador in ( 'A','B','C','D','E','F' ):
    vertex[identificador] = None

adjacents = (
  ( 'A', 'B' ),  ( 'A', 'D' ),  ( 'A', 'E' ),  ( 'A', 'F' ),
  ( 'B', 'A' ),  ( 'B', 'D' ),  ( 'B', 'C' ),
  ( 'C', 'B' ),  ( 'C', 'D' ),  ( 'C', 'F' ),
  ( 'D', 'A' ),  ( 'D', 'B' ),  ( 'D', 'C' ),  ('D', 'E'),
  ( 'E', 'A' ),  ( 'E', 'D' ),  ( 'E', 'F' ),
  ( 'F', 'A' ),  ( 'F', 'C' ),  ( 'F', 'E' ),
)

digits = ( 5,6,7,8,9,10 )

for (vertex['A'], vertex['B'], vertex['C'], 
     vertex['D'], vertex['E'], vertex['F'], ) in permutations ( digits ):
    if all( vertex[ v1 ] - vertex[v2] != 1 for ( v1, v2) in adjacents ):
        print ( 'A:', vertex['A'], 'B:', vertex['B'], 'C:', vertex['C'], 
                'D:', vertex['D'], 'E:', vertex['E'], 'F:', vertex['F'] ) 


El resultat


dani@egg-v3:~/tmp/llu$ python vertexs.py 
('A:', 5, 'B:', 8, 'C:', 6, 'D:', 10, 'E:', 7, 'F:', 9)
('A:', 10, 'B:', 7, 'C:', 9, 'D:', 5, 'E:', 8, 'F:', 6)

Altres Exercicis

http://beutil.blogspot.com.es/search/label/python_i_exercicis_mates



diumenge, 30 de desembre del 2012

Exercicis de Primària amb Python IV

Enunciat

Aquest exercici no té enunciat. Nomès apareix aquesta imatge:



Entenc que és un exercici tipus 'xifres i lletres' i cal obtenir el resultat indicat amb una combinació d'operacions amb tots els dígits disponibles.

Recordo que aquests exercicis són de Nou i mig 8 és un llibre de l'editorial Teide.

Resolució:


  • Creo les operacions com diccionaris per tal de tenir el nom i la operació.
  • Faig una tupla amb les operacions que intervenen.
  • Faig una llista amb els dígits disponibles.
  • Poso en una variable el resultat desitjat.
  • Per últim, busco totes les possibles combinacions d'operacions preses de 4 en 4. Per a cada combinació busco totes les seves permutacions i les combino amb totes les permutacions dels dígits disponibles.
  • El resultat el comparo amb el resultat desitjat


El programa:



from itertools import permutations, combinations_with_replacement

operacions = {}
operacions['+'] =  lambda x,y: x+y
operacions['-'] =  lambda x,y: x-y
operacions['*'] =  lambda x,y: x*y
operacions['/'] =  lambda x,y: x/y

numeros = ( 22, 2, 10, 6, 11 )

resultat_desitjat = 201

for (A, B, C, D, E ) in permutations ( numeros ):
    for combinacio_operacio in combinations_with_replacement( operacions, 4 ):
        for ( op1, op2, op3, op4 ) in permutations( combinacio_operacio ):
                r1 = operacions[op1]( float( A ),  float( B ) )
                r2 = operacions[op2]( float( r1 ), float( C ) )
                r3 = operacions[op3]( float( r2 ), float( D ) )
                r4 = operacions[op4]( float( r3 ), float( E ) )
                if r4 == resultat_desitjat and r1 > 0 and r2 > 0 and r3 > 0 and r4 > 0:
                    print A, op1, B, op2, C, op3, D, op4, E



Els resultats:


dani@egg-v3:~/tmp/llu$ python batedora.py  | more
22 * 10 - 2 - 6 - 11
22 * 10 - 2 - 6 - 11
22 * 10 - 2 - 6 - 11
22 * 10 - 2 - 6 - 11
22 * 10 - 2 - 6 - 11
22 * 10 - 2 - 6 - 11




Altres Exercicis





dissabte, 29 de desembre del 2012

Sala Polivalent Ara:



Sala Polivalent fa 1700 anys:


Central Nuclear a Garona:


Sala Polivalent a L'Escala:




Exercicis de Primària amb Python III

Enunciat: 


  • Quant sumen els punts de les 28 fitxes del dòmino?

Plantejament:


  • Anomenarè família a totes les fitxes que tenen en comú una mateixa puntuació. Per exemple, la família del 0 (blanc) serà: 0:0, 0:1, 0:2, ... 0:6
  • Hem de tenir en compte que la fixa 1:0 i la fitxa 0:1 és la mateixa. Per tant, si a la família del 0 hem inclòs el 0:1, a la família de l'1 no podem incloure el 1:0. 
  • Per a solucionar el punt anterior, cada família es combinarà amb els punts començant pel seu doble:


0:0 0:1 0:2 0:3 0:4 ... 0:6
    1:1 1:2 1:3 1:4 ... 1:6
        2:2 2:3 2:4 ... 2:6
                    ...
                        6:6


  • Per últim, fem servir un acumulador per tal de saber quant punts portem.

Solució:

acumulador = 0
for familia in range(0,7):
    for n in range(familia,7):  #No comencem des de 0
                                #comencem des del doble X:X
        print familia,n
        acumulador += familia+n
print 'Total:', acumulador

Resultat:

$ python domino.py 
0 0
0 1
...
4 6
5 5
5 6
6 6

dimarts, 18 de desembre del 2012

Exercicis de primària amb Python II

A la mateixa pàgina que l'exercici anterior trobem aquest exercici altre exercici ('Nou i mig 8', editorial teide):




Com es pot veure no necessita enunciat.

Per resoldre'l utilitzem diferents recursos del llenguatge, destaco els diccionaris, els bucles niuats i les expressions lambda:


from itertools import combinations

suma = { 'operacio': lambda x,y: x+y, 'nom':'suma' }
resta = { 'operacio': lambda x,y: x-y, 'nom':'resta' }

operacions = ( suma, resta )
for op1 in operacions:
    for op2 in operacions:
        for op3 in operacions:
            for op4 in operacions:
                r1 = op1['operacio']( 10, 9)
                r2 = op2['operacio']( r1, 15)
                r3 = op3['operacio']( r2, 7 )
                r4 = op4['operacio']( r3, 4 )
                if r4 == 19:
                    print op1['nom'], op2['nom'], op3['nom'], op4['nom']


Resultat:

resta suma suma resta

Cal dir que les itertools ens permeten substituir els bucles niuats per un sol bucle:

http://stackoverflow.com/questions/1280667/in-python-is-there-an-easier-way-to-write-6-nested-for-loops




Altres Exercicis



diumenge, 16 de desembre del 2012

Python i els exercicis de Mates

Python és un llenguatge de programació d'alt nivell. El codi escrit amb Python és de fàcil lectura, això forma part de la filosofia del llenguatge. És per això que recomano aquest llenguatge a qui vulgui iniciar-se al món de la programació d'una manera autodidàcta.

Nou i mig 8 és un llibre de l'editorial Teide. Els problemes d'aquest llibre són molt gràfics i divertits.

Resoldre els problemes del Nou i mig amb Python és encara més divertit.

Aquest problema apareix a la pàgina 11 del llibre. Ens donen una figura en forma d'estrella, cada línia de la figura conté tres caselles, una al mig i una a cada extrem. Cal repartir els dígits de l'1 al 9 dins d'aquestes caselles de manera que els dígits de totes les línies sumin el mateix.

És a dir que A + B + C ha de sumar el mateix que C + D + E i així per totes les línies.

Per solucionar aquest problema amb python utilitzo la llibreria itertools, allà hi ha una funció que ella sola em fabricarà totes les possibles permutacions dels digits de l'1 al 9.

Provarem cada permutació per comprovar si cumpleix els requeriments de l'enunciat.

L'operador per a comparar és == per això apareix aquest operador dins la sentència 'if'.


from itertools import permutations

digits = ( 1, 2, 3, 4, 5, 6, 7, 8, 9)

for (A, B, C, D, E, F, G, H, I ) in permutations( digits ):
    if ( A + B + C == 
         C + D + E ==
         E + F + G ==
         G + B + H ==
         H + D + I ):
        print 'Solucio: ', A, B, C, D, E, F, G, H, I

El resultat:


Solucio:  1 5 9 2 4 8 3 7 6
Solucio:  1 5 9 4 2 6 7 3 8
Solucio:  1 6 8 3 4 9 2 7 5
Solucio:  1 6 8 4 ...



Altres Exercicis