Этот блог изначально опубликован на Scribendi.ai.

Scribendi предлагает высококачественные онлайн-услуги по редактированию и корректуре англоязычных документов с 1997 года. С момента основания технологии были в нашей ДНК, и мы считаем, что поиск и внедрение новейших технологий являются ключом к тому, чтобы мы могли предоставлять выдающиеся услуги Наши клиенты. Как компания, сертифицированная по стандарту ISO 9001:2015, мы также придерживаемся строгого контроля качества и процессов постоянного улучшения. Опираясь на обширные данные по обеспечению качества, мы проводим исследования в области обработки естественного языка (NLP), включая извлечение текста, исправление грамматических ошибок (GEC), жанровую классификацию, языковое моделирование и прогнозную аналитику.

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

В первый год нашего исследовательского партнерства с Университетом Ватерлоо мы разработали новые алгоритмы GEC, обучили модели и использовали слепую оценку для проверки их эффективности. Наша исследовательская группа рассмотрела весь процесс в целом, принимая во внимание новые инновации и исследования по обучению и оптимизации моделей. Наши окончательные модели были обучены с использованием 30 миллионов предложений. К сожалению, было очень мало доступной информации о том, как использовать ограниченные ресурсы для обслуживания модели, обученной с использованием большого объема данных в производственной среде, особенно с большим количеством людей, использующих модель одновременно. Тем не менее, хотя поначалу модели было сложно развернуть, теперь мы используем их в производстве для поддержки наших редакторов-людей.

Недавно мы перешли с Torch на TensorFlow для разработки, обучения и обслуживания наших моделей GEC. Хотя в TensorFlow есть обширные ресурсы для внедрения и обучения моделей машинного обучения, его примеры для обслуживания (т. е. развертывания и запуска) моделей в производственной среде сосредоточены на сверточных нейронных сетях (ConvNET), таких как RESNET, а не на RNN.

В этом руководстве мы прольем свет на то, как обучить модель на основе долговременной кратковременной памяти (LSTM), чтобы подготовить ее к работе, выполнив следующие шаги:

  1. Обучение модели классификации изображений на основе LSTM
  2. Сохранение и оценка модели
  3. Экспорт модели
  4. Обслуживание модели в рабочей среде

Чтобы получить максимальную отдачу от этого поста, вы должны быть знакомы с:

Хотя мы признаем, что современная классификация изображений в настоящее время предоставляется ConvNET, наша цель — показать вам, как обслуживать модель RNN в производственной среде. Таким образом, мы решили использовать модифицированный набор данных Национального института стандартов и технологий (MNIST) с LSTM в качестве RNN, поскольку этот набор данных является стандартом де-факто для исследования классификации изображений и, следовательно, хорошо известен и легко доступен. Он достаточно мал, чтобы вы могли выполнить это руководство на настольном или портативном компьютере за считанные минуты. Кроме того, мы считаем, что как только читатели поймут, как обслуживать простую модель, они смогут распространить эту практику на более сложные модели.

Теперь давайте начнем с первого шага.

  1. Обучение модели классификации изображений на основе LSTM

TensorFlow делает обучение модели RNN очень простым и интуитивно понятным. Мы будем использовать слой линейной активации поверх слоя LSTM. Чтобы облегчить экспорт, мы представим входные и выходные данные модели, оба из которых будут полезны при подаче данных в процессе логического вывода. Поскольку мы в первую очередь сосредоточены на выводах, мы будем упрощать обучение. Если вас интересует только код, загляните в мой репозиторий на github.

Вот шаги, которые мы выполним для обучения модели:

А. Загрузка необходимых библиотек

Б. Загрузка данных, необходимых для обучения и тестирования модели

С. Настройка параметров обучения и сети

Д. Определение переменных

Е. Определение модели

Ф. Расчет потерь и оптимизация

Г. Обучение модели

В следующих разделах мы рассмотрим каждый шаг, обозначив цели и поделившись кодовой базой, необходимой для завершения обучения. Обратите внимание, что этот код был протестирован с Python 3.6 и TensorFlow 1.8.

А. Загрузка необходимых библиотек

Начните с загрузки необходимых библиотек. Мы будем использовать известный набор данных MNIST от TensorFlow.

from __future__ import print_function
import os
import numpy as np
import tensorflow as tf
from tensorflow.contrib import rnn
tf.app.flags.DEFINE_integer(‘model_version’, 1, ‘version number of the model.’)
FLAGS = tf.app.flags.FLAGS
# Import MNIST data
from tensorflow.examples.tutorials.mnist import input_data

Б. Загрузка данных, необходимых для обучения и тестирования модели

Загрузите данные во временное хранилище и преобразуйте метки в вектор one_hot. Чтобы классифицировать изображения с помощью RNN, рассмотрите каждую строку изображения как последовательность пикселей. Поскольку форма изображения MNIST имеет размер 28 × 28 пикселей, для каждого образца будет 28 последовательностей с 28 шагами.

mnist = input_data.read_data_sets(“/tmp/data/”, one_hot=True)

С. Настройка параметров обучения и сети

Используйте стохастический градиентный спуск (SGD), чтобы поддерживать низкую скорость обучения и убедиться, что модель не соответствует обучающим данным.

learning_rate = 0.001
training_steps = 10000
batch_size = 128
display_step = 200
# Network Parameters
num_input = 28 # MNIST data input (img shape: 28*28)
timesteps = 28 # timesteps
num_hidden = 128 # hidden layer num of features
num_classes = 10 # MNIST total classes (0–9 digits)

Д. Определение переменных

В TensorFlow обычно используется заполнитель и feed_dict для передачи данных в модель во время обучения, тестирования и вывода. Назовите вход Input_X для использования при экспорте модели и во время логического вывода.

# Training Parameters
# tf Graph input
X = tf.placeholder(“float”, [None, timesteps, num_input],name =’Input_X’)
Y = tf.placeholder(“float”, [None, num_classes])
# Define weights
weights = {
‘out’: tf.Variable(tf.random_normal([num_hidden, num_classes]))
}
biases = {
‘out’: tf.Variable(tf.random_normal([num_classes]))
}

Е. Определение модели

Чтобы определить простую модель RNN на основе LSTM, подготовьте форму данных в соответствии с требованиями модели. Затем создайте ячейку LSTM с помощью BasicLSTMCell, которая применяется к входным данным; создать ячейку static_rnn в области с именем rnn; и установите auto_reuse=true для повторного использования модуля.

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

def RNN(x, weights, biases):
# Prepare data shape to match `rnn` function requirements
# Current data input shape: (batch_size, timesteps, n_input)
# Required shape: 'timesteps' tensors list of shape (batch_size, n_input)
x = tf.unstack(x, timesteps, 1)
# Define a lstm cell with tensorflow
lstm_cell = rnn.BasicLSTMCell(num_hidden, forget_bias=1.0)
# Get lstm cell output
outputs, _ = rnn.static_rnn(lstm_cell, x, dtype=tf.float32)
# Linear activation, using rnn inner loop last output
with tf.name_scope('output_layer'):
logit = tf.add(tf.matmul(outputs[-1], weights['out']) , biases['out'],name ='add')
return logit

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

logits = RNN(X, weights, biases)
prediction = tf.nn.softmax(logits,name=’prediction’)

Ф. Расчет потерь и оптимизация

Чтобы использовать функцию потерь, softmax_cross_entropy_with_logits_v2 сравнивает прогнозируемый результат с фактической меткой и использует оптимизатор (например, Adam, SGD, RMSprop) для минимизации потерь. Рассчитайте прогноз и точность модели и распечатайте статистику точности и потерь во время обучения.

# Define loss and optimizer
loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(
logits=logits, labels=Y))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
train_op = optimizer.minimize(loss_op)
# Evaluate model
correct_pred = tf.equal(tf.argmax(prediction, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

Г. Обучение модели

Чтобы обучить модель и подготовить ее к производству, необходимо сначала инициализировать переменные, включая веса и смещения. Определите вход и выход для замороженного графика. Получите входные и выходные тензоры по их именам на графике. Определите входную переменную как Input_X и output_layer как output_layer/add, а затем добавьте :0 в конец каждого.

Само имя появляется как операция на графике; чтобы использовать эти имена в качестве тензоров, :0 необходимо добавить к концам имен (т. е. операций).

# Initialize the variables (i.e. assign their default value)
init = tf.global_variables_initializer()
output_tensor = tf.get_default_graph().get_tensor_by_name(“output_layer/add:0”)
input_tensor = tf.get_default_graph().get_tensor_by_name(“Input_X:0”)

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

Начните обучение, создав новый сеанс. После запуска инициализатора переменной задайте цикл обучения в соответствии с количеством шагов, заранее определенным в пункте C. Проведите итерацию по обучающим данным и подавайте их в модель, партия за порцией, чтобы оптимизировать модель и минимизировать потери.

saver = tf.train.Saver()
with tf.Session() as sess:
# Run the initializer
    sess.run(init)
for step in range(1, training_steps+1):
        batch_x, batch_y = mnist.train.next_batch(batch_size)
        # Reshape data to get 28 seq of 28 elements
        batch_x = batch_x.reshape((batch_size, timesteps, num_input))
        # Run optimization op (backprop)
        sess.run(train_op, feed_dict={X: batch_x, Y: batch_y})
        if step % display_step == 0 or step == 1:
            # Calculate batch loss and accuracy
            loss, acc = sess.run([loss_op, accuracy], feed_dict={X: batch_x,
                                                                 Y: batch_y})
            print("Step " + str(step) + ", Minibatch Loss= " + \
                  "{:.4f}".format(loss) + ", Training Accuracy= " + \
                  "{:.3f}".format(acc))
    for op in tf.get_default_graph().get_operations():
        if output_layer[0] in op.name:
                print(op.name)
    print("Optimization Finished!")

Как было определено ранее, переменная display_step будет печатать данные о потерях и точности из обучения, чтобы гарантировать, что потери уменьшатся, а точность повысится (см. пример ниже). Этот процесс расчета потерь также известен как внутренняя оценка модели.

Step 1, Minibatch Loss= 2.5360, Training Accuracy= 0.055
 Step 1000, Minibatch Loss= 1.5179, Training Accuracy= 0.555
 Step 2000, Minibatch Loss= 1.3314, Training Accuracy= 0.602
 Step 3000, Minibatch Loss= 1.0988, Training Accuracy= 0.641
 Step 4000, Minibatch Loss= 1.0893, Training Accuracy= 0.664
 Step 5000, Minibatch Loss= 0.8246, Training Accuracy= 0.734
 Step 6000, Minibatch Loss= 0.5758, Training Accuracy= 0.820
 Step 7000, Minibatch Loss= 0.5413, Training Accuracy= 0.852
 Step 8000, Minibatch Loss= 0.6734, Training Accuracy= 0.734
 Step 9000, Minibatch Loss= 0.5125, Training Accuracy= 0.836
 Step 10000, Minibatch Loss= 0.3872, Training Accuracy= 0.875

После пятиминутного обучения модели на процессоре и выполнения 10 000 шагов потери значительно уменьшаются, а точность приближается к 88%, что достаточно для наших целей. Хотя ConvNET может достичь лучших результатов, наша цель — создать простую модель RNN и использовать ее в производстве.

2. Сохранение и оценка модели

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

  1. Сохранение модели
  2. Оценка модели

А. Сохранение модели

После завершения цикла обучения сохраните контрольную точку для повторного обучения в будущем; tf.train.Saver() делает сохранение простым и может быть выполнено одной строкой кода.

# save the model for retraining
saver.save(sess,’./model.ckpt’)

Б. Оценка модели

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

# Calculate accuracy for 128 mnist test images
test_len = 128
test_data = mnist.test.images[:test_len].reshape((-1, timesteps, num_input))
test_label = mnist.test.labels[:test_len]
sess.run(prediction, feed_dict={X: test_data}))
print(“Testing Accuracy:”, \
sess.run(accuracy, feed_dict={X: test_data, Y: test_label}))

Точность теста составляет 0,90625 или 90,6%, что [0,16] очень близко к точности обучения. Таким образом, модель не переоснащается, но ее можно дополнительно обучить с точностью около 98%, что очень близко к точности, достигаемой с помощью современной модели ConvNet/RESNET.

3. Экспорт обученной модели для логического вывода

Хотя сохраненная контрольная точка содержит метаданные, которые не нужны для логического вывода, экспорт модели TensorFlow важен по нескольким причинам. Для производства все, что вам нужно, — это определение модели и веса, которые экспортируются, чтобы минимизировать размер модели и ускорить вывод. Ниже мы объясним, как экспортировать модель RNN, которую можно использовать в производстве.

Сначала экспортируйте обученную модель для логического вывода с помощью SavedModelBuilder и создайте каталог, если он еще не существует. Здесь можно добавить версию модели, но для целей этой демонстрации удалите ранее сохраненную модель перед сохранением другой. [.17]

Во-вторых, создайте тензорную информацию для ввода и вывода экспортированной модели с помощью SavedModelBuilder API [.18] . Затем определите буферы протоколов tensor_info_x и tensor_info_y.

# Export the model for prediction
export_base_path = ‘./exportmodel’
export_path = os.path.join(
tf.compat.as_bytes(export_base_path),
tf.compat.as_bytes(str(FLAGS.model_version)))
# Removing previously exported model
# shutil.rmtree(export_path)
builder = tf.saved_model.builder.SavedModelBuilder(export_path)
tensor_info_x = tf.saved_model.utils.build_tensor_info(input_tensor)
tensor_info_y = tf.saved_model.utils.build_tensor_info(output_tensor)

В-третьих, определите сигнатуру, которая полезна для предсказания. Создайте определение подписи, используя сопоставление значений ключей. Назовите ключ ввода x_input (т. е. буфер протокола для Input_X) и tensor_info_x вывода y_output ( то есть буфер протокола для логит-тензора, tensor_info_y), а затем использовать method_name в качестве метода логического вывода. Мы используем предопределенную константу для вывода.

prediction_signature = (
tf.saved_model.signature_def_utils.build_signature_def(
inputs={‘x_input’: tensor_info_x},
outputs={‘y_output’: tensor_info_y},
method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))

В-четвертых, добавьте в сборку метаграф и переменные, такие как Input_X и logit, с помощью SavedModelBuilder.add_meta_graph_and_variables() и следующих аргументов:

  • sess: сеанс TensorFlow, содержащий обученную модель.
  • теги: набор тегов, используемых для сохранения метаграфа. В этом случае, поскольку мы намерены использовать граф при обслуживании, мы можем использовать тег serve из предопределенных констант тега SavedModel.
  • signature_def_map сопоставленный предоставленный пользователем ключ подписи для tensorflow::SignatureDef, который добавляется в метаграф. Сигнатура указывает, какой тип модели экспортируется и к каким входным и выходным тензорам привязываться при выполнении логического вывода.

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

builder.add_meta_graph_and_variables(
       sess, [tf.saved_model.tag_constants.SERVING],
       signature_def_map={
      tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
          prediction_signature
       },
      )
    builder.save()

4. Обслуживание модели в производстве

Экспортируйте модель из каталога экспортных моделей. Теперь вы можете запустить вывод. Вывод можно осуществить несколькими способами. Например, мы можем:

А. Обслуживайте модель с помощью Python Flask API

Б. Обслуживайте модель с помощью TensorFlow Serving API

Здесь мы покажем оба варианта рядом, чтобы сравнить производительность моделей на сервере. Каждая часть имеет две стороны: серверную и клиентскую.

А. Обслуживание модели с помощью Python Flask API

Flask — это микро веб-фреймворк, написанный на Python и основанный на наборе инструментов Werkzeug и шаблонизаторе Jinja2. Приложения, использующие платформу Flask, включают Pinterest, LinkedIn и веб-страницу сообщества самого Flask.

Flask популярен в сообществе Python из-за его простого в интеграции приложения. Он также имеет как серверную, так и клиентскую части. Сервер загружает модель и ожидает запросов клиентов для предоставления ответов. Flask можно скачать с веб-страницы разработчика, где также есть множество примеров.

Используйте запрос POST со стороны клиента для отправки данных изображения и получения логита в ответ. Flask не требует дополнительных приложений для выполнения POST-запроса и отправки данных обратно.

Используйте нотацию объектов JavaScript (JSON) для обмена данными; запрос POST не поддерживает обмен массивами NumPy. Этот формат позволит вам отправлять данные любого типа, в зависимости от модели, которую вы обучили. Сначала преобразуйте изображение на стороне клиента из массива NumPy в список, чтобы его можно было отправить в виде JSON. Получив изображение в этом формате, сервер получит массив List, преобразует его в массив NumPy и переформирует в соответствии с требованиями модели.

Как только ввод будет готов, передайте данные в модель, чтобы получить логиты, и примените softmax, чтобы получить прогноз в виде массива NumPy. Преобразуйте его в JSON, чтобы отправить обратно клиенту.

я. Флэш-сервер

import tensorflow as tf
import numpy as np
from flask import Flask, request
import json
def softmax(x):
    """Compute softmax values for each sets of scores in x."""
    e_x = np.exp(x)
    return e_x / e_x.sum(axis=-1)
app =Flask(__name__)
@app.route('/',methods=['POST'])
def predict():
    
    from_client = request.get_json()
    inference_data = from_client['data']
    inference_data = np.array(inference_data)
    batch_x = inference_data.reshape(-1,28,28)
    
    logits = sess.run([y],feed_dict={x:batch_x})
    prediction = softmax(logits)
    json_data = json.dumps({'y':prediction.tolist()})
    return json_data

Создайте сеанс, получив ключ определения подписи по умолчанию. Затем назначьте ключ, используемый для сохранения входных и выходных данных модели, и загрузите экспортированную модель из TensorFlow SavedModel API в качестве метаграфа. Извлеките сигнатуру, чтобы извлечь входные и выходные тензоры по имени из сеансов, и назначьте вход графа как x, а логит — как y. Теперь мы готовы к выводам.

if __name__ == '__main__':                                                                                                                                  tf.app.flags.DEFINE_string('model_path','./savedmodel/1/',help='model Path')
    tf.app.flags.DEFINE_string('host','0.0.0.0',help='server ip address')
    tf.app.flags.DEFINE_integer('port',5000,help='server port')
    FLAGS = tf.app.flags.FLAGS
    sess=tf.Session()
    signature_key = tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY
    input_key = 'x_input'
    output_key = 'y_output'
    export_path =  FLAGS.model_path
    meta_graph_def = tf.saved_model.loader.load(
            sess,
            [tf.saved_model.tag_constants.SERVING],
            export_path)
    signature = meta_graph_def.signature_def
    x_tensor_name = signature[signature_key].inputs[input_key].name
    y_tensor_name = signature[signature_key].outputs[output_key].name
    x = sess.graph.get_tensor_by_name(x_tensor_name)
    y = sess.graph.get_tensor_by_name(y_tensor_name)
    app.run(host=FLAGS.host,port=FLAGS.port)

II. Клиент Flask

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

import numpy as np
import requests 
import json
from tensorflow.examples.tutorials.mnist import input_data
import argparse
import time
def main(args):  
    mnist = input_data.read_data_sets(args.data_dir, one_hot=True)
    counter = 0
    start_time = time.time()
    num_tests = args.num_tests
    for i in range(num_tests):
        image = mnist.test.images[i]
        data = {'data':image.tolist()}
        headers = {'content-type': 'application/json'} 
        url = args.host+':'+str(args.port)
response = requests.post(url,json.dumps(data),headers = headers,timeout=10)
        if response.status_code == 200:
            response.encoding = 'utf-8'
            response = json.loads(response.text)
            response = response['y']
            if np.argmax(response) ==np.argmax(mnist.test.labels[i]):
                counter +=1
            else:
                pass
        else:
            print(response)
    print("Accuracy= %0.2f"%((counter*1.0/num_tests)*100))
    print("Time takes to run the test %0.2f"%(time.time()-start_time))
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--data_dir', default='/tmp/data')
    parser.add_argument('--host',default='http://127.0.0.1')
    parser.add_argument('--port',default=5000)
    parser.add_argument('--num_tests',default=100)
    args = parser.parse_args()
main(args)

Мы видим, что точность предсказания примерно такая же, как и точность теста на уровне 89%.

Б. Обслуживание модели с помощью TensorFlow Serving API

Для TensorFlow Serving требуется сервер и клиент. К счастью, сервер TensorFlow можно запустить с помощью одной строки кода, хотя, как и для Flask, он требует использования данных JSON. Преобразование между NumPy и List не требуется, поскольку TensorFlow использует для связи gRPC, что сокращает количество шагов и увеличивает скорость обслуживания. Для установки следуйте этим инструкциям.

Настройте сервер следующим образом:

tensorflow_model_server — port=9000 — model_name=mnist — model_base_path=/tmp/mnist_model/

Теперь настройте клиентскую часть. Сначала подготовьте канал связи, указав IP-адрес узла и адрес порта. Затем создайте заглушку, которая является сервисным объектом на стороне клиента; здесь мы создаем объект PredictRequest для назначения спецификаций модели, которые принимают имя модели (имя_модели) и имя подписи (имя_подписи) . Это ключ к prediction_signature, определенному во время экспорта модели.

В экспортированной модели используйте x_input в качестве входных данных для prediction_signature для отправки данных путем создания тензорного протобуфера с помощью make_tensor_proto. В производственной системе важно добавить тайм-аут с обработкой запросов и исключений и ведением журнала; Stub.Predict принимает запрос и назначает время ожидания 10 секунд.

Если есть какие-то исключения, их просто нужно распечатать. В противном случае клиент получит вероятность softmax и сравнит вывод с золотой меткой, используя argmax.

Наконец, точность можно распечатать. Вот полный код:

import numpy as np
import requests 
import json
from tensorflow.examples.tutorials.mnist import input_data
import argparse
from grpc.beta import implementations
import tensorflow as tf
import time
from tensorflow_serving.apis import predict_pb2, prediction_service_pb2
from tensorflow.contrib.util import make_tensor_proto
def main(args):  
    
    host, port = args.host, args.port
mnist = input_data.read_data_sets(args.data_dir, one_hot=True)
channel = implementations.insecure_channel(host, int(port))
    stub = prediction_service_pb2.beta_create_PredictionService_stub(channel)
    
    start_time = time.time()
    counter = 0
    num_tests = args.num_tests
    time
    for _ in range(num_tests):
        image, label = mnist.test.next_batch(1)
        
        request = predict_pb2.PredictRequest()
        request.model_spec.name = 'mnist'
        request.model_spec.signature_name = tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY
        request.inputs['x_input'].CopyFrom(
            make_tensor_proto(image[0],shape=[1,28,28])
        )
        result_future = stub.Predict(request,10.0)
        exception = result_future.exception()
        if exception:
            print(exception)
        else:
            response = np.array(result_future.outputs['y_output'].float_val)
            if np.argmax(response) ==np.argmax(label):
                counter +=1
            else:
                pass
    print("Accuracy= %0.2f"%((counter*1.0/num_tests)*100))
    print("Time takes to run the test %0.2f"%(time.time()-start_time))
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--data_dir', default='/tmp/data')
    parser.add_argument('--host',default='127.0.0.1')
    parser.add_argument('--port',default=9000)
    parser.add_argument('--num_tests',default=100)
    args = parser.parse_args()
main(args)

TensorFlow Serving обеспечивает аналогичную точность, но в два раза быстрее, чем API Flask.

Заключение

Мы только что прошли этапы создания модели RNN от обучения до вывода. Можно изменить структуру RNN или использовать модель RNN для определенных задач, таких как моделирование языка или машинный перевод. Чтобы создать модель, которую можно использовать в производстве, входные и выходные данные должны быть изменены соответствующим образом.

Образы докеров из TensorFlow очень часто используются для обслуживания моделей в производстве. Как компания, Scribendi движется к разработке этих инструментов как микросервиса, и мы используем стек докеров для их обслуживания в рабочей среде. Это будет обсуждаться в следующем посте в блоге Scribendi.AI [.36].

Ссылки

https://www.tensorflow.org/serving/serving_basic
https://www.tensorflow.org/api_docs/python/tf/saved_model/signature_constants
https://grpc .io/
http://flask.pocoo.org/
http://colah.github.io/posts/2015-08-Understanding-LSTMs/

Об авторе

Мд Асадул Ислам — инженер по машинному обучению, специализирующийся на разработке, обучении и обслуживании моделей GEC, упрощающих работу редакторов-людей. У него есть степень магистра наук. в области компьютерных наук Университета Альберты. Во время учебы он в основном работал над идентификацией родного языка, распознаванием бенгальских символов, комбинаторной оптимизацией и вероятностным графическим моделированием. Он любит читать об исследовательских идеях, решать задачи и решать проблемы. Помимо работы, он любит проводить время со своей любящей семьей.

Примечания: Я хотел бы поблагодарить Scribendi за разрешение написать эту статью. Кроме того, я хочу выразить признательность Энрико Маньяни, генеральному директору Scribendi, за его глубокое понимание, а также нашей отличной команде редакторов за редактирование этой статьи и предоставление полезных предложений. Наконец, я благодарен Терри Джонсону, бывшему вице-президенту Scribendi, за его замечательные предложения.