Введение

Простая линейная регрессия — это простейший метод машинного обучения с учителем. В этом цель модели ML состоит в том, чтобы найти наилучшую линейную связь между двумя переменными: x (независимая переменная) и y (целевая/зависимая переменная) и выразить ее в форме y_predicted = b0 + b1 * x_input. Мы реализуем этот алгоритм с нуля, используя GoLang.

Область статьи:

  • В этой статье обсуждается, как найти b0, b1 в строке наилучшего соответствия y_predicted = b0 + b1*x_input.
  • В этой статье реализовано несколько функций в GoLang, таких как «обучение тестового разделения» для разделения данных, rmseValue для поиска значений RMSE для оценки модели и т. д.
  • В эту статью включены все коды в GoLang.

Простая линейная регрессия

Он изображает взаимосвязь между двумя переменными. Он представлен визуально в виде прямой линии (y=mx+c), наклон которой указывает, как изменение одной переменной влияет на другую. В линейной регрессии уравнение линии задается как y(x)=b₀+b₁*x, где b₀ и b₁ — коэффициенты регрессии.

Нахождение b₀ и b₁ и RMSE

b1 = sum((xi-mean(x)) * (yi-mean(y))) / sum((xi - mean(x))*(xi - mean(x))) где xi и yi - i -th входные атрибуты, а mean() — это среднее значение переменной в нашем наборе данных.

b0 = среднее (y) — b1 * среднее (x)

Ошибка рассчитывается с использованием среднеквадратичного значения или RMSE: RMSE = sqrt(sum((pi — yi)²)/n), где pi i-е — прогнозируемое целевое значение (прогнозируемый результат) из набора тестовых данных, а yi — i-е фактическое целевое значение (фактический результат) из набора данных.

Блок-схема различных функций в коде Golang ниже

Код на GoLang

package main
import (
 "fmt"
 "math"
"gonum.org/v1/gonum/stat"
)
// resultXY --> sum((x-meanX)*(y-meanY))
// resultXX --> sum((x-meanX)^2)
func sumXYandXX(arrayX []float64, arrayY []float64, meanX float64, meanY float64) (float64, float64) {
 resultXX := 0.0
 resultXY := 0.0
for x := 0; x < len(arrayX); x++ {
  for y := 0; y < len(arrayY); y++ {
   if x == y {
    resultXY += (arrayX[x] - meanX) * (arrayY[y] - meanY)
   }
  }
  resultXX += (arrayX[x] - meanX) * (arrayX[x] - meanX)
 }
return resultXY, resultXX
}
// estimateBoB1 --> Function that calculates the regression coefficients b0 and b1
// y_predicted = b0 + b1*x_input
func estimateB0B1(x []float64, y []float64) (float64, float64) {
 var meanX float64
 var meanY float64
 var sumXY float64
 var sumXX float64
meanX = stat.Mean(x, nil) //mean of x
 meanY = stat.Mean(y, nil) //mean pf y
sumXY, sumXX = sumXYandXX(x, y, meanX, meanY)
// regression coefficients
 b1 := sumXY / sumXX    // b1 or slope
 b0 := meanY - b1*meanX // b0 or intercept
return b0, b1
}
func rmseCost(y_predicted []float64, y_test []float64) float64 {
 sz := len(y_test)
 var rmse float64 = 0.0
for i := 0; i < len(y_test); i++ {
  rmse = rmse + math.Abs(y_test[i]-y_predicted[i])*math.Abs(y_test[i]-y_predicted[i])
 }
 rmse = rmse / float64(sz)
 rmse = math.Sqrt(rmse)
return rmse
}
func testing(x_test []float64, b0 float64, b1 float64) []float64 {
 sz := len(x_test)
 res := make([]float64, sz)
 for i := 0; i < len(x_test); i++ {
  res[i] = b0 + b1*x_test[i]
  fmt.Println("for input value : ", x_test[i], ", prediction is :  ", res[i])
 }
 return res
}
func train_test_split(x_ []float64, y_ []float64, train_ratio float64) ([]float64, []float64, []float64, []float64) {
 if len(x_) != len(y_) {
  fmt.Printf("Size of X and Y are different :", len(x_), " and ", len(y_))
 }
 var length float64 = float64(len(x_))
 pos := int(length * train_ratio)
var test_x = x_[pos-1:]
 var test_y = y_[pos-1:]
 var train_x = x_[:pos-1]
 var train_y = y_[:pos-1]
return test_x, test_y, train_x, train_y
}
func main() {
 var X_data = []float64{-5.1, -4, -3, 2.1, -1, 0, 0.9, 2, 3.02, 4, 5, 6, 7.09, 8, 8.98, 10, 11, 12, 1, 3, 14, 15, -11, -12, 29, 30, 1, 50, 455, 500}
 var y_data = []float64{-9, -7.1, -5, 5, -1, 1, 3.1, 5, 7, 9, 11, 13, 15, 17, 18.95, 21, 23, 25, 3, 7, 29, 31, -21, -23, 59.1, 60.95, 3, 101, 909.9, 999.78}
test_x, test_y, train_x, train_y := train_test_split(X_data, y_data, 0.80)
//coefficients
 b0, b1 := estimateB0B1(train_x, train_y)
 //preliminary output with calculated coefficients
 fmt.Printf("Los valores de b0=%v , b1=%v\n", b0, b1)
 var prediction = testing(test_x, b0, b1)
 var rmseValue float64 = 0.0
 rmseValue = rmseCost(prediction, test_y)
 fmt.Println("RMSE :  ", rmseValue)
}

Будущие работы

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