Как уже писал, занимаюсь освоением самых- самых основ machine learning. В курсах и литературе по ML обычно начинают с простой линейной регрессии. Предварительно обучив по массиву значений одной независимой переменной (X) и массиву значений зависимой от ней второй переменной (Y), можно для какого-либо x получить предположительное y. Например, по росту предположить вес.
Код написал на c#. Он находится на гитхабе — ВОТ ТУТ . Это библиотека, в которой на настоящий момент нет ничего, кроме класса простой линейной регрессии 🙂 Для начала объявляем два массива значений с плавающей запятой, равные по длине (для значений x и для значений y). Также объявим ряд переменных для хранения значений стандартного отклонения X, стандартного отклонения Y, пирсоновской корреляции, slope («a», наклон графика в линейном уравнении) и interception («b» — отступ по оси ординат от оси абсцисс). Напомню вид линейного уравнения: y = ax + b.
public double[] xVals, yVals; public double standardDevX, standardDevY, correlation, slope, interception;
Конструктор класса SimpleLinearRegression будет принимать 2 наших массива (xVals и yVals в коде). При вызове конструктора переменные инициализируются полученными в аргументах массивами.
this.xVals = xVals; this.yVals = yVals;
Далее в конструкторе вызывается метод получения стандартного отклонения для массива значений x (xVals) и аналогично для y (yVals). Этот метод, рассмотрим несколько позже.
standardDevX = GetStandardDeviation(xVals); standardDevY = GetStandardDeviation(yVals);
Далее, опять же в конструкторе, вызываем метод получения пирсоновской корреляции между массивами — его также потом рассмотрим.
correlation = GetCorrelation(xVals, yVals);
Ниже рассчитываем slope (наклон графика). Он будет равен корреляции, умноженной на стандартное отклонение для Y и деленной на стандартное отклонение для X.
slope = correlation * standardDevY / standardDevX;
И последнее в конструкторе — расчет отступа от оси абсцисс по оси ординат (interception). Он будет равен разности среднего значения в массиве значений Y и произведения наклона на среднее в массиве X.
interception = GetArrMean(yVals) - slope * GetArrMean(xVals);
Ниже полный код конструктора:
public SimpleLinearRegression(double[] xVals, double[] yVals)
{
this.xVals = xVals;
this.yVals = yVals;
standardDevX = GetStandardDeviation(xVals);
standardDevY = GetStandardDeviation(yVals);
correlation = GetCorrelation(xVals, yVals);
slope = correlation * standardDevY / standardDevX;
interception = GetArrMean(yVals) - slope * GetArrMean(xVals);
}
Далее идет метод для получения y по заданному x. Этот метод будет вызываться в приложении, использующем библиотеку. В нем всё просто — принимает в качестве аргумента x, возвращает y.
public double PredictY(double x)
{
return interception + slope * x;
}
Дальше метод для расчета среднего в массиве значений. Не знаю, зачем сделал для этого отдельный метод, ну да ладно 🙂 Метод принимает массив, возвращает среднее…
private static double GetArrMean(double[] arr)
{
return arr.Sum() / arr.Length;
}
Дальше посмотри на метод, используемый в конструкторе класса для получения стандартного отклонения. Он принимает массив значений с плавающей запятой и возвращает стандартное отклонение.
Вначале считаем среднее в массиве (double mean). Далее создаем массив (arrDev) double, такой же по длине, как и принимаемый методом массив (назовем его arr), и заполняем его в цикле значениями. Эти значения рассчитываются как разность значения arr[i] и среднего арифметического для значений всего arr, возведенная в квадрат.
После этого считаем квадратный корень из частного суммы значений массива отклонений arrDev и длины массива arrDev. Если мы имеем дело с выборкой, а не со всей генеральной совокупностью, то из делителя еще вычитаем 1. Полученное значение и возвращает метод. Ниже формула без расчета квадратного корня.

А теперь код метода:
private static double GetStandardDeviation(double[] arr)
{
double mean = GetArrMean(arr);
double[] devs = new double[arr.Length]; //отклонения от среднего
for (int i = 0; i < arr.Length; i++)
{
devs[i] = Math.Pow(arr[i] - mean, 2);
}
return Math.Sqrt(devs.Sum() / (devs.Length - 1));
}
И последний метод — расчет пирсоновской корреляции для двух массивов значений с плавающей запятой. Он принимает 2 массива double в качестве аргументов.
Вначале считаем среднее для каждого массива и создаем 2 массива x и y такой же длины, как и X и Y, принимаемых методом.
double XMean = X.Sum() / X.Length; double YMean = Y.Sum() / Y.Length; double[] x = new double[X.Length]; double[] y = new double[Y.Length];
Заполняем массив x значениями — разность X[i] и среднего в массиве Y. Аналогично для y.
for (int i = 0; i < X.Length; i++)
{
x[i] = X[i] - XMean;
y[i] = Y[i] - YMean;
}
Теперь создаем еще один массива double для хранения произведений x[i] и y[i]. После этого создаем еще 2 массива для хранения x[i] в квадрате и y[i] в квадрате. Заполняем их:
double[] xy = new double[X.Length];
for (int i = 0; i < X.Length; i++)
{
xy[i] = x[i] * y[i];
}
double[] xPowed = new double[X.Length];
double[] yPowed = new double[Y.Length];
for (int i = 0; i < X.Length; i++)
{
xPowed[i] = Math.Pow(x[i], 2);
yPowed[i] = Math.Pow(y[i], 2);
}
Метод возвращает частное от деления суммы значений массива произведений x и y (массив xy) на квадратный корень из произведения суммы значений массива xPowed (x-ы в квадрате) на сумму значений yPowed). Вот формула для расчета корреляции:

Ниже весь код метода:
private static double GetCorrelation(double[] X, double[] Y)
{
double XMean = X.Sum() / X.Length;
double YMean = Y.Sum() / Y.Length;
double[] x = new double[X.Length];
double[] y = new double[Y.Length];
for (int i = 0; i < X.Length; i++)
{
x[i] = X[i] - XMean;
y[i] = Y[i] - YMean;
}
double[] xy = new double[X.Length];
for (int i = 0; i < X.Length; i++)
{
xy[i] = x[i] * y[i];
}
double[] xPowed = new double[X.Length];
double[] yPowed = new double[Y.Length];
for (int i = 0; i < X.Length; i++)
{
xPowed[i] = Math.Pow(x[i], 2);
yPowed[i] = Math.Pow(y[i], 2);
}
return xy.Sum() / Math.Sqrt(xPowed.Sum() * yPowed.Sum());
}
Использовать библиотеку очень просто. Вначале объявляем и инициализируем значениями с плавающей запятой 2 массива (xVals и yVals). На них машина будет обучаться.
Далее, предварительно добавив ссылку на библиотеку MachineLearningLib, Создаем объект класса SimpleLinearRegression, передав в конструктор наши массивы. Теперь вызываем метод PredictY, передавая ему значение x. Метод возвратит рассчитанный y.
Собственно вот и всё 🙂
Код я писал, опираясь на статьи про линейную регрессию ВОТ ОТСЮДА.
На очереди множественная линейная регрессия, логистическая регрессия и метод ближайших соседей. Авось разберусь 🙂
Если условия применимости метода наименьших квадратов выполняются, необходимо проверить гипотезу о статистической значимости коэффициентов регрессии и построить доверительные интервалы, содержащие математическое ожидание и предсказанное значение отклика.