Эта страница была переведа с помощью Cloud Translation API.
Switch to English

Основная классификация текста

Посмотреть на TensorFlow.org Запуск в Google Colab Просмотр на GitHub Скачать ноутбук

В данном руководстве текст классификации, начиная от простых текстовых файлов, хранящихся на диске. Вы будете тренировать бинарный классификатор для выполнения анализа настроений на IMDB данных. В конце ноутбука, есть упражнение для вас попробовать, в котором вы будете обучать мультикласс классификатор предсказать тег для программирования вопрос на переполнение стека.

 import matplotlib.pyplot as plt
import os
import re
import shutil
import string
import tensorflow as tf

from tensorflow.keras import layers
from tensorflow.keras import losses
from tensorflow.keras import preprocessing
from tensorflow.keras.layers.experimental.preprocessing import TextVectorization
 
 print(tf.__version__)
 
2.3.0

анализ настроений

Этот ноутбук готовит модель анализа настроений классифицировать обзоры фильмов как положительные или отрицательные, основанных на тексте обзора. Это пример бинарной -ило два класса-классификацию, является важным и широко применимым видом машины проблемы обучения.

Вы будете использовать Большой Movie Dataset обзора , содержащий текст 50000 обзоров фильмов из базы данных Internet Movie . Они разделены на 25000 обзоров для подготовки и 25.000 обзоров для тестирования. Тренировочные и контрольные наборы сбалансированы, то есть они содержат одинаковое количество положительных и отрицательных отзывов.

Скачать и изучить IMDB набор данных

Давайте скачать и извлечь набор данных, а затем изучить структуру каталогов.

 url = "https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz"

dataset = tf.keras.utils.get_file("aclImdb_v1.tar.gz", url,
                                    untar=True, cache_dir='.',
                                    cache_subdir='')

dataset_dir = os.path.join(os.path.dirname(dataset), 'aclImdb')
 
Downloading data from https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
84131840/84125825 [==============================] - 7s 0us/step

 os.listdir(dataset_dir)
 
['imdb.vocab', 'train', 'test', 'README', 'imdbEr.txt']
 train_dir = os.path.join(dataset_dir, 'train')
os.listdir(train_dir)
 
['urls_pos.txt',
 'neg',
 'labeledBow.feat',
 'pos',
 'urls_neg.txt',
 'unsup',
 'unsupBow.feat',
 'urls_unsup.txt']

В aclImdb/train/pos и aclImdb/train/neg каталоги содержат много текстовых файлов, каждый из которых один фильма обзор. Давайте посмотрим на один из них.

 sample_file = os.path.join(train_dir, 'pos/1181_9.txt')
with open(sample_file) as f:
  print(f.read())
 
Rachel Griffiths writes and directs this award winning short film. A heartwarming story about coping with grief and cherishing the memory of those we've loved and lost. Although, only 15 minutes long, Griffiths manages to capture so much emotion and truth onto film in the short space of time. Bud Tingwell gives a touching performance as Will, a widower struggling to cope with his wife's death. Will is confronted by the harsh reality of loneliness and helplessness as he proceeds to take care of Ruth's pet cow, Tulip. The film displays the grief and responsibility one feels for those they have loved and lost. Good cinematography, great direction, and superbly acted. It will bring tears to all those who have lost a loved one, and survived.

Загрузите набор данных

Далее, вы будете загружать данные с диска и подготовить его в формат, пригодный для обучения. Для этого вы будете использовать полезную text_dataset_from_directory утилиту, которая ожидает структуру каталогов следующим образом .

 main_directory/
...class_a/
......a_text_1.txt
......a_text_2.txt
...class_b/
......b_text_1.txt
......b_text_2.txt
 

Для того, чтобы подготовить набор данных для бинарной классификации, вам потребуется две папки на диске, соответствующие class_a и class_b . Они будут положительные и отрицательные обзоры фильмов, которые могут быть найдены в aclImdb/train/pos и aclImdb/train/neg . Поскольку IMDB набор данных содержит дополнительные папки, вы удалите их перед использованием этой утилиты.

 remove_dir = os.path.join(train_dir, 'unsup')
shutil.rmtree(remove_dir)
 

Далее, вы будете использовать text_dataset_from_directory утилиту для создания меченого tf.data.Dataset . tf.data представляет собой мощный набор инструментов для работы с данными.

При запуске машинного обучения эксперимента, это лучшая практика , чтобы разделить набор данных на три расколов: поезд , проверку и испытание .

IMDB набор данных уже был разделен на поезд и испытания, но ему не хватает набор проверки. Давайте создадим набор проверки с использованием 80:20 раскол обучающих данных с помощью validation_split аргумент ниже.

 batch_size = 32
seed = 42

raw_train_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/train', 
    batch_size=batch_size, 
    validation_split=0.2, 
    subset='training', 
    seed=seed)
 
Found 25000 files belonging to 2 classes.
Using 20000 files for training.

Как вы можете видеть выше, есть 25000 примеров в обучающей папке, из которой вы будете использовать 80% (или 20000) для обучения. Как вы увидите в данный момент, вы можете тренировать модель, передавая массив данных непосредственно в model.fit . Если вы новичок в tf.data , вы можете также итерация по набору данных и распечатать несколько примеров следующим образом .

 for text_batch, label_batch in raw_train_ds.take(1):
  for i in range(3):
    print("Review", text_batch.numpy()[i])
    print("Label", label_batch.numpy()[i])
 
Review b'"Pandemonium" is a horror movie spoof that comes off more stupid than funny. Believe me when I tell you, I love comedies. Especially comedy spoofs. "Airplane", "The Naked Gun" trilogy, "Blazing Saddles", "High Anxiety", and "Spaceballs" are some of my favorite comedies that spoof a particular genre. "Pandemonium" is not up there with those films. Most of the scenes in this movie had me sitting there in stunned silence because the movie wasn\'t all that funny. There are a few laughs in the film, but when you watch a comedy, you expect to laugh a lot more than a few times and that\'s all this film has going for it. Geez, "Scream" had more laughs than this film and that was more of a horror film. How bizarre is that?<br /><br />*1/2 (out of four)'
Label 0
Review b"David Mamet is a very interesting and a very un-equal director. His first movie 'House of Games' was the one I liked best, and it set a series of films with characters whose perspective of life changes as they get into complicated situations, and so does the perspective of the viewer.<br /><br />So is 'Homicide' which from the title tries to set the mind of the viewer to the usual crime drama. The principal characters are two cops, one Jewish and one Irish who deal with a racially charged area. The murder of an old Jewish shop owner who proves to be an ancient veteran of the Israeli Independence war triggers the Jewish identity in the mind and heart of the Jewish detective.<br /><br />This is were the flaws of the film are the more obvious. The process of awakening is theatrical and hard to believe, the group of Jewish militants is operatic, and the way the detective eventually walks to the final violent confrontation is pathetic. The end of the film itself is Mamet-like smart, but disappoints from a human emotional perspective.<br /><br />Joe Mantegna and William Macy give strong performances, but the flaws of the story are too evident to be easily compensated."
Label 0
Review b'Great documentary about the lives of NY firefighters during the worst terrorist attack of all time.. That reason alone is why this should be a must see collectors item.. What shocked me was not only the attacks, but the"High Fat Diet" and physical appearance of some of these firefighters. I think a lot of Doctors would agree with me that,in the physical shape they were in, some of these firefighters would NOT of made it to the 79th floor carrying over 60 lbs of gear. Having said that i now have a greater respect for firefighters and i realize becoming a firefighter is a life altering job. The French have a history of making great documentary\'s and that is what this is, a Great Documentary.....'
Label 1

Обратите внимание , обзоры содержат текст (с пунктуацией и случайным HTML тегами , как <br/> ). Вы покажете, как обращаться с этим в следующем разделе.

Этикетки 0 или 1. Для того, чтобы увидеть , какие из них соответствуют положительным и отрицательным обзорам фильмов, вы можете проверить class_names свойства на наборе данных.

 print("Label 0 corresponds to", raw_train_ds.class_names[0])
print("Label 1 corresponds to", raw_train_ds.class_names[1])
 
Label 0 corresponds to neg
Label 1 corresponds to pos

Далее, вы будете создавать проверки и тестовый набор данных. Вы будете использовать оставшиеся 5000 обзоров из обучающего набора для проверки.

 raw_val_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/train', 
    batch_size=batch_size, 
    validation_split=0.2, 
    subset='validation', 
    seed=seed)
 
Found 25000 files belonging to 2 classes.
Using 5000 files for validation.

 raw_test_ds = tf.keras.preprocessing.text_dataset_from_directory(
    'aclImdb/test', 
    batch_size=batch_size)
 
Found 25000 files belonging to 2 classes.

Подготовка набора данных для обучения

Далее, вы стандартизировать, разметить и векторизации данные , используя полезный preprocessing.TextVectorization слой.

Стандартизация относится к предварительной обработке текста, как правило, для удаления пунктуации или HTML-элементов для упрощения набора данных. Токенизации относятся к расщеплению строк на лексемы (например, расщепление предложения на отдельные слова, путем разделения на пробельном). Векторизация относится к преобразованию маркеров в числа таким образом, они могут быть поданы в нейронную сеть. Все эти задачи могут быть выполнены с этим слоем.

Как вы видели выше, обзоры содержат различные HTML - теги , как <br /> . Эти метки не будут удалены стандартизатор по умолчанию в TextVectorization слое (который преобразует текст в lowecase и полосы пунктуации по умолчанию, но не лишит HTML). Вы написать пользовательскую функцию стандартизации для удаления HTML.

 def custom_standardization(input_data):
  lowercase = tf.strings.lower(input_data)
  stripped_html = tf.strings.regex_replace(lowercase, '<br />', ' ')
  return tf.strings.regex_replace(stripped_html,
                                  '[%s]' % re.escape(string.punctuation),
                                  '')
 

Далее вы создадите TextVectorization слой. вы будете использовать этот слой, чтобы стандартизировать, разметить и векторизации наши данные. Вы можете установить output_mode в int для создания уникальных целочисленных индексов для каждых маркеров.

Обратите внимание, что вы используете функцию разделения клавиатуры по умолчанию, а функция пользовательской стандартизации вы определили выше. Вы также определить некоторые константы для данной модели, как явная максимальной sequence_length , которая заставит слой прокладочных или усечь последовательности точно sequence_length значений.

 max_features = 10000
sequence_length = 250

vectorize_layer = TextVectorization(
    standardize=custom_standardization,
    max_tokens=max_features,
    output_mode='int',
    output_sequence_length=sequence_length)
 

Далее, вы назовете adapt к размеру состояния предварительной обработки слоя в наборе данных. Это приведет к тому, модели для построения индекса строк до целых чисел.

 # Make a text-only dataset (without labels), then call adapt
train_text = raw_train_ds.map(lambda x, y: x)
vectorize_layer.adapt(train_text)
 

Давайте создадим функцию, чтобы увидеть результат использования этого слоя препроцессировать некоторые данные.

 def vectorize_text(text, label):
  text = tf.expand_dims(text, -1)
  return vectorize_layer(text), label
 
 # retrieve a batch (of 32 reviews and labels) from the dataset
text_batch, label_batch = next(iter(raw_train_ds))
first_review, first_label = text_batch[0], label_batch[0]
print("Review", first_review)
print("Label", raw_train_ds.class_names[first_label])
print("Vectorized review", vectorize_text(first_review, first_label))
 
Review tf.Tensor(b'Silent Night, Deadly Night 5 is the very last of the series, and like part 4, it\'s unrelated to the first three except by title and the fact that it\'s a Christmas-themed horror flick.<br /><br />Except to the oblivious, there\'s some obvious things going on here...Mickey Rooney plays a toymaker named Joe Petto and his creepy son\'s name is Pino. Ring a bell, anyone? Now, a little boy named Derek heard a knock at the door one evening, and opened it to find a present on the doorstep for him. Even though it said "don\'t open till Christmas", he begins to open it anyway but is stopped by his dad, who scolds him and sends him to bed, and opens the gift himself. Inside is a little red ball that sprouts Santa arms and a head, and proceeds to kill dad. Oops, maybe he should have left well-enough alone. Of course Derek is then traumatized by the incident since he watched it from the stairs, but he doesn\'t grow up to be some killer Santa, he just stops talking.<br /><br />There\'s a mysterious stranger lurking around, who seems very interested in the toys that Joe Petto makes. We even see him buying a bunch when Derek\'s mom takes him to the store to find a gift for him to bring him out of his trauma. And what exactly is this guy doing? Well, we\'re not sure but he does seem to be taking these toys apart to see what makes them tick. He does keep his landlord from evicting him by promising him to pay him in cash the next day and presents him with a "Larry the Larvae" toy for his kid, but of course "Larry" is not a good toy and gets out of the box in the car and of course, well, things aren\'t pretty.<br /><br />Anyway, eventually what\'s going on with Joe Petto and Pino is of course revealed, and as with the old story, Pino is not a "real boy". Pino is probably even more agitated and naughty because he suffers from "Kenitalia" (a smooth plastic crotch) so that could account for his evil ways. And the identity of the lurking stranger is revealed too, and there\'s even kind of a happy ending of sorts. Whee.<br /><br />A step up from part 4, but not much of one. Again, Brian Yuzna is involved, and Screaming Mad George, so some decent special effects, but not enough to make this great. A few leftovers from part 4 are hanging around too, like Clint Howard and Neith Hunter, but that doesn\'t really make any difference. Anyway, I now have seeing the whole series out of my system. Now if I could get some of it out of my brain. 4 out of 5.', shape=(), dtype=string)
Label neg
Vectorized review (<tf.Tensor: shape=(1, 250), dtype=int64, numpy=
array([[1287,  313, 2380,  313,  661,    7,    2,   52,  229,    5,    2,
         200,    3,   38,  170,  669,   29, 5492,    6,    2,   83,  297,
         549,   32,  410,    3,    2,  186,   12,   29,    4,    1,  191,
         510,  549,    6,    2, 8229,  212,   46,  576,  175,  168,   20,
           1, 5361,  290,    4,    1,  761,  969,    1,    3,   24,  935,
        2271,  393,    7,    1, 1675,    4, 3747,  250,  148,    4,  112,
         436,  761, 3529,  548,    4, 3633,   31,    2, 1331,   28, 2096,
           3, 2912,    9,    6,  163,    4, 1006,   20,    2,    1,   15,
          85,   53,  147,    9,  292,   89,  959, 2314,  984,   27,  762,
           6,  959,    9,  564,   18,    7, 2140,   32,   24, 1254,   36,
           1,   85,    3, 3298,   85,    6, 1410,    3, 1936,    2, 3408,
         301,  965,    7,    4,  112,  740, 1977,   12,    1, 2014, 2772,
           3,    4,  428,    3, 5177,    6,  512, 1254,    1,  278,   27,
         139,   25,  308,    1,  579,    5,  259, 3529,    7,   92, 8981,
          32,    2, 3842,  230,   27,  289,    9,   35,    2, 5712,   18,
          27,  144, 2166,   56,    6,   26,   46,  466, 2014,   27,   40,
        2745,  657,  212,    4, 1376, 3002, 7080,  183,   36,  180,   52,
         920,    8,    2, 4028,   12,  969,    1,  158,   71,   53,   67,
          85, 2754,    4,  734,   51,    1, 1611,  294,   85,    6,    2,
        1164,    6,  163,    4, 3408,   15,   85,    6,  717,   85,   44,
           5,   24, 7158,    3,   48,  604,    7,   11,  225,  384,   73,
          65,   21,  242,   18,   27,  120,  295,    6,   26,  667,  129,
        4028,  948,    6,   67,   48,  158,   93,    1]])>, <tf.Tensor: shape=(), dtype=int32, numpy=0>)

Как вы можете видеть выше, каждый маркер был заменен целым числом. Вы можете поиск маркеров (строка) , что каждое целое число соответствует путем вызов .get_vocabulary() на слое.

 print("1287 ---> ",vectorize_layer.get_vocabulary()[1287])
print(" 313 ---> ",vectorize_layer.get_vocabulary()[313])
print('Vocabulary size: {}'.format(len(vectorize_layer.get_vocabulary())))
 
1287 --->  silent
 313 --->  night
Vocabulary size: 10000

Вы почти готовы обучать вашу модель. В качестве заключительного этапа предварительной обработки, вы будете применять TextVectorization слой, созданные ранее, поезд, проверку и тестирование данных.

 train_ds = raw_train_ds.map(vectorize_text)
val_ds = raw_val_ds.map(vectorize_text)
test_ds = raw_test_ds.map(vectorize_text)
 

Настройка набора данных для выполнения

Это два важных методов, которые следует использовать при загрузке данных, чтобы убедиться, что I / O не станет блокировки.

.cache() хранит данные в памяти после того, как он будет загружен с диска. Это обеспечит набор данных не становится узким местом во время обучения модели. Если набор данные слишком велики, чтобы поместиться в память, вы также можете использовать этот метод, чтобы создать производительный дисковый кэш, который является более эффективным, чем читать много маленьких файлов.

.prefetch() перекрывает данные предварительной обработки и выполнение модели во время тренировки.

Вы можете узнать о более обоих методов, а также как данные кэша на диск в руководстве производительности данных .

 AUTOTUNE = tf.data.experimental.AUTOTUNE

train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
test_ds = test_ds.cache().prefetch(buffer_size=AUTOTUNE)
 

Создание модели

Пришло время, чтобы создать нашу нейронную сеть:

 embedding_dim = 16
 
 model = tf.keras.Sequential([
  layers.Embedding(max_features + 1, embedding_dim),
  layers.Dropout(0.2),
  layers.GlobalAveragePooling1D(),
  layers.Dropout(0.2),
  layers.Dense(1)])

model.summary()
 
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, None, 16)          160016    
_________________________________________________________________
dropout (Dropout)            (None, None, 16)          0         
_________________________________________________________________
global_average_pooling1d (Gl (None, 16)                0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 16)                0         
_________________________________________________________________
dense (Dense)                (None, 1)                 17        
=================================================================
Total params: 160,033
Trainable params: 160,033
Non-trainable params: 0
_________________________________________________________________

Слои укладывают последовательно, чтобы построить классификатор:

  1. Первый слой представляет собой Embedding слой. Этот слой принимает целочисленные кодируются обзоры и смотрит вложение вектора для каждого слова-индекса. Эти векторы выучены как модели поездов. Векторы добавить измерение выходного массива. Полученные размеры: (batch, sequence, embedding) . Чтобы узнать больше о вложении см слова вложения учебника .
  2. Далее, GlobalAveragePooling1D слой возвращает выходной вектор фиксированной длины для каждого примера путем усреднения по размерности последовательности. Это позволяет модель ручки вводу переменной длины, в наиболее простом способе.
  3. Этот выходной вектор фиксированной длины по трубопроводу через полностью подключено ( Dense слой) с 16 скрытых блоками.
  4. Последний слой плотно соединен с одним выходным узлом.

Функция Loss и оптимизатор

Модель нуждается в функции потерь и оптимизатор для обучения. Так как это бинарная проблема классификации и модель выхода вероятности (один блок-слой с сигмовидной активацией), вы будете использовать losses.BinaryCrossentropy функцию потерь.

Теперь, настроить модель использовать оптимизатор и функцию потерь:

 model.compile(loss=losses.BinaryCrossentropy(from_logits=True), optimizer='adam', metrics=tf.metrics.BinaryAccuracy(threshold=0.0))
 

Поезд модели

Вы будете тренировать модель пропускания dataset объекта в пригонках метода.

 epochs = 10
history = model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=epochs)
 
Epoch 1/10
625/625 [==============================] - 3s 5ms/step - loss: 0.6632 - binary_accuracy: 0.6931 - val_loss: 0.6135 - val_binary_accuracy: 0.7752
Epoch 2/10
625/625 [==============================] - 3s 4ms/step - loss: 0.5472 - binary_accuracy: 0.8003 - val_loss: 0.4968 - val_binary_accuracy: 0.8220
Epoch 3/10
625/625 [==============================] - 3s 4ms/step - loss: 0.4434 - binary_accuracy: 0.8459 - val_loss: 0.4187 - val_binary_accuracy: 0.8486
Epoch 4/10
625/625 [==============================] - 3s 4ms/step - loss: 0.3770 - binary_accuracy: 0.8660 - val_loss: 0.3726 - val_binary_accuracy: 0.8622
Epoch 5/10
625/625 [==============================] - 2s 4ms/step - loss: 0.3349 - binary_accuracy: 0.8786 - val_loss: 0.3442 - val_binary_accuracy: 0.8678
Epoch 6/10
625/625 [==============================] - 2s 4ms/step - loss: 0.3046 - binary_accuracy: 0.8889 - val_loss: 0.3253 - val_binary_accuracy: 0.8722
Epoch 7/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2807 - binary_accuracy: 0.8977 - val_loss: 0.3118 - val_binary_accuracy: 0.8726
Epoch 8/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2609 - binary_accuracy: 0.9046 - val_loss: 0.3026 - val_binary_accuracy: 0.8762
Epoch 9/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2443 - binary_accuracy: 0.9123 - val_loss: 0.2961 - val_binary_accuracy: 0.8774
Epoch 10/10
625/625 [==============================] - 2s 4ms/step - loss: 0.2309 - binary_accuracy: 0.9163 - val_loss: 0.2915 - val_binary_accuracy: 0.8804

Оценить модель

Давайте посмотрим, как эта модель выполняет. Два значения будут возвращены. Потеря (число, которое представляет нашу ошибку, более низкие значения лучше), и точность.

 loss, accuracy = model.evaluate(test_ds)

print("Loss: ", loss)
print("Accuracy: ", accuracy)
 
782/782 [==============================] - 2s 3ms/step - loss: 0.3097 - binary_accuracy: 0.8740
Loss:  0.30967268347740173
Accuracy:  0.8740400075912476

Это довольно наивный подход обеспечивает точность около 86%.

Создать график точности и потери во время

model.fit() возвращает History объект , который содержит словарь со всем , что произошло во время тренировки:

 history_dict = history.history
history_dict.keys()
 
dict_keys(['loss', 'binary_accuracy', 'val_loss', 'val_binary_accuracy'])

Есть четыре элемента: один для каждого контролируемого Метрика во время тренировки и проверки. Вы можете использовать их, чтобы построить потери профессиональной подготовки и проверки для сравнения, а также подготовки и проверки точности:

 acc = history_dict['binary_accuracy']
val_acc = history_dict['val_binary_accuracy']
loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs = range(1, len(acc) + 1)

# "bo" is for "blue dot"
plt.plot(epochs, loss, 'bo', label='Training loss')
# b is for "solid blue line"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()
 

PNG

 plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')

plt.show()
 

PNG

На этом графике, точки представляют собой потерю профессиональной подготовки и точность, а сплошные линии потеря и точность проверки.

Обратите внимание , что потеря обучения уменьшается с каждой эпохой и обучение точности возрастает с каждой эпохой. Ожидается, что при использовании градиентного спуска оптимизации, он должен минимизировать требуемое количество на каждой итерации.

Это не тот случай потери и проверки точности, они, кажется, пика до точности обучения. Это пример переобучения: модель выполняет лучше на обучающих данных, чем это делает на данных, которые он никогда не видел раньше. После этого момента, модель более-оптимизирует и узнает ЗАЯВЛЕНИЯ специфический для подготовки данных , которые не обобщают на тестовые данные.

В данном конкретном случае, вы могли бы предотвратить переобучения, просто не остановить тренировку, когда точность проверки больше не растет. Один из способов сделать это является использование EarlyStopping обратного вызова .

Экспорт модели

В приведенном выше коде, вы применили TextVectorization слой к набору данных перед подачей текста в модели. Если вы хотите , чтобы ваша модель способна обрабатывать сырые строки (например, для упрощения его развертывания), вы можете включить TextVectorization слой внутри вашей модели. Для этого, вы можете создать новую модель с использованием весов просто обученными.

 export_model = tf.keras.Sequential([
  vectorize_layer,
  model,
  layers.Activation('sigmoid')
])

export_model.compile(
    loss=losses.BinaryCrossentropy(from_logits=False), optimizer="adam", metrics=['accuracy']
)

# Test it with `raw_test_ds`, which yields raw strings
loss, accuracy = export_model.evaluate(raw_test_ds)
print(accuracy)
 
782/782 [==============================] - 3s 4ms/step - loss: 0.3097 - accuracy: 0.8740
0.8740400075912476

В том числе текста предварительной обработки логики внутри вашей модели позволяет экспортировать модель для производства, развертывание упрощает и уменьшает потенциал для поезда / испытания перекоса .

Существует разница в производительности, чтобы иметь в виду при выборе, где применить TextVectorization слой. С его помощью за пределами вашей модели позволяет выполнять асинхронную обработку процессора и буферизацию ваших данных при обучении на GPU. Так что, если вы тренируетесь модель на GPU, вы, вероятно, хотите, чтобы пойти с этой опцией, чтобы получить максимальную производительность при разработке вашей модели, а затем перейти в то числе TextVectorization слоя внутри вашей модели, когда вы будете готовы к подготовке к развертыванию ,

Посетите этот учебник , чтобы узнать больше о сохранении моделей.

Упражнение: мультиклассируют классификация по переполнению стека вопросов

В этом учебнике показано, как подготовить бинарный классификатор с нуля на IMDB данных. В качестве упражнения, вы можете изменить этот ноутбук , чтобы обучить MultiClass классификатор предсказать тег вопроса программирования на переполнение стека .

Мы подготовили набор данных для использования с телом нескольких тысяч вопросов программирования (например, «Как можно отсортировать словарь по значению в Python?») Размещено на переполнение стека. Каждый из них помечен ровно один тег (либо Python, Csharp, JavaScript или Java). Ваша задача состоит в том, чтобы взять вопрос в качестве входных данных, и предсказать, соответствующий тег, в данном случае, Python.

Набор данных вы будете работать с содержат несколько тысяч вопросов , извлеченных из более широкой публики переполнения стеки набора данных на BigQuery , который содержит более 17 миллионов сообщений.

После загрузки набора данных, вы обнаружите, что имеет такую ​​же структуру каталогов на IMDB набора данных вы работали с ранее:

 train/
...python/
......0.txt
......1.txt
...javascript/
......0.txt
......1.txt
...csharp/
......0.txt
......1.txt
...java/
......0.txt
......1.txt
 

Для выполнения этого упражнения, вы должны изменить этот ноутбук для работы с набором данных с переполнением стека, сделав следующие изменения:

  1. В верхней части ноутбука, обновите код , который загружает IMDB набор данных с кодом , чтобы загрузить набор данных переполнения стеки мы prepreared. Поскольку набор данных о переполнении стека имеет аналогичную структуру каталогов, вам не нужно будет сделать много изменений.

  2. Изменение последнего слоя модели для чтения Dense(4) , так как в настоящее время существует четыре выходных классы.

  3. При компиляции модели, изменить потери SparseCategoricalCrossentropy . Это правильная функция потерь использовать для мультиклассируют задачи классификации, когда метки для каждого класса являются целыми числами (в нашем случае, они могут быть 0, 1, 2 или 3).

  4. После того, как эти изменения будут завершены, вы сможете тренировать мультикласс классификатора.

Если вы застряли, вы можете найти решение здесь .

Узнать больше

Этот учебник представил текст классификацию с нуля. Чтобы узнать больше о классификации процессе текста в целом, мы рекомендуем прочитать данное руководство от Google Developers.

 
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.