Независимо от того, пытаетесь ли вы выбрать лучшие акции или оценить связь между климатом и выбросами CO 2 , всегда полезно увидеть математический тренд. В этой статье мы рассмотрим процесс построения алгоритма, который поможет вам найти линейные тренды в наборах данных. Если вас больше интересуют нелинейные тренды, вы можете просмотреть другую мою статью «Поиск трендов в данных — нелинейные».

Что такое тренд? Это «наилучшее» линейное уравнение для набора данных.

В этом уравнении у вас есть отношение тренда между x и наклоном (m), умноженными вместе, плюс константа (b), которая дает значение y, что позволяет составить таблицу или график x с соответствующими значениями y.

Что мы ищем

В конце концов, нам нужен наклон и точка пересечения по оси Y, которые относятся к нашим данным, и линия, которая лучше всего соответствует этим данным.

Давайте построим структуру для хранения нашего уравнения:

type Equation struct { M, B float64 }

Как видно, мы будем хранить две наши константы (наклон [M] и y-перехват [B]) в структуре уравнения. Обратите внимание, что переменные внутри структуры Equation пишутся с заглавной буквы и, следовательно, общедоступны.

У нас есть то, что мы ищем, но как мы можем найти эти две ценности? Имея набор данных, можно легко найти эти числа с помощью компьютерного алгоритма. Посмотрим, какие переменные понадобятся.

Наши уравнения

M = (total sum y)*(total sum x^2)-(total sum x)*(total sum x * y)/n(total sum x^2)-(total sum x)^2 B = n(total sum x * y)-(total sum x)*(total sum y)/n(total sum x^2)-(total sum x)^2

Чтобы перевести это в код, мы можем просто создать приватную структуру, которая поможет нам отслеживать все.

Все переменные, которые нам нужны

Итак, при рассмотрении формул линейной регрессии нам понадобится

Затем мы строим структуру, чтобы вместить все, что нам нужно.

type LinearRegression struct { x, y []float64 xTotal, yTotal, xSqTotal, xYTotal, numerator, denominator, slope, yInt float64 }

x и y: будут просто хранить копию нашего ввода данных

мы будем хранить наши итоги в различных общих переменных

другие важные переменные, необходимые для наших расчетов.

Вернуть то, что мы хотим

Между двумя созданными нами структурами (Уравнение и Линейная регрессия) теперь у нас есть желаемый результат и база данных для хранения наших вычислений.

Нас интересует только получение уравнения. Нам нужно будет создать функцию, которая берет массивы данных x и y и выдает соответствующую структуру Equation.

func (e *Equation) ReturnEquationParts(x,y []float64) { var l LinearRegression l.LinearRegressionInit(x, y) e.M = l.slope e.B = l.yInt }

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

Линейная регрессия

Когда вы посмотрите на требования к расчету из приведенного выше уравнения, вы увидите, что самая сложная часть — это нахождение итогов. Итак, давайте создадим функцию, которая находит все эти суммы, а затем все вычисляет.

func (l *LinearRegression)LinearRegressionInit(x,y []float64){ l.x = x l.y = y for i, _ := range l.x { l.xTotal = l.xTotal + l.x[i] l.yTotal = l.yTotal + l.y[i] l.xSqTotal = l.xSqTotal + math.Pow(l.x[i], 2) l.xYTotal = l.xYTotal + (l.x[i] * l.y[i]) } l.numerator = (float64(len(l.x)) * l.xYTotal) - (l.xTotal * l.yTotal) l.denominator = (float64(len(l.x)) * l.xSqTotal) - (math.Pow(l.xTotal, 2)) yIntNumerator := (l.yTotal * l.xSqTotal) - (l.xTotal * l.xYTotal) l.yInt = yIntNumerator / l.denominator l.slope = l.numerator / l.denominator }

Как видите, мы просто перебираем массивы и строим все наши суммы в одном цикле. Затем вы подставляете действительные числа, которые были суммированы, в уравнение. Вычислите знаменатель (они одинаковы для каждого уравнения). Наконец, разделите каждый числитель на знаменатель, чтобы получить значение наклона и точки пересечения по оси y.

Построить основной()

Вот и все. Чтобы на самом деле использовать этот код, мы можем создать простой основной метод. Его также можно добавить к любым существующим функциям.

func main(){ x := []float64{0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0} y := []float64{0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0} var equation Equation equation.ReturnEquationParts(x,y) fmt.Println(`y = `, equation.M, `x + `, equation.B) }

Этот конкретный набор массивов x и y должен возвращать:

Собираем все вместе

package main import "math" import "fmt" type LinearRegression struct { x, y []float64 xTotal, yTotal, xSqTotal, xYTotal, numerator, denominator, slope, yInt float64 } type Equation struct { M, B float64 } func (e *Equation) ReturnEquationParts(x,y []float64) { var l LinearRegression l.LinearRegressionInit(x, y) e.M = l.slope e.B = l.yInt } func (l *LinearRegression)LinearRegressionInit(x,y []float64){ l.x = x l.y = y //fmt.Println(len(l.X)) for i, _ := range l.x { l.xTotal = l.xTotal + l.x[i] l.yTotal = l.yTotal + l.y[i] l.xSqTotal = l.xSqTotal + math.Pow(l.x[i], 2) l.xYTotal = l.xYTotal + (l.x[i] * l.y[i]) } l.numerator = (float64(len(l.x)) * l.xYTotal) - (l.xTotal * l.yTotal) l.denominator= (float64(len(l.x)) * l.xSqTotal) - (math.Pow(l.xTotal, 2)) yIntNumerator := (l.yTotal * l.xSqTotal) - (l.xTotal * l.xYTotal) l.yInt = yIntNumerator / l.denominator l.slope = l.numerator / l.denominator } func main(){ x := []float64{0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0} y := []float64{0.0, 2.0, 7.0, 8.0, 3.0, 2.0, 4.0} var equation Equation equation.ReturnEquationParts(x,y) fmt.Println(`y = `, equation.M, `x + `, equation.B) }

Первоначально опубликовано на https://synchrodynamic.com 7 октября 2019 г.