¿Cómo realizar una clasificación de palabras usando NLTK en Google Colab?
La clasificación de palabras es una habilidad esencial en el procesamiento del lenguaje natural y lo puedes lograr fácilmente empleando Python y herramientas como NLTK. Este proceso comienza por la preparación de un notebook en Google Colab y la importación de las librerías principales: NLTK y random. ¿Te gustaría saber más? ¡Sigue leyendo!
¿Cómo importar un dataset en NLTK?
El primer paso es descargar un dataset crucial para la clasificación. Utilizaremos names, un corpus de NLTK que contiene nombres masculinos y femeninos en inglés. Puedes acceder a él de la siguiente forma:
import nltk
import random
# Descarga e importa el datasetnltk.download('names')from nltk.corpus import names
¿Cómo construir una función de extracción de atributos?
Para empezar a clasificar, necesitas definir qué atributos vas a considerar. La última letra del nombre es un atributo básico, pero también puede ser muy revelador:
¿Cómo crear y mezclar listas de nombres etiquetados?
Crear listas de nombres y sus etiquetas es un proceso fundamental. Aquí te muestro cómo hacer esto tanto para nombres masculinos como femeninos:
male_names =[(name,'male')for name in names.words('male.txt')]female_names =[(name,'female')for name in names.words('female.txt')]# Combina ambas listasdataset = male_names + female_names
# Mezcla los datos para evitar sesgosrandom.shuffle(dataset)
¿Cómo construir un modelo de clasificación básico?
Una vez definidas las listas, el siguiente paso es crear un modelo de clasificación utilizando la librería naivebayes de NLTK:
# Clara las listas de atributosfeaturesets =[(attribute_extractor(n), gender)for(n, gender)in dataset]# Divide el conjunto de datostrain_set, test_set = featuresets[500:], featuresets[:500]# Crea el clasificador Naive Bayesclassifier = nltk.NaiveBayesClassifier.train(train_set)
¿Cómo verificar el desempeño del modelo?
Una vez construido tu modelo, es esencial evaluar su precisión para determinar su efectividad:
# Verifica la precisiónprint(nltk.classify.accuracy(classifier, test_set))
En nuestro ejemplo, la precisión oscila alrededor del 75%, lo cual puede no ser lo ideal, pero es un comienzo prometedor.
¿Cómo mejorar los atributos para una clasificación más precisa?
Mejorar el modelo implica definir atributos más complejos y precisos. Una nueva función de extracción de atributos puede considerar, además de la última letra, la primera letra u otras características más sofisticadas como el número de veces que una letra aparece en un nombre:
defenhanced_attribute_extractor(name): features ={'first_letter': name[0].lower(),'last_letter': name[-1].lower(),}for letter in'abcdefghijklmnopqrstuvwxyz': features[f"count({letter})"]= name.lower().count(letter) features[f"has({letter})"]=(letter in name.lower())return features
Con esto, puedes reconstruir las listas de atributos y seguir el mismo procedimiento para el entrenamiento y evaluación del modelo.
¿Qué sigue después de la ingeniería de atributos?
Recuerda, la ingeniería de atributos es una tarea iterativa y creativa. Practica usando un dataset en español para aplicar lo aprendido y descubrir si las mismas técnicas funcionan igual al cambiar de idioma. Atrévete a experimentar y comparte tus resultados. ¡No olvides que cada intento es un aprendizaje para convertirte en un experto en procesamiento de lenguaje natural!
Creo que en este punto es que debemos entender una parte clave de hacer data science o ai, y es que no se trata de solo mejorar un accuracy y subirlo, sino que es muy importante tener un “entendimiento del contexto de problema”. Veo que aunque se pueden hacer pruebas tomando más o menos letras, falta realmente el conocimiento del campo y el punto de vista que un experto lingüista podría dar sobre el tema, por que fácilmente aún cuando suban el accuracy a 99% no significa que si traemos un nuevo set de datos el comportamiento va a ser tan bueno, claramente este tema de nombre es complejo(es común encontrar nombres que rompen cualquier regla supuesta, mezclas de idiomas, ..etc) y fácilmente podemos caer en temas de overfit, además recuerden también que hay otras métricas más allá de solo hablar de accuracy, por ejemplo hablar de un F1-score donde integremos un factor de sensbilidad(recall) de nuestro modelo también es útil.
Creo que es cuestión de entender que es una muestra de un campo que es muy basto
Tienes razon Johan,
Facilmente al tener un accuracy de mas del 90% no necesariamente significa que nuestro algoritmo este haciendo las predicciones correcta, podria estar facilmente haciendo un overfitting, el cual no esta generalizando bien los datos de entrenamiento y esta memorizandolos y cuando se aplique a nuestro test dataset se comportara de manera podre y estara haciendo predicciones erroneas en saber el genero de los nombres.
para evitarse escribir el alfabeto mejor hacer:
import string
string.ascii_lowercase
Completado el reto!
Pueden ver mi solución: Aqui
:)
0.95 de accuracy! :O
10 de 10 :)
Concurro con mis compañeros que dicen que utilizar las ultimas cuatro letras del nombre aumenta el "performance" del modelo, aquí estan algunas comparaciones de métricas utrilizando diferentes atributos:
.
.
Sin embargo ninguna configuración de atributos puede predecir con exactitud que el nombre Jose Maria es de hombre por alguna razón 😅, cosa rara porque nosotros sabemos que :
jose Maria -> Hombre
Maria Jose -> Mujer
(Hola si tienes uno de esos nombres :)!)
.
Leyendo la última y las ultimas 4 letras se llega a un 90% de Accuracy
# Cargamos los datasets
!git clone https://github.com/jvalhondo/spanish-names-surnames
import numpy as np
tag_men = np.genfromtxt('/content/spanish-names-surnames/male_names.csv', skip_header=1, delimiter=',', dtype=('U20','i8','f8'))tag_women = np.genfromtxt('/content/spanish-names-surnames/female_names.csv', skip_header=1, delimiter=',', dtype=('U20','i8','f8'))f_set =[(name[0],'male')for name in tag_men]+[(name[0],'female')for name in tag_women]import random
random.shuffle(f_set)# Funcion con mejores atributos
def atributos2(nombre): atrib ={} atrib["ultima_letra"]= nombre[-1].lower() #Ultima letra
atrib["ultimas_dos_letra"]= nombre[-1:-5:-1].lower() #ultimas 4 letras
return atrib
f_varios_atributo =[(atributos2(n), g)for(n, g)in f_set]#Usamos el 80% de los datos para train y 20% para test
f_varios_atributo_train, f_varios_atributo_test =train_test_split(f_varios_atributo, test_size=0.20, random_state=45)#Entrenamos y Probamosclassifier_2 = nltk.NaiveBayesClassifier.train(f_varios_atributo_train)print(classifier_2.classify(atributos('Juan')))print(nltk.classify.accuracy(classifier_2, f_varios_atributo_test))```
Hola! Agregando la informacion de las ultimas 4 letras, sumado de los otros features de mi solucion pude aumentar el accuracy a 0.95. Gracias por el aporte! :)
Aunque probándolo con distintos nombres genera muchos errores en nombres masculinos etiquetándolos como femeninos.
Un poco largo, pero este fue mi forma de abordar el ejercicio:
!git clone https://github.com/jvalhondo/spanish-names-surnames
import pandas as pd
#Cargando los archivos
tag_male_names = pd.read_csv('C:/Users/crist/OneDrive/Python para Ciencia de Datos/NPL/Intermedio/spanish-names-surnames/male_names.csv')tag_famale_names = pd.read_csv('C:/Users/crist/OneDrive/Python para Ciencia de Datos/NPL/Intermedio/spanish-names-surnames/female_names.csv')#Creando la función de atributos
def atributos_cris(palabra):return{'3_ultimas_letras':str(palabra).replace(" ","")[-3:].lower()}atributos_cris("cristian yesid")#Se define el tagset
tagset_eje =[(name,'male')for name in tag_male_names.name]+[(name,'female')for name in tag_famale_names.name]random.shuffle(tagset_eje) # Para generar un orden aleatorio del dataset TAGtagset_eje[:10]# Se crea el diccionario con los atributos
fset_eje =[(atributos_cris(n), g)for(n, g)in tagset_eje]fset_eje[:10]
# modelo
train, test = fset_eje[39472:], fset_eje[:39472]classifier_eje = nltk.NaiveBayesClassifier.train(train)print(nltk.classify.accuracy(classifier_eje, test))
Esto me dio un accuracry de: 86.53%
Luego ajuste el modelo para capturar las 3 primeras y últimas letras de los nombres:
# escribe tu código aquí
#Creando la función de atributos
def atributos_cris_2(palabra): dic ={} dic['3_primeras_letras']=str(palabra).replace(" ","")[:3].lower() dic['3_ultimas_letras']=str(palabra).replace(" ","")[-3:].lower()return dic
atributos_cris_2("cristian yesid")fset_eje_2 =[(atributos_cris_2(n), g)for(n, g)in tagset_eje]fset_eje_2[:10]train, test = fset_eje_2[39472:], fset_eje_2[:39472]classifier_eje_2 = nltk.NaiveBayesClassifier.train(train)print(nltk.classify.accuracy(classifier_eje_2, test))
Con este ajuste el modelo mejoro 3pp (89.5% en accuracy)
Buen ejemplo, gracias por el aporte. Pero hay un error en el train y en el test, están invertidos.
Hice varias pruebas y al igual que para el resto, mis mejores resultados fueron tomando la ultima letra y las ultimas cuatro:
test.accuracy: 0.76train.accuracy: 0.91
dejo mi algoritmo de pre-procesamiento:
import re
patron1 = re.compile('[A-Z]+')male_names =open("spanish-names-surnames/male_names.csv","r",encoding="utf-8")mn_list =[]for line inmale_names: filtrado = patron1.findall(line)try: mn_list.append((filtrado[0],"male")) mn_list.append((filtrado[1],"male"))except:continuefemale_names =open("spanish-names-surnames/female_names.csv","r",encoding="utf-8")fn_list =[]for line infemale_names: filtrado = patron1.findall(line)try: fn_list.append((filtrado[0],"female")) fn_list.append((filtrado[1],"female"))except:continuen_list = mn_list + fn_list
n_set =set(n_list)nn_list =list(n_set)random.shuffle(nn_list)
# Clonamos el repositorio
!git clone https://github.com/jvalhondo/spanish-names-surnames
Leo los dos archivos con pandas, los paso a un dataframe
female_names=list(df_female['name'])male_names=list(df_male['name'])tagset =[(n,'female')for n in female_names]+[(n,'male')for n in male_names]random.shuffle(tagset)tagset[:10]
🎯Clasificación de Palabras con NLTK (Google Colab)
🧠 ¿Qué es la clasificación de palabras?
La clasificación de palabras es una técnica del procesamiento del lenguaje natural (PLN) que permite identificar características (por ejemplo, el género de un nombre).
Con Python + NLTK, puedes construir un modelo automático para clasificar nombres fácilmente.
🧰 1. Prepara tu entorno
💻 En Google Colab:
Abre un nuevo notebook.
Importa las librerías necesarias:
import nltk
import random
📦 2. Descarga el dataset
📚 Dataset: names (de NLTK)
Incluye listas de nombres masculinos y femeninos en inglés.
nltk.download('names')
from nltk.corpus import names
📁 Archivos:
male.txt → nombres masculinos
female.txt → nombres femeninos
🧩 3. Define los atributos
🎯 Meta: decirle al modelo qué observar.
Primer atributo: última letra del nombre.
def attribute_extractor(word):
return {'last_letter': word[-1]}
💡 La última letra puede revelar mucho sobre el género del nombre.
🧍♂️🧍♀️ 4. Etiqueta y mezcla los datos
🧾 Crea listas de nombres con sus etiquetas:
male_names = [(name, 'male') for name in names.words('male.txt')]
female_names = [(name, 'female') for name in names.words('female.txt')]
🔄 Combina y mezcla los datos:
dataset = male_names + female_names
random.shuffle(dataset)
🌀 Mezclar evita sesgos en el entrenamiento.
⚙️ 5. Construye el modelo
🏗️ Usa el clasificador Naive Bayes de NLTK:
featuresets = [(attribute_extractor(n), gender) for (n, gender) in dataset]
features[f"has({letter})"] = (letter in name.lower())
return features
🧩 Con esta versión, el modelo dispone de mucha más información para decidir.
💡 8. Ingeniería de atributos: tu siguiente paso
⚙️ La mejora de un modelo depende de la creatividad para diseñar buenos atributos.
📊 Prueba con un dataset en español, compara los resultados y analiza las diferencias.
✨ Recuerda:
Cada cambio te enseña algo nuevo.
Experimentar = aprender.
No hay un único camino correcto.
¿Por qué al incrementar el numero de datos en el fset de 500 a 2000 o 3000, en vez de mejorar la precisión, ésta empeora?. Creí que el modelo entre mas datos de entrenamiento tuviera mas acertado iba a ser.
Interesante pregunta, tiene razón pero al mismo tiempo esta fallando al ver un pequeño detalle. Al agregar más datos el modelo se debe encargar de reconocer muchos más casos no solo unos pocos de los que aprende rápidamente, tiene mucha más variabilidad en los datos lo cual por ende generará más variabilidad en la respuesta. de está forma el modelo se volverá más robusto ya que sabrá manejar una mayor cantidad de casos pero de la misma manera encontrará muchos otros que no.
Debe tener en cuenta los términos población y muestra, la población se refiere a absolutamente todos los posibles datos que en la mayoría de ocasiones es imposible de reunir en su totalidad, mientras que la muestra es una porción de la población por lo tanto no tiene todos los posibles casos, entre más grande sea la muestra más similar será a la población, en caso contrario, cuando la muestra es pequeña los modelos se adaptan fácilmente por lo general caen en overfitting.
En conclusión si agrega más datos será un mejor modelo pero que sea un mejor modelo significa que será más acertado.
Gracias Andres. Sin embargo, como dijiste al final entre mas datos agregue debería ser mas acertado y más teniendo en cuenta que lo estoy probando con datos del mismo data set. Acá sucede lo contrario.
Preprocesamiento: Se extraen características simples del nombre, como la primera y última letra, además de la longitud. Estas características se utilizan para entrenar el modelo.
Clasificador Naive Bayes: Este algoritmo es adecuado para datos categóricos y es sencillo de implementar.
Evaluación: La precisión del modelo se calcula en el conjunto de test para medir su rendimiento.
Esta fue mi solucion:
Manejo de los archivos CSV:
#!git clone https://github.com/jvalhondo/spanish-names-surnamesimport pandas as pd
import random
#Convirtiendo el conjunto de datos en DataFramesmasculino = pd.read_csv("SpanishData/male_names.csv", header=None, delimiter=',')femenino = pd.read_csv("SpanishData/female_names.csv", header=None, delimiter=',')# print(masculino)# print(femenino)#Separando la primera columna, la de nombres, que es la que interesa.Quitando el encabezado
#Asignando el atributo male a la lista de masculino y female a la lista de femenino para despues unir los dos dataframes en una tupla
tagset =([(name,'male')for name in masculino[0]]+[(name,'female')for name in femenino[0]])```*Función que maneja los atributos, en este caso es la mejorada.*
```js
def atributos2(palabra):ifisinstance(palabra, str):return{'longitud':len(palabra),'primera_letra': palabra[0].lower(),'ultima_letra': palabra[-1].lower(),'primera_vocal':next((v for v in palabra if v in'aeiouáéíóúü'),None),'ultima_vocal':next((v for v in palabra[::-1]if v in'aeiouáéíóúü'),None),'cantidad_vocales':sum(1for v in palabra if v in'aeiouáéíóúü'),'cantidad_consonantes':sum(1for c in palabra if c.isalpha() and c not in'aeiouáéíóúü')}else: palabra =str(palabra) # Convertir a cadena
return{'longitud':len(palabra),'primera_letra': palabra[0].lower(),'ultima_letra': palabra[-1].lower(),'primera_vocal':next((v for v in palabra if v in'aeiouáéíóúü'),None),'ultima_vocal':next((v for v in palabra[::-1]if v in'aeiouáéíóúü'),None),'cantidad_vocales':sum(1for v in palabra if v in'aeiouáéíóúü'),'cantidad_consonantes':sum(1for c in palabra if c.isalpha() and c not in'aeiouáéíóúü')}```Creando la lista de atributos y genero y diviendo el conjunto.
```js
fset =[(atributos2(n), g)for(n, g)in tagset]train, test = fset[500:], fset[:500]```Mostrando los resultados
```js
print('Poniendo a prueba el entrenamiento con un nombre')classifier.classify(atributos('amanda'))print('Mostrando la precision del conjunto de entrenamiento')print(nltk.classify.accuracy(classifier, train))print('Mostrando la precision del conjunto de prueba')print(nltk.classify.accuracy(classifier, test))```Y he aqui los resultados:Mostrando la precision del conjunto de entrenamiento
0.8011056511056511Mostrando la precision del conjunto de prueba
0.888No logré llegar a 9 pero al menos mejoró.
Descargando el dataset podemos observar como este está organizado donde se pueden tener dos o más nombres.
import nltk
import pandas as pd
import numpy as np
import random
male_df = pd.read_csv('/content/spanish-names-surnames/male_names.csv')female_df = pd.read_csv('/content/spanish-names-surnames/female_names.csv')tagset =[(str(name).lower(),'Male')for name inlist(male_df['name'])]+[(str(name).lower(),'Female')for name inlist(female_df['name'])]random.shuffle(tagset)tagset[:10]
Definimos la separación de los nombres y determinamos sus primeras y últimas letras
Para mejorar el entrenamiento agregamos las últimas 4 letras y si las vocales están en el nombre, se aconseja que no sea más de 4 últimas letras ya que hay nombres de solo 3 por lo que no sería conveniente.
defmore_attributes(full_name): attrib ={} names = full_name.split(' ')for name_num, name inenumerate(names): attrib[f'first_letter_{name_num}']= name[0].lower() attrib[f'last_letter_{name_num}']= name[-1].lower() attrib[f'last_4letters_{name_num}']= name[-1:-5:-1].lower()[::-1]for letter in'aeiou':for name_num, name inenumerate(names): attrib[f'count({letter})_{name_num}']= name.lower().count(letter) attrib[f'has({letter})_{name_num}']=(letter in name.lower())return attrib
Realizando la separación de datos como se vio en clases pasadas usando sklearn, el 80% del dataset para entrenamiento.
#%%import nltk
import random
import pandas as pd
#%%#### importar datos de nombres de hombres y mujeres con pandasdf_male = pd.read_csv('./spanish-names-surnames/male_names.csv')df_female= pd.read_csv('./spanish-names-surnames/female_names.csv')#%%#### agregar fila male en df_maledf_male = df_male.assign(gender='male')df_female = df_female.assign(gender='female')#%%#### unir dos dataframesdf = pd.merge(df_male, df_female,'outer')#%%#### Definir lista de tuplastagset =[(fila['name'], fila['gender'])for i,fila in df.iterrows()]random.shuffle(tagset)# %%#### Definir atributosdefatributes(word): atrib ={} atrib['last_letter']= word[-1].lower() atrib['first_letter']= word[0].lower()for letra in'abcdefghijklmnopqrstuvwxyz': atrib['count({})'.format(letra)]= word.lower().count(letra) atrib['has({})'.format(letra)]=(letra in word.lower())return atrib
# %%### Crear una segunda lista de atributosfset =[(atributes(str(n)), g)for(n,g)in tagset]# %%train, test = fset[(int((len(fset)*10)/100)):], fset[:(int((len(fset)*10)/100))]# %%classfier = nltk.NaiveBayesClassifier.train(train)# %%### Medir performance del modelonltk.classify.accuracy(classfier, test)# %%classfier.classify(atributes('ariel'))
Hola, aquí dejo algunas funciones que hice para apoyarme en la clase, una es para obtener directamente el train y test dando el tagset y el tamaño que queramos. La otra función regresa el modelo entrenado y lo evalúa a partir de los mismos parámetros que la función anterior. Este es el código
def mas_atributos(nombre): atrib ={} atrib['primera_letra']= nombre[0].lower() atrib['ultima_letra']= nombre[-1].lower() # iteramos el abecedario
for letra in'abcdefghijklmnñopqrstuvwxyz': # contamos cuantas letras y de cuales tiene el nombre
atrib[f'count({letra})']= nombre.lower().count(letra) # vemos si la letra esta en la palabra
atrib[f'has({letra})']=(letra in nombre.lower())return atrib
# una función para obtener train y test directamente
def get_fsets(nombres, n): fset =[(mas_atributos(nombre), genero)for(nombre ,genero)in tagset] train, test = fset[n:], fset[:n]return train, test
# evaluar el modelo directamente
def try_model(nombres, n): # obtenemos train y test
train, test =get_fsets(nombres,500) # intanciamos y evaluamos el modelo
model = nltk.NaiveBayesClassifier.train(train) # lo evaluamos y muestra el resultado
print(f'accuracy: {nltk.classify.accuracy(model, test)}') # retorna el modelo y los datos
return model
train, test =get_fsets(tagset,500)model =try_model(tagset,500)
Aqui mi aportacion
# escribe tu código aquí
!git clone https://github.com/jvalhondo/spanish-names-surnames
import pandas as pd
from sklearn.model_selectionimport train_test_split
male_names = pd.read_csv('/content/spanish-names-surnames/male_names.csv')female_names = pd.read_csv('/content/spanish-names-surnames/female_names.csv')female_names.dropna(axis=0, inplace=True)tagnames =[(name.lower(),'male')for name in male_names['name']]+[(name.lower(),'female')for name in female_names['name']]random.shuffle(tagset)
# definición de atributos relevantes
def atributos(palabra):return{'ultima_letra': palabra[-1]}# Creando dataset con atributos
fset =[(atributos(n), g)for(n, g)in tagset]# Dividiendo en train_data y test_data
train_data, test_data =train_test_split(fset, test_size=0.20)# Evaluacionclassifier = nltk.NaiveBayesClassifier.train(train_data)print(f'test_data accuracy: {nltk.classify.accuracy(classifier, test_data)}')print(f'train_data accuracy {nltk.classify.accuracy(classifier, train_data)}')test_data accuracy:0.7482693517935809train_data accuracy 0.7664830841856806
def atributos2(nombre): atrib ={} atrib["nombre"]= nombre.lower() atrib["primera_letra"]= nombre[0].lower() atrib["ultima_letra"]= nombre[-1].lower() atrib["primeras_dos_letras"]= nombre[:2].lower() atrib["ultimas_dos_letras"]= nombre[-2:].lower()for letra in'abcdefghijklmnopqrstuvwxyz': #atrib 3. numero de veces aparece la letra
atrib["count({})".format(letra)]= nombre.lower().count(letra) #atrib 4. si tiene o no la letra
atrib["has({})".format(letra)]=(letra in nombre.lower())return atrib
fset2 =[(mas_atributos(n), g)for(n, g)in tagset]# Dividiendo en train_data y test_data
train_data2, test_data2 =train_test_split(fset2, test_size=0.20)# Evaluacionclassifier2 = nltk.NaiveBayesClassifier.train(train_data2)print(f'train_data accuracy: {nltk.classify.accuracy(classifier2, train_data2)}')print(f'test_data accuracy {nltk.classify.accuracy(classifier2, test_data2)}')
En mi caso, yo use el nombre de la persona,, la primera letra del nombre y sacar la ultima letra del primer nombre, por ejemplo:
Jose María, la ultima letra seria e.
En caso de solo haber un nombre se saca la ultima letra del mismo, por ejemplo:
María, la ultima letra seria a.
con esos tres valores mi precisión subió a 84.08%, lo cual considero que es un predicción aceptable pero estoy consiente que se necesitan mas features para poder entrenar el modelo y tener una mejor predicción. Probablemente agregando la columna con la frecuencia, ya que en algunos casos como el nombre asuncion la frecuencia es major en mujeres que en hombres.
import pandas as pd
path ="D:/Udacity Natural Language Processing/Curso Platzi - Algoritmo de Clasificacion de Texto/names/"male = pd.read_csv(path +"male_names.txt", header =0, encoding='latin-1', delimiter =',')female = pd.read_csv(path +"female_names.txt", header =0, encoding='latin-1', delimiter =',')male = male.to_numpy()female = female.to_numpy()tagset =[(male[i][0],"male")for i inrange(len(male))]+ \
[(str(female[i][0]),"female")for i inrange(len(female))]random.shuffle(tagset)# Definicion de atributos relaventes
def atributos(nombre): atrib ={} nombre_list = nombre.split(" ") atrib["nombre"]= nombre
atrib["ultima letra"]= nombre_list[0][-1].lower() atrib["primera letra"]= nombre_list[0][0].lower()return atrib
fset =[(atributos(name), genre)for(name, genre)in tagset]train, test =train_test_split(fset, test_size =0.20, random_state=42)classifer = nltk.NaiveBayesClassifier.train(train)# performance del modelo
print(nltk.classify.accuracy(classifer, test))0.8407985407377382
Entrenando con el diccionario en español me da estos resultados
Se podría hacer un pequeño cambio al momento de definir los set de prueba y de entrenamiento.
train, test = fset[:500], fset[500:]
En vez de:
train, test = fset[500:], fset[:500]
Y así se tiene un poco mas de control en el entrenamiento y a medida que incluyo mas datos en el set de entrenamiento (también debo quitar ese mismo numero del set de prueba) aumento la precisión del modelo.