martes, 5 de enero de 2016

PROGRAMA DE REGRESION LINEAL

Aquí os dejo el código de un programa que ajusta rectas a una distribución lineal de puntos.
Normalmente las rectas que ajustaremos serán sobre datos experimentales, por lo que habrá errores de medida de algún otro tipo. Por esta razón no encontraremos una recta que pase por todos los puntos, sino que tendremos que encontrar una que se aproxime a todos los puntos que encontramos con un error mínimo.
A esto también se le llama mínimos cuadrados.
Estos son los calculaos que hay que hacer:
Sean los datos experimentales (x,y) ={ (2,5), (3,6), (1,4),(7,6),(5,8)}, se nos plantea el siguiente sistema de ecuaciones:
B + 2M = 5
B + 3M = 6
B + 1M = 4
B + 7M = 6
B + 5M = 8
Donde la M es la pendiente de nuestra recta y la B es la ordenada en el origen. Como se ha explicado antes, no podremos encontrar una única solución , por lo que deberemos aproximarla mediante mínimos cuadrados.
Para ello primero escribiremos el sistema de manera matricial.



Para hallar la recta de regresión, aplicamos la siguiente formula que es la de mínimos cuadrados.






Que si la resolvemos con sin los coeficientes, encontramos una expresión más general de nuestro sistema, que al resolverlo ya si encontraremos la solución a nuestro problema.







Este último sistema de ecuaciones, es el que utiliza el programa para hayar las rectas. La n es el numero de datos experimentales que tenemos.

Aquí dejo los cálculos codificados en C, se entiende que ya se sabe programar en C, y el código sólo está comentado.


#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main() {
    float sistema[2][3], *resultx, *resulty, pendiente = 0, ordenada = 0, sumax = 0, sumay = 0,sumax2 = 0,sumaxy = 0, aux=0;
    /*
     la matriz sistema la usaremos para resolver el sistema de ecuaciones y y hallar la pendiente y ordenada en el origen de nuestra recta
     los punteros resultx y resulty los usaremos para alamacenar los datos tomados experimentalmente en arrays dinamicos
     las variables pendiente y ordenada sera donde se alojaran los resultados del sistema de ecuaciones
     en las variables suma... se almacenaran los distintos sumatorios que utilizaremos durnte los calculos
     */
    int n=0, i=0,j=0;// estas variables seran contadores durante nuestro programa
    // do el programa está metido dentro de un bucle do- while para preguntar al final a usuario si quiere calcular mas rectas
    do {
        printf("Programa de regresion lineal por metodo matricial\n");
        printf("MUY IMPORTANTE, SI INTRODUCES RESULTADOS EXPERIMENTALES IGUALES O REPETIDOS, EL RESULTADO SERA ERRONEO\n");
        // lo primero de todo es preguntar al usuario por el numero de datos a introducir para crea la memoria dinamica
        printf("Introduzca cuantos datos experimentales ha tomado\n");
        scanf("%d", &n);
        //despues asignamos memoria a los arrays
        resultx = (float *)malloc(n*sizeof(float));
        if (resultx == NULL) {
            printf("No hay suficiente memoria\n");
            system("pause");
            return -1;
        }
        resulty = (float *)malloc(n*sizeof(float));
        if (resulty == NULL) {
            printf("No hay suficiente memoria\n");
            system("pause");
            return 0
            ;
        }
        //tercero recogemos los datos esperimentales mediante bucles for
        for (i = 0; i < n; i++)
        {
            system("cls");
            printf("Valor experimental numero %d \n", i + 1);
            printf("Introduzca el valor del eje x\n");
            scanf("%f", &resultx[i]);
            printf("Introduzca el valor del eje y\n");
            scanf("%f", &resulty[i]);
            system("cls");
        }
        // calculamos los distintos sumatorios
        //smatorio x
        for (i = 0;i < n;i++) {
            sumax = sumax + resultx[i];
        }
        // sumatorio y
        for (i = 0;i < n;i++) {
            sumay = sumay + resulty[i];
        }
        //sumatorio xy
        for (i = 0;i < n;i++) {
            sumaxy = sumaxy + resultx[i] * resulty[i];
        }
        // sumatorio x2
        for (i = 0;i < n;i++) {
            sumax2 = sumax2 + resultx[i] * resultx[i];
        }
        //metemos los datos en la matriz del sistema
        sistema[0][0] = n;
        sistema[0][1] = sumax;
        sistema[0][2] = sumay;
        sistema[1][0] = sumax;
        sistema[1][1] = sumax2;
        sistema[1][2] = sumaxy;
        // como dejamos de utilizar lo arrays dinamicos los liberamos
        free(resultx);
        free(resulty);
       
        //resolvemos el sistema por el metodo de gaus-jordan
        //primero hacemos 1 el elemto 00
        aux = sistema[0][0];
        sistema[0][0] = sistema[0][0] / aux;
        sistema[0][1] = sistema[0][1] / aux;
        sistema[0][2] = sistema[0][2] / aux;
        //segundo hacemos 0 el elemtento 10
        aux = sistema[1][0];
        sistema[1][0] = sistema[1][0] - sistema[0][0] * aux;
        sistema[1][1] = sistema[1][1] - sistema[0][1] * aux;
        sistema[1][2] = sistema[1][2] - sistema[0][2] * aux;
        // despejamos la variable del elemento 11
        pendiente = sistema[1][2] / sistema[1][1];
        //despejamos la ordenada en el orijen
        ordenada = sistema[0][2] - sistema[0][1] * pendiente;
       
        //muestra el resultado por pantalla
       
        printf("La recta resultante es y = %.2f x + %.2f\n", pendiente, ordenada);
        printf("øDesea hacer otra recta?\n");
        printf("1. Si\n");
        printf("2. No\n");
        scanf("%d", &j);
        system("cls");
    } while (j==1);
   
   
   
    system("pause");
    return 0;
}



Si tenéis alguna duda, no dudéis en dejar un comentario o escríbenos un mail a makersexperience@hotmail.com.
Síguenos en Twitter @makers_exp y entérate al instante de las novedades del blog.