Введение
По сравнению с другими языками с открытым исходным кодом, такими как Perl и Python, сообществу PHP не хватает усилий по разработке математических библиотек.
Одной из причин этого может быть то, что уже существует большое количество зрелых математических инструментов, что может помешать усилиям сообщества по разработке инструментов PHP самостоятельно. Например, я работал над мощным инструментом S System, который имел впечатляющий набор статистических библиотек, был специально разработан для анализа наборов данных и получил премию ACM в 1998 году за свой языковой дизайн. Если S или его родственник R с открытым исходным кодом — это всего лишь вызов exec_shell, зачем беспокоиться о реализации той же функциональности статистических вычислений в PHP? Для получения дополнительной информации о системе S, ее награде ACM или R см. соответствующие ссылки.
Не является ли это пустой тратой энергии разработчиков? Если мотивацией разработки математической библиотеки PHP является экономия усилий разработчиков и использование лучшего инструмента для работы, то текущая тема PHP имеет смысл.
С другой стороны, педагогические мотивы могут стимулировать разработку математических библиотек PHP. Примерно для 10% людей математика — интересный предмет, который стоит изучить. Для тех, кто также хорошо владеет PHP, разработка математической библиотеки PHP может улучшить процесс изучения математики. Другими словами, не просто прочитайте главу о T-тестах, но и реализуйте программу, которая может вычислять соответствующие промежуточные значения. значения и отображать их в стандартном формате своих классов.
Посредством руководства и обучения я надеюсь продемонстрировать, что разработка математической библиотеки PHP не является сложной задачей и может представлять собой интересную техническую и учебную задачу. В этой статье я приведу пример математической библиотеки PHP под названием SimpleLinearReгрессия, который демонстрирует общий подход, который можно использовать для разработки математических библиотек PHP. Начнем с обсуждения некоторых общих принципов, которыми я руководствовался при разработке класса SimpleLinearReгрессия.
Руководящие принципы
При разработке класса SimpleLinearReгрессия я использовал шесть общих принципов.
Создайте класс для каждой модели анализа.
Используйте обратные ссылки для разработки классов.
Ожидается большое количество добытчиков.
Сохраните промежуточные результаты.
Установите настройки для подробных API.
Совершенство не является целью.
Давайте рассмотрим каждое из этих указаний более подробно.
Создайте класс для каждой модели анализа.
Каждый основной тест или процесс анализа должен иметь класс PHP с тем же именем, что и тест или процесс. Этот класс содержит функции ввода, функции для расчета промежуточных значений и сводных значений, а также функции вывода ( замена промежуточных значений). Значения и сводные значения отображаются на экране в текстовом или графическом формате).
Использование обратной цепочки для разработки классов
. В математическом программировании целью кодирования обычно является стандартное выходное значение, которое желает получить процедура анализа (например, MultipleReгрессия, TimeSeries или ChiSquared). С точки зрения решения проблем это означает, что вы можете использовать обратную цепочку для разработки математических методов.
Например, на экране вывода сводки отображаются результаты одной или нескольких сводных статистических данных. Эти сводные статистические результаты основаны на расчете промежуточных статистических результатов, и эти промежуточные статистические результаты могут включать более глубокие промежуточные статистические результаты и так далее. Этот подход к разработке на основе обратных ссылок приводит к следующему принципу.
Ожидайте большого количества
математических классов по геттерам. Большая часть работы по разработке классов включает в себя вычисление промежуточных и итоговых значений. На практике это означает, что вам не следует удивляться, если ваш класс содержит множество методов-получателей, вычисляющих промежуточные и итоговые значения.
Сохранение промежуточных результатов.
Сохраняет результаты промежуточных вычислений в объекте результата, чтобы их можно было использовать в качестве входных данных для последующих вычислений. Этот принцип реализован в конструкции языка S. В текущем контексте этот принцип реализуется путем выбора переменных экземпляра для представления рассчитанных промежуточных значений и сводных результатов.
Установка предпочтений для подробного API
При разработке схемы именования функций-членов и переменных экземпляра в классе SimpleLinearReгрессия я обнаружил, что если я использую более длинные имена (что-то вроде getSumSquaredError вместо getYY2 ) для описания функций-членов и переменных экземпляра, то легче понять содержание операции функции и значение переменных.
Я не отказался полностью от сокращенных имен, однако, когда использую сокращенную форму имени, мне приходится стараться давать примечание, полностью поясняющее значение имени. Моя точка зрения такова: сильно сокращенные схемы именования распространены в математическом программировании, но они затрудняют понимание и доказательство правильности определенной математической процедуры, чем это необходимо.
Совершенство — не цель
Целью этого упражнения по программированию не обязательно является разработка высокооптимизированного и строгого математического механизма для PHP. На ранних этапах следует сделать акцент на обучении проведению значимых аналитических тестов и решению сложных проблем в этой области.
Переменные экземпляра
При моделировании статистического теста или процесса необходимо указать, какие переменные экземпляра объявлены.
Выбор переменных экземпляра может быть определен путем учета промежуточных и итоговых значений, генерируемых в процессе анализа. Каждое промежуточное и сводное значение может иметь соответствующую переменную экземпляра, значение которой является свойством объекта.
Я использовал этот анализ, чтобы определить, какие переменные объявить для класса SimpleLinearReгрессия в листинге 1. Аналогичный анализ можно выполнить с помощью процедур MultipleReгрессия, ANOVA или TimeSeries.
Листинг 1. Переменные экземпляра класса SimpleLinearReгрессия
<?php
// Copyright 2003, Пол Мигер.
// Распространяется под лицензией GPL
класс SimpleLinearReгрессия {
вар $n;
вар $X = массив();
вар $Y = массив();
вар $ConfInt;
вар $Альфа;
вар $XMean;
вар $YMean;
вар $SumXX;
вар $SumXY;
вар $SumYY;
вар $Slope;
вар $YInt;
вар $PredictedY = массив();
вар $Error = массив();
вар $SquaredError = массив();
вар $TotalError;
вар $SumError;
вар $SumSquaredError;
вар $ErrorVariance;
вар $StdErr;
вар $SlopeStdErr;
var $SlopeVal // значение T наклона;
вар $YIntStdErr;
var $YIntTVal // значение T для перехвата Y;
вар $R;
вар $RSquared;
var $DF // Степени свободы;
var $SlopeProb // Вероятность оценки наклона;
var $YIntProb // Оценка вероятности пересечения Y
var $AlphaTVal // Значение T для заданной настройки альфа;
вар $ConfIntOfSlope;
var $RPath = "/usr/local/bin/R" // Здесь ваш путь
var $format = "%01.2f" // Используется для форматирования вывода
}
?>
Конструктор
Метод конструктора класса SimpleLinearReгрессия принимает вектор X и Y, каждый из которых имеет одинаковое количество значений. Вы также можете установить доверительный интервал по умолчанию 95 % для ожидаемого значения Y.
Метод конструктора начинается с проверки того, что форма данных пригодна для обработки. Как только входные векторы проходят тесты «равный размер» и «значение больше 1», выполняется основная часть алгоритма.
Выполнение этой задачи предполагает расчет промежуточных и итоговых значений статистического процесса с помощью ряда геттерных методов. Присвойте возвращаемое значение каждого вызова метода переменной экземпляра класса. Сохранение результатов вычислений таким способом гарантирует, что промежуточные и сводные значения будут доступны для вызова подпрограмм в цепных вычислениях. Вы также можете отобразить эти результаты, вызвав метод вывода этого класса, как описано в листинге 2.
Листинг 2. Вызов методов вывода класса
<?php
// Copyright 2003, Пол Мигер.
// Распространяется под лицензией GPL
function SimpleLinearReprofit($X, $Y, $ConfidenceInterval="95") {
$numX = счетчик ($X);
$numY = количество ($Y);
если ($numX != $numY) {
die("Ошибка: размеры векторов X и Y должны быть одинаковыми.");
}
если ($numX <= 1) {
die("Ошибка: размер входного массива должен быть не менее 2.");
}
$this->n = $numX;
$это->X = $X;
$это->Y = $Y;
$this->ConfInt = $ConfidenceInterval;
$this->Alpha = (1 + ($this->ConfInt / 100)) / 2;
$this->XMean = $this->getMean($this->X);
$this->YMean = $this->getMean($this->Y);
$this->SumXX = $this->getSumXX();
$this->SumYY = $this->getSumYY();
$this->SumXY = $this->getSumXY();
$this->Slope = $this->getSlope();
$this->YInt = $this->getYInt();
$this->PredictedY = $this->getPredictedY();
$this->Error = $this->getError();
$this->SquaredError = $this->getSquaredError();
$this->SumError = $this->getSumError();
$this->TotalError = $this->getTotalError();
$this->SumSquaredError = $this->getSumSquaredError();
$this->ErrorVariance = $this->getErrorVariance();
$this->StdErr = $this->getStdErr();
$this->SlopeStdErr = $this->getSlopeStdErr();
$this->YIntStdErr = $this->getYIntStdErr();
$this->SlopeTVal = $this->getSlopeTVal();
$this->YIntTVal = $this->getYIntTVal();
$this->R = $this->getR();
$this->RSquared = $this->getRSquared();
$this->DF = $this->getDF();
$this->SlopeProb = $this->getStudentProb($this->SlopeTVal, $this->DF);
$this->YIntProb = $this->getStudentProb($this->YIntTVal, $this->DF);
$this->AlphaTVal = $this->getInverseStudentProb($this->Alpha, $this->DF);
$this->ConfIntOfSlope = $this->getConfIntOfSlope();
вернуть истину;
}
?>
Названия методов и их последовательности были получены путем сочетания обратных ссылок и ссылок на учебник по статистике, используемый студентами бакалавриата, в котором шаг за шагом объясняется, как вычислять промежуточные значения. Имя промежуточного значения, которое мне нужно вычислить, имеет префикс «get», таким образом получая имя метода.
Подгонка модели к данным
Процедура SimpleLinearReгрессия используется для создания прямой линии, подходящей к данным, где линия имеет следующее стандартное уравнение:
y = b + mx.
Формат этого уравнения PHP аналогичен листингу 3:
Листинг 3. Соответствие модели данным. Соответствие уравнению PHP.
$PredictedY[$i] = $YIntercept + $Slope * $X[$i]
Класс SimpleLinearReгрессия использует критерий наименьших квадратов для получения оценок параметров пересечения Y (Y Intercept) и наклона (Slope). Эти оцененные параметры используются для построения линейного уравнения (см. листинг 3), которое моделирует взаимосвязь между значениями X и Y.
Используя полученное линейное уравнение, вы можете получить прогнозируемое значение Y для каждого значения X. Если линейное уравнение хорошо соответствует данным, то наблюдаемые и прогнозируемые значения Y имеют тенденцию совпадать.
Как определить, подходит ли оно?
Класс SimpleLinearReгрессия генерирует довольно много сводных значений. Важным итоговым значением является Т-статистика, которая измеряет, насколько хорошо линейное уравнение соответствует данным. Если согласие очень хорошее, статистика T будет иметь тенденцию быть большой. Если статистика T мала, то линейное уравнение следует заменить моделью, которая предполагает, что среднее значение значений Y является лучшим предиктором (то есть среднее значение набора значений обычно является полезным предиктором). следующего наблюдения сделайте его моделью по умолчанию).
Чтобы проверить, достаточно ли велика статистика T, чтобы не рассматривать среднее значение значений Y как лучший предиктор, вам необходимо вычислить случайную вероятность получения статистики T. Если вероятность получения Т-статистики мала, то можно отвергнуть нулевую гипотезу о том, что среднее значение является лучшим предиктором, и, соответственно, быть уверенным, что простая линейная модель хорошо соответствует данным.
Итак, как рассчитать вероятность значения статистики T?
Вычисление вероятности значения T-статистики.
Поскольку в PHP отсутствуют математические процедуры для расчета вероятности значения T-статистики, я решил оставить эту задачу пакету статистических вычислений R (см. www.r-project.org в разделе «Ресурсы»). получить необходимые значения. Я также хочу привлечь внимание к этому пакету, потому что:
R предоставляет множество идей, которые разработчик PHP может эмулировать в математической библиотеке PHP.
С помощью R можно определить, соответствуют ли значения, полученные из математической библиотеки PHP, значениям, полученным из зрелых, свободно доступных статистических пакетов с открытым исходным кодом.
Код в листинге 4 демонстрирует, насколько легко предоставить R возможность получения значения.
Листинг 4. Обработка его статистическим пакетом R для получения значения
<?php
// Copyright 2003, Пол Мигер.
// Распространяется под лицензией GPL
класс SimpleLinearReгрессия {
var $RPath = "/usr/local/bin/R" // Здесь ваш путь
функция getStudentProb($T, $df) {
$ Вероятность = 0,0;
$cmd = "echo 'dt($T, $df)' | $this->RPath --slave";
$result =shell_exec($cmd);
список($LineNumber, $Probability) = взорваться(" ", обрезка($результат));
вернуть $ Вероятность;
}
функция getInverseStudentProb($alpha, $df) {
$InverseProbability = 0,0;
$cmd = "echo 'qt($alpha, $df)' | $this->RPath --slave";
$result =shell_exec($cmd);
list($LineNumber, $InverseProbability) = взорваться(" ", Trim($result));
вернуть $InverseProbability;
}
}
?>
Обратите внимание, что путь к исполняемому файлу R задан и используется в обеих функциях. Первая функция возвращает значение вероятности, связанное со статистикой T, на основе распределения T Стьюдента, а вторая обратная функция вычисляет статистику T, соответствующую заданной настройке альфа. Метод getStudentProb используется для оценки соответствия линейной модели; метод getInverseStudentProb возвращает промежуточное значение, которое используется для расчета доверительного интервала для каждого прогнозируемого значения Y.
Из-за ограниченного места я не могу подробно описать все функции этого класса одну за другой, поэтому, если вы хотите разобраться в терминологии и шагах, связанных с простым анализом линейной регрессии, я рекомендую вам обратиться к используемому учебнику по статистике. студентами бакалавриата.
Исследование выгорания
Чтобы продемонстрировать, как использовать этот класс, я могу использовать данные исследования выгорания в утилите. Майкл Лейтер и Кимберли Энн Мичан изучали взаимосвязь между показателем выгорания, называемым индексом утомления, и независимой переменной, называемой концентрацией. Концентрация относится к доле социальных контактов людей, которые происходят в их рабочей среде.
Чтобы изучить взаимосвязь между значениями индекса потребления и значениями концентрации для отдельных лиц в их выборке, загрузите эти значения в массив с соответствующим именем и создайте экземпляр этого класса с этими значениями массива. После создания экземпляра класса отобразите некоторые сводные значения, сгенерированные классом, чтобы оценить, насколько хорошо линейная модель соответствует данным.
В листинге 5 показан скрипт, загружающий данные и отображающий сводные значения:
Листинг 5. Скрипт, загружающий данные и отображающий сводные значения.
<?php
// BurnoutStudy.php
// Авторские права 2003, Пол Мигер.
// Распространяется под лицензией GPL
включить «SimpleLinearReprofit.php»;
// Загрузка данных из исследования выгорания
$Concentration = массив(20,60,38,88,79,87,
68,12,35,70,80,92,
77,86,83,79,75,81,
75,77,77,77,17,85,96);
$ExhaustionIndex = массив(100 525 300 980 310 900,
410 296 120 501 920 810,
506 493 892 527 600 855,
709 791 718 684 141 400 970);
$slr = новый SimpleLinearRegrade($Concentration, $ExhaustionIndex);
$YInt = sprintf($slr->format, $slr->YInt);
$Slope = sprintf($slr->format, $slr->Slope);
$SlopeTVal = sprintf($slr->format, $slr->SlopeTVal);
$SlopeProb = sprintf("%01.6f", $slr->SlopeProb);
?>
<table border='1' cellpadding='5'>
<тр>
<th align='right'>Уравнение:</th>
<тд></тд>
</tr>
<тр>
<th align='right'>T:</th>
<тд></тд>
</tr>
<тр>
<th align='right'>Вероятность > T:</th>
<td><td>
</tr>
</таблица>
Запуск этого сценария через веб-браузер дает следующий результат:
Уравнение: Утомление = -29,50 + (8,87 * Концентрация).
Т: 6.03
Prob > T: 0,000005
Последняя строка этой таблицы указывает на то, что случайная вероятность получения такого большого значения T очень мала. Можно сделать вывод, что простая линейная модель имеет лучшую предсказательную силу, чем простое использование среднего значения значений потребления.
Зная концентрацию связей на рабочем месте, можно использовать для прогнозирования уровня выгорания, который они могут испытывать. Это уравнение говорит нам: на каждую единицу увеличения значения концентрации потребительская ценность человека в сфере социальных услуг увеличится на 8 единиц. Это еще одно свидетельство того, что для снижения потенциального выгорания людям, работающим в социальных службах, следует подумать о том, чтобы завести друзей за пределами своего рабочего места.
Это лишь приблизительный набросок того, что могут означать эти результаты. Чтобы полностью изучить значение этого набора данных, вы можете изучить данные более подробно, чтобы убедиться, что это правильная интерпретация. В следующей статье я расскажу, какие еще анализы следует сдать.
Чему вы научились?
Во-первых, вам не обязательно быть ученым-ракетчиком, чтобы разрабатывать значимые математические пакеты на основе PHP. Придерживаясь стандартных объектно-ориентированных методов и явно применяя методы решения задач обратной цепочки, можно относительно легко использовать PHP для реализации некоторых из наиболее простых статистических процессов.
С точки зрения преподавания я считаю это упражнение очень полезным хотя бы потому, что оно требует от вас размышлений о статистических тестах или процедурах на более высоких и низких уровнях абстракции. Другими словами, отличный способ дополнить статистическое тестирование или процедурное обучение — реализовать процедуру в виде алгоритма.
Реализация статистических тестов часто требует выхода за рамки предоставленной информации и творческого решения и открытия проблем. Это также хороший способ обнаружить пробелы в знаниях по предмету.
С другой стороны, вы обнаружите, что PHP не имеет встроенных средств для выборки распределений, которые необходимы для реализации большинства статистических тестов. Вам нужно будет позволить R выполнить обработку, чтобы получить эти значения, но я боюсь, что у вас не будет времени или интереса для установки R. Эту проблему могут решить собственные реализации PHP некоторых распространенных вероятностных функций.
Другая проблема: класс генерирует множество промежуточных и сводных значений, но сводный вывод на самом деле не использует это преимущество. Я предоставил некоторые громоздкие результаты, но они не являются ни достаточными, ни хорошо организованными, чтобы вы могли адекватно интерпретировать результаты анализа. На самом деле я совершенно не представляю, как можно интегрировать метод вывода в этот класс. Это необходимо решить.
Наконец, для понимания данных требуется нечто большее, чем просто просмотр сводных значений. Вам также необходимо понимать, как распределяются отдельные точки данных. Один из лучших способов сделать это — построить график ваших данных. Опять же, я мало что в этом знаю, но если вы хотите использовать этот класс для анализа реальных данных, вам нужно решить эту проблему.