<jupyter_start><jupyter_text>Word Vectors---  IntroducciónEl primer problema con el que nos enfrentamos para convertir un texto un dataset estructurado para entrenar un algoritmo de Machine Learning es que, justamente, un texto es no estructurado. Por lo tanto, el primer paso para entrenar un modelo es convertir un texto en una tabla en que cada fila es una tabla de con muestras (ya sean supervisadas o no supervisadas). Obviamente, las muestras tienen que ser lo más representativas posibles del problema que quiero resolver, para que el modelo pueda entrenar bien. Por eso, muchas veces se usan algunas herramientas de lingüística para convertir texto en algo entendible por una computadora, es decir, en un array de números. (Sí, el objetivo último es que, de un texto, se extraiga un vector que sirva para resolver una tarea determinada.)  Representaciones de texto con vectores La era denotacionalDurante muchos años se utilizaron muchas técnicas de matemática y lógica para representar texto a través de números, que es lo que puede entender la computadora. Muchas de estas ideas se basaban en mapear oraciones y pedazos de texto en conjuntos de acciones a través de funciones, en su mayoría, recursivas. Esto permite trabajar con patrones del lenguaje y generar algoritmos que resuelvan una determinada tarea.Este proceso, conocido como **semántica denotacional**, también puede usarse para representar texto a través de vectores que puedan usarse para entrenar un algoritmo estadístico. Por ejemplo, la representación *one-hot* de una palabra es denotacional, puesto que la regla para mapear palabras a significados es determinística y discreta. De hecho, cualquier regla que use información de otro lado como diccionarios de sinónimos o de morfología también va a ser discreta. El tema es que, una vez que se mapeen a un espacio vectorial, automáticamente se convierten en una represetación continua, o sea que eso de "denotacional" no es del todo cierto.  La hipótesis distribucionalUn avance muy importante a favor de hacer todo con redes neuronales fue el hecho de proponer hacer un entrenamiento de representaciones de vectores utilizando el contexto de las palabras como fuente de significado. El hecho de suponer que se puede deducir el significado de las palabras a partir del contexto que integran se conoce como **hipótesis distribucional** y es lo que mejor funciona hasta ahora. Con esto se dejan de lado las reglas determinísticas para convertir texto en vectores y comienzan a entrenarse palabras a partir de grandes cantidades de texto. El tema es que esto funciona muy bien para palabras aisladas pero todavía no tanto para oraciones largas y complejas.De esta forma de trabajar, existen dos escuelas:* *Métodos de conteo*: el método más viejo es contar cuántas veces aparece una palabra en el contexto de las otras y sacar una representación vectorial a partir de ella. Esta forma suele complementarse con métodos no supervisados de inspección de patrones.* *Métodos neuronales*: Cuando tenés que trabajar con muchos datos, siempre terminan apareciendo las redes neuronales.   Evaluación de representación de texto con vectoresUna vez que se tiene una representación de un texto con un vector se suelen hacer diferentes tipos de análisis para observar este espacio de una manera comprensible.* Visualización* Evaluación para cierta tarea* Analogías y correlaciones sintácticas/semánticas --- Visualización de Word Embeddings---<jupyter_code>import pandas as pd
import numpy as np

%matplotlib notebook
import matplotlib.pyplot as plt

%load_ext autoreload
%autoreload 2<jupyter_output><empty_output><jupyter_text>Cargamos el archivo `data/vsmdata/imdb_window20-flat.csv.gz` con un conjunto de vectores ya entrenados con el método de coocurrencias sobre el corpus IMDb con un tamaño de ventana 20.<jupyter_code>imdb20 = pd.read_csv('../data/vsmdata/imdb_window20-flat.csv.gz', index_col=0)
imdb20.head(10)
vocab = list(imdb20.columns.values)
print(vocab[:10])
print(len(vocab))
print('good' in vocab, 'bad' in vocab, 'excellent' in vocab, 'terrible' in vocab)<jupyter_output>['!', ');', '.', '..', '...', ':)', '?', 'abandoned', 'abdomen', 'abduct']
5000
True True True True<jupyter_text>Inspeccionamos los vectores. Observamos las coordenadas "good" y "bad" de las palabras "excellent" y "terrible".<jupyter_code>excellent_vec = np.array([imdb20['excellent']['good'], imdb20['excellent']['bad']])
terrible_vec = np.array([imdb20['terrible']['good'], imdb20['terrible']['bad']])

fig, ax = plt.subplots()
ax.scatter(excellent_vec[0],excellent_vec[1])
ax.scatter(terrible_vec[0],terrible_vec[1])<jupyter_output><empty_output><jupyter_text>Aplicamos reducción de la dimensionalidad para visualizar los vectores encontrados<jupyter_code>from sklearn.decomposition import TruncatedSVD
import vsm


def dim_reduce(word_matrix,vocab,words):
    w2idx = {w: idx for idx, w in enumerate(vocab)}
    idx = [w2idx[w] for w in words]
    word_matrix = word_matrix[idx,:]
    
    word_matrix = word_matrix - word_matrix.mean(axis=0,keepdims=True)
    #svd = TruncatedSVD(n_components=2)
    #word_matrix_reduced = svd.fit_transform(word_matrix)
    rowmat, singvals, colmat = np.linalg.svd(word_matrix, full_matrices=False)
    singvals = np.diag(singvals)
    word_matrix_reduced = np.dot(rowmat[:, 0:2], singvals[0:2, 0:2])

    fig, ax = plt.subplots()
    ax.scatter(word_matrix_reduced[:,0],word_matrix_reduced[:,1])
    for i, ind in enumerate(idx):
        ax.annotate(vocab[ind], (word_matrix_reduced[i,0], word_matrix_reduced[i,1]))
    return fig, ax

words = 'good bad terrible awesome right wrong accept deny excellent awful'.split(' ') + \
        'adult child adventure drama comedy'.split(' ') + \
        'blue brown orange red white black'.split(' ')

X_r = dim_reduce(vsm.pmi(imdb20).values,vocab,words)<jupyter_output><empty_output><jupyter_text>Probamos buscar si se cumple alguna analogía pero no encontramos ninguna<jupyter_code>X = vsm.pmi(imdb20)
w = X.loc['terrible',:] - X.loc['bad',:] + X.loc['good',:]
X.apply(lambda x: vsm.euclidean(w, x), axis=1).sort_values()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07871577574967406, 'fraction_numerical': 0.00863754889178618, 'mean_word_length': 5.4532071503680335, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '631679', 'license': 'Apache-2.0', 'n_tokens_mistral': 2038, 'n_tokens_neox': 1984, 'n_words': 732, 'path': 'Lecture 02 - Word Vectors/Notas.ipynb', 'repo_name': 'LautaroEst/cs224u', 'size': '6136'}