Машинное обучение

«Искусственный интеллект меньше нашего интеллекта?» - Спайк Джонз

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

Модель ML, которую мы называем [Модель Крокодила] :),

состоит из искусственных нейронных сетей, особенно временных рядов NN, то есть рекуррентных нейронных сетей, основанных на LSTM (долгосрочная краткосрочная память) и CRF (случайные поля свертки) в качестве вероятностной модели. Ссылка - https://guillaumegenthial.github.io/sequence-tagging-with-tensorflow.html

В общих чертах его можно разделить на три части:

1. Представление слов. Прежде всего, нам нужно представить слова в поисковом запросе в виде вектора признаков, для которого мы использовали предварительно обученную модель встраивания слов, разработанную в рамках проекта с открытым исходным кодом в Стэнфорде под названием "Перчатка". Он обеспечивает 300-мерный вектор встраивания слов. Мы собираемся объединить встраивание ElMo вместе с этим.

2. Контекстное представление слова: для поиска контекстной информации между словами в запросе она передается через двунаправленный LSTM, за которым следует плотный слой, производящий на выходе размер, равный количеству тегов.

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

Существуют три варианта современной модели, которые представлены ниже:

1. LSTM-CRF: состоит из тех же трех частей, что описаны выше.

2. CharLSTM-LSTM-CRF: Мы создали встраивание слова на уровне символа с помощью LSTM, потому что могут быть некоторые слова, такие как бренд, которые могут отсутствовать в словаре предварительно обученной модели встраивания слов, то есть GloVe.

3. CharConv-LSTM-CRF: то же, что и в вышеупомянутой модели, с той лишь разницей, что NN используется для генерации встраивания уровня символов, которым здесь является CNN вместо LSTM.

4. CharLSTM-LSTM-CRF с встраиванием Elmo:

Мы использовали вторую модель CharLSTM-LSTM-CRF для нашего варианта использования, поскольку она работала лучше, чем любая другая модель. Мы также работаем над внедрением Модели-4.

Реализация Модели 2 [Модель Крокодила] в Tensorflow:

Tensorflow tf.Data API - хороший кандидат для передачи данных в вашу модель при работе с высокоуровневым API, таким как Estimator. Он вводит класс tf.data.Dataset, который создает входной конвейер для чтения данных. У него есть метод from_generator, который генерирует элементы из генератора. Вы также можете использовать метод map для разработки функций.

#Accepting a method which yields the generator after reading each line from csv file
dataset = tf.data.Dataset.from_generator( functools.partial(generator_fn, words, tags), output_shapes=shapes, output_types=types)

После получения набора данных мы можем сделать что-то вроде:

# it will shuffle the the dataset first sampled from 100 elements, and then repeat the same dataset for 5 times- which can be used for iterating through number of epochs
dataset = dataset.shuffle(100).repeat(5)
#creates the batch which is padded in the defaults shape and buffer 2500 records for the next iteration
dataset = (dataset.padded_batch(2500, shapes, defaults).prefetch(2500))

Другой класс, расширяющий tf.data.Dataset, называется tf.data.TextLineDataset, который принимает имя файла csv в качестве аргумента и читает его для вас. Этот API будет много управлять памятью за вас, когда вы используете его наборы данных на основе файлов. Вы можете, например, читать файлы набора данных, размер которых намного превышает размер памяти, или читать несколько файлов, указав список в качестве аргумента.

API оценщика Tensorflow с использованием настраиваемых оценщиков и tf.data Tensorflow использовались для написания кода всего обучения, моделирования и оценки. Пользовательский оценщик в Tensorflow имеет класс tf.estimator.Estimator, который обертывает модель, заданную служебной функцией model_fn и tf.estimator.train_and_evaluate, которая обучает, оценивает и (необязательно ) экспортирует модель с использованием заданного оценщика. model_fn для модели выглядит следующим образом:

  1. Для представления слова: Сначала сгенерируйте вложение символа:
#For each sentence and words, we have a list of characters
#We find the index of character present in the dictionary of all characters
char_ids = vocab_chars.lookup(chars) #[sentence, words, chars] 
#Initialize a variable [total_number_of_chars, dimension of char_embedding=100] storing the initial embedding of all characters with some random floating point numbers
variable = tf.get_variable(
 ‘chars_embeddings’, [num_chars, params[‘dim_chars’]], tf.float32)
#Lookup the embeddings of the chars in char_ids 
char_embeddings = tf.nn.embedding_lookup(variable, char_ids, validate_indices=False)  #[sentence, word, chars, char_dim=100]
#Adding a dropout in the layer
char_embeddings = tf.layers.dropout(char_embeddings, rate=dropout,
 training=training) 
#[max_length of sentences in batch]
dim_words = tf.shape(char_embeddings)[1]
#[max_length of words in all the sentences]
dim_chars = tf.shape(char_embeddings)[2]
flat = tf.reshape(char_embeddings, [-1, dim_chars, params['dim_chars']])  #[sentence*max_words_in_sentence ,max_chars_in_all_words, char_dim=100]
#making time major from batch major as required by tf.contrib.rnnt = tf.transpose(flat, perm=[1, 0, 2])
#Initializing LSTM each having 25 units
lstm_cell_fw = tf.contrib.rnn.LSTMBlockFusedCell(25)
lstm_cell_bw = tf.contrib.rnn.LSTMBlockFusedCell(25)
#Creating backward dir LSTM
lstm_cell_bw = tf.contrib.rnn.TimeReversedFusedRNN(lstm_cell_bw)
#output having dim [max_chars_in_all_words, sentence*max_words_in_sentence, char_embd_size=25]
#Here time_steps i.e.[sequence_length] = number of chars in each words
_, (_, output_fw) = lstm_cell_fw(t, dtype=tf.float32, sequence_length=tf.reshape(nchars, [-1]))
#Reverse Bi-LSTM output
_, (_, output_bw) = lstm_cell_bw(t, dtype=tf.float32, sequence_length=tf.reshape(nchars, [-1]))
output = tf.concat([output_fw, output_bw], axis=-1) # [max_chars_in_all_words, sentence*max_words_in_sentence, char_embd_size=25+25=50]
#Reshape to [num_of_sentences, max_num_of_words, 50]
char_embeddings = tf.reshape(output, [-1, dim_words, 50])

Теперь также сгенерируйте вложения слов:

#For each sentence, we have a list of words
#We find the index of words present in the dictionary of all words
word_ids = vocab_words.lookup(words) #[sentence, words]
#Getting the glove embeddings of all the words
glove = np.load(params[‘glove’])[‘embeddings’]
#Appending an extra embeddings to return if some word is not found
variable = np.vstack([glove, [[0.] * params[‘dim’] ]])variable = tf.Variable(variable, dtype=tf.float32, trainable=False)
#Look up the word embeddings in the dictionary we created as non-trainable
word_embeddings = tf.nn.embedding_lookup(variable, word_ids) #[sentence, word, glove_word_dim = 300]
# Concatenate Word and Char Embeddings
embeddings = tf.concat([word_embeddings, char_embeddings], axis=-1)
#[sentence, word, 300+50=350]

2. Контекстное представление слов

#Time major, input shape= [sentences, words, 350]
t = tf.transpose(embeddings, perm=[1, 0, 2]) 
#Forward and Backward lstm each of 100 units
lstm_cell_fw = tf.contrib.rnn.LSTMBlockFusedCell(100)
lstm_cell_bw = tf.contrib.rnn.LSTMBlockFusedCell(100)
lstm_cell_bw = tf.contrib.rnn.TimeReversedFusedRNN(lstm_cell_bw)
# time steps i.e. [sequence_length] having number of words in each sentence
output_fw, _ = lstm_cell_fw(t, dtype=tf.float32, sequence_length=nwords) #[sentence, words, 100]
output_bw, _ = lstm_cell_bw(t, dtype=tf.float32, sequence_length=nwords) #[sentence, words, 100]
# Concatenate the both forward and backword encoding 
output = tf.concat([output_fw, output_bw], axis=-1) #[sentence, words, 100+100=200]
output = tf.transpose(output, perm=[1, 0, 2]) 
#transponse to original shape
#Create a dense layer to reduce the output to num of tags
logits = tf.layers.dense(output, num_tags) # [sentence, word, num_of_tag=6]

3. Расшифровка с использованием CRF:

#Create a variable and initialize as a transition score from one tags to another tags in determining the score of a particular combination of tags
crf_params = tf.get_variable(“crf”, [num_tags, num_tags], dtype=tf.float32)
# determining the tags for each sentence # [sentence, no_of_tags]
pred_ids, _ = tf.contrib.crf.crf_decode(logits, crf_params, [length_of_tags])

Расчет убытка и его оптимизация:

#Using Log likelihood as the loss function
log_likelihood, _ = tf.contrib.crf.crf_log_likelihood(logits, correct_tags, [length_of_tags], crf_params)
loss = tf.reduce_mean(-log_likelihood)

#Using adam optimizer to minimize the loss
if mode == tf.estimator.ModeKeys.TRAIN:
     train_op = tf.train.AdamOptimizer().minimize(loss, global_step=tf.train.get_or_create_global_step())

Обслуживание TensorFlow:

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

estimator.export_savedmodel(‘/content/model’, serving_input_receiver_fn)

Вышеупомянутый метод принимает путь к каталогу, в котором будут сохранены параметры модели, и input_fn типа ServingInputReceiver, в котором входные функции передаются как dict.

SavedModel экспортируется описанными выше способами после обучения на наборах данных, созданных по нескольким сценариям. Та же модель загружается в T Ensorflow serve API (docker-version), который предоставляет REST API и возвращает теги, предсказанные в соответствии с конкретным поисковым запросом.

docker run -p 8501:8501 \
--mount type=bind,source=/path/to/my_model/,target=/models/my_model\
--mount type=bind,source=/path/to/my/models.config,target=/models/models.config \
-t tensorflow/serving --model_config_file=/models/models.config

Ответ модели обслуживания клиентов на запрос «шоколад без орехов» выглядит примерно так:

{
    "outputs": [
        [
            "NV-S",
            "PR-S",
            "BQ-S"
        ]
    ]
}

Тег «NV-S»: представляет тег питания, «PR-S»: представляет тег предлога, а «BQ-S»: представляет базовый запрос.

Обсуждение части развертывания будет продолжено в Части III.