web-dev-qa-db-fra.com

Keras Text Preprocessing - Enregistrement d'un objet Tokenizer dans un fichier pour le scoring

J'ai formé un modèle de classificateur de sentiments à l'aide de la bibliothèque Keras en suivant les étapes ci-dessous (en gros).

  1. Convertir un corpus de texte en séquences à l'aide d'un objet/classe Tokenizer
  2. Construire un modèle en utilisant la méthode model.fit () 
  3. Evaluer ce modèle

Maintenant, pour la notation utilisant ce modèle, j'ai pu enregistrer le modèle dans un fichier et le charger à partir d'un fichier. Cependant, je n'ai pas trouvé de moyen de sauvegarder l'objet Tokenizer dans un fichier. Sans cela, je devrai traiter le corpus chaque fois que je devrai marquer une seule phrase. Y a-t-il un moyen de contourner ceci?

22

Le moyen le plus courant consiste à utiliser pickle ou joblib . Ici, vous avez un exemple d'utilisation de pickle afin de sauver Tokenizer:

import pickle

# saving
with open('tokenizer.pickle', 'wb') as handle:
    pickle.dump(tokenizer, handle, protocol=pickle.HIGHEST_PROTOCOL)

# loading
with open('tokenizer.pickle', 'rb') as handle:
    tokenizer = pickle.load(handle)
46
Marcin Możejko

La réponse acceptée montre clairement comment enregistrer le tokenizer. Ce qui suit est un commentaire sur le problème de la notation (généralement) après ajustement ou de la sauvegarde. Supposons qu'une liste texts soit composée de deux listes Train_text et Test_text, l'ensemble des jetons dans Test_text étant un sous-ensemble de l'ensemble des jetons dans Train_text (hypothèse optimiste). Ensuite, fit_on_texts(Train_text) donne des résultats différents pour texts_to_sequences(Test_text) par rapport au premier appelant fit_on_texts(texts), puis à text_to_sequences(Test_text).

Exemple concret:

from keras.preprocessing.text import Tokenizer

docs = ["A heart that",
         "full up like",
         "a landfill",
        "no surprises",
        "and no alarms"
         "a job that slowly"
         "Bruises that",
         "You look so",
         "tired happy",
         "no alarms",
        "and no surprises"]
docs_train = docs[:7]
docs_test = docs[7:]
# EXPERIMENT 1: FIT  TOKENIZER ONLY ON TRAIN
T_1 = Tokenizer()
T_1.fit_on_texts(docs_train)  # only train set
encoded_train_1 = T_1.texts_to_sequences(docs_train)
encoded_test_1 = T_1.texts_to_sequences(docs_test)
print("result for test 1:\n%s" %(encoded_test_1,))

# EXPERIMENT 2: FIT TOKENIZER ON BOTH TRAIN + TEST
T_2 = Tokenizer()
T_2.fit_on_texts(docs)  # both train and test set
encoded_train_2 = T_2.texts_to_sequences(docs_train)
encoded_test_2 = T_2.texts_to_sequences(docs_test)
print("result for test 2:\n%s" %(encoded_test_2,))

Résultats:

result for test 1:
[[3], [10, 3, 9]]
result for test 2:
[[1, 19], [5, 1, 4]]

Bien sûr, si l'hypothèse optimiste ci-dessus n'est pas satisfaite et que l'ensemble des jetons dans Test_text est disjoint de celui de Train_test, le résultat du test 1 est une liste de crochets vides [].

6
Quetzalcoatl

J'ai créé le numéro https://github.com/keras-team/keras/issues/9289 dans le dépôt de keras. Jusqu'à ce que l'API soit modifiée, le problème a un lien vers un Gist contenant un code expliquant comment enregistrer et restaurer un tokenizer sans avoir les documents d'origine sur lesquels le tokenizer était adapté. Je préfère stocker toutes les informations de mon modèle dans un fichier JSON (pour des raisons, mais principalement dans un environnement JS/Python mixte), ce qui le permettra même avec sort_keys = True. 

1
UserOneFourTwo

Une autre option consiste à enregistrer Tokenizer au format JSON:

tokenizer_json = tokenizer.to_json()
with io.open('tokenizer.json', 'w', encoding='utf-8') as f:
    f.write(json.dumps(tokenizer_json, ensure_ascii=False))

Les données peuvent être chargées en utilisant la fonction tokenizer_from_json à partir de keras_preprocessing.text:

with open('tokenizer.json') as f:
    data = json.load(f)
    tokenizer = tokenizer_from_json(data)
0
Max