Julho de 2015

Número 7 do Volume 30

Execução de teste - Regressão Linear Usando C#

Por James McCaffrey

James McCaffreyO objetivo de um problema de regressão linear é prever o valor de uma variável numérica com base nos valores de uma ou mais variáveis de previsão numéricas. Por exemplo, você talvez queira prever a renda anual de uma pessoa com base em seu nível de escolaridade, anos de experiência profissional e sexo (masculino = 0, feminino = 1).

A variável a ser prevista normalmente é chamada de variável dependente. As variáveis de previsão geralmente são chamadas de variáveis independentes. Quando há apenas uma única variável de previsão, algumas vezes a técnica é chamada de regressão linear simples. Quando houver duas ou mais variáveis de previsão, a técnica é geralmente chamada de regressão linear múltipla ou multivariada.

A melhor maneira de saber o rumo que este artigo tomará é examinar o programa de demonstração na Figura 1. O programa de demonstração em C# prevê a renda anual com base em grau de instrução, trabalho e sexo. A demonstração começa gerando 10 itens de dados sintéticos. O nível de escolaridade é um valor entre 12 e 16. A experiência profissional é um valor entre 10 e 30. O sexo é uma variável de indicador em que masculino é o valor de referência, codificado como 0, e feminino é codificado como 1. A renda, em milhares de dólares, está na última coluna. Fora de um cenário de demonstração, você provavelmente poderia ler dados de um arquivo de texto usando um método com um nome parecido a MatrixLoad.

regressão linear usando C##
Figura 1: regressão linear usando C#

Depois de gerar os dados sintéticos, o programa de demonstração usa os dados para criar uma matriz de design. Uma matriz de design é apenas a matriz de dados com uma coluna à esquerda em que todos os valores de 1,0 são adicionados. Há vários algoritmos diferentes que podem ser usados para regressão linear; alguns podem usar a matriz de dados brutos, enquanto outros usam uma matriz de design. A demonstração usa uma técnica que requer uma matriz de design.

Depois de criar a matriz de design, o programa de demonstração localiza os valores de quatro coeficientes, (12,0157, 1,0180, 0,5489,-2,9566). Algumas vezes, os coeficientes são chamados de valores de b ou valores de beta. O primeiro valor, 12,0157, geralmente é chamado de interceptação. É uma constante não associada a qualquer variável de previsão. O segundo, terceiro e quarto valores de coeficiente (1,0180, 0,5489,-2,9566) são associados ao nível de escolaridade, experiência profissional e sexo, respectivamente.

A última parte da saída da Figura 1 usa os valores dos coeficientes para prever a renda de uma pessoa hipotética que tenha um nível de escolaridade de 14; 12 anos de experiência profissional; e cujo sexo seja 0 (masculino). A resultante para a renda prevista é 32,86, calculada da seguinte forma:

income = 12.0157 + (1.0180)(14) + (0.5489)(12) + (-2.9566)(0)
                = 12.0157 + 14.2520 + 6.5868 + 0
                = 32.86

Em outras palavras, para fazer uma previsão usando regressão linear, os valores de previsão são multiplicados pelos valores do coeficiente correspondente, e somados. É muito simples. Observe que o valor de interceptação principal (12,0157 no exemplo) pode ser considerado um coeficiente associado a uma variável de previsão que sempre tem o valor de 1. Isso explica em parte a coluna de valores 1,0 na matriz de design.

A essência de um problema de regressão linear é calcular os valores dos coeficientes usando dados brutos ou, de maneira equivalente, a matriz de design. Isso não é tão fácil. A demonstração usa uma técnica chamada inversão de matriz de forma fechada, também conhecida como o método comum de quadrados mínimos. As técnicas alternativas para localizar os valores dos coeficientes incluem quadrados mínimos reponderados iterativamente, estimativa de probabilidade máxima, regressão de cume, gradiente descendente e muitas outras.

Na Figura 1, antes que a previsão seja feita, o programa de demonstração computa uma métrica chamada valor R-quadrado, também chamado de coeficiente de determinação. R-quadrado é um valor entre 0 e 1 que descreve como o modelo de previsão se encaixa nos dados brutos. Pode ser que isso seja expresso como "a porcentagem da variação explicada pelo modelo". Interpretado livremente, quanto mais próximo de 1 for o R-quadrado, melhor é o modelo de previsão. O valor de demonstração de 0,7207, ou 72%, seria considerado relativamente alto (bom) para dados do mundo real.

Este artigo pressupõe que você tenha habilidades de programação de C# que sejam, pelo menos, intermediárias, mesmo que não tenha familiaridade alguma com regressão linear. O programa de demonstração é um pouco longo para ser apresentado por completo, mas o código-fonte está disponível no download que acompanha este artigo.

Noções básicas sobre regressão Linear

Geralmente, a melhor maneira de explicar regressão linear é usando um diagrama. Dê uma olhada no gráfico na Figura 2. Os dados no gráfico representam a previsão de renda anual a partir de uma única variável: anos de experiência profissional. Cada ponto vermelho corresponde a um ponto de dados. Por exemplo, o item de dados mais à esquerda tem experiência profissional = 10 e renda = 32,06. A regressão linear localiza dois coeficientes: um de intercepção e outro para a variável de trabalho. Como resultado, os valores dos coeficientes serão 27,00 e 0,43.

regressão Linear com uma variável independente
Figura 2: regressão Linear com uma variável independente

Os valores do coeficiente determinam a equação de uma linha, que é exibida em azul na Figura 2. A linha (os coeficientes) minimiza a soma dos quadrados dos desvios entre os pontos de dados reais (yi) e os pontos de dados previstos (fi). Dois dos 10 desvios são exibidos com linhas pontilhadas na Figura 2. O desvio primeiro mostrado é yi - fi = 28,6 - 32,6 = - 4,0. Observe que os desvios podem ser positivos ou negativos. Se os desvios não estavam ao quadrado, os positivos e negativos podem cancelar um ao outro.

O gráfico na Figura 2 mostra como a regressão linear simples funciona com apenas uma variável independente. A Regressão linear multivariada estende a mesma idéia, encontrar coeficientes que minimizam a soma dos quadrados dos desvios, usando diversas variáveis independentes.

Expressada intuitivamente, a regressão linear localiza a linha melhor por um conjunto de pontos de dados. Essa linha melhor pode ser usada para previsão. Por exemplo, na Figura 2, se uma pessoa hipotética tinha 25 anos de experiência profissional, sua renda prevista na linha azul seria cerca de 38.

Resolvendo a equação dos quadrados mínimos

Se um problema de regressão linear tiver n variáveis de previsão, n + 1 valores de coeficientes devem ser encontrados, um para cada previsão mais o valor de intercepção. O programa de demonstração usa a técnica mais básica para encontrar os valores dos coeficientes. Os valores dos coeficientes são geralmente fornecidos usando a equação um pouco complexa da Figura 3. A equação não é tão complicada como pode parecer.

solução de coeficientes de regressão linear usando matrizes
Figura 3: solução de coeficientes de regressão linear usando matrizes

A letra grega beta é semelhante a um script B e representa os valores dos coeficientes. Observe que todas as letras na equação estão em negrito, o que indica, na matemática, que representam objetos com valores múltiplos (matrizes ou matrizes/vetores) em vez de valores escalares simples (números sem formatação). A letra X maiúscula representa a matriz de design. A letra X maiúscula com um expoente T significa a transposição da matriz de design. O símbolo * significa a multiplicação de matriz. O expoente -1 significa inversão de matriz. O Y maiúsculo é um vetor de coluna (uma matriz com uma coluna) dos valores de variável dependente. Portanto, para solucionar os valores dos coeficientes é realmente preciso compreender operações de matriz.

Os diagramas na Figura 4 ilustram transposição de matriz, multiplicação de matriz e inversão de matriz. A transposição de uma matriz apenas realiza trocas entre linhas e colunas. Por exemplo, se você tem uma matriz de 2x3, ou seja, com 2 linhas e 3 colunas. A transposição da matriz será de 3x2: as linhas da matriz original tornam-se as colunas da matriz transposta.

três operações de matriz usadas para localizar os coeficientes de regressão linear
Figura 4: três operações de matriz usadas para localizar os coeficientes de regressão linear

A multiplicação de matriz pode parecer um pouco estranha se você não tiver encontrado ela antes. Se você multiplicar uma matrix de tamanho (n x m) por uma de matriz de tamanho (m x p), o resultado será uma matriz de tamanho (n x p). Por exemplo, uma matriz de 3x4 * uma de 4x2 terá o tamanho 3x2. Uma discussão detalhada sobre a multiplicação de matrizes sairia fora do escopo deste artigo, mas é fácil de compreender o processo e implementar em código depois de ver alguns exemplos.

A terceira operação de matriz necessária para resolver valores de coeficiente de regressão linear é inversão de matriz, que, infelizmente, é difícil de compreender e difícil de implementar. Para os fins deste artigo, basta saber que o inverso de uma matriz é definido apenas quando a matriz tem o mesmo número de linhas e colunas (uma matriz quadrada). A Figura 4 mostra uma matriz 3x3 e o seu inverso.

Há vários algoritmos que podem ser usados para encontrar o inverso de uma matriz. O programa de demonstração usa uma técnica chamada Decomposição de Doolittle.

Para resumir, um problema de regressão linear com n variáveis de previsão é envolvida na localização dos valores para os coeficientes n + 1. Isso pode ser feito através de transposição de matriz, multiplicação de matriz e inversão de matriz. Tanto transposição quanto multiplicação são fáceis, mas encontrar o inverso de uma matriz é difícil.

A estrutura do programa de demonstração

Para criar o programa de demonstração, eu iniciei o Visual Studio e selecionei o modelo do projeto do aplicativo do console. Nomeei o projeto como LinearRegression. O programa não tem dependências significativas do .NET Framework, portanto, funcionará em qualquer versão do Visual Studio.

Depois de carregar o código do modelo no editor, na janela Gerenciador de Soluções cliquei com o botão direito do mouse no arquivo Program.cs para renomeá-lo como LinearRegressionProgram.cs. Permiti que o Visual Studio renomeasse a classe Programa automaticamente. Na parte superior da janela Editor, exclui tudo usando instruções, exceto o que faz referência ao namespace do Sistema de nível superior.

A estrutura geral do programa de demonstração, com algumas edições secundárias para economizar espaço, é apresentada na Figura 5. Toda a lógica de controle do programa está contida no método Principal. O programa de demonstração usa uma abordagem de método estático ao invés de uma abordagem OOP.

Figura 5: estrutura do programa de demonstração de regressão Linear

using System;
namespace LinearRegression
{
  class LinearRegressionProgram
  {
    static void Main(string[] args)
    {
      Console.WriteLine("Begin linear regression demo");
      // Generate synthetic data
      // Create design matrix
      // Solve for LR coefficients
      // Calculate R-squared value
      // Do a prediction
      Console.WriteLine("End linear regression demo");
      Console.ReadLine();
    }
    static double Income(double x1, double x2,
      double x3, double[] coef) { . . }
    static double RSquared(double[][] data,
      double[] coef) { . . }
    static double[][] DummyData(int rows,
      int seed) { . . }
    static double[][] Design(double[][] data) { . . }
    static double[] Solve(double[][] design) { . . }
    static void ShowMatrix(double[][] m, int dec) { . . }
    static void ShowVector(double[] v, int dec) { . . }
    // ----------
    static double[][] MatrixTranspose(double[][] matrix)
      { . . }
    static double[][] MatrixProduct(double[][] matrixA,
      double[][] matrixB) { . . }
    static double[][] MatrixInverse(double[][] matrix)
      { . . }
    // Other matrix routines here
  }
} // ns

O método Income retorna uma renda prevista de parâmetros de entrada com valores de nível de escolaridade, experiência profissional e sexo, usando uma matriz de valores de coeficientes. O método RSquared retorna o valor de R-quadrado do modelo a partir dos dados e coeficientes. O método DummyData gera os dados sintéticos usados para a demonstração.

O método Design aceita uma matriz de dados e retorna uma matriz de design aumentada com uma coluna à esquerda dos valores de 1,0. O Método Solve aceita uma matriz de design e usa operações de matriz para encontrar os coeficientes de regressão linear.

A maior parte do trabalho pesado é realizado por um conjunto de métodos estáticos que executam operações de matriz. O programa de demonstração define uma matriz da maneira mais simples possível, como uma matriz de matrizes. Uma alternativa seria criar uma classe de matriz definida pelo programa, mas, em minha opinião, essa abordagem é desnecessariamente complicada. Muitas vezes, matrizes comuns são melhores que objetos definidos pelo programa.

O método MatrixTranspose retorna a transposição de uma matriz. O método MatrixProduct retorna o resultado da multiplicação de duas matrizes. O método MatrixInverse retorna o inverso de uma matriz. A demonstração tem muitos métodos auxiliares. Especificamente, o método MatrixInverse chama os métodos auxiliares MatrixDuplicate, MatrixDecompose e HelperSolve.

O método Solve

O método Solve é o coração do programa de demonstração de regressão linear. A definição do método começa com:

static double[] Solve(double[][] design)
{
  int rows = design.Length;
  int cols = data[0].Length;
  double[][] X = MatrixCreate(rows, cols - 1);
  double[][] Y = MatrixCreate(rows, 1);
...

O único parâmetro de entrada é uma matriz de design. Uma abordagem alternativa que talvez você queira considerar é passar a matriz de fonte de dados e, então, fazer Solve chamar o método auxiliar Design para obter a matriz de design. O método auxiliar MatrixCreate aloca espaço para (e retorna) uma matriz com o número especificado de linhas e colunas. A matriz de X local mantém os valores das variáveis independentes (com um valor principal de 1,0). A matriz de Y local tem apenas uma coluna e mantém os valores da variável dependente (na demonstração, renda anual).

Em seguida, as células nas matrizes X e Y são preenchidas com os valores na matriz de design:

int j;
for (int i = 0; i < rows; ++i)
{
  for (j = 0; j < cols - 1; ++j)
  {
    X[i][j] = design[i][j];
  }
  Y[i][0] = design[i][j]; // Last column
}

Observe que esse índice variável j é declarado fora do aninhado para loops, para que possa ser usado para popular a matriz de Y. Com as matrizes X e Y em mãos, os coeficientes de regressão linear podem ser encontrados de acordo com a equação na Figura 3:

...
  double[][] Xt = MatrixTranspose(X);
  double[][] XtX = MatrixProduct(Xt, X);
  double[][] inv = MatrixInverse(XtX);
  double[][] invXt = MatrixProduct(inv, Xt);
  double[][] mResult = MatrixProduct(invXt, Y);
  double[] result = MatrixToVector(mResult);
  return result;
} // Solve

Na demonstração, a matriz X tem o tamanho de 10x4; logo, sua transposta, Xt, tem tamanho 4x10. O produto de Xt e X tem o tamanho de 4x4 e o inverso, inv, também tem o tamanho de 4x4. Em geral, para um problema de regressão linear com n variáveis de previsão independentes, ao usar a técnica de inversão de matriz você precisará localizar o inverso de uma matriz com o tamanho (n + 1) x (n + 1). Isso significa que a técnica de inversão não é adequada para problemas de regressão linear que tenham um grande número de variáveis de previsão.

O produto da matriz inversa 4x4 e a matriz transposta de 4x10, invXt no código, tem tamanho 4x10. O produto de invXt e a matriz de Y de 10x1, mResult ("resultado de matriz") no código, tem tamanho 4x1. Esses valores são os coeficientesnecessários. Para sua conveniência, os valores na matriz de Y de coluna única são transferidos para uma matriz comum usando o método auxiliar MatrixToVector.

Calculando R-quadrado

Conforme observado anteriormente, a métrica R-quadrado é uma medida de quanto os pontos de dados reais se encaixam na linha de regressão computada. Em termos matemáticos, o R-quadrado é definido como R2 = 1 - (SSres / SStot). O termo SSres normalmente é chamado de "soma residual dos quadrados". É a soma dos quadrados das diferenças entre os valores Y reais e os valores Y previstos, conforme ilustrado no gráfico da Figura 2. O termo SStot é a "soma total dos quadrados". É a soma dos quadrados das diferenças entre cada valor de Y real e a média de todos os valores Y reais.

A métrica R-quadrado na regressão linear também é chamada de coeficiente de determinação, e está relacionada (mas é diferente) a outra métrica estatística chamada r-quadrado ("pequeno r-quadrado"). Interpretar R-quadrado é um pouco complicado e depende do domínio do problema específico sob questão. Para as ciências sociais e naturais, em que dados normalmente são confusos e incompletos, um valor R-quadrado de 0,6 ou superior geralmente é considerado muito bom.

Há uma medida alternativa da variação explicada pelo modelo de regressão chamado R-quadrado ajustado. Essa métrica leva em conta o número de variáveis de previsão e o número de itens de dados. Em geral, o valor de R quadrado simples é suficiente para ter uma idéia da qualidade da previsão de um modelo de regressão linear.

Conclusão

Se você pesquisar na Internet para obter exemplos de como executar regressão linear usando uma linguagem de programação, você não encontrará muitas referências. Acredito que há duas razões principais para essa relativa falta de informações. Primeiro, a resolução de coeficientes de regressão linear usando operações de matrizes é bem difícil, principalmente devido à operação de inversão de matriz. De alguma maneira, considero o método MatrixInverse do programa de demonstração uma das rotinas de código mais complicadas que eu já escrevi. Em segundo lugar, existem muitas ferramentas autônomas que podem executar regressão linear, especialmente o programa de planilhas Excel com o suplemento de análise de dados. É relativamente raro precisar incorporar diretamente o código da solução de regressão linear em um sistema de software.

A regressão linear vem sido estudada por décadas e há muitas maneiras de estender a técnica. Por exemplo, você pode introduzir os chamados efeitos de interação, que combinam duas ou mais variáveis de indicador. Por vezes, essas extensões são chamadas de modelos gerais lineares, para distingui-las da forma básica de regressão linear.

Na minha opinião, a regressão linear é a técnica de "Hello World" da estatística clássica. Não há um consenso claro e universal sobre a distinção entre estatística clássica e aprendizado de máquina, mas sou levado entender técnicas estatísticas clássicas como as primeiras estudadas pelos matemáticos no início do século XX. Para mim, técnicas de aprendizagem de máquina (como classificação de rede neural) são as mais recentes, que começaram a aparecer na década de 1950. A regressão linear de estatísticas clássica está intimamente relacionada a uma técnica de aprendizado de máquina chamada regressão logística, que já foi assunto de muitas colunas em Execução de Teste.


Dr. James McCaffrey* trabalha para a Microsoft Research em Redmond, Washington. Ele trabalhou em vários produtos da Microsoft, incluindo Internet Explorer e Bing. Entre em contato com o Dr. McCaffrey pelo email jammc@microsoft.com.*

Agradecemos ao seguinte especialista técnico da Microsoft Research pela revisão deste artigo: Charles Parker