Clasificación avanzada: métodos kernel y SVM ,un ejemplo práctico

Puesto que las máquinas de vectores soporte funcionan bien con conjuntos de datos de altas dimensiones, se aplican más a menudo a problemas científicos con muchos datos y otros problemas que tratan con conjuntos de datos muy complejos. Algunos ejemplos incluyen:

  1. Clasificar expresiones faciales
  2. Detectar intrusos utilizando conjuntos de datos
  3. Predecir la estructura de colaboración entre dos planes de estudios
  4. Reconocimiento de escritura
  5. Determinar el potencial de un alumno en función de sus ejercicios

El problema de estos algoritmos es que necesitan un entrenamiento para conseguir unos resultados fiables, y esto implica conceptos matemáticos que requieren muchos recursos de la máquina…

Una librería que ayuda en el proceso se llama LIBSVM , se puede descargar en http://www.csie.ntu.edu.tw/~cjlin/libsvm/, está escrito en C++ e incluye una versión en Java, sin embargo el paquete incluye un evoltorio para Python llamado svm.py, se necesita la versión compilada para la plataforma usada.

Ahora veremos un ejemplo para el caso 3 propuesto antes: predecir la estructura de colaboración entre dos planes de estudios utilizando los datos de la red social de facebook, probablemente sea una buena idea combinar datos dentro de la plataforma, provinientes de varias redes sociales, aunque nos encargaremos sólo de una para que no se nos escape de las manos.

Lo primero es crear un conjunto de datos de concordancia desde Facebook, para ello necesitaremos la siguiente llamada a la API:

import facebook
s = facebook.fbsession()
amigos = s.obtenerAmigos()

Ahora podemos utilizar amigos[1] ;  s.obtenerInfo(amigos[0:2]) como “respuesta” en nuestro nuevo conjunto de datos. La llamada permite pasar dos listas de ID de igual longitud y devolver una lista con un número para cada par , 1 si las personas son amigos y 0 si no lo son. Puedes usar una clase como esta:

class fbsession:
def __init_ _(self):
self.session_secret = None
self.session_key = None
self.token = self.createtoken()
webbrowser.open(self.getlogin())
print "Pulsa enter tras el login:",
raw_input()
self.getsession()
def sendrequest(self, args):
args['api_key'] = apikey
args['sig¡] = self.makehash(args)
post_data = urllib.urlencode(args)
url = FacebookURL + "?" + post_data
data = urllib.urlopen(url).read()
return parseString(data)

def makehash(self, args):
hasher = md5.new(''.join(
[x+'='+args[x] for x in sorted (
args.keys())]))
if self.session_secret:
 hasher.update(self.session_secret)
else:
 hasher.update(secret)
return hasher.hexdigest()

def createtoken(self):
res = self.sendrequest({'method':
"facebook.auth.createToken"})
self.token = getsinglevalue(res, 'token')

def getlogin(self):
return "http://api.facebook.com/login.php?api_key="+\
apikey+"&auth_token="+self.token

def obtenerAmigos(self):
doc = self.sendrequest({'method':'facebook.friends.get',
 'session_key':self.session_key,'call_id':callid()})
results = []
for n in doc.getElementsByTagName('result_elt'):
results.append(n.firstChild.nodeValue)
return results

def obtenerInfo(self, usuarios):
ulist = ', '.join(usuarios)
campos = 'gender,current_location,
relationship_status,affiliations,hometown_location'
doc = self.sendrequest({'method':
'facebook.user.getInfo','session_key':
self.session_key, 'call_id':callid(),'users':ulist,
'fields':campos})
resultados = {}
for n,id in zip(doc.getElementsbyTagName('result_elt'),users):
# obtener ubicación
locnode = n.getElementsByTagName('hometown_location')[0]
loc = getsinglevalue(locnode,'city')+', '+\
getsinglevalue(locnode, 'state')
# obtener la escuela
escuela = ''
graduanio = '0'
asocia = n.getElementsByTagName('affiliations_elt')
for aso in asocia:
#tipo 1 es universidad:
if getsinglevalue(aso, 'type') == '1':
escuela = getsinglevalue(aso, 'name')
graduanio = getsinglevalue(aso, 'year')

resultados[id] = {'sexo':getsinglevalue(n,'gender'),
 'estado':getsinglevalue(n,'relationship_status'),
'direccion':loc, 'escuela': escuela, 'graduanio':graduanio}
return resultados

def sonamigos(self, idlist1, idlist2):
id1 = ','.join(idlist1)
id2 = ','.join(idlist2)
doc= self.sendrequest({'method':
'facebook.friends.areFriends',
'session_key':self.session_key, 'call_id':callid(),
'id1':id1 , 'id2': id2})
resultados = []
for n in doc.getElementByTagName('result_elt'):
resultados.append(n.firstChild.nodeValue)
return resultados

La función más compleja y larga es la que junta todos los datos para crear un conjunto de datos que funciona con LIBSVM; obtiene una lista de todos los amigos del usuario conectado en esta iteración, y descarga información sobre aquellos, creando una fila para cada par de personas, luego comprueba cada par para ver si son amigos, habría que ver si comparten la aplicación instalada de la plataforma y si comparten un grupo. Función makedataset:

def makedataset(self):
from advancedclassify import milesdistance
#obtiene toda la info de todos los amigos:
amigos = self.obtenerAmigos()
info = self.obtenerInfo(amigos)
ids1, ids2 = [], []
filas = []
#Bucle anidado para examinar cada par de amigos:
for i in range(len(amigos)):
a1 = amigos[i]
datos1 = info[a1]
#Empezar en i+1
for j in range(i+1, len(amigos)):
a2 = amigos[j]
datos2 = info[a2]
ids1.append(a1)
ids2.append(a2)
#Generar algunos numeros desde los datos:
if datos1['escuela'] == datos2['escuela']: mismaescuela = 1
else : mismaescuela = 0
ciudad = (datos1['direccion']==datos2['direccion']) and 1 or 0
relacion = (datos1['estado']==datos2['estado']) and 1 or 0
fila = [ciudad,int(datos1['graduanio']),relacion,int(datos2['graduanio']),mismaescuela]
filas.append(fila)
#Invocar al método sonAmigos() en bloques para cada par de personas:
loson = []
for i in range(0,len(ids1),30):
j  = min(i+20,len(ids))
pa = self.sonamigos(ids1[i:j],ids2[i:j])
loson += pa
return loson, filas

Este método cambia la localización (ciudad) y estado de la relación a números para que puedan ser utilizados directamente por LIBSVM, el último bucle solicita el estatus de amigo de cada par de personas en el bloque, ya que Facebook limita la longitud de una sóla petición.

Para crear un modelo SVM:

reload(facebook)
s=facebook.fbsession)=
answer,data=s.makedataset()

Deberíamos poder ejecutar los métodos sym directamente:

param = svm_parametrer (kernel_type=RBF)
prob = svm_problem(answers,data)
m=svm_model(prob,param)
m.predict([1,2003,1,2003,1]) #dos personas de la misma ciudad ,año y escuela
m.predict([1,2003,1,1996,0]) #diferentes años ,diferentes escuelas

Por supuesto los resultados variarán, el modelo determinará que las personas que fueron al mismo colegio o eran de la misma ciudad ,probablemente sean amigos , dos personas de la misma universidad, o de las misma asignaturas, posiblemente estaría bien que fueran amigos para compartir conocimientos y ayudarse mutuamente.

Deja un comentario