В этом материале расскажу, как использовать MATLAB и Python вместе (в мире и гармонии). Эти два языка часто используются вместе для разработки приложений ИИ (настолько часто, что существуют прямой импорт и экспорт для сетей глубокого обучения через MATLAB, ONNX и TensorFlow). Вот несколько хороших примеров совместного использования MATLAB и Python: приложения для прогнозирования качества воздуха и алгоритм анализа настроения.

Основы

Во-первых, давайте разберемся с требованиями. Нам понадобится последняя версия Python и MATLABR 2014b или более поздняя. Проверьте здесь конкретную версию.

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

Вызов Python из MATLAB

Прежде всего, убедимся, что MATLAB может найти интерпретатор Python. Мы можем сделать это в MATLAB с функцией pyenv:

>> pyenv
ans =
  PythonEnvironment with properties:

          Version: "3.6"
       Executable: "C:\Python36\WPy-3670\python-3.6.7.amd64\python.EXE"
          Library: "C:\Python36\WPy-3670\python-3.6.7.amd64\python36.dll"
             Home: "C:\Python36\WPy-3670\python-3.6.7.amd64"
           Status: Loaded
    ExecutionMode: OutOfProcess
        ProcessID: "20980"
      ProcessName: "MATLABPyHost"

Последнее возвратило версию Python и настройки среды, которые также можно изменить с помощью функции pyenv.

Теперь, когда у нас есть доступ к Python, приступим к делу. Мы попробуем функцию sqrt из математической библиотеки, чтобы понять ее. В Python мы вызываем ее так:

>>> import math
>>> math.sqrt(42)
6.48074069840786

Чтобы вызвать ту же функцию Python из MATLAB, мы можем использовать следующее:

>> py.math.sqrt(42)
ans =
    6.480740698407860

Мы использовали format long для отображения той же точности в MATLAB и Python.

Доступ к модулям и функциям Python осуществляется с помощью следующего синтаксиса:

>> py.module_name.function_name

Таким же образом вызываются пользовательские модули. Например, модуль weather.py в приложении air qualityapp включает функции, которые считывают данные о погоде для данного местоположения через web-API:

>> data = py.weather.get_current_weather("Boston","US",key)
data =
  Python dict with no properties.

{'coord': {'lon': -71.06, 'lat': 42.36}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'base': 'stations', 'main': {'temp': 53.2, 'feels_like': 34.9, 'temp_min': 51.01, 'temp_max': 55, 'pressure': 1003, 'humidity': 46}, 'visibility': 16093, 'wind': {'speed': 26.4, 'deg': 230, 'gust': 34.45}, 'clouds': {'all': 90}, 'dt': 1587342601, 'sys': {'type': 1, 'id': 3486, 'country': 'US', 'sunrise': 1587290159, 'sunset': 1587339006}, 'timezone': -14400, 'id': 4930956, 'name': 'Boston', 'cod': 200}

Обратите внимание, что на выходе получается словарь Python (в MATLAB). Мы могли бы преобразовать его в тип MATLAB (подробнее о типах данных далее), но пока мы продолжим работать с ним напрямую. Давайте извлечем интересующую информацию с помощью другой функции из модуля:

>> weatherData = py.weather.parse_current_json(data)
data =
  Python dict with no properties.

{'temp': 39.31, 'feels_like': 31.44, 'temp_min': 37, 'temp_max': 41, 'pressure': 1010, 'humidity': 80, 'speed': 8.05, 'deg': 340, 'city': 'Boston', 'lat': 42.36, 'lon': -71.06, 'current_time': '2020-04-18 20:48:00.985146'}

Мы также можем индексировать в словаре, чтобы вспомнить конкретные значения:

>> T = weatherData{"temp"}
T = 39.3100

Обратите внимание, что мы использовали фигурные скобки {} вместо круглых скобок (). В MATLAB фигурные скобки часто используются при доступе к значениям из разнородных типов данных, таких как массивы ячеек и таблицы. Легкий способ запомнить: когда вы используете (), вы получаете подмножество большего набора данных того же типа, то есть массив ячеек или таблицу. И наоборот, если вы используете {}, вы получите индексированное значение в исходном типе данных, то есть double, string, character. Следовательно, в приведенном выше примере dict – это гетерогенный тип данных, и мы будем использовать {}, чтобы получить значение температуры как двойное. В этом примере показано индексирование в Python dict.

Теперь, когда мы получили представление о синтаксисе, давайте поговорим еще об одном различии в вызове функций. Скажем, хотели изменить единицы измерения погодных данных. В Python функция get_forecast принимает аргументы ключевого слова standard Python, как показано в последнем аргументе здесь:

>>> forecast = weather.get_forecast("Boston","US",key,units="metric")

В MATLAB они передаются как пары имя-значение с функцией pyargs:

>> forecast = py.weather.get_forecast("Boston","US",key,pyargs("units","metric")

Теперь, когда мы понимаем, как адаптировать синтаксис Python и вызывать функции из MATLAB, давайте попробуем по- другому.

Вызов MATLAB из Python

API MATLAB Engine для Python позволяет вызывать MATLAB в качестве механизма вычислений, поэтому мы можем использовать функции MATLAB из Python. Во-первых, нам нужно установить его через пакет Python, входящий в состав MATLAB. Выполните следующие команды в командной строке ОС:

$ cd "matlabroot/extern/engines/python"
$ python setup.py install

«Matlabroot» – это каталог, в котором установлен MATLAB (проверьте, вызвав >> matlabroot в MATLAB). Здесь можно посмотреть дополнительную информацию.

А теперь приступим к самому интересному. Чтобы вызвать функции MATLAB из Python, сначала импортируйте и запустите движок (мы также могли бы использовать текущий сеанс MATLAB, если он уже запущен):

>>> import matlab.engine
>>> eng = matlab.engine.start_matlab()

Теперь, когда engine запущен, давайте вызовем функцию извлечения квадратного корня:

>>> x = eng.sqrt(42.0)
6.48074069840786

Обратите внимание, что мы вызываем функцию sqrt с 42.0, а не просто с 42. Подробнее об этом расскажем дальше.

Функции MATLAB вызываются с их собственным синтаксисом, но есть некоторые отчетливые различия. Одно из отличий заключается в способе захвата нескольких выходных данных. Например, в алгоритме анализа настроения код MATLAB возвращает несколько выходных данных. Мы можем указать количество выходов с помощью nargout:

>>> [sentiment,scores] = eng.sentimentAnalysis(text,nargout=2)
Positive
[[0.0,0.510948896408081,0.48905110359191895]]

Точно так же, если функция MATLAB не возвращает выходных данных (скажем, функция записывает результаты в файл), вам нужно передать nargout = 0.

Когда мы закончим, мы должны остановить движок MATLAB, чтобы освободить системные ресурсы:

>>> eng.exit()

Чтобы вызвать операторов MATLAB (например, известный оператор обратный слэш «\» для решения линейных систем уравнений), нам нужно использовать имя функции (mldivide). Вот полный список операторов MATLAB и связанных функций.

Конвертация типов данных

Когда мы ранее вызывали sqrt, мы использовали 42 в MATLAB, но 42.0 в Python. В чем разница?

Ввод 42 возвращает двойное значение в MATLAB и целое число в Python. В нашем примере с квадратным корнем ошибки были бы выполнены без использования функции преобразования ввода (42) или ввода 42.0, поскольку sqrt в MATLAB принимает одинарные, двойные или сложные типы.

>>> eng.sqrt(42.0)
6.48074069840786

>>> eng.sqrt(float(42))
6.48074069840786

Мы также можем использовать целочисленные и другие функции преобразования типов (показанные в таблице ниже) в MATLAB для передачи ожидаемых типов в функции Python.

Это касается входов, но как насчет выходов? Мы уже видели несколько примеров: в MATLAB sqrt вернул значение типа double, но функции в weather.py вернули объекты словаря Python. Так что же происходит? Там где это возможно, выходные данные функции будут представлены соответствующим типом на этом языке. В противном случае мы можем преобразовать данные в соответствующие типы.

В таблице ниже показаны сопоставления для общих типов данных (полный список тут).

Некоторые специализированные типы данных MATLAB, такие как timetable или categorical, потребуют некоторого дополнительного внимания и должны быть преобразованы вручную. Конечно, мы все еще можем использовать эти типы данных в наших функциях, но функции должны возвращать типы, которые интерпретатор Python может понять.

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

Файлы также часто используются для передачи данных, особенно при совместной работе между группами и разными языками. Если наши данные являются табличными, мы можем использовать Apache Parquet для передачи данных между двумя языками. MATLAB использует Apache Arrow для эффективного чтения и записи данных в Parquet. Мы можем читать данные, выполнять вычисления и записывать данные в Parquet с нескольких поддерживаемых языков.

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

Обработка ошибок

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

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

Давайте снова вызовем sqrt, но с неправильным типом данных:

>> py.math.sqrt("42")
Python Error: TypeError: must be real number, not str

В MATLAB мы видим ошибку Python в начале строки, за которой следует ошибка, вызванная Python, что упрощает отладку! MATLAB перехватил исключение Python и повторно выбросил его как исключение MATLAB exception, содержащее то же сообщение.

Сделаем то же самое из Python:

>>> eng.sqrt("42")
Traceback (most recent call last):
...
MatlabExecutionError: Undefined function 'sqrt' for input arguments of type 'char'.

Здесь минимизирована обратная трассировка Python, но если мы посмотрим на последнюю строку, мы увидим MatlabExecutionError и сообщение об ошибке MATLAB. Исключение MATLAB было поймано и повторно вызвано как исключение Python с тем же сообщением.

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

Создание Python Packages из MATLAB Code

Пока мы обсудили только использование MATLAB из Python и наоборот, предполагая, что оба языка установлены на одном компьютере. Как быть если мы хотим поделиться своей работой с теми, у кого не установлен MATLAB? Для этого можно использовать MATLAB Compiler SDK, который позволит нам упаковать код MATLAB и вспомогательные файлы на других языках.  

В примере с приложением прогнозирующим качества воздуха этот процесс используется для создания пакета Python из функции MATLAB prediction, predAirQual.m. Мы можем использовать приложение компилятора библиотеки и выбрать функцию(и) для включения (зависимости обнаруживаются автоматически).

Приложение упаковывает необходимые нам файлы и создает файлы setup.py и readme.txt с инструкциями в Python.

Чтобы вызвать это в Python, существует этап установки, аналогичный процессу для MATLAB Engine API (инструкции здесь), с использованием сгенерированного файла setup.py.

Затем нам нужно импортировать и инициализировать пакет и вызывать функции, например:

>>> import AirQual
>>> aq = AirQual.initialize()
>>> result = aq.predictAirQual()

После окончания необходимо завершить процесс:

>>> aq.terminate()

Пример с приложением для прогнозирования качества воздуха идет на один шаг дальше в совместном использовании функциональности MATLAB в веб-интерфейсе. В этом случае производственный сервер MATLAB может использоваться для балансировки нагрузки, а к коду MATLAB можно получить доступ через RESTful API или Pythonclient.

Интересные видео по теме:

Комментарии (2)


  1. OGR_kha
    20.12.2021 21:07

    Нам понадобится последняя версия Python

    Executable: "C:\Python36\WPy-3670\python-3.6.7

    Мда


    1. Kekushiftkey
      21.12.2021 11:16
      +1

      очередной бот/аккаунт для комментирования?

      оригинал: Posted by Alexa Sanchez, September 14, 2020