Библиотека Numeric. Решение численных задач на Javascript
А.А. Марков,
д.т.н., профессор кафедры информационных систем МГУП имени Ивана Федорова
Свободно распространяемая библиотека Numeric позволяет решать целый ряд численных задач в программах, написанных на языке Javascript. Загрузить последнюю версию библиотеки можно с сайта http://www.numericjs.com. Хотя Javascript не предназначен для решения сложных вычислительных задач, во многих случаях производительности Javascript достаточно для проведения требуемых расчетов. В статье рассматривается применение библиотеки на примере задачи построения линейной регрессионной модели. Графическое представление результатов вычислений выполнено с использованием библиотеки Flop.
В настоящее время библиотека Numeric содержит более сотни функций для решения задач из некоторых разделов численной математики. В частности, в библиотеке имеются функции для выполнения операций над векторами и матрицами, функции для решения задач линейной алгебры, функции для работы с разряженными матрицами, функции для работы с комплексными числами (в том числе матричные операции), функции для решения систем обыкновенных дифференциальных уравнений и др. В библиотеке реализованы функции для работы с данными, графическое представление результатов вычислений осуществляется средствами библиотеки Flot. Numeric имеет хорошее описание, представленное многими примерами в 11-страничном PDF-документе.
В данной статье рассматривается применение Numeric для решения задач построения регрессионных моделей. Лежащий в основе решения метод наименьших квадратов позволяет продемонстрировать важные функции библиотеки Numeric и особенности их применения.
Рассмотрим последовательность шагов для решения задачи рассматриваемой в статье.
Подключение библиотеки. Библиотеку Numeric можно разместить в той же папке, что и html-страницу, созданную для демонстрации примера.
Листинг 1. — Подключение библиотеки Numeric
1 <html>
2 <head>
3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4 <title>Numeric Examples</title>
5 <script language="javascript" type="text/javascript" src="numeric/numeric-1.1.1.js">
6 </script>
7 <script type="text/javascript" src= "ex.js" ></script>
8 </head>
9 <body>
10 <div id="placeholder" style="width:600px;height:300px;"></div>
11 </body>
12 </html>
Собственно подключение библиотеки выполняется стандартным способом (строки 5-6, лист. 1). Код программы разместим во внешнем файле ех^, размещаемом в той же папке, что и ^т^-страница примера. Для вывода результата работы будет использован блок (строка 10, лист. 1).
Постановка задачи. Для построения линейной регрессионной модели был выбран набор исходных данных, полученный рандомизацией значений функции у = ах + Ь + на множестве значений х = [0.1, К 10], при а = 1 и Ь = -1, величина при вычислении каждого значения функции задавалась случайным числом, распределенным равномерно на интервале [-0,2-(ах+ Ь) + 0,2-(ах+ Ь)]. Вычисленные значения представлены в табл. 1.
Таблица 1
Рандомизированные значения линейной функции
X Y
1 0 -0,861
2 1 -0,007
3 2 1,044
4 3 2,138
Окончание табл. 1
X У
5 4 3,105
6 5 4,077
7 6 5,177
8 7 6,073
9 8 7,160
10 9 8,087
11 10 8,828
В табл. 1 показаны для нашего примера 11 строк данных.
Обозначим х, у значения аргумента и функции, указанные в строке № табл. 1.
Задача состоит в том, чтобы на заданном наборе данных найти такие А и В, использование которых минимизирует сумму квадратов отклонений модельной функции Y= Ах + В от значений, представленных в исходном наборе данных.
Сумма квадратов отклонений задается формулой
Е(Лх, +В-у,)2.
В двумерном случае А и В можно получить с использованием формул, в общем случае, в методе наименьших квадратов коэффициенты линейной модели вычисляются как решения системы линейных алгебраических уравнений (СЛАУ).
Приведем соответствующую СЛАУ.
N N N
А£х2 +В^х, = Ех,У, ,=1 /=1 /=1 N N
А£х,- + N■B=ZУr
/=1 ,=1
(1)
Для данных, представленных в табл. 1, N= 11. Систему уравнений (1) нужно решать относительно переменных А и В
Запишем решение задачи в матричной форме. Обозначим матрицу системы (2).
М=
N N
Ех2 ,=1
N
Ех
,=1
,=1 N
Вектор решений будем обозначать буквой R.
ГА]
R =
B
Для вектора свободных членов используем обозначение F.
F=
N
i=1 N
E/i
i=1
(4)
В матричной форме решение системы записывается следующим образом: R = F- M1.
Библиотека Numeric предоставляет быстрые и удобные функции для выполнения матричных и векторных операций.
Представление исходных данных. Для хранения исходного массива используем переменную XY. Нам понадобится представление данных в виде матрицы. Для библиотеки Numeric как матрицы, так и векторы задаются массивами.
Приведем код для инициализации массива:
ХУ=[ [0,-0.861], [1,-0.007], [2, 1.044], [3, 2.138], [4, 3.105], [5, 4.077], [6, 5.177], [7, 6.073], [8, 7.160], [9, 8.087],[10,8.828] ];
Из исходного массива (матрицы) нам понадобится выделить два вектора X и Y. Сделать это можно следующим способом:
XYT=numeric.transpose(XY);
X=XYT[0];
Y=XYT[1];
Первая строка приведенного кода транспонирует матрицу XY. В результате строка с индексом 0 матрицы XYT, содержит значения X, а строка с индексом 1 указанной матрицы содержит значения Y. В результате показанных действий мы получили векторы X и Y.
Для определения коэффициентов системы (1) необходимо вычислить несколько сумм. Эти вычисления производятся следующим образом:
SUM_X=numeric.sum(X); SUM_Y=numeric.sum(Y); SUM_X_SQR=numeric.sum(numeric[»*»](X,X)); SUM_XY=numeric.sum(numeric[»*»](X,Y));
2 О
Функция питепсБитО вычисляет сумму элементов задаваемого аргументом массива. Таким образом БиМ_Х и SUM_Y задают нам суммы значений X и Y соответственно. Для вычисления суммы квадратов X используется функция, выполняющая поэлементное умножение векторов:
питепс^ит(питепс[»*»](Х,Х)).
Результатом выполнения этой функции является массив, сумма элементов которого вычисляется с помощью питемслитО. Результат присваивается переменной SUM_X_SQR.
Аналогичным способом вычисляется переменная SUM_XY. Она используется для хранения суммы .
Чтобы задать матрицу системы (2), введем переменную . Она определяется следующим образом:
M=[[SUM_X_SQR,SUM_X],[SUM_X,N]];
Обратная матрица (обозначим ее INVM) вычисляется так:
^М=питепс.^(М);
Для определения вектора свободных членов (4) введем соответствующую переменную:
F=[[SUM_XY],[SUM_Y]];
Решение системы (3) определяется следующим оператором:
R=nuтeric.dot(INVM,F);
Исходный код программы. На листинге 21 приводится соответствующий код:
Листинг 2. — Код программы (файл ех^Б)
1 //Построение линейной регрессионной модели Y=AX+B по массиву исходных данных XY
2 var А;// оэффициент А
3 var В;// оэффициент В
1 На листинге не показан код, обеспечивающий вывод результата на НТМ^-страницу.
4 var ХУ=[ [0,-0.861], [1,-0.007], [2, 1.044], [3, 2.138], [4, 3.105],
5 [5 , 4.077], [6, 5.177], [7, 6.073], [8, 7.160], [9, 8.087],[10,8.828] ]; //Исходные данные
6 var ХУТ;//Транспонированная матрица исходных данных
7 var Х;//Вектор исходных значений X
8 var У;//Вектор исходных значений У
9 var Ы;//Длина массива данных
10 var SUM_X;//Сумма X
11 var SUM_У;//Сумма У
12 var SUM_X_SQR;//Сумма квадратов X
13 var SUM_XУ;//Сумма произведений х[1]*у[1]
14 var М;//Матрица СЛАУ
15 var 11\^М;//Обратная матрица
16 var F;//Вектор свободных членов
17 var R;//Решение СЛАУ
18 var SSUMSQR;//Среднее отклонение
19 //Определение длины исходного массива
20 N=XY.length;
21 //Вычисление векторов X,У
22 XУT=numeric.transpose(XУ);
23 X=XУT[0];
24 У=XУT[1];
25 //Вычисление матрицы СЛАУ
26 SUM_X=numeric.sum(X);
27 SUM_У=numeric.sum(У);
28 SUM_X_SQR=numeпcsum(numeпc["*"KX,X));
29 SUM_XУ=numeпcsum(numeпc["*"](X,У));
30 M=[[SUM_X_SQR,SUM_X],[SUM_X,N]];//Матрица системы
31 //Решение системы
32 ^М=питепс.1т(М);
33 F=[[SUM_XY],[SUM_Y]];
34
35 А=К[0][0];
36 В=К[1][0];
37 //Среднее отклонение
38 SSUMSQR = питепс.погт2(
39 питепс["+"](
40 питепс^^АД),
41 В ,
42 питепс["*"](-1Д)
43 )
44 )
45 / Ма^^г"^);
Поясним последние строки кода. Переменная SSUMSQR используется для оценки среднего квадрата отклонения данных от линейной модели. Формула, по которой вычисляется эта величина, следующая (5):
ББиМБОП=
N 2
^(А-х, +В-у,у ^__(5)
Для вычисления по формуле 5, использовано свойство по-лиморфности функций над векторами. Так функция питепф»*»]^^) выполняет поэлементное умножение вектора X на скалярную величину А. Результатом этой функции является вектор. Свойство полиморфно-сти использовано для вычисления вектора (см. лист. 2 строки 38-43).
Для вычисления квадратного корня из суммы квадратов элементов вектора использована функция питепспогт2 (см. лист. 2 строки 38-44).
Результаты работы программы. Программа вычисляет следующие значения:
А=0.9919
В=-0.8849
SSUMSQR=0.0895
Приведем графики, показывающие в виде диаграммы рассеивания исходные данные и линию регрессии, проведенную в соответствии с вычисленными в приведенной программе коэффициентами А и В (рис. 1).
О 123456789 10
Рис. 1. Исходные данные и линия регрессии2
Точными значениями являются A=1, B=-1. Расхождение с точными значениями объясняется малой длиной (N=11) исходного массива данных. Небольшое значение было выбрано для сокращения числа строк кода, приведенного в статье.
Заключение. Библиотека Numeric за счет применения удобных операций над векторами и матрицами, с учетом их полиморфно-сти, а также за счет применения функций для решения задач линейной алгебры позволяет решать многие задачи практически не используя циклов и вспомогательных функций. Numeric является удобным инструментом для решения задач численного анализа.
В статье рассмотрено лишь небольшое число функций, реализованных в библиотеке. Приведенные примеры демонстрируют удобство применения реализованных алгоритмов в языке Javascript.
Библиографический список
[1] Сайт разработчика библиотеки Numeric: http:// www.numericjs.com
[2] Сайт разработчика библиотеки Flot: http://www.flot.com
2 График построен с использованием библиотеки Flot.