Data science. Начало
Первая статья из цикла от том как подружить бизнес-приложения и data science
Для многих 1С-ников (в том числе и достаточно опытных) может быть открытием то, что модные сейчас Data science и Machine learning уже довольно давно присутствуют в платформе. По причинам, которые я постараюсь раскрыть в дальнейшем, эти технологии почти никем не используются. Но лично я убежден, что как минимум базовые навыки в этой области пригодятся любому специалисту 1С. В этой серии статей я попробую достаточно детально, но без лишних сложностей рассказать о том, что это такое и "с чем это едят"
Обратимся к документации по платформе. В самом начале главы, посвященной анализу данных и прогнозированию, авторы прямо и без обиняков говорят нам, что не будут ничего говорить нам о способах использования того, что они описывают. И это, на мой взгляд, и есть первая и едва ли не основная причина того, что объект "АнализДанных" до сих пор применяется далеко не так активно, как он того заслуживает. Все-таки Data science по общему признанию является сплавом трех компонент: статистики, программирования и коммуникации. И без последней невозможно получить хоть какой-то результат.

Сейчас в арсенале специалиста по DS(data science) и ML(machine learning) есть довольно много различных средств и технологий. Что-то из этого есть в платформе 1С, чего-то нет. Но мы начнем знакомство со всем этим с одной проверенной и заслуженной технологии, которую коротко называют "регрессией".

В платформе 1С для всех возможных типов анализа используется один и тот же объект "АнализДанных". Регрессии в этом объекте соответствует тип анализа "Дерево решений".

Анализ=новый АнализДанных; Анализ.ТипАнализа=Тип("АнализДанныхДеревоРешений");
Рассказывать, как работает регрессия, я буду на примере, который должен быть близок всем. Почти каждому из нас (прямо или косвенно, через родственников, друзей, знакомых) приходилось иметь дело с арендой или покупкой недвижимости. И, соответственно, так или иначе приходилось решать вопрос оценки. Мы будем использовать регрессию для того, чтобы не ломать голову, а получать оценку на научной основе. К тому же, вам по любому не будет жаль потраченного на чтение статьи времени. В конце вы получите на руки инструмент, который вам наверняка пригодится в будущем.

Учебные данные я взял на законной основе с Kaggle. Это одна их наиболее известных "тусовок" специалистов по DS и ML, с некоторых пор под эгидой Google. Это данные о реальных сделках по покупке-продаже недвижимости. Хороши они еще и тем, что достаточно детальны. Вы можете увидеть это на иллюстрации.

Прежде, чем обращаться к методам объекта "АнализДанных", не помешает разобраться как это работает в принципе. Математика тут совсем простая, если не сказать примитивная. Тем более должно быть удивительным - что из этой простоты можно получить. Вообще описаний метода регрессионного анализа существует чуть ли не миллион. Для разных людей подойдут разные. Я же попробую дать описание, подходящее для программистов. Такое, после которого вы могли бы сказать себе: ага! ну этот алгоритм я мог бы быстренько написать. Давайте снова взглянем на данные. Что вообще можно с ними с делать? Так прямо в лоб? Можно взять среднее значение цены продажи. Тоже ведь метод оценки. Да, не очень точный. Но насколько неточный? Как сильно мы будем промахиваться "в среднем", если воспользуемся этим методом? Чтобы понять это, нам надо рассчитать что-то типа среднего отклонения. Для каждой строки таблицы получим разность цены и средней цены. Просуммируем, а затем разделим на количество строк. Если суммировать не просто разности, а квадраты разностей, и потом извлекать квадратный корень, получим так называемое "стандартное отклонение". Оно и будет у нас мерой точности. Как ее можно повысить? Очень просто. Сгруппируем записи исходной таблицы по значениям какой-нибудь очевидно значимой колонки, например, "количество комнат". Что произойдет со стандартным отклонением внутри каждой из групп? Интуиция подсказывает нам, что стандартное отклонение должно уменьшиться. И так оно и есть! Теперь, я надеюсь, понятно что надо делать. Сгруппируем исходную таблицу по каждой из колонок отдельно. Рассчитаем уменьшение (регрессию) стандартного отклонения для каждого случая и выберем самый лучший. А далее будем повторять этот процесс рекурсивно внутри каждой группы записей. В результате получим иерархическую структуру или дерево решений. Узлами этого дерева будут значения группировок, а в листьях будет то, что мы ищем. В нашем случае, это будет предполагаемая цена объекта недвижимости.

Чтобы построить дерево решений в 1С, надо сделать следующее:

Анализ=новый АнализДанных; Анализ.ТипАнализа=Тип("АнализДанныхДеревоРешений"); Анализ.ИсточникДанных=ТЗМодель; Анализ.Параметры.ТипУпрощения.Значение=ТипУпрощенияДереваРешений.НеУпрощать; РДерево=Анализ.Выполнить();

А для того, чтобы получить расчет предполагаемых цен, надо сделать вот это:

Прогноз=РДерево.СоздатьМодельПрогноза(); Прогноз.ИсточникДанных=ТЗПрогноз; Результат=Прогноз.Выполнить();
Как видно, все сводится к тому, чтобы задать источники данных для модели и для прогноза. Учебные данные я сохранил в макет внешней обработки. И хотя объект "АнализДанных" допускает табличный документ (а также и результат запроса) в качестве источника данных, я все же буду использовать таблицу значений. Причины этого будут понятны ниже.

//получение данных Макет=РеквизитФормыВЗначение("Объект").ПолучитьМакет("ИсходныеДанные"); ТЗМодель=новый ТаблицаЗначений; ТЗМодель.Колонки.Добавить("ПлощадьУчастка"); ТЗМодель.Колонки.Добавить("ГодПостройки"); ТЗМодель.Колонки.Добавить("Площадь1этажа"); ТЗМодель.Колонки.Добавить("Площадь2этажа"); ТЗМодель.Колонки.Добавить("КоличествоПолныхСанузлов"); ТЗМодель.Колонки.Добавить("КоличествоСпален"); ТЗМодель.Колонки.Добавить("КоличествоКомнат"); ТЗМодель.Колонки.Добавить("Цена"); ТЗПрогноз=ТЗМодель.Скопировать();
для й=2 по Макет.ВысотаТаблицы цикл
нстр=ТЗМодель.Добавить(); нстр.ПлощадьУчастка=число(Макет.Область(й,5).Текст); нстр.ГодПостройки=число(Макет.Область(й,20).Текст); нстр.Площадь1этажа=число(Макет.Область(й,44).Текст); нстр.Площадь2этажа=число(Макет.Область(й,45).Текст); нстр.КоличествоПолныхСанузлов=число(Макет.Область(й,50).Текст); нстр.КоличествоСпален=число(Макет.Область(й,52).Текст); нстр.КоличествоКомнат=число(Макет.Область(й,55).Текст); нстр.Цена=число(Макет.Область(й,81).Текст);
если й<11 тогда
нстрпрогноз=ТЗПрогноз.Добавить(); ЗаполнитьЗначенияСвойств(нстрпрогноз,нстр);
конецесли;
конеццикла;
//подготовка
Анализ=новый АнализДанных; Анализ.ТипАнализа=Тип("АнализДанныхДеревоРешений"); Анализ.ИсточникДанных=ТЗМодель; Анализ.Параметры.ТипУпрощения.Значение=ТипУпрощенияДереваРешений.НеУпрощать; РДерево=Анализ.Выполнить(); //прогноз Прогноз=РДерево.СоздатьМодельПрогноза(); Прогноз.ИсточникДанных=ТЗПрогноз; Результат=Прогноз.Выполнить(); //визуализация ТабДок.Очистить(); ТабДок.УстановитьРастягиваниеПоГоризонтали(Истина);
для й=1 по Результат.Колонки.Количество()-1 цикл ТабДок.Область(1,й).Текст=Результат.Колонки[й-1].Имя; ТабДок.Область(1,й).Шрифт=Новый Шрифт(ТабДок.Область(1,й).Шрифт, ,, Истина);
конеццикла;
для й=1 по Результат.Количество() цикл
для ы=1 по Результат.Колонки.Количество()-1 цикл ТабДок.Область(й+1,ы).Текст=строка(Результат[й-1][ы-1]);
конеццикла;
конеццикла;

По умолчанию платформа считает, что получать прогноз нужно для самой последней колонки, а группировать по всем прочим. Для построения модели я взял все строки исходных данных и 7 колонок. Для проверки работы прогноза - первые десять строк. И вот что получилось: