Выражаем большое спасибо за подготовку статьи Евгению Григоренко, Microsoft Student Partner, (@evgri243) за помощь в написании данной статьи. Остальные наши статьи по теме Azure можно найти по тегу azureweek
Машинное обучение – одна из самых популярных областей Computer Science, хотя в то же время одна их самый избегаемых среди разработчиков. Основная причина этого в том, что теоретическая часть машинного обучения требует глубокой математической подготовки, которую многие предпочитают сразу же забыть по окончании университетского обучения. Но необходимо понимать, что помимо теоретических основ, существует также и практическая сторона, которая оказывается значительно проще для освоения и ежедневного использования. Цель этой работы – ликвидировать разрыв между программистами и специалистами по обработке данных и показать, что использование машинного обучения в своих приложениях может быть достаточно простой задачей. В статье излагается вся последовательность шагов, необходимая для построения модели предсказания цены автомобиля в зависимости от набора его характеристик с последующим ее использованием в мобильном приложении на Windows 10 Mobile.
Что такое Azure ML?
Если кратко, то Azure Machine Learning – это:
- облачное решение, позволяющее построение и использование сложных моделей машинного обучения в простой и наглядной форме;
- экосистема, предназначенные для распространения и монетизации готовых алгоритмов.
Больше информации об Azure ML вы можете найти дальше в этой статье, а также перейдя по ссылке
Почему именно Azure ML?
Потому, что Azure Machine Learning – один из простейших инструментов для использования машинного обучения, убирающий входной барьер для всех, кто решает использовать его для своих нужд. С Azure ML больше не надо быть математиком.
Логический процесс построения алгоритма машинного обучения
- Определение цели. Все алгоритмы машинного обучения бесполезны без явно-определенной цели проведения эксперимента. В данной лабораторной работе цель – это предсказание цены автомобиля на основе набора характеристик, предоставленных конечным пользователем.
- Сбор данных. Во время этого этапа формируется выборка данных, необходимая для дальнейшего обучения модели. В данном случае будут использоваться данные репозитария машинного обучения университета Калифорнии.
archive.ics.uci.edu/ml/datasets/Automobile - Подготовка данных. На этом этапе производится подготовка данных путем формирования характеристик, удаления выбросов и разделения выборки на обучающую и тестовую.
- Разработка модели. В процессе разработки модели производиться выбор одного или нескольких моделей данных и соответствующих алгоритмов обучения, которые по мнению разработчика должны будут дать требуемый результат. Часто этот процесс совмещен с параллельным исследованием эффективности нескольких моделей и визуальным анализом данных с целью отыскания каких-либо закономерностей.
- Обучение модели. Во время обучения алгоритм обучения производит поиск скрытых закономерностей в выборке данных с целью отыскания способа предсказания. Сам процесс поиска определяется выбранной моделью и алгоритмом обучения.
- Оценка модели. После того как модель обучена необходимо исследовать ее прогностические характеристики. Чаще всего для этого ее прогоняют на тестовой выборке и оценивают получившийся уровень ошибки. В зависимости от этого и требований к точности модель может быть как принята в качестве итоговой, так и произведено повторное обучение после добавления новых входных характеристик или даже изменения алгоритма обучения.
- Использование модели. В случае успешного тестирования обученной модели наступает стадия ее использования. И это тот случай, когда Azure ML становится незаменим, давая все необходимые инструменты для публикации, мониторинга и монетизации алгоритмов
Построение прогностической модели
Для начала перейдите по ссылке , в пункте меню Products выберите Analytics и нажмите Machine Learning. Или воспользуйтесь прямой ссылкой.
На открывшейся странице нажмите Get Started now.
Для работы с Azure ML вам необходима активная подписка Microsoft Azure. Если она у вас уже есть, то просто войдите в Azure Management Portal, иначе – предварительно зарегистрируйте бесплатную пробную учетную запись, перейдя по ссылке.
После успешной авторизации вы окажетесь на главной странице Azure ML Studio – среде, где будет происходить вся дальнейшая работа.
Загрузка данных
В первую очередь необходимо загрузить обучающую выборку. Для этого перейдите по ссылке и загрузите на свой компьютер файл imports-85.data, содержащий выборку данных по автомобилям.
Для загрузки этого файла в Azure ML Studio нажмите на New в нижней части страницы и в открывшейся панели последовательно выберите Dataset и From Local File. В меню загрузки укажите путь к загруженному файлу, название и в качестве типа выберите Generic CSV File with no header (.hn.csv).
Создание нового эксперимента
Для того чтобы создать новый эксперимента выберите New -> Experiment -> Blank Experiment. В результате будет создана новая рабочая область эксперимента с панелью инструментов справа.
Определение выборки данных
Загруженные ранее данные должны быть отражены в разделе Saved Datasets слева. Выберите его и перетащите в любое место рабочего пространства, например, туда, куда указывает стрелка Drag Items Here.
Обратите внимание, что источник данных имеет точку соединения в форме кружка, которая используется для подключение его к другим компонентам.
Подготовка данных
При разработке моделей машинного обучения хорошей практикой является проверка предварительных результатов эксперимента после каждого изменения. Поэтому нажмите правой кнопкой на точку соединения и выберите Visualize. В результате появится окно, дающее общее представление о данных и их распределении.
Как можно заметить, в выборке имеется проблема – отсутствуют значения во втором столбце. Это может создать нежелательный эффект в процессе обучения и значительно ухудшить качество модели. Но, к счастью, эти значения характеризует страховые издержки и слабо связаны с ценой автомобиля, а потому их можно удалить. Помимо всего прочего у столбцов отсутствуют имена, что значительно усложняет работу с ними.
Для исправления проблемы с именами из группы Data Transformation/Manipulation перенесите на рабочую поверхность Metadata Editor.
Перетяните выход (снизу) выборки данных на вход (сверху) нового компонента, чтобы соединить их. Теперь кликните на него, чтобы открыть окно настроек справа. Metadata Editor позволяет изменить метаинформацию одного или нескольких столбцов, включая тип или название. Откройте мастер выбора столбцов нажатием на Launch column selector. Чтобы выбрать все столбцы, в поле Begin With выберите All columns, удалите строку уточнения выбора нажатием на знак “-“ справа и подтвердите нажатием на галочку.
В поле New column names панели настроек введите новые имена столбцов через запятую, которые можно найти в файле import-85.names по ранее приводившейся ссылке. Значение поля должно быть следующим:
symboling,normalized-losses,make,fuel-type,aspiration,num-of-doors,body-style,drive-wheels,engine-location,wheel-base,length,width,height,curb-weight,engine-type,num-of-cylinders,engine-size,fuel-system,bore,stroke,compression-ratio,horsepower,peak-rpm,city-mpg,highway-mpg,price
Для того, чтобы увидеть результат работы компонента, нажмите на Run снизу и визуализируйте выход Metadata Editor описанным ранее способом.
Теперь удалим normalized-losses. Для этого перетащите в рабочую область Project Columns из той же группы, соедините его с Metadata Editor и перейдите к его настройкам. Снова выберите мастер выбора строк и в этот раз выберите все строки за исключением normalized-losses, сделав настройки, аналогичные приведенным на рисунке ниже.
Запустите эксперимент и визуализируйте результат, чтобы убедиться, что второй столбец пропал из выборки.
К сожалению, есть еще столбцы, в которых отсутствуют значения. Но их не много, а потому можно ограничиться лишь отбрасыванием неполных строк. Для этого выберите Missing Value Scrubber и соедините его с Project Columns. В поле For missing values измените значение на Remove entire row. Запустите, визуализируйте и убедитесь, что строки с пустыми значениями пропали.
Остался последний вопрос, который необходимо ответить на этапе подготовки: все ли характеристики влияют на цену автомобиля? На данном этапе можно ограничиться следующим небольшим числом показателей, список которых приведен ниже. В дальнейшем вы всегда сможете добавить новые и проверить гипотезу об их достаточности, сравнив точность полученных моделей.
make,body-style,wheel-base,engine-size,horsepower,peak-rpm,highway-mpg,num-of-cylinders,price
Добавьте новый Project Columns и выберите приведенные выше столбцы.
В заключение убедитесь, что подготовка данных выполняется успешно, запустив эксперимент и визуализировав результат.
Разбивка выборки
Теперь данные готовы к использованию в процессе обучения. Но в машинном обучении возможен эффект, получивший название «переобучение», – заучивание моделью данных без обобщения. Такое поведение ведет к невозможности адекватного предсказания на сколько-нибудь отличающихся данных. Для обработки этой ситуации выборку принято разделить на обучающую и тестовую в отношении близком к 3:1. Последняя из них никак не участвует в процессе обучения и по окончании используется для оценки ошибки предсказания. Если эта ошибка значительно отличается в большую сторону от ошибки на обучающей выборке, значит, наблюдается описанный выше эффект.
Для создания тестовой выборки перенесите на рабочую область эксперимента и соедините с последним Project Columns компонент Split Data из группы Data Transformation/Sample and Split. Установите долю строк на первом выходе равной 0.75 и убедитесь, что установлен флаг Randomize Split.
Обучение модели линейной регрессии
Первым делом перенесите из панели инструментов компоненты Linear Regression, Train Model, Score Model и Evaluate Model. Train Model – универсальный компонент, позволяющий обучение любой модели на любой обучающей выборке. Для настройки нашего конкретного случая подсоедините первый (левый) выход Split Data и выход Linear Regression к соответствующим входам Train Model. В настройках Train Model в качестве целевого значения (outcome column) укажите price. Теперь модель готова к обучению.
Но, помимо самого обучения, важно узнать результат обучения. Компонент Score Model позволяет вычислить выход обученной модели на произвольной выборке и рассчитать результат предсказания. Соедините выход Train Model, содержащий обученную модель, с соответствующим входом Score Model, а в качестве выборки данных на другой вход подайте тестовую выборку со второго выхода Split Data. Выход Score Model соедините с любым из входов Evaluate Model для того, чтобы рассчитать численные характеристики качества обучения. В результате должна получиться процесс, аналогичный представленному на рисунке.
Запустите модель и визуализируйте результат выполнения Evaluate Model.
Коэффициент детерминации указывает, как хорошо линия регрессии описывает исходные данные. Принимаемые ей значения варьируются от 0 до 1, где единице соответствует абсолютная точность. В нашем случае коэффициент равен 82%. Хороший ли это результат или нет – напрямую зависит от постановки задачи и определенной толерантности к ошибке. Для случая предсказания цены автомобиля 82% — отличный результат. Если вы хотите его улучшить попробуйте добавить другие столбцы в Project Columns или попробовать принципиально другой алгоритм. Например, Poisson Regression. Последнее может быть достигнуто путем простой замены компонента линейной регрессии на пуасонову. Но более интересный подход – это собрать из элементов параллельное обучение и подключить результат ко второму выходу Evaluate Model, что позволит в удобной форме сравнить результаты обучения обоих моделей.
Выполните модель и визуализируйте результат. Как видно из результата, данные значительно лучше описываются моделью линейной регрессии, а потому есть все основания выбрать именно ее в качестве итоговой.
Кликните правой кнопкой по мыши по компоненту Train Model, отвечающему линейной регрессии и выберите Save as Trained Model. Это позволит использовать полученную модель в любых других экспериментах без необходимости повторного обучения.
Публикация веб-сервиса
Для публикации сервиса выберите компонент Train Model, отвечающий линейной регрессии и нажмите в Set Up Web Service. В открывшемся меню выберите Predictive Web Service [Recommended] и дождитесь пока Azure ML создаст новый эксперимент, оптимизированный для нужд сервиса. Удалите автоматически созданные компоненты Web Service Input и Web Service Output – мы создадим их позднее после небольшой подготовки.
На данный момент элемент Score Model повторяет на выходе все входящие столбцы, а предсказанному значению дает название Score Labels. Это необходимо исправить.
Для этого перенесите из панели инструментов на рабочую поверхность два уже знакомых компонента: Project Columns и Metadata Editor. И соедините их в последовательности изображенной на рисунке ниже. В настройках Project Columns выберите только один столбец Score Labels, и используя Metadata Editor переименуйте его в price.
В заключение необходимо добавить вход и выход создаваемого сервиса. Для этого добавьте в эксперимент Web Service Input и Web Service Output. Соедините первый со входом Score Model, а второй с выходом Metadata Editor. В настройках обоих элементов измените название на «input» и «prediction», соответственно.
Запустите модель еще раз, нажав на Run, и по окончании валидации опубликуйте сервис нажатием Deploy Web Service.
Тестирование сервиса
После нажатия на Deploy Web Service вы будете перенаправлены на страницу с информацией о только что созданном сервисе. Ссылки под API HELP PAGE содержат достаточно подробное описание с информацией о содержимом входящего и исходящего JSON пакетов, а также пример кода консольного приложения, дающего преставление о способе использования.
Для интерактивного исследования нажмите на Test и в открывшемся окне введите значения для каждого входного параметра. Например, те, что указаны ниже, и нажмите галочку, чтобы отправить тестовый запрос.
audi sedan 99.8 four 109 102 5500 30 13950
Разработка приложения
В заключение рассмотрим процесс разработки мобильного приложения, использующего Azure ML в роли back-end сервиса. Сначала создайте новый проект универсального приложения Windows. Для этого в открытом Visual Studio 2015 выберите File -> New -> Project… В открывшемся окне перейдите на вкладку Windows в меню слева и выберите Blank App (Universal Windows). В поле названия введите AzureMLDemo и нажмите OK. В случае необходимости готовый проект может быть найден на GitHub.
После некоторой подготовки Visual Studio откроет новый проект универсального приложения. Убедитесь, что в поле процессорной архитектуры справа от Debug указано x86, и правее выберите одну из мобильных виртуальных машин в качестве среды запуска. Например, Mobile Emulator 10.0.10240.0 720p 5 inch 1GB.
Теперь можно перейти к написанию самого приложения. В меню Solution Explorer двойным кликом откройте MainPage.xaml. Описание языка разметки XAML графического интерфейса выходит за границы этой работы, поэтому просто замените открывающийся и закрывающийся теги <Grid …> на код ниже.
<ScrollViewer Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
HorizontalScrollMode="Disabled" VerticalScrollBarVisibility="Hidden">
<StackPanel>
<TextBlock Text="Estimate the price of your dream car"
Style="{ThemeResource TitleTextBlockStyle}"
TextAlignment="Center" HorizontalAlignment="Center"
Margin="5,20,5,5" TextWrapping="WrapWholeWords"/>
<Border Margin="5 10" BorderBrush="LightGray" BorderThickness="2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<TextBlock Text="Make" Grid.Row="0" Grid.Column="0"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5"/>
<TextBox Name="tbxMake" Text="Audi" Grid.Row="0" Grid.Column="1"
Grid.ColumnSpan="2" VerticalAlignment="Center"
HorizontalAlignment="Stretch" Margin="5"/>
<TextBlock Text="Body Style" Grid.Row="1" Grid.Column="0"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5"/>
<TextBox Name="tbxBodyStyle" Text="Sedan" Grid.Row="1"
Grid.Column="1" Grid.ColumnSpan="2"
VerticalAlignment="Center" HorizontalAlignment="Stretch"
Margin="5"/>
<TextBlock Text="Wheel Base" Grid.Row="2" Grid.Column="0"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5"/>
<Slider Name="slWheelBase" Value="99" Grid.Row="2" Grid.Column="1"
Minimum="86" Maximum="121" StepFrequency="1"
VerticalAlignment="Center" HorizontalAlignment="Stretch"
Margin="5,5,3,5"/>
<TextBlock Name="tbWheelBase" Grid.Row="2" Grid.Column="2"
Text="{x:Bind slWheelBase.Value, Mode=OneWay}"
VerticalAlignment="Center" Margin="2,5,5,5"/>
<TextBlock Text="Number of Cylinders" Grid.Row="3" Grid.Column="0"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5"/>
<TextBox Name="tbxNumberOfCylinders" Text="Four" Grid.Row="3"
Grid.Column="1" Grid.ColumnSpan="2"
VerticalAlignment="Center" HorizontalAlignment="Stretch"
Margin="5"/>
<TextBlock Text="Engine Size" Grid.Row="4" Grid.Column="0"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5"/>
<Slider Name="slEngineSize" Value="109" Grid.Row="4" Grid.Column="1"
Minimum="61" Maximum="326" StepFrequency="1"
VerticalAlignment="Center" HorizontalAlignment="Stretch"
Margin="5,5,3,5"/>
<TextBlock Name="tbEngineSize" Grid.Row="4" Grid.Column="2"
Text="{x:Bind slEngineSize.Value, Mode=OneWay}"
VerticalAlignment="Center" Margin="2,5,5,5"/>
<TextBlock Text="Horsepowers" Grid.Row="5" Grid.Column="0"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5"/>
<Slider Name="slHorsepowers" Value="102" Grid.Row="5" Grid.Column="1"
Minimum="48" Maximum="288" StepFrequency="1"
VerticalAlignment="Center" HorizontalAlignment="Stretch"
Margin="5,5,3,5"/>
<TextBlock Name="tbHorsepowers" Grid.Row="5" Grid.Column="2"
Text="{x:Bind slHorsepowers.Value, Mode=OneWay}"
VerticalAlignment="Center" Margin="2,5,5,5"/>
<TextBlock Text="Peak PRM" Grid.Row="6" Grid.Column="0"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5"/>
<Slider Name="slPeakRPM" Value="5500" Grid.Row="6" Grid.Column="1"
Minimum="4150" Maximum="6600" StepFrequency="1"
VerticalAlignment="Center" HorizontalAlignment="Stretch"
Margin="5,5,3,5"/>
<TextBlock Name="tbPeakRPM" Grid.Row="6" Grid.Column="2"
Text="{x:Bind slPeakRPM.Value, Mode=OneWay}"
VerticalAlignment="Center" Margin="2,5,5,5"/>
<TextBlock Text="Highway MPG" Grid.Row="7" Grid.Column="0"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5"/>
<Slider Name="slHighwayMPG" Value="30" Grid.Row="7" Grid.Column="1"
Minimum="16" Maximum="54" StepFrequency="1"
VerticalAlignment="Center" HorizontalAlignment="Stretch"
Margin="5,5,3,5"/>
<TextBlock Name="tbHighwayMPG" Grid.Row="7" Grid.Column="2"
Text="{x:Bind slHighwayMPG.Value, Mode=OneWay}"
VerticalAlignment="Center" Margin="2,5,5,5"/>
</Grid>
</Border>
<Button Name="btnGetEstimate" Grid.Row="2" Content="Get estimate"
HorizontalAlignment="Center"/>
<TextBlock Name="tbResult" TextAlignment="Left" Margin="10 5"
TextWrapping="Wrap"/>
</StackPanel>
</ScrollViewer>
Несмотря на всю кажущуюся сложность этот код создает достаточно простую разметку, необходимую для ввода пользовательских данных. Каждый элемент ввода одного из параметров модели имеет название вроде tbxMake, txbBodyStyle и т.п. Под ними находится кнопка Get Estimate, отвечающая за отправку сообщения к сервису Azure ML, а завершается все элементом tbResult, в который и будет помещаться результат вызова.
Запустите приложение нажатием на Debug -> Start Debugging, чтобы убедиться, что все было сделано правильно, проект компилируется и запускается. Проверьте, что изменение положения слайдеров приводит к соответствующему изменению численного значения справа от них.
Остановите сессию отладки нажатием на Debug -> Stop Debugging.
Определение программной логики
Теперь необходимо определить код обработки нажатия на кнопку Get Estimate. В Solution Explorer разверните MainPage.xaml и кликните дважды по MainPage.xaml.cs, чтобы открыть Code-behind файл этого графического интерфейса.
Первым делом следует подключить несколько требуемых библиотек. Для этого кликните правой кнопкой мыши по имени проекта и выберите Manage Nuget Packages… В открывшемся меню сделайте поиск по WebApi.Сlient и установите пакет с названием Microsoft.AspNet.WebApi.Client.
После этого добавьте в начало файла следующие дополнительные объявления using:
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using System.Threading.Tasks;
</source
Следующим шагом добавьте в класс MainPage несколько полей, содержащих необходимую информацию для подключения к сервису.
<source lang="cs">
public sealed partial class MainPage : Page
{
const string _apiKey = @"<your API key>";
const string _requestUri = @"Your key";
Ключ доступа можно найти на Dashboard странице вашего сервиса, а адрес запроса на странице помощи REQUEST/RESPONSE, ссылка на которую приведена немного ниже.
Следующим шагом добавим вспомогательную функцию, которая будет осуществлять запрос к сервису Azure ML. В соответствии с документацией, приведенной на той же странице помощи REQUEST/RESPONSE для получения ответа мы должны выполнить следующую последовательность действий: сформировать запрос, отправить его в сторону сервиса POST-запросом протокола HTTP и обработать ответ.
Создайте функцию CallAzureML, принимающую на вход значения всех параметров модели и возвращающую значение типа float c оценкой цены. Async Task здесь отвечает реализации паттерна async/await, значительно упрощающего работу с асинхронными вызовами в приложении (дополнительная информация может быть найдена здесь).
private async Task<float> CallAzureML(string make, string bodyStyle, double wheelBase,
string numberOfCylinders, int engineSize,
int horsepowers, int peakRPM, int highwayMPG)
{
}
Также для упрощения работы с JSON мы будем использовать библиотеку Newtonsoft.Json. Отличительной ее особенностью является то, что она позволяет взаимодействовать с JSON-объектами через удобную абстракцию в виде обычных объектов уровня .NET. Поместите в начало метода следующий код.
var requestBody = new
{
Inputs = new Dictionary<string, object>()
{
{
"input",
new
{
ColumnNames = new string[] {"make", "body-style",
"wheel-base", "num-of-cylinders",
"engine-size", "horsepower",
"peak-rpm", "highway-mpg",
"price"},
Values = new string[,] {
{ make, bodyStyle, wheelBase.ToString(),
numberOfCylinders, engineSize.ToString(),
horsepowers.ToString(), peakRPM.ToString(),
highwayMPG.ToString(), "0" } }
}
}
},
GlobalParameters = new Dictionary<string, int>()
};
Здесь структура JSON-объекта запроса воссоздается с помощью анонимного класса и полностью (с учетом регистра) повторяет структуру ожидаемого запроса. Для сравнения пример такого запроса со страницы REQUEST/RESPONSE представлен ниже.
{
"Inputs": {
"input": {
"ColumnNames": [ "make", "body-style", “wheel-base", "num-of-cylinders",
"engine-size", "horsepower", "peak-rpm", "highway-mpg",
"price" ],
"Values": [
[ "value", "value", "0", "value", "0", "0", "0", "0", "0" ],
[ "value", "value", "0", "value", "0", "0", "0", "0", "0" ]
]
}
},
"GlobalParameters": {}
}
Следующим шагом является выполнение запроса к самому сервису. Для этого добавьте следующий код в разрабатываемый метод.
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("bearer", _apiKey);
client.BaseAddress = new Uri(_requestUri);
var response = await client.PostAsJsonAsync("", requestBody);
if (response.IsSuccessStatusCode)
{
// succeeded
throw new NotImplementedException();
}
else
{
// failed
throw new NotImplementedException();
}
}
}
catch (Exception e)
{
throw;
}
Первым делам создается HTTP-клиент и устанавливается вся информация необходимая для успешного подключения к сервису в Azure ML: адрес и ключ доступа. Далее осуществляется POST-запрос в сторону сервиса с JSON-объектом, созданным ранее. Успешность вызова проверяется по коду состояния HTTP.
Замените код в области отмеченной комментарием succeeded на представленный ниже. В нем последовательно происходит получение ответа сервера в виде строки, ее разбор в динамический объект с помощью конвертера Newtonsoft.Json с последующим извлечением информации о цене. Пример ответа сервера для сравнения может быть найден в разделе «Тестирование сервиса».
var responseContent = await response.Content.ReadAsStringAsync();
var val = JsonConvert.DeserializeObject<dynamic>(responseContent);
float? price = (float)val?.Results?.prediction?.value?.Values[0][0];
if (price == null)
throw new InvalidDataException("Response message has unknown format" +
" or is empty.");
return (float)price;
В случае ошибочного состояния метод должен вернуть максимум информации. Поэтому как и в прошлом случае в виде строки извлекается содержимое запроса, но в этот раз оно последовательно преобразуется в объект и обратно в строку. Это необходимо для того, чтобы добавить отступы, позволяющее более удобное чтения его содержимого. Замените код в области, отмеченной комментарием failed на приведенный ниже.
var responseContent = await response.Content.ReadAsStringAsync();
var responseObject = JsonConvert.DeserializeObject(responseContent);
var formattedResponseContent =
JsonConvert.SerializeObject(responseObject, Formatting.Indented);
var message = String.Format("Server returned status code {0} with message {1}",
response.StatusCode, formattedResponseContent);
throw new InvalidDataException(message);
Метод вызова к Azure ML можно считать завершенным. Как можно заметить его реализация достаточно проста, хотя за ней и строит целый процесс по реализации статистической модели данных, алгоритма обучения и способа оценки произвольного оценки входного вектора. Достаточно сложные математические теории умещаются в пару строк программного кода.
В заключение необходимо реализовать обработчик события нажатия кнопки Get estimate. Первым делом перейдите в MainPage.xaml и добавьте в XML-тег кнопки GetEstimate информацию об обработчике событий.
<Button … Click="GetEstimate_Click"/>
Вернитесь в MainPage.xaml.cs и создайте соответствующий метод. Он вызывает созданный ранее метод для обращения к сервису Azure ML и устанавливает результат в tbResult.
private async void GetEstimate_Click(object sender, RoutedEventArgs e)
{
try
{
var price = await CallAzureML(tbxMake.Text, tbxBodyStyle.Text,
slWheelBase.Value, tbxNumberOfCylinders.Text,
(int)slEngineSize.Value, (int)slHorsepowers.Value,
(int)slPeakRPM.Value, (int)slHighwayMPG.Value);
tbResult.Text = String.Format("You are lucky!n" +
"Today it is as cheap as {0:c}. Don't miss your chance!", price);
}
catch (Exception ex)
{
// Shows error in result TextBlock
tbResult.Text = String.Format("Oops! Something went wrong.n" +
"This can be helpful:n{0}", ex.ToString());
}
}
Все, приложение готово. Запустите его и поэкспериментируйте с оценкой стоимости автомобиля при различных наборах характеристик.
Заключение
Azure Machine Learning – это новый высокопродуктивный инструмент для работы с алгоритмами машинного обучения. Возможно, это даже единственная среда, которая позволяет так легко опубликовать свои алгоритмы в виде отдельного сервиса и в последствии использовать их в своих приложениях. В этой работе использовался один из простейших алгоритмов обучения – алгоритм линейной регрессии. В Azure ML доступны еще десятки других, созданных учеными для самых разных целей. И самое важное, что для их использования совсем нет необходимости быть математиком. Достаточно с помощью компонентов собрать необходимый процесс обработки данных, провести несколько экспериментов и в случае успеха опубликовать все в виде сервиса.
Вот еще несколько выборок данных, на которых можно поэкспериментировать:
Автор: Microsoft