#!/usr/bin/env python # coding: utf-8 # ![](imgs/miredtwitter_header2.png) #
#

# Recomendación de Información basada en
# Análisis de Redes Sociales
# y Procesamiento de Lenguaje Natural #

#

Trabajo Final de la Licenciatura en Ciencias de la Computación

#

Pablo Gabriel Celayes

#

Martes 30 de mayo de 2017

#
# # Resumen # # * Introducción # # * Herramientas # # * Datos # # * Predicción social # # * Agregando PLN # # * Conclusiones # # Introducción # ## Idea original # # - Recomendador *personalizado* de artículos basado en contenido ( NLP ) # - Mejorarlo con información social ( de fuentes externas o relaciones *inferidas* ) # - Preferencias de usuarios de Cogfor # # ![](imgs/cogfor.png) # ## Mutación # # - Set the datos propio ( usuarios, preferencias, conexiones ) # - Predecir preferencias usando información social # - Combinar con recomendación basada en contenido # # # Herramientas # # ## Datos # ![](imgs/tweepy.png) # ![](imgs/sqlalchemy.png) # # ## Grafos # ![](imgs/networkx.png) # ![](imgs/graphtool.png) # ## Análisis # ![](imgs/numpy.png) # ![](imgs/pandas.png) # ![](imgs/jupyter.png) # # ## ML + PLN # ![](imgs/sklearn.png) # ![](imgs/nltk.png) # ![](imgs/gensim.png) # ## Visualización # ![](imgs/bokeh.png) # ![](imgs/gephi_small.png) # # Datos: Grafo social # # - Todos los usuarios que sigo en Twitter # - relación $\texttt{seguir}$ entre ellos # - $1213$ nodos-usuarios # - $40489$ aristas-relaciones # ![](imgs/miredtwitter.png) # # # Datos: Contenido # # - *timelines* entre 18/3/2017 y 17/4/2017 (+ *retweets* y *favs*) # - $163173$ tweets totales. # - $109040$ en español # # # Predicción social # # ¿ Dado un usuario, cuanto puedo saber de sus preferencias sabiendo las de su entorno ? # # - **Contenido** = tweets en español # - **Preferencias** = retweets # - **Entorno** = seguidos + seguidos-por-seguidos # # ## Selección de usuarios # # * Al menos $100$ (re)tweets # * Al menos $100$ usuarios en su entorno # * $98$ usuarios # ## Tweets visibles # # * Contenido compartido por $u$ o sus seguidos # * Excluímos contenido generado por $u$ # * $ T_u := (\bigcup_{x \in \{ u \} \cup \texttt{seguidos}(u)} \texttt{timeline}(x)) - \{ t \in T | \texttt{autor}(t) = u \} $ # # * máximo $10000$ ( submuestra de negativos si es necesario ) # ## Extracción de características # # * Entorno $ E_u = (\bigcup_{x \in \{ u \} \cup \texttt{seguidos}(u)} \texttt{seguidos}(x)) - \{ u \} $ # * $E_u = \{u_1, u_2, \ldots , u_n \}$ y $T_u = \{ t_1, \ldots, t_m \}$ # # $$ # M_u := [ \verb|tweet_en_tl|(t_i, u_j) ]_{\substack{ 1 \leq i \leq m \\ 1 \leq j \leq n}} # $$ # # # $$ # y_u := [ \texttt{tweet_en_tl}(t_i, u) ]_{ 1 \leq i \leq m } # $$ # # # ## Problema de clasificación # # * Predecir $y_u$ en base a filas de $M_u$ # * Particionado: # * $70\%$ entrenamiento ($M^{en}_u, y^{en}_u$) # * $10\%$ ajuste ($M^{aj}_u, y^{aj}_u$) # * $20\%$ evaluación ($M^{ev}_u, y^{ev}_u$) # ## Support Vector Machines # # * Objetivo: **maximizar** margen y **minimizar** errores # * Funciones *kernel* permiten encontrar fronteras **no lineales**: # * *Radial Basis Function* # * Polinómico # # ![](imgs/svm_linsep_err.png) # # # ## Calidad de clasificación # # $$\texttt{precision} := \frac{|\{x_i | f(x_i) = 1 \text{ y } y_i = 1 \}|}{|\{x_i | f(x_i) = 1 \}|}$$ # # $$ $$ # # $$\texttt{recall} := \frac{|\{x_i | f(x_i) = 1 \text{ y } y_i = 1 \}|}{|\{x_i | y_i = 1 \}|}$$ # # $$ $$ # # $$\texttt{F1} := \frac{2}{\frac{1}{\texttt{precision}} + \frac{1}{\texttt{recall}}} = \frac{2 * \texttt{precision} * \texttt{recall} }{\texttt{precision} + \texttt{recall}}$$ # # # ## Ajuste de parámetros # # * Búsqueda exhaustiva $\verb|GridSearchCV|$ # * Validación cruzada en $3$ partes # * Objetivo: maximizar $F1$ # * Grilla: # ``` # { # "C": [ 0.01, 0.1, 1 ], # "class_weight": [ "balanced", None ], # "gamma": [ 0.1, 1, 10 ], # "kernel": [ "rbf", "poly" ] # } # ``` # * $C$: controla balance entre margen y errores # * $class\_weight$: ¿dar más importancia a clase minoritaria? # * $gamma$: forma de la frontera de decisión # ## Resultados # # * $F1$ sobre $M^{aj}_u$ # * Promedio $0,84$ # # ![](imgs/f1svalidsocial__.png) # # *¡Y sin tener en cuenta el contenido!* # # # # ![](imgs/robot2.png) # # Agregando PLN # # ## Selección de usuarios # # * $F1 < 0,75$ en $M^{aj}_u$ ( $23$ usuarios ) # # * $10$ usuarios más (al azar) # ## Pre-procesamiento # # - Normalización # - Tokenizado # - Extracción de frases # - Diccionario de términos # - *Bag of terms* # - LDA # # ## Normalización # # ![](imgs/normalize.png) # ## Tokenizado # # ![](imgs/tokenize.png) # ## Extracción de frases # # * $\verb|Phraser|$ de $\verb|gensim|$ # * Bigramas $a\ b$ relevantes: # * $min\_count = 5$ # * $cnt(a, b) \geq min\_count$ # * $ \frac{(cnt(a, b) - min\_count) * N}{cnt(a) * cnt(b)} > 10 $ # * 2 pasadas sobre el corpus tokenizado ( bigramas y trigramas ) # ## Diccionario de términos # # * $T$ retokenizado con frases # * término = palabra o frase # * significativo ( al menos $3$ veces ). # * informativo ( en menos del $30\%$ de los tweets ). # # * Diccionario $D$ de $26201$ términos. # # # ## *Bag of terms* # # - Texto $t$: $\rightarrow$ multiconjunto (*bag*) de los términos en $t$. # - No importa el orden, pero sí repeticiones. # - En tweets ( $\leq 140$ caracteres ), en general son *conjuntos* ( $0$ o $1$ ocurrencia). # - Diccionario fijo $D = \{ t_1, \ldots, t_{26201} \}$ : $\rightarrow$ vector de características enteras (booleanas): # # $$ v_{BOT}(tweet) = [count(t_i, tokens(tweet))]_{i=1}^{26201} $$ # # - $v_{BOT}$ se representa ralo (*sparse*): # # ![](imgs/bagofterms.png) # # ## LDA # # * Descubre temas subyacentes en textos # # * Reducción de dimensionalidad ( espacio de *términos* a espacio de *temas* ) # # * Probamos modelos de $10$ y $20$ temas # # ### Ejemplo: LDA 10 temas # # ![](imgs/lda10.png) # ## Extendiendo características # # * Características sociales + LDA: # # ![](imgs/socialldavec.png) # # * Agregamos escalado ( cada columna con media $0$ y varianza $1$ ) # ## Evaluando sobre $M_u^{ev}$ # # * $LDA10$ # * mejora para $4$ usuarios # * mejora media de $2,8\%$ # * $LDA20$ # * mejora para $5$ usuarios # * mejora media de $3,8\%$. # ![](imgs/f1lda_eval.png) # ## Sobreajuste # ![](imgs/f1lda_train.png) # # ## Discretizando... # # * Sobreajuste puede venir de características *demasiado* descriptivas # * Asignamos $1$ para cada tema con puntaje $\geq 0,25$ y $0$ en caso contrario # ## Mejoras? # # * $LDAbool10$ # * mejora para $8$ usuarios # * mejora media de $2,4\%$ # * $LDAbool20$ # * mejora para $7$ usuarios # * mejora media de $2,5\%$. # # Impacta a más usuarios, pero mejora menos # ![](imgs/f1ldabool_eval.png) # ## ...pero sigue el sobreajuste # # ![](imgs/f1ldabool_train.png) # # # Conclusiones # # * Predicción social pura mejor de lo esperado # * LDA mejora casos flojos, pero hay que resolver sobreajuste # * Twitter es muy buena fuente de datos # # Próximos pasos # # - Reducir sobreajuste # - Características adicionales # - Considerar temporalidad # - Generalizar ( modelo que no dependa del usuario ) # # # ¿Preguntas? # # ![](imgs/twitter.png) @PCelayes # # ![](imgs/github.jpg) https://github.com/pablocelayes/sna_classifier # #