Вычисление коэффициента детерминации (R²) на C

CBeginner
Практиковаться сейчас

Введение

В этом лабораторном практикуме мы изучим, как вычислить коэффициент детерминации (R²) в языке C. Практикум охватывает следующие шаги:

Во-первых, мы вычислим предсказанные значения y с помощью линейной регрессии. Мы создадим программу, которая вычисляет предсказанные значения на основе простой линейной регрессионной модели. Затем мы вычислим значение R² с использованием объясненной и общей вариаций. Наконец, мы выведем значение R².

Этот практикум предоставляет практический подход к пониманию концепции коэффициента детерминации и его реализации в программировании на языке C, что является ценным навыком для статистического анализа данных.

Вычисление предсказанных значений y с помощью регрессии

В этом шаге мы научимся вычислять предсказанные значения y с помощью линейной регрессии в языке C. Мы создадим программу, которая вычисляет предсказанные значения на основе простой линейной регрессионной модели.

Сначала создадим файл C для наших расчётов регрессии:

cd ~/project
nano regression_prediction.c

Теперь введите следующий код:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// Функция для вычисления предсказанных значений y
void computePredictedY(double *x, double *y, int n, double slope, double intercept, double *predicted_y) {
    for (int i = 0; i < n; i++) {
        predicted_y[i] = slope * x[i] + intercept;
    }
}

int main() {
    // Примерные точки данных
    double x[] = {1.0, 2.0, 3.0, 4.0, 5.0};
    double y[] = {2.0, 4.0, 5.0, 4.0, 5.0};
    int n = sizeof(x) / sizeof(x[0]);

    // Заданные значения наклона и свободного члена (для демонстрации)
    double slope = 0.6;
    double intercept = 1.5;

    // Массив для хранения предсказанных значений y
    double predicted_y[n];

    // Вычисление предсказанных значений y
    computePredictedY(x, y, n, slope, intercept, predicted_y);

    // Вывод исходных и предсказанных значений y
    printf("Исходные и предсказанные значения Y:\n");
    for (int i = 0; i < n; i++) {
        printf("X: %.1f, Исходное Y: %.1f, Предсказанное Y: %.1f\n",
               x[i], y[i], predicted_y[i]);
    }

    return 0;
}

Компилируем программу:

gcc -o regression_prediction regression_prediction.c -lm

Запускаем программу:

./regression_prediction

Пример вывода:

Исходные и предсказанные значения Y:
X: 1.0, Исходное Y: 2.0, Предсказанное Y: 2.1
X: 2.0, Исходное Y: 4.0, Предсказанное Y: 2.7
X: 3.0, Исходное Y: 5.0, Предсказанное Y: 3.3
X: 4.0, Исходное Y: 4.0, Предсказанное Y: 3.9
X: 5.0, Исходное Y: 5.0, Предсказанное Y: 4.5

Давайте разберём ключевые компоненты этого кода:

  1. Функция computePredictedY() вычисляет предсказанные значения y, используя уравнение линейной регрессии: y = kx + b
  2. Мы используем заданные значения наклона (0.6) и свободного члена (1.5) для демонстрации
  3. Программа выводит как исходные, так и предсказанные значения y для сравнения

Вычисление R² с использованием объяснённой/общей вариации

В этом шаге мы расширим нашу предыдущую программу регрессии, чтобы вычислить коэффициент детерминации (R²), который показывает, насколько хорошо модель регрессии соответствует данным.

Сначала изменим наш существующий файл C:

cd ~/project
nano r_squared_calculation.c

Введите следующий код:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// Функция для вычисления среднего значения массива
double calculateMean(double *arr, int n) {
    double sum = 0.0;
    for (int i = 0; i < n; i++) {
        sum += arr[i];
    }
    return sum / n;
}

// Функция для вычисления R-квадрат
double computeRSquared(double *x, double *y, int n, double slope, double intercept) {
    // Вычисление предсказанных значений y
    double predicted_y[n];
    double total_variation = 0.0;
    double explained_variation = 0.0;

    // Вычисление среднего значения фактических значений y
    double y_mean = calculateMean(y, n);

    // Вычисление вариаций
    for (int i = 0; i < n; i++) {
        // Предсказанное значение y
        predicted_y[i] = slope * x[i] + intercept;

        // Общая вариация (расстояние от среднего значения)
        total_variation += pow(y[i] - y_mean, 2);

        // Объяснённая вариация (расстояние от предсказанного значения)
        explained_variation += pow(y[i] - predicted_y[i], 2);
    }

    // Вычисление R-квадрат
    return 1 - (explained_variation / total_variation);
}

int main() {
    // Примерные точки данных
    double x[] = {1.0, 2.0, 3.0, 4.0, 5.0};
    double y[] = {2.0, 4.0, 5.0, 4.0, 5.0};
    int n = sizeof(x) / sizeof(x[0]);

    // Заданные значения наклона и свободного члена (для демонстрации)
    double slope = 0.6;
    double intercept = 1.5;

    // Вычисление и вывод R-квадрат
    double r_squared = computeRSquared(x, y, n, slope, intercept);

    printf("Результаты регрессионного анализа:\n");
    printf("Наклон: %.2f\n", slope);
    printf("Свободный член: %.2f\n", intercept);
    printf("R-квадрат (R²): %.4f\n", r_squared);

    return 0;
}

Компилируем программу:

gcc -o r_squared_calculation r_squared_calculation.c -lm

Запускаем программу:

./r_squared_calculation

Пример вывода:

Результаты регрессионного анализа:
Наклон: 0.60
Свободный член: 1.50
R-квадрат (R²): 0.5600

Ключевые компоненты вычисления R²:

  1. calculateMean() вычисляет среднее значение массива
  2. computeRSquared() вычисляет R² по формуле: 1 - (Объяснённая вариация / Общая вариация)
  3. Общая вариация измеряет разброс фактических значений y относительно их среднего значения
  4. Объяснённая вариация измеряет разброс предсказанных значений от фактических значений
  5. R² изменяется от 0 до 1, при больших значениях модель лучше соответствует данным

Вывод Значения R²

В этом заключительном шаге мы создадим полную программу, которая считывает данные из файла, вычисляет параметры регрессии и выводит значение R² с подробным описанием.

Сначала создайте файл с образцовыми данными:

cd ~/project
nano regression_data.txt

Добавьте образцовые данные регрессии:

1.0 2.0
2.0 4.0
3.0 5.0
4.0 4.0
5.0 5.0

Теперь создайте программу для окончательного вычисления R²:

nano r_squared_print.c

Введите следующий код:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// Функция для вычисления параметров линейной регрессии
void calculateRegressionParameters(double *x, double *y, int n,
                                   double *slope, double *intercept) {
    double sum_x = 0, sum_y = 0, sum_xy = 0, sum_x_squared = 0;

    for (int i = 0; i < n; i++) {
        sum_x += x[i];
        sum_y += y[i];
        sum_xy += x[i] * y[i];
        sum_x_squared += x[i] * x[i];
    }

    // Вычисление наклона и свободного члена методом наименьших квадратов
    *slope = (n * sum_xy - sum_x * sum_y) / (n * sum_x_squared - sum_x * sum_x);
    *intercept = (sum_y - *slope * sum_x) / n;
}

// Функция для вычисления R-квадрат
double computeRSquared(double *x, double *y, int n, double slope, double intercept) {
    double total_variation = 0.0;
    double explained_variation = 0.0;
    double y_mean = 0.0;

    // Вычисление среднего значения y
    for (int i = 0; i < n; i++) {
        y_mean += y[i];
    }
    y_mean /= n;

    // Вычисление вариаций
    for (int i = 0; i < n; i++) {
        total_variation += pow(y[i] - y_mean, 2);
        double predicted_y = slope * x[i] + intercept;
        explained_variation += pow(y[i] - predicted_y, 2);
    }

    // Вычисление R-квадрат
    return 1 - (explained_variation / total_variation);
}

// Функция для интерпретации значения R-квадрат
void interpretRSquared(double r_squared) {
    printf("\nИнтерпретация R²:\n");
    if (r_squared < 0.3) {
        printf("Слабая модель: модель объясняет менее 30%% дисперсии.\n");
    } else if (r_squared < 0.5) {
        printf("Умеренная модель: модель объясняет 30-50%% дисперсии.\n");
    } else if (r_squared < 0.7) {
        printf("Хорошая модель: модель объясняет 50-70%% дисперсии.\n");
    } else {
        printf("Отличная модель: модель объясняет более 70%% дисперсии.\n");
    }
}

int main() {
    FILE *file;
    int n = 0, max_lines = 100;
    double x[100], y[100];
    double slope, intercept, r_squared;

    // Открытие файла данных
    file = fopen("regression_data.txt", "r");
    if (file == NULL) {
        printf("Ошибка открытия файла!\n");
        return 1;
    }

    // Чтение данных из файла
    while (fscanf(file, "%lf %lf", &x[n], &y[n]) == 2) {
        n++;
        if (n >= max_lines) break;
    }
    fclose(file);

    // Вычисление параметров регрессии
    calculateRegressionParameters(x, y, n, &slope, &intercept);

    // Вычисление R-квадрат
    r_squared = computeRSquared(x, y, n, slope, intercept);

    // Вывод результатов
    printf("Результаты регрессионного анализа:\n");
    printf("Количество точек данных: %d\n", n);
    printf("Наклон: %.4f\n", slope);
    printf("Свободный член: %.4f\n", intercept);
    printf("R-квадрат (R²): %.4f\n", r_squared);

    // Интерпретация R-квадрат
    interpretRSquared(r_squared);

    return 0;
}

Компилируем программу:

gcc -o r_squared_print r_squared_print.c -lm

Запускаем программу:

./r_squared_print

Пример вывода:

Результаты регрессионного анализа:
Количество точек данных: 5
Наклон: 0.6000
Свободный член: 1.5000
R-квадрат (R²): 0.5600

Интерпретация R²:
Хорошая модель: модель объясняет 50-70% дисперсии.

Ключевые моменты:

  1. Считывает данные из внешнего файла
  2. Вычисляет параметры регрессии методом наименьших квадратов
  3. Вычисляет значение R²
  4. Предоставляет интерпретацию значения R²
  5. Помогает понять предсказательную силу модели

Резюме

В этом лабораторном практикуме мы изучили, как вычислять предсказанные значения y с помощью простой линейной модели регрессии на языке C. Мы создали программу, которая принимает на вход точки данных x и y, а также наклон и свободный член прямой регрессии, и затем вычисляет предсказанные значения y. Ключевыми этапами были вычисление предсказанных значений y на основе уравнения регрессии и вывод исходных и предсказанных значений y для сравнения.

Далее мы изучим, как вычислить коэффициент детерминации (R²) с использованием объяснённой и общей вариации данных.