Compartir a través de



Julio de 2015

Volumen 30, número 7

Ejecución de pruebas: regresión lineal con C#

Por James McCaffrey

James McCaffreyEl objetivo de un problema de regresión lineal es predecir el valor de una variable numérica según los valores de una o más variables de predictor numérico. Por ejemplo, quizás busquen predecir los ingresos anuales de una persona basados en su nivel de educación, años de experiencia laboral y sexo (hombre = 0, mujer = 1).

La variable para predecir normalmente se denomina la variable dependiente. Las variables de predictor normalmente se denominan las variables independientes. Cuando hay una variable predictor única, la técnica a veces se denomina regresión lineal simple. Cuando hay dos o más variables de predictor, la técnica suele denominarse regresión lineal múltiple o multivariable.

Una buena manera de ver hacia dónde se dirige este artículo es echar un vistazo al programa de demostración de la figura 1. El programa de demostración de C# predice los ingresos anuales basados en educación, trabajo y sexo. La demostración comienza mediante la generación de 10 elementos de datos sintéticos. El nivel de educación es un valor entre 12 y 16. La experiencia laboral es un valor entre 10 y 30. El sexo es una variable de indicador donde hombre es el valor de referencia, que se codifica como 0, y mujer se codifica como 1. Los ingresos, en miles de dólares estadounidenses, se indican en la última columna. En un escenario que no sea de demostración, probablemente leerían los datos desde un archivo de texto con un método denominado algo como MatrixLoad.

Regresión lineal con C#
Figura 1 Regresión lineal con C#

Después de generar los datos sintéticos, el programa de demostración usa los datos para crear lo que se denomina una matriz de diseño. Una matriz de diseño es la matriz de datos con una columna inicial de todos los valores 1.0 agregados. Existen varios algoritmos que se pueden usar para la regresión lineal; algunos de ellos usan la matriz de datos sin procesar mientras otros usan una matriz de diseño. La demostración usa una técnica que requiere una matriz de diseño.

Después de crear la matriz de diseño, el programa de demostración encuentra los valores de cuatro coeficientes, (12.0157, 1.0180, 0.5489, -2.9566). Los coeficientes a veces se denominan valores b o valores beta. El primer valor, 12.0157, normalmente se denomina el corte. Se trata de una constante que no está asociada a ninguna variable de predictor. Los valores de coeficiente dos, tres y cuatro (1.0180, 0.5489,-2.9566) están asociados con el nivel de educación, la experiencia laboral y el sexo, respectivamente.

En la última parte de la salida de la figura 1 se usan los valores de los coeficientes para predecir los ingresos para una persona hipotética que tiene un nivel de educación de 14, 12 años de experiencia laboral y cuyo sexo es masculino 0 (hombre). Los ingresos previstos son 32.86, que se calculan del modo siguiente:

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

En otras palabras, para hacer una predicción con la regresión lineal, los valores de predictor se multiplican por sus correspondientes valores de coeficiente y luego se suman. Es muy sencillo. Observen que el valor de corte inicial (12.0157, en el ejemplo) puede considerarse un coeficiente asociado a la variable de predictor que siempre tiene un valor de 1. Este hecho, en parte, explica la columna de valores 1.0 en la matriz de diseño.

La esencia de un problema de regresión lineal es calcular los valores de los coeficientes con datos sin procesar o, de forma equivalente, la matriz de diseño. Esto no es tan fácil. La demostración usa una técnica denominada inversión de matriz de formulario cerrado, también conocida como el método normal de mínimos cuadrados. Entre las técnicas alternativas para buscar los valores de los coeficientes se incluyen mínimos cuadrados reponderados iterativos, estimación de probabilidad máxima, regresión de arista, descenso degradado, entre otras.

En la figura 1, antes de que se realice la predicción, el programa de demostración calcula una métrica llamada el valor R cuadrado, que también se denomina el coeficiente de determinación. R cuadrado es un valor entre 0 y 1 que describe lo bien que el modelo de predicción se ajusta a los datos sin procesar. Esto a veces se expresa como, "el porcentaje de variación explicado por el modelo". Una interpretación de esto sería que cuanto más se acerca a 1 el cuadrado R, mejor será el modelo de predicción. El valor de demostración de 0.7207 o del 72 % se consideraría relativamente alto (bueno) para los datos del mundo real.

En este artículo se supone que tienen al menos conocimientos intermedios en la programación de C#, pero no se supone que saben nada acerca de la regresión lineal. El programa de demostración es demasiado largo para presentarlo en su totalidad, pero el código fuente completo está disponible en la descarga que acompaña este artículo.

Descripción de la regresión lineal

La regresión lineal se explica mejor normalmente con un diagrama. Eche un vistazo al gráfico de la Figura 2. Los datos del gráfico representan la predicción de ingresos anuales desde una única variable, años de experiencia laboral. Cada uno de los puntos rojos corresponde a un punto de datos. Por ejemplo, el elemento de datos del extremo izquierdo contiene work = 10 e income = 32.06. La regresión lineal busca dos coeficientes: un corte y otra para la variable de trabajo. Según parece, los valores de los coeficientes son 27.00 y 0.43.

Regresión lineal con una variable independiente
Figura 2 Regresión lineal con una variable independiente

Los valores de coeficiente determinan la ecuación de una línea, que se muestra en azul en la figura 2. La línea (los coeficientes) minimiza la suma de las desviaciones cuadradas entre los puntos de datos reales (yi) y los puntos de datos de predicción (fi). Dos de las 10 desviaciones se muestran con líneas discontinuas en la figura 2. La primera desviación que se muestra es yi - fi = 28.6 - 32.6 = -4.0. Observen que las desviaciones pueden ser positivo o negativo. Si las desviaciones fuesen cuadradas, los valores negativos y positivos se cancelarían entre sí.

En el gráfico de la figura 2 se muestra cómo funciona la regresión lineal sencilla, con solo una variable independiente. La regresión lineal multivariable amplía la misma idea, buscar coeficientes que minimizan la suma de las desviaciones cuadradas, con varias variables independientes.

Expresado de forma intuitiva, la regresión lineal busca la mejor línea a través de un conjunto de puntos de datos. Esta mejor línea se puede para la predicción. Por ejemplo, en la figura 2, si una persona hipotética tenía 25 años de experiencia laboral, sus ingresos previstos en la línea azul serían aproximadamente 38.

Resolver la ecuación de mínimos cuadrados

Si un problema de regresión lineal tiene variables de predictor n, entonces se deben buscar los valores de coeficiente n+1, uno para cada elemento de predicción, más el valor de corte. El programa de demostración usa la técnica más básica para buscar los valores de coeficiente. Los valores de los coeficientes a menudo se dan mediante la ecuación algo abrumadora que se muestra en la figura 3. La ecuación no es tan complicada como podría aparecer inicialmente.

Solución de coeficientes de regresión lineal mediante matrices
Figura 3 Solución de coeficientes de regresión lineal mediante matrices

La letra griega beta es similar a un script B y representa los valores de coeficiente. Observen que todas las letras de la ecuación aparecen en negrita, lo que en matemáticas indica que representan objetos con varios valores (matrices o matrices y vectores) en lugar de valores escalares simples (números sin formato). La X mayúscula representa la matriz de diseño. La X mayúscula con un exponente T significa la transposición de la matriz de diseño. El símbolo * significa la multiplicación de matrices. El exponente -1 significa la inversión de la matriz. La Y mayúscula es un vector de columna (una matriz con una columna) de los valores de variable dependiente. Por lo tanto, resolver los valores de los coeficientes realmente significa comprender las operaciones de matriz.

En los diagramas de la figura 4 se muestra la transposición de matrices, la multiplicación de matrices y la inversión de matrices. La transposición de una matriz simplemente intercambia las filas y columnas. Por ejemplo, supongamos que hay una matriz de 2x3; es decir, una matriz con 2 filas y 3 columnas. La transposición de la matriz será 3x2, donde las filas de la matriz original se convierten en las columnas de la matriz de transposición.

Tres operaciones de matriz que se usan para buscar los coeficientes de regresión lineal
Figura 4 Tres operaciones de matriz que se usan para buscar los coeficientes de regresión lineal

Multiplicación de matrices puede parecer algo extraño si no nunca la han visto. Si se multiplica una matriz de tamaño (n x m) por una matriz de tamaño (m x p), el resultado sería una matriz de tamaño (n x p). Por ejemplo, una matriz de 3x4 * de 4x2 tiene el tamaño 3x2. Un análisis detallado sobre la multiplicación de matrices está fuera del ámbito de este artículo, pero cuando hayan visto algunos ejemplos, el proceso es fácil de comprender y de implementar en el código.

La tercera operación de matriz que se necesita para resolver los valores de coeficiente de regresión lineal es la inversión de matrices, que, lamentablemente, es difícil de comprender e implementar. Para este artículo, cabe saber que el inverso de una matriz se define solo cuando la matriz tiene el mismo número de filas y columnas (una matriz cuadrada). En la figura 4 se muestra una matriz de 3x3 y su inversa.

Existen varios algoritmos que se pueden usar para buscar el inverso de una matriz. El programa de demostración usa una técnica denominada descomposición de Doolittle.

En modo de resumen, un problema de regresión lineal con variables de predictor n implica buscar los valores de los coeficientes n+1. Esto se puede hacer mediante matrices con la transposición de matrices, la multiplicación de matrices y la inversión de matrices. La transposición y multiplicación son sencillos, pero buscar la inversa de una matriz es difícil.

Estructura del programa de demostración

Para crear el programa de demostración, inicié Visual Studio y seleccioné la plantilla de proyecto de aplicación de consola. Al proyecto le asigné el nombre LinearRegression. El programa no tiene ninguna dependencia significativa de .NET Framework, por lo que funcionará con cualquier versión de Visual Studio.

Después de que se haya cargado el código de plantilla en el editor, en la ventana Explorador de soluciones, hice clic con el botón derecho en el archivo Program.cs y cambié el nombre a LinearRegressionProgram.cs. Permití que Visual Studio cambie automáticamente el nombre de clase a Program. En la parte superior de la ventana del Editor, eliminé toda mediante instrucciones excepto la referencia del espacio de nombres System nivel superior.

La estructura general del programa de demostración, con algunos cambios menores para ahorrar espacio, se presenta en la figura 5. Toda la lógica de control del programa está en el método Main. El programa de demostración usa un enfoque de método estático, en lugar de un método de programación orientada a objetos.

Figura 5 Estructura de programa de demostración de regresión lineal

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

El método Income devuelve los ingresos previstos a partir de los parámetros de entrada con los valores de nivel de educación, experiencia laboral y sexo, usando una matriz de valores de coeficiente. El método RSquared devuelve el valor de R cuadrado del modelo desde los datos y coeficientes. El método DummyData genera los datos sintéticos que se usan para la demostración.

El método Design acepta una matriz de datos y devuelve una matriz de diseño aumentada con una columna inicial de 1.0 valores. El método Solve acepta una matriz de diseño y usa las operaciones de matriz para buscar los coeficientes de regresión lineal.

La mayor parte del trabajo lo hace un conjunto de métodos estáticos que realizan operaciones de matriz. El programa de demostración define una matriz de la manera más simple posible, como una matriz de matrices. Una alternativa es crear una clase Matrix definida por el programa, pero en mi opinión ese método es innecesariamente complicado. Las matrices normales a veces son mejores que los objetos definidos por el programa.

El método MatrixTranspose devuelve la transposición de una matriz. El método MatrixProduct devuelve el resultado de la multiplicación de dos matrices. El método MatrixInverse devuelve el inverso de una matriz. La demostración tiene muchos métodos auxiliares. En concreto, el método MatrixInverse llama a los métodos auxiliares MatrixDuplicate, MatrixDecompose y HelperSolve.

El método Solve

El núcleo del programa de demostración de regresión lineal es el método Solve. La definición del método comienza con lo siguiente:

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);
...

El único parámetro de entrada es una matriz de diseño. Un método alternativo que se recomienda tener en cuenta es pasar la matriz de datos de origen y luego hacer que Solve llame al método auxiliar Design para obtener la matriz de diseño. El método auxiliar MatrixCreate asigna espacio para una matriz con el número especificado de filas y columnas, y la devuelve. La matriz X local contiene los valores de las variables independientes (con un valor de 1.0 inicial). La matriz Y local tiene una sola columna y contiene los valores de la variable dependiente (ingresos anuales en la demostración).

A continuación, las celdas de las matrices X e Y se rellenan con los valores de la matriz de diseño:

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
}

Observen que esa variable de índice j se declara fuera de los bucles for anidados, por lo que se puede usar para rellenar la matriz Y. Con las matrices de X e Y en mano, los coeficientes de regresión lineal se pueden buscar según la ecuación que se muestra en la 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

En la demostración, las matriz X tiene un tamaño de 10x4, por lo que su transposición, Xt, tiene un tamaño de 4x10. El producto de Xt y X tiene un tamaño de 4x4 y el inverso, inv, también tiene un tamaño de 4x4. En general, para un problema de regresión lineal con n variables de predictor independientes, cuando se usa la técnica de inversión de matrices, será necesario buscar el inverso de una matriz de tamaño (n+1) x (n+1). Esto significa que la técnica de inversión no es adecuada para los problemas de regresión lineal que tienen un gran número de variables de predictor.

El producto de la matriz inversa 4x4 y la matriz de transposición 4x10, invXt en el código, tiene un tamaño de 4x10. El producto de invXt y la matriz Y de 10x1, mResult ("resultado de la matriz") en el código, tiene un tamaño de 4x1. Estos valores son los coeficientes que se necesitan. Para mayor comodidad, los valores de la matriz de columna única Y se transfieren a una matriz normal mediante el método auxiliar MatrixToVector.

Calcular R cuadrado

Como indiqué anteriormente, la métrica de R cuadrado es una medición de lo bien que los puntos de datos reales se ajustan a la línea de regresión calculada. En términos matemáticos, R cuadrado se define como R2 = 1 - (SSres / SStot). El término SSres normalmente se denomina la "suma residual de cuadrados." Es la suma de las diferencias cuadradas entre los valores Y reales y los valores Y de predicción, tal como se muestra en el gráfico de la figura 2. El término SStot es la "suma total de los cuadrados." Es la suma de las diferencias cuadradas entre cada valor Y real y el promedio (media) de todos los valores Y reales.

La métrica de R cuadrado en la regresión lineal también se denomina el coeficiente de determinación y está relacionada con otra métrica estadística denominada r cuadrado ("r cuadrado pequeña"), aunque es diferente a ella. La interpretación de R cuadrado es algo complicado y depende del dominio del problema concreto que se esté investigando. Para las ciencias naturales y sociales, donde los datos suelen ser complicados e incompletos, un valor R cuadrado de 0,6 o más a menudo se considera bastante bueno.

Hay una medida alternativa de la varianza explicada por el modelo de regresión llamada R cuadrado ajustada. Esta métrica tiene en cuenta el número de variables de predictor y el número de elementos de datos. Para la mayoría de los casos, el uso del valor de R cuadrado simple es suficientemente adecuado como para hacerse una idea de la calidad predictiva de un modelo de regresión lineal.

Resumen

Si buscan ejemplos en Internet sobre cómo hacer la regresión lineal con un lenguaje de programación, no encontrarán muchas referencias. Creo que hay dos motivos principales por esta falta de información. En primer lugar, para resolver los coeficientes de regresión lineal con operaciones de matriz es bastante difícil, principalmente debido a la operación de inversión de la matriz. De alguna manera, creo que el método MatrixInverse del programa de demostración se encuentra entre las rutinas de código más complicadas que he escrito. En segundo lugar, existen muchas herramientas independientes que pueden realizar la regresión lineal, en particular, el programa de hoja de cálculo Excel con su complemento Análisis de datos. Es muy poco común tener que integrar directamente código de solución de regresión lineal en un sistema de software.

La regresión lineal se ha estudiado durante décadas y hay muchas maneras de ampliar la técnica. Por ejemplo, se puede introducir lo que se denomina efectos de interacción que combinan dos o más variables de predictor. Estas extensiones a veces se denominan modelos lineales generales para distinguirlos de la forma básica de la regresión lineal.

En mi opinión, la regresión lineal es la técnica "Hello World" de la estadística clásica. No existe ninguna distinción clara, aceptada universalmente, entre la estadística clásica y el aprendizaje automático. Sin embargo, tiendo a pensar en las técnicas de estadística clásica como aquellas que los matemáticos estudiaron inicialmente a partir de principios del siglo XX. En mi opinión, las técnicas de aprendizaje automático, al igual que la clasificación de redes neuronales, son las que son más recientes y que aparecieron en la década de los cincuenta. La regresión lineal de la estadística clásica está estrechamente relacionada con una técnica de aprendizaje automático denominada regresión logística, que ha sido el tema de varias columnas de Test Run.


Dr. James McCaffrey trabaja para Microsoft Research en Redmond, Washington. Ha colaborado en el desarrollo de varios productos de Microsoft como, por ejemplo, Internet Explorer y Bing. Dr. Puede ponerse en contacto James en jammc@microsoft.com.

Gracias al siguiente experto técnico de Microsoft Research por revisar este artículo: Charles Parker