Introdução
Em comparação com outras linguagens de código aberto, como Perl e Python, a comunidade PHP carece de um grande esforço para desenvolver bibliotecas matemáticas.
Uma razão para isto pode ser que já existe um grande número de ferramentas matemáticas maduras, o que pode dificultar os esforços da comunidade para desenvolver ferramentas PHP por conta própria. Por exemplo, trabalhei em uma ferramenta poderosa, o S System, que tinha um conjunto impressionante de bibliotecas estatísticas, foi projetada especificamente para analisar conjuntos de dados e ganhou um prêmio ACM em 1998 por seu design de linguagem. Se S ou seu primo de código aberto R é apenas uma chamada exec_shell, por que se dar ao trabalho de implementar a mesma funcionalidade de computação estatística em PHP? Para obter mais informações sobre o Sistema S, seu Prêmio ACM, ou R, consulte as referências relacionadas.
Isso não é um desperdício de energia do desenvolvedor? Se a motivação para desenvolver uma biblioteca matemática PHP é economizar o esforço do desenvolvedor e usar a melhor ferramenta para o trabalho, então o tópico atual do PHP faz sentido.
Por outro lado, motivações pedagógicas podem incentivar o desenvolvimento de bibliotecas matemáticas em PHP. Para cerca de 10% das pessoas, a matemática é um assunto interessante que vale a pena explorar. Para aqueles que também são proficientes em PHP, o desenvolvimento de uma biblioteca matemática em PHP pode aprimorar o processo de aprendizagem de matemática. Em outras palavras, não apenas leia o capítulo sobre testes T, mas também implemente um programa que possa calcular o intermediário correspondente. valores e exibi-los em um formato padrão de suas classes.
Através de orientação e treinamento, espero demonstrar que desenvolver uma biblioteca matemática em PHP não é uma tarefa difícil e pode representar um interessante desafio técnico e de aprendizagem. Neste artigo, fornecerei um exemplo de biblioteca matemática PHP, chamada SimpleLinearRegression, que demonstra uma abordagem geral que pode ser usada para desenvolver bibliotecas matemáticas PHP. Vamos começar discutindo alguns princípios gerais que me guiaram no desenvolvimento da classe SimpleLinearRegression.
Princípios Orientadores
Usei seis princípios gerais para orientar o desenvolvimento da classe SimpleLinearRegression.
Crie uma classe para cada modelo de análise.
Use link reverso para desenvolver classes.
Espera-se um grande número de getters.
Armazene resultados intermediários.
Defina preferências para APIs detalhadas.
A perfeição não é o objetivo.
Vamos examinar cada uma dessas diretrizes com mais detalhes.
Crie uma classe para cada modelo de análise.
Cada teste ou processo de análise principal deve ter uma classe PHP com o mesmo nome do teste ou processo. Esta classe contém funções de entrada, funções para calcular valores intermediários e valores de resumo e funções de saída (. substituindo os valores intermediários). Valores e valores resumidos são todos exibidos na tela em formato de texto ou gráfico).
Usando encadeamento reverso para desenvolver classes
Na programação matemática, o alvo de codificação é geralmente o valor de saída padrão que um procedimento de análise (como MultipleRegression, TimeSeries ou ChiSquared) deseja produzir. Do ponto de vista da resolução de problemas, isso significa que você pode usar o encadeamento regressivo para desenvolver métodos semelhantes aos matemáticos.
Por exemplo, a tela de saída resumida exibe os resultados de uma ou mais estatísticas resumidas. Estes resultados estatísticos resumidos baseiam-se no cálculo de resultados estatísticos intermédios, e estes resultados estatísticos intermédios podem envolver resultados estatísticos intermédios mais profundos, e assim por diante. Esta abordagem de desenvolvimento baseada em backlinks leva ao próximo princípio.
Espere um grande número de aulas de matemática getter
. A maior parte do trabalho de desenvolvimento de classe envolve o cálculo de valores intermediários e resumidos. Na prática, isso significa que você não deverá se surpreender se sua classe contiver muitos métodos getter que calculam valores intermediários e resumidos.
Armazenar resultados intermediários
Armazena os resultados de um cálculo intermediário em um objeto de resultado para que você possa usar os resultados intermediários como entrada para cálculos subsequentes. Este princípio é implementado no design da linguagem S. No contexto atual, este princípio é implementado selecionando variáveis de instância para representar valores intermediários calculados e resultados resumidos.
Definindo preferências para uma API detalhada
Ao desenvolver um esquema de nomenclatura para funções-membro e variáveis de instância na classe SimpleLinearRegression, descobri que se eu usasse nomes mais longos (algo como getSumSquaredError em vez de getYY2 ) para descrever as funções-membro e variáveis de instância, então é mais fácil entender o conteúdo da operação da função e o significado das variáveis.
Não abandonei completamente os nomes abreviados; no entanto, quando uso uma forma abreviada de um nome, tenho que tentar fornecer uma nota que explique completamente o significado do nome. Minha opinião é a seguinte: esquemas de nomenclatura altamente abreviados são comuns na programação matemática, mas tornam mais difícil entender e provar que uma determinada rotina matemática está correta do que deveria ser.
A perfeição não é o objetivo
O objetivo deste exercício de codificação não é necessariamente desenvolver um mecanismo matemático altamente otimizado e rigoroso para PHP. Nas fases iniciais, a ênfase deve ser colocada na aprendizagem para implementar testes analíticos significativos e na resolução de problemas difíceis nesta área.
Variáveis de instância
Ao modelar um teste ou processo estatístico, você precisa indicar quais variáveis de instância são declaradas.
A seleção das variáveis de instância pode ser determinada contabilizando os valores intermediários e resumidos gerados pelo processo de análise. Cada valor intermediário e de resumo pode ter uma variável de instância correspondente, com o valor da variável como uma propriedade do objeto.
Usei essa análise para determinar quais variáveis declarar para a classe SimpleLinearRegression na Listagem 1. Análise semelhante pode ser realizada em procedimentos MultipleRegression, ANOVA ou TimeSeries.
Listagem 1. Variáveis de instância da classe SimpleLinearRegression
<?php
// Direitos autorais 2003, Paul Meagher
// Distribuído sob GPL
classeRegressãoLinearSimples {
var$n;
var$X=array();
var $Y = array();
var $ConfInt;
var $Alfa;
var $XMédia;
var $YMean;
var $SomaXX;
var $SomaXY;
var $SomaYY;
var $Inclinação;
var $YInt;
var $PreditoY = array();
var $Erro = array();
var $SquaredError = array();
var $TotalError;
var $SumError;
var $SumSquaredError;
var $ErroVariance;
var $StdErr;
var $InclinaçãoStdErr;
var $SlopeVal; // valor T da inclinação
var $YIntStdErr;
var $YIntTVal; // valor T para interceptação Y
var$R;
var $RSquared;
var $DF; // Graus de liberdade
var $SlopeProb; // Probabilidade de estimativa de inclinação
var $YIntProb; // Probabilidade da estimativa de interceptação Y
var $AlphaTVal; // Valor T para determinada configuração alfa
var $ConfIntOfSlope;
var $RPath = "/usr/local/bin/R"; // Seu caminho aqui
var $format = "%01.2f"; // Usado para formatar a saída
}
?>
Construtor
O método construtor da classe SimpleLinearRegression aceita um vetor X e um vetor Y, cada um com o mesmo número de valores. Você também pode definir um intervalo de confiança padrão de 95% para o valor Y esperado.
O método construtor começa verificando se o formulário de dados é adequado para processamento. Depois que os vetores de entrada passam nos testes de "tamanho igual" e "valor maior que 1", a parte central do algoritmo é executada.
A execução desta tarefa envolve o cálculo dos valores intermediários e resumidos do processo estatístico por meio de uma série de métodos getter. Atribua o valor de retorno de cada chamada de método a uma variável de instância da classe. Armazenar os resultados dos cálculos dessa forma garante que os valores intermediários e resumidos estejam disponíveis para chamar rotinas em cálculos encadeados. Você também pode exibir esses resultados chamando o método de saída desta classe, conforme descrito na Listagem 2.
Listagem 2. Chamando métodos de saída de classe
<?php
// Direitos autorais 2003, Paul Meagher
// Distribuído sob GPL
função SimpleLinearRegression($X, $Y, $ConfidenceInterval="95") {
$numX = contagem($X);
$numY = contagem($Y);
if ($numX != $numY) {
die("Erro: O tamanho dos vetores X e Y deve ser o mesmo.");
}
if ($numX <= 1) {
die("Erro: O tamanho do array de entrada deve ser pelo menos 2.");
}
$isto->n = $numX;
$isto->X = $X;
$isto->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->Inclinação = $this->getSlope();
$this->YInt = $this->getYInt();
$this->PredictedY = $this->getPredictedY();
$this->Erro = $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();
retornar verdadeiro;
}
?>
Os nomes dos métodos e suas sequências foram derivados através de uma combinação de backlinking e referência a um livro de estatística usado por estudantes de graduação, que explica passo a passo como calcular valores intermediários. O nome do valor intermediário que preciso calcular é prefixado com "get", derivando assim o nome do método.
Ajustar o modelo aos dados
O procedimento SimpleLinearRegression é usado para produzir um ajuste de linha reta aos dados, onde a linha tem a seguinte equação padrão:
y = b + mx
O formato PHP desta equação é semelhante à Listagem 3:
Listagem 3. Ajustar o modelo à equação PHP de correspondência de dados
$PredictedY[$i] = $YIntercept + $Slope * $X[$i]
A classe SimpleLinearRegression usa o critério de mínimos quadrados para derivar estimativas dos parâmetros de interceptação Y (Y Intercept) e inclinação (Slope). Esses parâmetros estimados são usados para construir uma equação linear (ver Listagem 3) que modela a relação entre os valores de X e Y.
Usando a equação linear derivada, você pode obter o valor Y previsto para cada valor X. Se a equação linear se ajusta bem aos dados, então os valores observados e previstos de Y tendem a ser consistentes.
Como determinar se há um bom ajuste
A classe SimpleLinearRegression gera alguns valores de resumo. Um valor resumido importante é a estatística T, que mede quão bem uma equação linear se ajusta aos dados. Se a concordância for muito boa, a estatística T tenderá a ser grande. Se a estatística T for pequena, então a equação linear deve ser substituída por um modelo que assume que a média dos valores de Y é o melhor preditor (ou seja, a média de um conjunto de valores geralmente é um preditor útil da próxima observação, torne-o o modelo padrão).
Para testar se a estatística T é grande o suficiente para não considerar a média dos valores de Y como o melhor preditor, é necessário calcular a probabilidade aleatória de obter a estatística T. Se a probabilidade de obter uma estatística T for baixa, então você pode rejeitar a hipótese nula de que a média é o melhor preditor e, consequentemente, ter certeza de que o modelo linear simples se ajusta bem aos dados.
Então, como calcular a probabilidade do valor da estatística T?
Calculando a probabilidade do valor da estatística T
Como o PHP não possui rotinas matemáticas para calcular a probabilidade do valor da estatística T, decidi deixar esta tarefa para o pacote de computação estatística R (consulte www.r-project.org em Recursos) para obtenha os valores necessários. Também quero chamar a atenção para este pacote porque:
R fornece muitas ideias que um desenvolvedor PHP pode emular em uma biblioteca matemática PHP.
Com R, é possível determinar se os valores obtidos na biblioteca matemática PHP são consistentes com aqueles obtidos em pacotes estatísticos de código aberto maduros e disponíveis gratuitamente.
O código na Listagem 4 demonstra como é fácil deixar para R obter um valor.
Listagem 4. Tratamento para o pacote estatístico R para obter um valor
<?php
// Direitos autorais 2003, Paul Meagher
// Distribuído sob GPL
classeRegressãoLinearSimples {
var $RPath = "/usr/local/bin/R"; // Seu caminho aqui
function getStudentProb($T, $df) {
$Probabilidade = 0,0;
$cmd = "echo 'dt($T, $df)' | $this->RPath --slave";
$resultado = shell_exec($cmd);
list($LineNumber, $Probabilidade) = explode(" ", trim($resultado));
retornar $Probabilidade;
}
function getInverseStudentProb($alfa, $df) {
$ProbabilidadeInversa = 0,0;
$cmd = "echo 'qt($alpha, $df)' | $this->RPath --slave";
$resultado = shell_exec($cmd);
list($LineNumber, $InverseProbability) = explode(" ", trim($resultado));
retornar $ProbabilidadeInversa;
}
}
?>
Observe que o caminho para o executável R foi definido e usado em ambas as funções. A primeira função retorna o valor de probabilidade associado à estatística T com base na distribuição T de Student, enquanto a segunda função inversa calcula a estatística T correspondente à configuração alfa fornecida. O método getStudentProb é usado para avaliar o ajuste do modelo linear. O método getInverseStudentProb retorna um valor intermediário, que é usado para calcular o intervalo de confiança para cada valor Y previsto.
Devido ao espaço limitado, é impossível detalhar todas as funções desta classe uma por uma, portanto, se você quiser descobrir a terminologia e as etapas envolvidas na análise de regressão linear simples, recomendo que você consulte o livro de estatística usado por estudantes de graduação.
Estudo de Burnout
Para demonstrar como usar esta classe, posso usar dados de um estudo de burnout em uma concessionária. Michael Leiter e Kimberly Ann Meechan estudaram a relação entre uma medida de burnout chamada Índice de Exaustão e uma variável independente chamada Concentração. A concentração refere-se à proporção de contatos sociais das pessoas provenientes do seu ambiente de trabalho.
Para estudar a relação entre os valores do índice de consumo e os valores de concentração para indivíduos em sua amostra, carregue esses valores em um array com nome apropriado e instancie essa classe com esses valores do array. Após instanciar uma classe, exiba alguns valores resumidos gerados pela classe para avaliar quão bem o modelo linear se ajusta aos dados.
A Listagem 5 mostra um script que carrega dados e exibe valores resumidos:
Listagem 5. Script que carrega dados e exibe valores resumidos
<?php
//BurnoutStudy.php
// Direitos autorais 2003, Paul Meagher
// Distribuído sob GPL
inclua "SimpleLinearRegression.php";
// Carrega dados do estudo de burnout
$Concentração = array(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 = array(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($Concentração, $ExhaustionIndex);
$YInt = sprintf($slr->formato, $slr->YInt);
$Inclinação = sprintf($slr->formato, $slr->Inclinação);
$SlopeTVal = sprintf($slr->formato, $slr->SlopeTVal);
$SlopeProb = sprintf("%01.6f", $slr->SlopeProb);
?>
<borda da tabela='1' cellpadding='5'>
<tr>
<th align='right'>Equação:</th>
<td></td>
</tr>
<tr>
<thalign='right'>T:</th>
<td></td>
</tr>
<tr>
<th align='right'>Problema > T:</th>
<td><td>
</tr>
</tabela>
A execução deste script por meio de um navegador da web produz a seguinte saída:
Equação: Exaustão = -29,50 + (8,87 * Concentração)
T: 6,03
Prob > T: 0,000005
A última linha desta tabela indica que a probabilidade aleatória de obter um valor T tão grande é muito baixa. Pode-se concluir que um modelo linear simples tem melhor poder preditivo do que simplesmente utilizar a média dos valores de consumo.
Conhecer a concentração de conexões no local de trabalho de alguém pode ser usado para prever o nível de esgotamento que essa pessoa pode estar consumindo. Esta equação nos diz: para cada aumento de 1 unidade no valor de concentração, o valor de consumo de uma pessoa na área de serviço social aumentará em 8 unidades. Esta é mais uma prova de que, para reduzir o potencial esgotamento, os indivíduos que trabalham nos serviços sociais devem considerar fazer amigos fora do seu local de trabalho.
Este é apenas um esboço do que esses resultados podem significar. Para explorar completamente as implicações deste conjunto de dados, você pode querer estudar os dados com mais detalhes para ter certeza de que esta é a interpretação correta. No próximo artigo discutirei quais outras análises devem ser realizadas.
O que você aprendeu?
Por um lado, você não precisa ser um cientista espacial para desenvolver pacotes matemáticos significativos baseados em PHP. Aderindo às técnicas padrão orientadas a objetos e adotando explicitamente métodos de resolução de problemas de encadeamento reverso, é relativamente fácil usar PHP para implementar alguns dos processos estatísticos mais básicos.
Do ponto de vista didático, acho que este exercício é muito útil, até porque exige que você pense em testes estatísticos ou rotinas em níveis mais altos e mais baixos de abstração. Em outras palavras, uma ótima maneira de complementar seus testes estatísticos ou aprendizado processual é implementar o procedimento como um algoritmo.
A implementação de testes estatísticos muitas vezes exige ir além das informações fornecidas e da resolução e descoberta criativa de problemas. Também é uma boa forma de descobrir lacunas no conhecimento sobre um assunto.
Por outro lado, você descobre que o PHP carece de meios inerentes para amostragem de distribuições, o que é necessário para implementar a maioria dos testes estatísticos. Você precisará deixar o R fazer o processamento para obter esses valores, mas temo que você não terá tempo ou interesse para instalar o R. Implementações nativas em PHP de algumas funções de probabilidade comuns podem resolver esse problema.
Outro problema: a classe gera muitos valores intermediários e resumidos, mas a saída resumida na verdade não tira vantagem disso. Forneci alguns resultados complicados, mas não são suficientes nem bem organizados para que você possa interpretar adequadamente os resultados da análise. Na verdade, não tenho absolutamente nenhuma ideia de como posso integrar o método de saída nesta classe. Isto precisa ser resolvido.
Finalmente, compreender os dados requer mais do que apenas observar os valores resumidos. Você também precisa entender como os pontos de dados individuais são distribuídos. Uma das melhores maneiras de fazer isso é representar graficamente seus dados. Novamente, não sei muito sobre isso, mas se quiser usar essa classe para analisar dados reais, você precisa resolver esse problema.