Ceci est un mémo pour moi pendant que je lis Introduction aux applications de traitement du langage naturel en 15 étapes. Cette fois, au chapitre 3, étape 09, j'écrirai mes propres points.
Implémentons un classificateur multi-classes en utilisant le perceptron multi-couches discuté dans le chapitre précédent.
--softmax: Fonction d'activation pour l'identification multi-classes ⇄ sigmoïde (pour l'identification 2 classes) --categorical_crossentropy: fonction de perte pour l'identification multi-classes ⇄ binary_crossentropy (pour l'identification à 2 classes)
Le nombre d'unités dans la couche de sortie est différent entre le classificateur à deux classes et le classificateur à plusieurs classes, et l'étiquette de l'enseignant est donnée différemment.
--Classificateur à deux classes: une unité avec une couche de sortie unidimensionnelle. Classe d'identification de sortie avec 0 ou 1
--Expression par ID de classe
- 0,
-> Class ID is 0
- 1,
-> Class ID is 1
- 2,
-> Class ID is 2
--Classificateur multi-classes: une unité dont la couche de sortie est égale au nombre de classes. Sortie de la classe d'identification avec 1 uniquement pour l'unité correspondant à l'ID de classe et 0 pour les autres
[1, 0, 0],
-> Class ID is 0[0, 1, 0],
-> Class ID is 1[0, 0, 1],
-> Class ID is 2Softmax est souvent utilisé.
--La sortie est comprise entre 0 et 1
En passant par softmax, la valeur avec la différence de grandeur est établie entre 0 et 1, puis elle s'approche de 0 ou 1 de sorte que le rapport de grandeur devient plus grand.
S'il y a des unités log2N, la classification de classe N est théoriquement possible avec une combinaison de ces sorties 0 ou 1 de sorte qu'une classification à deux classes peut être effectuée avec la sortie 0 ou 1 d'une unité. Cependant, l'unité inférieure doit apprendre le même 0 ou 1 dans plus d'une classe, ce qui semble intuitivement artificiel et l'apprentissage ne se passe pas bien.
Contrairement à binary_crossentropy pour l'identification à deux classes, categorical_crossentropy est utilisé pour l'identification multi-classes.
Lors de la classification en classe N, N neurones doivent être préparés dans la couche de sortie. À ce stade, l'étiquette de sortie doit être spécifiée afin que N neurones puissent recevoir une valeur de 0 ou 1 au lieu de l'ID de classe lui-même.
--Convertir en expression unique avec keras.util.to_categorical --Définissez la fonction de perte sur sparse_categorical_crossentropy pour prendre en charge les expressions non one-hot
Modèle de montage | point |
---|---|
de base | #Réglage ・ Réglez le nombre de dimensions d'entrée du modèle séparément ・ Réglez le nombre de dimensions de sortie du modèle séparément ・ Pendant l'apprentissage ・ Étiquette de l'enseignant un-Besoin de convertir en représentation chaude ・ Au moment de l'identification · Un-Nécessite la conversion de la représentation dynamique en ID de classe #Courir ・ Pendant l'apprentissage ・ Ajustement du vectoriseur_exécuter la transformation ・ Ajuster l'exécution du classificateur ・ Au moment de l'identification ・vectorizerのexécuter la transformation ・ Exécuter la prédiction du classificateur |
Keras scikit-avec l'API d'apprentissage sklearn.pipeline.Incorporation dans Pipeline |
#Réglage ・ Réglez le nombre de dimensions d'entrée du modèle séparément ・ Réglez le nombre de dimensions de sortie du modèle séparément #Courir ・ Pendant l'apprentissage ・ Ajuster l'exécution du vectoriseur ・ Exécution d'ajustement de pipeline ・ Au moment de l'identification ・ Exécution de la prévision du pipeline |
Dans keras.wrappers.scikit_learn.KerasClassifier, fit () exécute le processus équivalent à to_categorical, et predict () exécute le processus équivalent à np.argmax. De plus, en utilisant le pipeline, fit () et predict () du vectoriseur et du classificateur peuvent être exécutés ensemble, mais notez que seul fit () du vectorizer est requis séparément pour spécifier la dimension d'entrée lors de la définition du modèle.
Ajouts / modifications par rapport au chapitre précédent (étape 06)
def _build_mlp(self, input_dim, hidden_units, output_dim):
mlp = Sequential()
mlp.add(Dense(units=hidden_units,
input_dim=input_dim,
activation='relu'))
mlp.add(Dense(units=output_dim, activation='softmax')) #1: fonction d'activation de la couche de sortie
mlp.compile(loss='categorical_crossentropy', #2: fonction de perte
optimizer='adam')
return mlp
def train(self, texts, labels):
~~
feature_dim = len(vectorizer.get_feature_names())
n_labels = max(labels) + 1
#3: identificateur
classifier = KerasClassifier(build_fn=self._build_mlp,
input_dim=feature_dim,
hidden_units=32,
output_dim=n_labels)
~~
Résultat d'exécution
# evaluate_dialogue_agent.Modifiez le nom du module de chargement py si nécessaire
from dialogue_agent_sklearn_pipeline import DialogueAgent
$ docker run -it -v $(pwd):/usr/src/app/ 15step:latest python evaluate_dialogue_agent.py
0.65957446
Mise en œuvre normale (étape 01): 37,2% Pré-traitement ajouté (étape 02): 43,6% Pré-traitement + changement d'extraction de caractéristiques (étape 04): 58,5% Pré-traitement + changement d'extraction de caractéristiques + changement de classificateur (étape 06): 61,7% Pré-traitement + changement d'extraction de caractéristiques + changement de classificateur (étape 09): 66,0%
Ajout de hidden_units
et classifier__epochs
à l'argument de la méthode train de la classe DialogueAgent.
dialogue_agent_sklearn_pipeline.py
def train(self, texts, labels, hidden_units = 32, classifier__epochs = 100):
~~
classifier = KerasClassifier(build_fn=self._build_mlp,
input_dim=feature_dim,
hidden_units=hidden_units,
output_dim=n_labels)
~~
pipeline.fit(texts, labels, classifier__epochs=classifier__epochs)
~~
Spécifiez hidden_units
et classifier__epochs
lors de l'appel de la méthode train de la classe DialogueAgent.
evaluate_dialogue_agent.py
HIDDEN_UNITS = 64
CLASSIFIER_EPOCHS = 50
# Training
training_data = pd.read_csv(join(BASE_DIR, './training_data.csv'))
dialogue_agent = DialogueAgent()
dialogue_agent.train(training_data['text'], training_data['label'], HIDDEN_UNITS, CLASSIFIER_EPOCHS)
Résultat d'exécution
Epoch 50/50
917/917 [==============================] - 0s 288us/step - loss: 0.0229
###J'ai aussi jeté un œil à diverses choses###
# pprint.pprint(dialogue_agent.pipeline.steps)
[('vectorizer',
TfidfVectorizer(analyzer='word', binary=False, decode_error='strict',
dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
lowercase=True, max_df=1.0, max_features=None, min_df=1,
ngram_range=(1, 2), norm='l2', preprocessor=None, smooth_idf=True,
stop_words=None, strip_accents=None, sublinear_tf=False,
token_pattern='(?u)\\b\\w\\w+\\b',
tokenizer=<bound method DialogueAgent._tokenize of <dialogue_agent_sklearn_pipeline.DialogueAgent object at 0x7f7fc81bd128>>,
use_idf=True, vocabulary=None)),
('classifier',
<keras.wrappers.scikit_learn.KerasClassifier object at 0x7f7fa4a6a320>)]
# pprint.pprint(dialogue_agent.pipeline.steps[1][1].get_params())
{'build_fn': <bound method DialogueAgent._build_mlp of <dialogue_agent_sklearn_pipeline.DialogueAgent object at 0x7f7fc81bd128>>,
'hidden_units': 64,
'input_dim': 3219,
'output_dim': 49}
# print([len(v) for v in dialogue_agent.pipeline.steps[1][1].model.layers[0].get_weights()])
[3219, 64]
# print([len(v) for v in dialogue_agent.pipeline.steps[1][1].model.layers[1].get_weights()])
[64, 49]
Il peut être confirmé que la dimension de la couche d'entrée est 3219, la dimension de la couche masquée est 64 et la dimension de la couche de sortie est 49. Il a été confirmé qu'il était correct à partir du format de la liste de poids de la 0ème couche et de la 1ère couche. (Au fur et à mesure que l'apprentissage progresse, cette liste de poids sera mise à jour de plus en plus)
Recommended Posts