Introducción
En comparación con otros lenguajes de código abierto como Perl y Python, la comunidad PHP carece de un gran esfuerzo para desarrollar bibliotecas matemáticas.
Una razón para esto puede ser que ya existe una gran cantidad de herramientas matemáticas maduras, lo que puede obstaculizar los esfuerzos de la comunidad para desarrollar herramientas PHP por sí mismas. Por ejemplo, trabajé en una poderosa herramienta, S System, que tenía un impresionante conjunto de bibliotecas estadísticas, fue diseñada específicamente para analizar conjuntos de datos y ganó un premio ACM en 1998 por su diseño de lenguaje. Si S o su primo de código abierto R es solo una llamada a exec_shell, ¿por qué tomarse la molestia de implementar la misma funcionalidad de computación estadística en PHP? Para obtener más información sobre S System, su ACM Award o R, consulte las referencias relacionadas.
¿No es esto un desperdicio de energía para los desarrolladores? Si la motivación para desarrollar una biblioteca matemática PHP es ahorrar esfuerzo al desarrollador y utilizar la mejor herramienta para el trabajo, entonces el tema actual de PHP tiene sentido.
Por otro lado, las motivaciones pedagógicas pueden fomentar el desarrollo de bibliotecas matemáticas PHP. Para aproximadamente el 10% de las personas, las matemáticas son un tema interesante que vale la pena explorar. Para aquellos que también dominan PHP, el desarrollo de una biblioteca matemática PHP puede mejorar el proceso de aprendizaje de matemáticas. En otras palabras, no solo lea el capítulo sobre pruebas T, sino que también implemente un programa que pueda calcular el intermedio correspondiente. valores y mostrarlos en un formato estándar en sus clases.
A través de orientación y capacitación, espero demostrar que desarrollar una biblioteca matemática PHP no es una tarea difícil y puede representar un desafío técnico y de aprendizaje interesante. En este artículo, proporcionaré un ejemplo de biblioteca matemática PHP, llamado SimpleLinearRegression, que demuestra un enfoque general que se puede utilizar para desarrollar bibliotecas matemáticas PHP. Comencemos analizando algunos principios generales que me guiaron en el desarrollo de la clase SimpleLinearRegression.
Principios rectores
Utilicé seis principios generales para guiar el desarrollo de la clase SimpleLinearRegression.
Cree una clase para cada modelo de análisis.
Utilice enlaces inversos para desarrollar clases.
Se espera una gran cantidad de captadores.
Almacenar resultados intermedios.
Establezca preferencias para API detalladas.
La perfección no es el objetivo.
Examinemos cada una de estas pautas con más detalle.
Cree una clase para cada modelo de análisis.
Cada prueba o proceso de análisis principal debe tener una clase PHP con el mismo nombre que la prueba o el proceso. Esta clase contiene funciones de entrada, funciones para calcular valores intermedios y valores de resumen, y funciones de salida (. reemplazando los valores intermedios). Los valores y los valores de resumen se muestran todos en la pantalla en formato de texto o gráfico).
Uso del encadenamiento inverso para desarrollar clases
En programación matemática, el objetivo de codificación suele ser el valor de salida estándar que un procedimiento de análisis (como MultipleRegression, TimeSeries o ChiSquared) desea producir. Desde una perspectiva de resolución de problemas, esto significa que puede utilizar el encadenamiento hacia atrás para desarrollar métodos similares a los matemáticos.
Por ejemplo, la pantalla de resultados de resumen muestra los resultados de una o más estadísticas de resumen. Estos resultados estadísticos resumidos se basan en el cálculo de resultados estadísticos intermedios, y estos resultados estadísticos intermedios pueden implicar resultados estadísticos intermedios más profundos, y así sucesivamente. Este enfoque de desarrollo basado en vínculos de retroceso conduce al siguiente principio.
Espere una gran cantidad de
clases de matemáticas getter. La mayor parte del trabajo de desarrollo de la clase implica calcular valores intermedios y resumidos. En la práctica, esto significa que no debería sorprenderse si su clase contiene muchos métodos getter que calculan valores intermedios y de resumen.
Almacenamiento de resultados intermedios
Almacena los resultados de un cálculo intermedio dentro de un objeto de resultado para que pueda utilizar los resultados intermedios como entrada para cálculos posteriores. Este principio se implementa en el diseño del lenguaje S. En el contexto actual, este principio se implementa seleccionando variables de instancia para representar valores intermedios calculados y resultados resumidos.
Establecer preferencias para una API detallada
Al desarrollar un esquema de nombres para las funciones miembro y variables de instancia en la clase SimpleLinearRegression, descubrí que si usaba nombres más largos (algo como getSumSquaredError en lugar de getYY2) para describir las funciones miembro y las variables de instancia, entonces Es más fácil comprender el contenido de la operación de la función y el significado de las variables.
No he abandonado por completo los nombres abreviados; sin embargo, cuando uso una forma abreviada de un nombre, tengo que intentar proporcionar una nota que explique completamente el significado del nombre. Mi opinión es la siguiente: los esquemas de denominación muy abreviados son comunes en la programación matemática, pero hacen que sea más difícil de entender y demostrar que una determinada rutina matemática es correcta de lo necesario.
La perfección no es el objetivo
El objetivo de este ejercicio de codificación no es necesariamente desarrollar un motor matemático riguroso y altamente optimizado para PHP. En las primeras etapas, se debe poner énfasis en aprender a implementar pruebas analíticas significativas y resolver problemas difíciles en esta área.
Variables de instancia
Al modelar una prueba o proceso estadístico, es necesario indicar qué variables de instancia se declaran.
La selección de variables de instancia se puede determinar teniendo en cuenta los valores intermedios y resumidos generados por el proceso de análisis. Cada valor intermedio y de resumen puede tener una variable de instancia correspondiente, con el valor de la variable como una propiedad del objeto.
Utilicé este análisis para determinar qué variables declarar para la clase SimpleLinearRegression en el Listado 1. Se pueden realizar análisis similares en procedimientos de Regresión múltiple, ANOVA o Serie temporal.
Listado 1. Variables de instancia de la clase SimpleLinearRegression
<?php
// Derechos de autor 2003, Paul Meagher
// Distribuido bajo GPL
clase Regresión Lineal Simple {
var$n;
var $X = matriz();
var $Y = matriz();
var $ConfInt;
var $Alfa;
var $XMedia;
var $YMedia;
var $SumaXX;
var $SumaXY;
var $SumaAA;
var $Pendiente;
var$YInt;
var $PredictedY = matriz();
var $Error = matriz();
var $SquaredError = matriz();
var $ErrorTotal;
var $SumaError;
var $SumaCuadradaError;
var $ErrorVarianza;
var$StdErr;
var $PendienteStdErr;
var $PendienteVal; // Valor T de Pendiente
var$YIntStdErr;
var $YIntTVal; // valor T para la intercepción Y
var$R;
var $RScuadrado;
var $DF; // Grados de libertad
var $SlopeProb // Probabilidad de estimación de pendiente
var $YIntProb; // Estimación de probabilidad de intersección en Y
var $AlphaTVal; // Valor T para la configuración alfa dada
var $ConfIntOfSlope;
var $RPath = "/usr/local/bin/R" // Tu ruta aquí
var $format = "%01.2f"; // Usado para formatear la salida
}
?>
Constructor
El método constructor de la clase SimpleLinearRegression acepta un vector X e Y, cada uno con el mismo número de valores. También puede establecer un intervalo de confianza predeterminado del 95% para su valor Y esperado.
El método constructor comienza verificando que el formulario de datos sea adecuado para su procesamiento. Una vez que los vectores de entrada pasan las pruebas de "igual tamaño" y "valor mayor que 1", se ejecuta la parte central del algoritmo.
Realizar esta tarea implica calcular los valores intermedios y resumidos del proceso estadístico a través de una serie de métodos getter. Asigne el valor de retorno de cada llamada al método a una variable de instancia de la clase. Almacenar los resultados de los cálculos de esta manera garantiza que los valores intermedios y resumidos estén disponibles para llamar a rutinas en cálculos encadenados. También puede mostrar estos resultados llamando al método de salida de esta clase, como se describe en el Listado 2.
Listado 2. Llamar a métodos de salida de clase
<?php
// Derechos de autor 2003, Paul Meagher
// Distribuido bajo GPL
función SimpleLinearRegression($X, $Y, $ConfidenceInterval="95") {
$numX = contar($X);
$numY = recuento($Y);
si ($numX != $numY) {
die("Error: el tamaño de los vectores X e Y debe ser el mismo.");
}
si ($numX <= 1) {
die("Error: el tamaño de la matriz de entrada debe ser al menos 2.");
}
$this->n = $numX;
$esto->X = $X;
$esto->Y = $Y;
$this->ConfInt = $Interval de confianza;
$this->Alpha = (1 + ($this->ConfInt / 100) ) / 2;
$esto->XMean = $esto->getMean($esto->X);
$this->YMean = $this->getMean($this->Y);
$this->SumXX = $this->getSumXX();
$this->SumYY = $this->getSumYY();
$this->SumXY = $this->getSumXY();
$this->Pendiente = $this->getPendiente();
$esto->YInt = $esto->getYInt();
$this->PredictedY = $this->getPredictedY();
$esto->Error = $esto->getError();
$this->SquaredError = $this->getSquaredError();
$this->SumError = $this->getSumError();
$this->TotalError = $this->getTotalError();
$this->SumSquaredError = $this->getSumSquaredError();
$this->ErrorVariance = $this->getErrorVariance();
$esto->StdErr = $esto->getStdErr();
$this->SlopeStdErr = $this->getSlopeStdErr();
$esto->YIntStdErr = $esto->getYIntStdErr();
$this->SlopeTVal = $this->getSlopeTVal();
$esto->YIntTVal = $esto->getYIntTVal();
$esto->R = $esto->getR();
$esto->RSquared = $esto->getRSquared();
$esto->DF = $esto->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();
devolver verdadero;
}
?>
Los nombres de los métodos y sus secuencias se obtuvieron mediante una combinación de vínculos de retroceso y referencias a un libro de texto de estadística utilizado por estudiantes universitarios, que explica paso a paso cómo calcular valores intermedios. El nombre del valor intermedio que necesito calcular tiene el prefijo "get", derivando así el nombre del método.
Ajustar el modelo a los datos
El procedimiento SimpleLinearRegression se utiliza para producir un ajuste de línea recta a los datos, donde la línea tiene la siguiente ecuación estándar:
y = b + mx
El formato PHP de esta ecuación es similar al Listado 3:
Listado 3. Ajustar el modelo a los datos Coincidir con la ecuación PHP
$PredichoY[$i] = $YIntercepto + $Pendiente * $X[$i]
La clase SimpleLinearRegression utiliza el criterio de mínimos cuadrados para derivar estimaciones de los parámetros de intersección en Y (Y Intercept) y pendiente (Pendiente). Estos parámetros estimados se utilizan para construir una ecuación lineal (ver Listado 3) que modela la relación entre los valores X e Y.
Utilizando la ecuación lineal derivada, puede obtener el valor Y previsto para cada valor X. Si la ecuación lineal se ajusta bien a los datos, entonces los valores observados y predichos de Y tienden a ser consistentes.
Cómo determinar si hay un buen ajuste
La clase SimpleLinearRegression genera bastantes valores de resumen. Un valor resumido importante es el estadístico T, que mide qué tan bien se ajusta una ecuación lineal a los datos. Si el acuerdo es muy bueno, el estadístico T tenderá a ser grande. Si el estadístico T es pequeño, entonces la ecuación lineal debe reemplazarse con un modelo que suponga que la media de los valores de Y es el mejor predictor (es decir, la media de un conjunto de valores suele ser un predictor útil de la siguiente observación, conviértalo en el modelo predeterminado).
Para probar si el estadístico T es lo suficientemente grande como para no considerar la media de los valores de Y como el mejor predictor, es necesario calcular la probabilidad aleatoria de obtener el estadístico T. Si la probabilidad de obtener un estadístico T es baja, entonces se puede rechazar la hipótesis nula de que la media es el mejor predictor y, en consecuencia, tener confianza en que el modelo lineal simple se ajusta bien a los datos.
Entonces, ¿cómo calcular la probabilidad del valor estadístico T?
Calcular la probabilidad del valor del estadístico T
Dado que PHP carece de rutinas matemáticas para calcular la probabilidad del valor del estadístico T, decidí dejar esta tarea al paquete de computación estadística R (ver www.r-project.org en Recursos) para obtener los valores necesarios. También quiero llamar la atención sobre este paquete porque:
R proporciona muchas ideas que un desarrollador de PHP podría emular en una biblioteca matemática de PHP.
Con R, es posible determinar si los valores obtenidos de la biblioteca matemática PHP son consistentes con los obtenidos de paquetes estadísticos de código abierto maduros y disponibles gratuitamente.
El código del Listado 4 demuestra lo fácil que es dejar que R obtenga un valor.
Listado 4. Manejándolo en el paquete estadístico R para obtener un valor
<?php
// Derechos de autor 2003, Paul Meagher
// Distribuido bajo GPL
clase Regresión Lineal Simple {
var $RPath = "/usr/local/bin/R" // Tu ruta aquí
función obtenerProbEstudiante($T, $df) {
$Probabilidad = 0,0;
$cmd = "echo 'dt($T, $df)' | $this->RPath --slave";
$resultado = shell_exec($cmd);
lista($Número de línea, $Probabilidad) = explotar(" ", recortar($resultado));
devolver $Probabilidad;
}
función getInverseStudentProb($alfa, $df) {
$ProbabilidadInversa = 0.0;
$cmd = "echo 'qt($alpha, $df)' | $this->RPath --slave";
$resultado = shell_exec($cmd);
lista ($Número de línea, $Probabilidad inversa) = explotar(" ", recortar($resultado));
devolver $ProbabilidadInversa;
}
}
?>
Tenga en cuenta que la ruta al ejecutable de R se ha configurado y utilizado en ambas funciones. La primera función devuelve el valor de probabilidad asociado con la estadística T según la distribución T de Student, mientras que la segunda función inversa calcula la estadística T correspondiente a la configuración alfa dada. El método getStudentProb se utiliza para evaluar el ajuste del modelo lineal; el método getInverseStudentProb devuelve un valor intermedio, que se utiliza para calcular el intervalo de confianza para cada valor Y predicho.
Debido al espacio limitado, me resulta imposible detallar todas las funciones de esta clase una por una, por lo que si desea comprender la terminología y los pasos involucrados en el análisis de regresión lineal simple, le recomiendo que consulte el libro de texto de estadística utilizado. por estudiantes de pregrado.
Estudio de agotamiento
Para demostrar cómo utilizar esta clase, puedo utilizar datos de un estudio de agotamiento en una utilidad. Michael Leiter y Kimberly Ann Meechan estudiaron la relación entre una medida de agotamiento llamada índice de agotamiento y una variable independiente llamada concentración. La concentración se refiere a la proporción de contactos sociales de las personas que provienen de su entorno laboral.
Para estudiar la relación entre los valores del índice de consumo y los valores de concentración para los individuos de su muestra, cargue estos valores en una matriz con el nombre apropiado y cree una instancia de esta clase con estos valores de la matriz. Después de crear una instancia de una clase, muestre algunos valores resumidos generados por la clase para evaluar qué tan bien se ajusta el modelo lineal a los datos.
El Listado 5 muestra un script que carga datos y muestra valores resumidos:
Listado 5. Script que carga datos y muestra valores resumidos
<?php
// BurnoutStudy.php
// Derechos de autor 2003, Paul Meagher
// Distribuido bajo GPL
incluir "SimpleLinearRegression.php";
// Cargar datos del estudio de agotamiento
$Concentración = matriz(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);
$Índice de agotamiento = matriz(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 = new SimpleLinearRegression($Concentración, $ExhaustionIndex);
$YInt = sprintf($slr->formato, $slr->YInt);
$Pendiente = sprintf($slr->formato, $slr->Pendiente);
$PendienteTVal = sprintf($slr->formato, $slr->PendienteTVal);
$PendienteProb = sprintf("%01.6f", $slr->PendienteProb);
?>
<borde de tabla='1' cellpadding='5'>
<tr>
<th align='right'>Ecuación:</th>
<td></td>
</tr>
<tr>
<th align='right'>T:</th>
<td></td>
</tr>
<tr>
<th align='right'>Problema > T:</th>
<td><td>
</tr>
</tabla>
La ejecución de este script a través de un navegador web produce el siguiente resultado:
Ecuación: Agotamiento = -29,50 + (8,87 * Concentración)
T: 6,03
Prob > T: 0.000005
La última fila de esta tabla indica que la probabilidad aleatoria de obtener un valor T tan grande es muy baja. Se puede concluir que un modelo lineal simple tiene mejor poder predictivo que simplemente usar la media de los valores de consumo.
Conocer la concentración de conexiones en el lugar de trabajo de una persona puede usarse para predecir el nivel de agotamiento que puede estar consumiendo. Esta ecuación nos dice: por cada aumento de 1 unidad en el valor de concentración, el valor de consumo de una persona en el campo de los servicios sociales aumentará en 8 unidades. Esta es una prueba más de que, para reducir el posible agotamiento, las personas que trabajan en servicios sociales deberían considerar hacer amigos fuera de su lugar de trabajo.
Esto es sólo un esbozo de lo que podrían significar estos resultados. Para explorar completamente las implicaciones de este conjunto de datos, es posible que desee estudiar los datos con más detalle para asegurarse de que esta sea la interpretación correcta. En el próximo artículo discutiré qué otros análisis deben realizarse.
¿Qué aprendiste?
Por un lado, no es necesario ser un científico espacial para desarrollar paquetes matemáticos significativos basados en PHP. Al adherirse a técnicas estándar orientadas a objetos y adoptar explícitamente métodos de resolución de problemas de encadenamiento inverso, es relativamente fácil usar PHP para implementar algunos de los procesos estadísticos más básicos.
Desde el punto de vista didáctico, creo que este ejercicio es muy útil, aunque sólo sea porque requiere pensar en pruebas o rutinas estadísticas en niveles superiores e inferiores de abstracción. En otras palabras, una excelente manera de complementar sus pruebas estadísticas o aprendizaje de procedimientos es implementar el procedimiento como un algoritmo.
La implementación de pruebas estadísticas a menudo requiere ir más allá de la información proporcionada y la resolución y el descubrimiento creativos de problemas. También es una buena manera de descubrir lagunas en el conocimiento sobre un tema.
En el lado negativo, encontrará que PHP carece de medios inherentes para las distribuciones de muestreo, lo cual es necesario para implementar la mayoría de las pruebas estadísticas. Deberá dejar que R realice el procesamiento para obtener estos valores, pero me temo que no tendrá el tiempo ni el interés para instalar R. Las implementaciones nativas de PHP de algunas funciones de probabilidad comunes pueden resolver este problema.
Otro problema: la clase genera muchos valores intermedios y de resumen, pero el resultado del resumen en realidad no aprovecha esto. He proporcionado algunos resultados difíciles de manejar, pero no son suficientes ni están bien organizados para que usted pueda interpretar adecuadamente los resultados del análisis. En realidad, no tengo ni idea de cómo puedo integrar el método de salida en esta clase. Es necesario abordar esto.
Finalmente, dar sentido a los datos requiere algo más que mirar los valores resumidos. También es necesario comprender cómo se distribuyen los puntos de datos individuales. Una de las mejores formas de hacer esto es graficar sus datos. Nuevamente, no sé mucho sobre esto, pero si desea utilizar esta clase para analizar datos reales, debe resolver este problema.