Развертывание модели в Функциях Azure

Сведения о развертывании предварительно обученной модели машинного обучения ML.NET для создания прогнозов по протоколу HTTP через бессерверную среду Функций Azure.

Необходимые компоненты

  • Visual Studio 2022 с установленными рабочими нагрузками разработки классических приложений .NET и Azure. Пакет SDK для .NET 6 устанавливается автоматически при выборе этой рабочей нагрузки.
  • Средства Функций Azure.
  • PowerShell
  • Предварительно обученная модель. Скачайте эту предварительно обученную модель машинного обучения анализа тональности или используйте руководство по анализу тональности ML.NET для создания собственной модели.

Обзор примера для Функций Azure

В этом примере предоставляется приложение триггера HTTP на языке C# для Функций Azure, которое использует предварительно обученную модель двоичной классификации для выбора положительной или отрицательной тональности текста. Функции Azure предоставляют простой способ выполнять небольшие фрагменты кода в большом масштабе для управляемой бессерверной облачной среды. Код для этого примера можно найти в репозитории dotnet/machinelearning-samples на сайте GitHub.

Создание проекта Функций Azure

  1. В Visual Studio 2022 откройте диалоговое окно "Создание проекта ".

  2. В диалоговом окне "Создание проекта" выберите шаблон проекта Функции Azure.

  3. В текстовом поле "Имя " введите "SentimentAnalysisFunctionsApp" и нажмите кнопку "Далее ".

  4. В диалоговом окне "Дополнительные сведения" оставьте все значения по умолчанию и нажмите кнопку "Создать ".

  5. Установка пакета NuGet Microsoft.ML

    1. В обозревателе решений щелкните проект правой кнопкой мыши и выберите Управление пакетами NuGet.
    2. Выберите nuget.org в качестве источника пакета.
    3. Перейдите на вкладку "Обзор".
    4. Выполните поиск Microsoft.ML.
    5. Выберите этот пакет в списке и нажмите кнопку "Установить ".
    6. Нажмите кнопку ОК в диалоговом окне Предварительный просмотр изменений.
    7. Нажмите кнопку Принимаю в диалоговом окне Принятие условий лицензионного соглашения, если вы согласны с условиями лицензионного соглашения для указанных пакетов.

    Выполните те же действия, чтобы установить пакеты NuGet Microsoft.Extensions.ML, Microsoft.Extensions.DependencyInjection и Microsoft.Azure.Functions.Extensions .

Добавление предварительно обученной модели в проект

  1. Создайте каталог с именем MLModels в проекте, чтобы сохранить модель предварительной сборки: в Обозреватель решений щелкните проект правой кнопкой мыши и выберите "Добавить > новую папку". Введите MLModels и нажмите клавишу ВВОД.
  2. Скопируйте предварительно созданную модель в папку MLModels.
  3. В обозревателе решений щелкните правой кнопкой мыши файл предварительно созданной модели и выберите Свойства. В разделе Дополнительно для параметра Копировать в выходной каталог установите значение Копировать более позднюю версию.

Создание функции Azure для анализа тональности

Создайте класс для прогнозирования тональности. Добавьте в проект новый класс:

  1. В Обозреватель решений щелкните проект правой кнопкой мыши и нажмите кнопку "Добавить>новую функцию Azure...".

  2. В диалоговом окне Добавление нового элемента выберите Функция Azure и измените значение поля Имя на AnalyzeSentiment.cs. Теперь нажмите кнопку Добавить.

  3. В диалоговом окне "Новая функция Azure" выберите "Триггер HTTP" и выберите "Анонимный" в раскрывающемся списке "Уровень авторизации". Затем нажмите кнопку OK.

    В редакторе кода откроется файл AnalyzeSentiment.cs. Добавьте следующий оператор using в начало файла AnalyzeSentiment.cs.

    using System;
    using System.IO;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    using Microsoft.Extensions.ML;
    using SentimentAnalysisFunctionsApp.DataModels;
    

    По умолчанию класс AnalyzeSentimentstatic. Удалите ключевое слово static из объявления класса.

    public class AnalyzeSentiment
    {
    
    }
    

Создание моделей данных

Вам потребуется создать несколько классов для входных данных и прогнозов. Добавьте в проект новый класс:

  1. Создайте каталог с именем DataModels в проекте для сохранения моделей данных: в Обозреватель решений щелкните проект правой кнопкой мыши и выберите "Добавить > новую папку". Введите DataModels и нажмите клавишу ВВОД.

  2. В Обозреватель решений щелкните правой кнопкой мыши каталог DataModels и выберите пункт "Добавить > класс".

  3. В диалоговом окне Добавление нового элемента выберите Класс и измените значение поля Имя на SentimentData.cs. Теперь нажмите кнопку Добавить.

    Файл SentimentData.cs откроется в редакторе кода. Добавьте в начало файла SentimentData.cs следующий оператор using:

    using Microsoft.ML.Data;
    

    Удалите из файла SentimentData.cs существующее определение класса и добавьте следующий код:

    public class SentimentData
    {
        [LoadColumn(0)]
        public string SentimentText;
    
        [LoadColumn(1)]
        [ColumnName("Label")]
        public bool Sentiment;
    }
    
  4. В Обозреватель решений щелкните правой кнопкой мыши каталог DataModels и выберите пункт "Добавить > класс".

  5. В диалоговом окне Добавление нового элемента выберите Класс и измените значение поля Имя на SentimentPrediction.cs. Теперь нажмите кнопку Добавить. В редакторе кода откроется файл SentimentPrediction.cs. Добавьте в начало файла SentimentPrediction.cs следующий оператор using:

    using Microsoft.ML.Data;
    

    Удалите из файла SentimentPrediction.cs существующее определение класса и добавьте следующий код:

    public class SentimentPrediction : SentimentData
    {
    
        [ColumnName("PredictedLabel")]
        public bool Prediction { get; set; }
    
        public float Probability { get; set; }
    
        public float Score { get; set; }
    }
    

    SentimentPrediction наследует от SentimentData, который обеспечивает доступ к исходным данным в свойстве SentimentText, а также выходным данным модели.

Регистрация службы PredictionEnginePool

Для формирования одного прогноза необходимо создать PredictionEngine. PredictionEngine не является потокобезопасным. Кроме того, необходимо создать его экземпляр везде, где он понадобится в вашем приложении. По мере увеличения размера приложения этот процесс может стать неуправляемым. Для улучшенной производительности и потокобезопасности используйте сочетание внедрения зависимостей и службы PredictionEnginePool, которое создает объекты PredictionEngine (ObjectPool) для использования во всем приложении.

См. дополнительные сведения о внедрении зависимостей по следующей ссылке.

  1. В Обозреватель решений щелкните проект правой кнопкой мыши и выберите пункт "Добавить>класс".

  2. В диалоговом окне Добавление нового элемента выберите Класс и измените значение поля Имя на Startup.cs. Теперь нажмите кнопку Добавить.

  3. Добавьте в начало файла Startup.cs следующие операторы using:

    using Microsoft.Azure.Functions.Extensions.DependencyInjection;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.ML;
    using SentimentAnalysisFunctionsApp;
    using SentimentAnalysisFunctionsApp.DataModels;
    using System.IO;
    using System;
    
  4. Удалите существующий код ниже инструкций using и добавьте следующий код:

    [assembly: FunctionsStartup(typeof(Startup))]
    namespace SentimentAnalysisFunctionsApp
    {
        public class Startup : FunctionsStartup
        {
    
        }
    }
    
  5. Определите в классе Startup переменные для хранения среды, в которой выполняется приложение, и путь к файлу, в котором находится модель.

    private readonly string _environment;
    private readonly string _modelPath;
    
  6. Ниже показано, как создать конструктор для задания значений переменных _environment и _modelPath. При локальном запуске приложения средой по умолчанию считается среда Development (Разработка).

    public Startup()
    {
        _environment = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT");
    
        if (_environment == "Development")
        {
            _modelPath = Path.Combine("MLModels", "sentiment_model.zip");
        }
        else
        {
            string deploymentPath = @"D:\home\site\wwwroot\";
            _modelPath = Path.Combine(deploymentPath, "MLModels", "sentiment_model.zip");
        }
    }
    
  7. Затем добавьте под конструктором новый метод с именем Configure, который будет регистрировать службу PredictionEnginePool.

    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddPredictionEnginePool<SentimentData, SentimentPrediction>()
            .FromFile(modelName: "SentimentAnalysisModel", filePath: _modelPath, watchForChanges: true);
    }
    

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

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

Задайте для параметра watchForChanges значение true. В таком случае PredictionEnginePool запустит объект FileSystemWatcher, который прослушивает уведомления об изменениях файловой системы и вызывает события при изменении файла. При наличии изменений PredictionEnginePool автоматически перезагружает модель.

Модель определяется параметром modelName, поэтому при изменении может быть перезагружено несколько моделей на одно приложение.

Совет

Кроме того, можно использовать метод FromUri при работе с моделями, сохраненными удаленно. Вместо наблюдения за событиями изменения файлов FromUri опрашивает удаленное расположение на предмет изменений. Интервал опроса по умолчанию равен 5 минутам. Вы можете увеличить или уменьшить интервал опроса в зависимости от требований вашего приложения. В приведенном ниже примере кода PredictionEnginePool опрашивает модель, сохраненную по указанному универсальному коду ресурса (URI), каждую минуту.

builder.Services.AddPredictionEnginePool<SentimentData, SentimentPrediction>()
  .FromUri(
      modelName: "SentimentAnalysisModel",
      uri:"https://github.com/dotnet/samples/raw/main/machine-learning/models/sentimentanalysis/sentiment_model.zip",
      period: TimeSpan.FromMinutes(1));

Загрузка модели в функцию

Вставьте следующий код внутри класса AnalyzeSentiment:

public AnalyzeSentiment(PredictionEnginePool<SentimentData, SentimentPrediction> predictionEnginePool)
{
    _predictionEnginePool = predictionEnginePool;
}

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

Использование модели для прогнозирования

Замените существующую реализацию метода запуска в классе AnalyzeSentiment следующим кодом:

public async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
    ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    // Parse HTTP Request Body
    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    SentimentData data = JsonConvert.DeserializeObject<SentimentData>(requestBody);

    //Make Prediction
    SentimentPrediction prediction = _predictionEnginePool.Predict(modelName: "SentimentAnalysisModel", example: data);

    //Convert prediction to string
    string sentiment = Convert.ToBoolean(prediction.Prediction) ? "Positive" : "Negative";

    //Return Prediction
    return new OkObjectResult(sentiment);
}

Когда метод Run выполняется, входящие данные из HTTP-запроса десериализуются и используются в качестве входных данных для PredictionEnginePool. Затем метод Predict вызывается для формирования прогнозов с использованием модели SentimentAnalysisModel, зарегистрированной в классе Startup, и возвращает результаты пользователю в случае успеха.

Локальное тестирование.

Завершив настройку параметров, протестируйте приложение:

  1. Выполнение приложения

  2. Откройте PowerShell и введите код в командной строке, где PORT — это порт, через который работает приложение. Как правило, используется порт 7071.

    Invoke-RestMethod "http://localhost:<PORT>/api/AnalyzeSentiment" -Method Post -Body (@{SentimentText="This is a very bad steak"} | ConvertTo-Json) -ContentType "application/json"
    

    В случае успешного выполнения результат должен выглядеть, как показано ниже:

    Negative
    

Поздравляем! Вы успешно использовали модель для прогнозирования через Интернет с помощью Функций Azure.

Next Steps