Эта статья является расширением моей предыдущей статьи под названием « Использование обученных Python моделей машинного обучения из приложений Phoenix (Elixir) ». В моей предыдущей статье я показал, как использовать обученные на Python модели машинного обучения из приложений Elixir с помощью ErlPort. Однако параметры модели, передаваемые из приложения Phoenix (Elixir) для прогнозирования с использованием кода Python, были простым типом данных списка и поддерживались встроенными сопоставлениями типов данных в ErlPort.
Однако для сложных данных нам понадобится какой-то механизм для сериализации / десериализации данных. В этой статье я расширю свой предыдущий проект, чтобы выполнить сериализацию / десериализацию данных, используя - «Буферы протокола».
Что такое буферы протокола?
Изобретено Google - Буферы протоколов - это не зависящий от языка и платформы расширяемый механизм Google для сериализации структурированных данных - подумайте о XML, но меньше, быстрее и проще. Вы определяете, как вы хотите, чтобы ваши данные были структурированы один раз, а затем вы можете использовать специальный сгенерированный исходный код, чтобы легко записывать и считывать структурированные данные в различные потоки данных и из них, используя множество языков . (источник: https://developers.google.com/protocol-buffers/)
Google предоставляет расширяемую документацию для буферов протоколов на своем веб-сайте, в частности, руководство для разработчиков и пример кода с учебными пособиями на поддерживаемых языках доступны здесь - https://developers.google.com/protocol-buffers/docs/overview
Как это работает?
Буферы протокола работают довольно просто. Нам нужно написать файл .proto, который определяет формат сообщения. Этот файл. proto компилируется компилятором протокола (protoc), который генерирует код на желаемых языках.
.proto → компилятор протоколов → сгенерированный языковой код
В этой статье мы передадим данные из кода Elixir в Python. Поэтому нам нужно сгенерировать код как для Elixir, так и для Python с помощью компилятора protoc. Поддержка Python уже встроена в компилятор. Но для части Elixir мы будем использовать protobuf-elixir (https://github.com/tony612/protobuf-elixir), который является чистой реализацией протокола Elixir. Буферы.
Установить Protobuf
Сначала нам нужно установить компилятор буфера протокола. Мы можем сделать это с помощью Homebrew (https://formulae.brew.sh/formula/protobuf) на Mac с помощью следующей команды -
варить установить protobuf
Часть Феникса (Эликсира)
Измените mix.exs и добавьте зависимости:
defp deps do [ {:phoenix, "~> 1.4.0"}, {:phoenix_pubsub, "~> 1.1"}, {:phoenix_html, "~> 2.11"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, {:gettext, "~> 0.11"}, {:jason, "~> 1.0"}, {:plug_cowboy, "~> 2.0"}, {:erlport, "~> 0.10.0"}, {:protobuf, "~> 0.5.3"}, # Only for files generated from Google's protos. # Can be ignored if you don't use Google's protos. {:google_protos, "~> 0.1"} ] end
Нам нужно добавить жирную часть в файл mix.exs и обновить зависимости, используя команду ниже -
смешать deps.get
Установите плагин protoc:
Нам нужно установить плагин protoc protoc-gen-elixir для Elixir, используя следующую команду -
смешайте escript.install шестнадцатеричный protobuf
ПРИМЕЧАНИЕ: protoc-gen-elixir
должен быть в PATH.
Определить сообщение (файл .proto):
Мы поместили наши файлы .proto и сгенерированный код в папку lib / phoenix_ml / protobuf. Наш файл определения сообщений iris.proto выглядит следующим образом:
syntax = "proto3"; package PhoenixMl; message IrisParams { float sepal_length = 1; float sepal_width = 2; float petal_length = 3; float petal_width = 4; }
Мы будем использовать синтаксис proto3, который подробно описан здесь - https://developers.google.com/protocol-buffers/docs/proto3
По сути, наш формат сообщения прост и содержит четыре значения с плавающей запятой для параметров нашей модели - sepal_length, sepal_width, petal_length, petal_width.
Скомпилируйте файл .proto и сгенерируйте код Elixir:
Мы будем использовать следующую команду для генерации кода Эликсира из файла .proto выше -
протокол - elixir_out =. iris.proto (запускается из папки lib / phoenix_ml / protobuf)
Будет создан файл iris.pb.ex.
Обновить исходный код:
Затем мы обновим файл page_controller.ex приведенным ниже кодом (отредактированным) -
alias PhoenixMl.IrisParams, as: Iris ... ... with {sepal_length, _} <- Float.parse(sepal_length), {sepal_width, _} <- Float.parse(sepal_width), {petal_length, _} <- Float.parse(petal_length), {petal_width, _} <- Float.parse(petal_width) do iris_params = %Iris{ sepal_length: sepal_length, sepal_width: sepal_width, petal_length: petal_length, petal_width: petal_width } class = ML.predict([Iris.encode(iris_params)])
Полужирным шрифтом выделены необходимые изменения кода. Мы тут -
- импортировал модуль PohenixMl.IrisParams как Iris
- определил структуру % Iris {} с параметрами
- называется Iris.encode для создания сериализованных данных
Часть Python
Скомпилируйте файл .proto и сгенерируйте код Python:
Мы будем использовать следующую команду для генерации кода Python из вышеуказанного файла .proto -
протокол - python_out =. iris.proto (запускается из папки lib / phoenix_ml / protobuf)
Будет создан файл iris_pb2.py.
Обновить исходный код:
Затем мы обновим файл classifier.py приведенным ниже кодом (отредактированным) -
import os from sklearn.externals import joblib import sys sys.path.insert(0, 'lib/phoenix_ml/protobuf') import iris_pb2 def load_model(): path = os.path.abspath('lib/phoenix_ml/model/classifier.pkl') return joblib.load(path) def predict_model(args): iris_params = iris_pb2.IrisParams() iris_params.ParseFromString(args) model_params = [[iris_params.sepal_length, iris_params.sepal_width, iris_params.petal_length, iris_params.petal_width]] iris_classifier = load_model() return iris_classifier.predict(model_params)[0]
Полужирным шрифтом выделены необходимые изменения кода. Мы тут -
- импортированный сгенерированный модуль iris_pb2
- десериализовал аргументы, полученные от приложения Elixir - ParseFromString (args), и определил двухмерный массив model_params.
- сделал прогноз с помощью model_params
На этом этапе наши изменения сделаны, и мы сможем делать прогнозы, как и раньше, как показано на скриншоте ниже -
Исходный код
Исходный код более раннего проекта можно найти здесь - https://github.com/imeraj/Phoenix_Playground/tree/master/1.4/phoenix_ml (главная ветка )
Обновленный исходный код с использованием буферов протокола можно найти здесь - https://github.com/imeraj/Phoenix_Playground/tree/protobuf_file/1.4/phoenix_ml (ветка protobuf_file )
использованная литература
- Https://developers.google.com/protocol-buffers/
- Https://itnext.io/using-machine-learning-models-python-from-phoenix-elixir-applications-cd028e4e5f01
3. https://github.com/tony612/protobuf-elixir
Я надеюсь, что эти статьи помогли некоторым читателям понять, как можно использовать буферы протокола для сериализации и десериализации данных и передачи между Elixir и Python для создания полезных приложений.
Чтобы получить более подробные и подробные технические сообщения в будущем, подпишитесь на меня здесь или в твиттере.