Oplos van 'n eenvoudige lineêre regressievergelyking

Die artikel bespreek verskeie maniere om die wiskundige vergelyking van 'n eenvoudige (paar) regressielyn te bepaal.

Alle metodes om die vergelyking wat hier oorweeg word op te los, is gebaseer op die kleinste kwadrate metode. Ons noem die metodes soos volg:

  • Analitiese oplossing
  • gradiënt afkoms
  • Stogastiese Gradiënt Afkoms

Vir elk van die maniere om die vergelyking van 'n reguit lyn op te los, bied die artikel verskeie funksies aan, wat hoofsaaklik verdeel is in dié wat geskryf is sonder om die biblioteek te gebruik Numpy en dié wat vir berekeninge gebruik word Numpy. Daar word geglo dat die vaardige gebruik Numpy sal die koste van rekenaars verminder.

Alle kode in hierdie artikel is geskryf in python 2.7 met Jupyter Notaboek. Die bronkode en die voorbeelddatalêer is beskikbaar by Github

Die artikel is meer gefokus op beide beginners en diegene wat reeds geleidelik die studie van 'n baie uitgebreide afdeling in kunsmatige intelligensie - masjienleer - begin bemeester het.

Kom ons gebruik 'n baie eenvoudige voorbeeld om die materiaal te illustreer.

Voorbeeld voorwaardes

Ons het vyf waardes wat verslawing kenmerk Y van X (Tabel #1):

Tabel No. 1 "Voorwaardes van die voorbeeld"

Oplos van 'n eenvoudige lineêre regressievergelyking

Ons sal aanvaar dat die waardes Oplos van 'n eenvoudige lineêre regressievergelyking is die maand van die jaar, en Oplos van 'n eenvoudige lineêre regressievergelyking - verdienste hierdie maand. Met ander woorde, inkomste hang af van die maand van die jaar, en Oplos van 'n eenvoudige lineêre regressievergelyking - die enigste teken waarvan inkomste afhang.

Die voorbeeld is so-so, beide in terme van die voorwaardelike afhanklikheid van inkomste op die maand van die jaar, en in terme van die aantal waardes - daar is baie min van hulle. So 'n vereenvoudiging sal egter toelaat, soos hulle op die vingers sê, om die materiaal wat deur beginners geassimileer word, te verduidelik, nie altyd met gemak nie. En ook die eenvoud van die getalle sal diegene wat die voorbeeld op "papier" wil oplos sonder noemenswaardige arbeidskoste toelaat.

Gestel dat die afhanklikheid wat in die voorbeeld gegee word redelik goed benader kan word deur die wiskundige vergelyking van die lyn van 'n eenvoudige (paar) regressie van die vorm:

Oplos van 'n eenvoudige lineêre regressievergelyking

waar Oplos van 'n eenvoudige lineêre regressievergelyking is die maand waarin die opbrengs ontvang is, Oplos van 'n eenvoudige lineêre regressievergelyking - inkomste wat ooreenstem met die maand, Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking is die regressiekoëffisiënte van die geskatte lyn.

Let daarop dat die koëffisiënt Oplos van 'n eenvoudige lineêre regressievergelyking dikwels na verwys as die helling of gradiënt van die geskatte lyn; is die bedrag waarmee die Oplos van 'n eenvoudige lineêre regressievergelyking wanneer dit verander Oplos van 'n eenvoudige lineêre regressievergelyking.

Dit is duidelik dat ons taak in die voorbeeld is om sulke koëffisiënte in die vergelyking te kies Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking, waarteen die afwykings van ons beraamde inkomstewaardes per maande vanaf die ware antwoorde, d.w.s. waardes wat in die steekproef aangebied word, sal minimaal wees.

Kleinste vierkante metode

Volgens die kleinste kwadrate-metode moet die afwyking bereken word deur dit te kwadraeer. So 'n tegniek maak dit moontlik om die wedersydse terugbetaling van afwykings te vermy, as hulle teenoorgestelde tekens het. Byvoorbeeld, as in een geval, die afwyking is +5 (plus vyf), en in die ander -5 (minus vyf), dan sal die som van die afwykings wedersyds gekanselleer word en 0 (nul) wees. Dit is moontlik om nie die afwyking te kwadraat nie, maar om die modulus-eienskap te gebruik en dan sal al die afwykings positief wees en sal ophoop. Ons sal nie in detail op hierdie punt stilstaan ​​nie, maar bloot aandui dat dit vir die gerief van berekeninge gebruiklik is om die afwyking te vier.

Dit is hoe die formule lyk, met behulp waarvan ons die kleinste som van kwadraatafwykings (foute) sal bepaal:

Oplos van 'n eenvoudige lineêre regressievergelyking

waar Oplos van 'n eenvoudige lineêre regressievergelyking is 'n funksie van benadering van ware antwoorde (dit is die inkomste wat deur ons bereken word),

Oplos van 'n eenvoudige lineêre regressievergelyking is die ware antwoorde (inkomste verskaf in die steekproef),

Oplos van 'n eenvoudige lineêre regressievergelyking is die indeks van die steekproef (die nommer van die maand waarin die afwyking bepaal word)

Kom ons differensieer die funksie, definieer die parsiële differensiaalvergelykings, en wees gereed om aan te beweeg na 'n analitiese oplossing. Maar eers, kom ons neem 'n kort afwyking oor wat differensiasie is en onthou die meetkundige betekenis van die afgeleide.

Differensiasie

Differensiasie is die operasie om die afgeleide van 'n funksie te vind.

Waarvoor is die afgeleide? Die afgeleide van 'n funksie kenmerk die tempo van verandering van die funksie en wys vir ons die rigting daarvan. As die afgeleide op 'n gegewe punt positief is, neem die funksie toe; anders neem die funksie af. En hoe groter die waarde van die modulo-afgeleide, hoe hoër is die tempo van verandering van die funksiewaardes, asook hoe steiler die helling van die funksiegrafiek.

Byvoorbeeld, onder die toestande van 'n Cartesiese koördinaatstelsel, is die waarde van die afgeleide by die punt M(0,0) gelyk aan +25 beteken dat op 'n gegewe punt, wanneer die waarde verskuif word Oplos van 'n eenvoudige lineêre regressievergelyking na regs deur 'n konvensionele eenheid, waarde Oplos van 'n eenvoudige lineêre regressievergelyking verhoog met 25 konvensionele eenhede. Op die grafiek lyk dit na 'n redelik steil hoek van styging in waardes Oplos van 'n eenvoudige lineêre regressievergelyking vanaf 'n gegewe punt.

Nog 'n voorbeeld. Die waarde van die afgeleide is -0,1 beteken dat wanneer verskuiwing Oplos van 'n eenvoudige lineêre regressievergelyking per een konvensionele eenheid, die waarde Oplos van 'n eenvoudige lineêre regressievergelyking verminder met slegs 0,1 konvensionele eenheid. Terselfdertyd, op die grafiek van die funksie, kan ons 'n skaars merkbare afwaartse helling waarneem. As ons 'n analogie met 'n berg trek, is dit asof ons baie stadig met 'n sagte helling van 'n berg afklim, anders as die vorige voorbeeld, waar ons baie steil pieke moes neem :)

Dus, na die differensieer van die funksie Oplos van 'n eenvoudige lineêre regressievergelyking per kans Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking, definieer ons die vergelykings van parsiële afgeleides van die 1ste orde. Nadat ons die vergelykings gedefinieer het, sal ons 'n stelsel van twee vergelykings kry, wat oplos wat ons sulke waardes van die koëffisiënte kan kies Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking, waarteen die waardes van die ooreenstemmende afgeleides by gegewe punte met 'n baie, baie klein hoeveelheid verander, en in die geval van 'n analitiese oplossing glad nie verander nie. Met ander woorde, die foutfunksie by die gevind koëffisiënte sal 'n minimum bereik, aangesien die waardes van gedeeltelike afgeleides by hierdie punte gelyk aan nul sal wees.

Dus, volgens die reëls van differensiasie, die vergelyking van die parsiële afgeleide van die 1ste orde met betrekking tot die koëffisiënt Oplos van 'n eenvoudige lineêre regressievergelyking sal die vorm aanneem:

Oplos van 'n eenvoudige lineêre regressievergelyking

1ste orde parsiële afgeleide vergelyking met betrekking tot Oplos van 'n eenvoudige lineêre regressievergelyking sal die vorm aanneem:

Oplos van 'n eenvoudige lineêre regressievergelyking

As gevolg hiervan het ons 'n stelsel van vergelykings gekry wat 'n redelik eenvoudige analitiese oplossing het:

begin{vergelyking*}
begin{gevalle}
na + bsumlimits_{i=1}^nx_i - sumlimits_{i=1}^ny_i = 0

sumlimits_{i=1}^nx_i(a +bsumlimits_{i=1}^nx_i - sumlimits_{i=1}^ny_i) = 0
einde{gevalle}
einde{vergelyking*}

Voordat ons die vergelyking oplos, kom ons laai vooraf, kontroleer die korrektheid van die laai en formateer die data.

Laai en formateer data

Daar moet kennis geneem word dat as gevolg van die feit dat ons die kode in twee variasies sal gebruik vir die analitiese oplossing, en in die toekoms vir gradiënt en stogastiese gradiënt afkoms: die gebruik van die biblioteek Numpy en sonder om dit te gebruik, benodig ons die toepaslike dataformatering (sien kode).

Data laai en verwerking kode

# импортируем все нужные нам библиотеки
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import math
import pylab as pl
import random

# графики отобразим в Jupyter
%matplotlib inline

# укажем размер графиков
from pylab import rcParams
rcParams['figure.figsize'] = 12, 6

# отключим предупреждения Anaconda
import warnings
warnings.simplefilter('ignore')

# загрузим значения
table_zero = pd.read_csv('data_example.txt', header=0, sep='t')

# посмотрим информацию о таблице и на саму таблицу
print table_zero.info()
print '********************************************'
print table_zero
print '********************************************'

# подготовим данные без использования NumPy

x_us = []
[x_us.append(float(i)) for i in table_zero['x']]
print x_us
print type(x_us)
print '********************************************'

y_us = []
[y_us.append(float(i)) for i in table_zero['y']]
print y_us
print type(y_us)
print '********************************************'

# подготовим данные с использованием NumPy

x_np = table_zero[['x']].values
print x_np
print type(x_np)
print x_np.shape
print '********************************************'

y_np = table_zero[['y']].values
print y_np
print type(y_np)
print y_np.shape
print '********************************************'

Visualisering

Nou, nadat ons eerstens die data gelaai het, tweedens die korrektheid van die laai nagegaan het en die data uiteindelik geformateer het, sal ons die eerste visualisering uitvoer. Dikwels word hierdie metode gebruik paar plot biblioteke Seebaard. In ons voorbeeld, as gevolg van die beperkte getalle, maak dit geen sin om die biblioteek te gebruik nie Seebaard. Ons sal die gewone biblioteek gebruik matplotlib en kyk net na die verspreidingsdiagram.

Spreidiagram kode

print 'График №1 "Зависимость выручки от месяца года"'

plt.plot(x_us,y_us,'o',color='green',markersize=16)
plt.xlabel('$Months$', size=16)
plt.ylabel('$Sales$', size=16)
plt.show()

Grafiek No. 1 "Afhanklikheid van inkomste op die maand van die jaar"

Oplos van 'n eenvoudige lineêre regressievergelyking

Analitiese oplossing

Ons gebruik die mees algemene gereedskap in python en los die stelsel vergelykings op:

begin{vergelyking*}
begin{gevalle}
na + bsumlimits_{i=1}^nx_i - sumlimits_{i=1}^ny_i = 0

sumlimits_{i=1}^nx_i(a +bsumlimits_{i=1}^nx_i - sumlimits_{i=1}^ny_i) = 0
einde{gevalle}
einde{vergelyking*}

Volgens Cramer se reël vind 'n gemeenskaplike determinant, sowel as determinante deur Oplos van 'n eenvoudige lineêre regressievergelyking en deur Oplos van 'n eenvoudige lineêre regressievergelyking, waarna die determinant gedeel word deur Oplos van 'n eenvoudige lineêre regressievergelyking na 'n gemeenskaplike determinant - vind die koëffisiënt Oplos van 'n eenvoudige lineêre regressievergelyking, insgelyks vind ons die koëffisiënt Oplos van 'n eenvoudige lineêre regressievergelyking.

Analitiese oplossing kode

# определим функцию для расчета коэффициентов a и b по правилу Крамера
def Kramer_method (x,y):
        # сумма значений (все месяца)
    sx = sum(x)
        # сумма истинных ответов (выручка за весь период)
    sy = sum(y)
        # сумма произведения значений на истинные ответы
    list_xy = []
    [list_xy.append(x[i]*y[i]) for i in range(len(x))]
    sxy = sum(list_xy)
        # сумма квадратов значений
    list_x_sq = []
    [list_x_sq.append(x[i]**2) for i in range(len(x))]
    sx_sq = sum(list_x_sq)
        # количество значений
    n = len(x)
        # общий определитель
    det = sx_sq*n - sx*sx
        # определитель по a
    det_a = sx_sq*sy - sx*sxy
        # искомый параметр a
    a = (det_a / det)
        # определитель по b
    det_b = sxy*n - sy*sx
        # искомый параметр b
    b = (det_b / det)
        # контрольные значения (прооверка)
    check1 = (n*b + a*sx - sy)
    check2 = (b*sx + a*sx_sq - sxy)
    return [round(a,4), round(b,4)]

# запустим функцию и запишем правильные ответы
ab_us = Kramer_method(x_us,y_us)
a_us = ab_us[0]
b_us = ab_us[1]
print ' 33[1m' + ' 33[4m' + "Оптимальные значения коэффициентов a и b:"  + ' 33[0m' 
print 'a =', a_us
print 'b =', b_us
print

# определим функцию для подсчета суммы квадратов ошибок
def errors_sq_Kramer_method(answers,x,y):
    list_errors_sq = []
    for i in range(len(x)):
        err = (answers[0] + answers[1]*x[i] - y[i])**2
        list_errors_sq.append(err)
    return sum(list_errors_sq)

# запустим функцию и запишем значение ошибки
error_sq = errors_sq_Kramer_method(ab_us,x_us,y_us)
print ' 33[1m' + ' 33[4m' + "Сумма квадратов отклонений" + ' 33[0m'
print error_sq
print

# замерим время расчета
# print ' 33[1m' + ' 33[4m' + "Время выполнения расчета суммы квадратов отклонений:" + ' 33[0m'
# % timeit error_sq = errors_sq_Kramer_method(ab,x_us,y_us)

Hier is wat ons gekry het:

Oplos van 'n eenvoudige lineêre regressievergelyking

Dus, die waardes van die koëffisiënte word gevind, die som van die kwadraatafwykings word gestel. Kom ons trek 'n reguit lyn op die verstrooiingshistogram in ooreenstemming met die gevonde koëffisiënte.

Regressielynkode

# определим функцию для формирования массива рассчетных значений выручки
def sales_count(ab,x,y):
    line_answers = []
    [line_answers.append(ab[0]+ab[1]*x[i]) for i in range(len(x))]
    return line_answers

# построим графики
print 'Грфик№2 "Правильные и расчетные ответы"'
plt.plot(x_us,y_us,'o',color='green',markersize=16, label = '$True$ $answers$')
plt.plot(x_us, sales_count(ab_us,x_us,y_us), color='red',lw=4,
         label='$Function: a + bx,$ $where$ $a='+str(round(ab_us[0],2))+',$ $b='+str(round(ab_us[1],2))+'$')
plt.xlabel('$Months$', size=16)
plt.ylabel('$Sales$', size=16)
plt.legend(loc=1, prop={'size': 16})
plt.show()

Grafiek No. 2 "Korrekte en berekende antwoorde"

Oplos van 'n eenvoudige lineêre regressievergelyking

Jy kan na die grafiek van afwykings vir elke maand kyk. In ons geval sal ons geen noemenswaardige praktiese waarde daaruit put nie, maar ons sal nuuskierigheid bevredig in hoe goed die eenvoudige lineêre regressievergelyking die afhanklikheid van inkomste op die maand van die jaar kenmerk.

Afwyking grafiek kode

# определим функцию для формирования массива отклонений в процентах
def error_per_month(ab,x,y):
    sales_c = sales_count(ab,x,y)
    errors_percent = []
    for i in range(len(x)):
        errors_percent.append(100*(sales_c[i]-y[i])/y[i])
    return errors_percent

# построим график
print 'График№3 "Отклонения по-месячно, %"'
plt.gca().bar(x_us, error_per_month(ab_us,x_us,y_us), color='brown')
plt.xlabel('Months', size=16)
plt.ylabel('Calculation error, %', size=16)
plt.show()

Grafiek No. 3 "Afwykings,%"

Oplos van 'n eenvoudige lineêre regressievergelyking

Nie perfek nie, maar ons het ons werk gedoen.

Kom ons skryf 'n funksie wat, om die koëffisiënte te bepaal Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking gebruik die biblioteek Numpy, meer presies, ons sal twee funksies skryf: een deur 'n pseudo-inverse matriks te gebruik (nie in die praktyk aanbeveel nie, aangesien die proses rekenaarmatig kompleks en onstabiel is), die ander met 'n matriksvergelyking.

Analitiese Oplossingskode (NumPy)

# для начала добавим столбец с не изменяющимся значением в 1. 
# Данный столбец нужен для того, чтобы не обрабатывать отдельно коэффицент a
vector_1 = np.ones((x_np.shape[0],1))
x_np = table_zero[['x']].values # на всякий случай приведем в первичный формат вектор x_np
x_np = np.hstack((vector_1,x_np))

# проверим то, что все сделали правильно
print vector_1[0:3]
print x_np[0:3]
print '***************************************'
print

# напишем функцию, которая определяет значения коэффициентов a и b с использованием псевдообратной матрицы
def pseudoinverse_matrix(X, y):
    # задаем явный формат матрицы признаков
    X = np.matrix(X)
    # определяем транспонированную матрицу
    XT = X.T
    # определяем квадратную матрицу
    XTX = XT*X
    # определяем псевдообратную матрицу
    inv = np.linalg.pinv(XTX)
    # задаем явный формат матрицы ответов
    y = np.matrix(y)
    # находим вектор весов
    return (inv*XT)*y

# запустим функцию
ab_np = pseudoinverse_matrix(x_np, y_np)
print ab_np
print '***************************************'
print

# напишем функцию, которая использует для решения матричное уравнение
def matrix_equation(X,y):
    a = np.dot(X.T, X)
    b = np.dot(X.T, y)
    return np.linalg.solve(a, b)

# запустим функцию
ab_np = matrix_equation(x_np,y_np)
print ab_np

Vergelyk die tyd wat dit geneem het om die koëffisiënte te bepaal Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking, volgens die 3 metodes wat aangebied word.

Kode vir Berekening Tyd Berekening

print ' 33[1m' + ' 33[4m' + "Время выполнения расчета коэффициентов без использования библиотеки NumPy:" + ' 33[0m'
% timeit ab_us = Kramer_method(x_us,y_us)
print '***************************************'
print
print ' 33[1m' + ' 33[4m' + "Время выполнения расчета коэффициентов с использованием псевдообратной матрицы:" + ' 33[0m'
%timeit ab_np = pseudoinverse_matrix(x_np, y_np)
print '***************************************'
print
print ' 33[1m' + ' 33[4m' + "Время выполнения расчета коэффициентов с использованием матричного уравнения:" + ' 33[0m'
%timeit ab_np = matrix_equation(x_np, y_np)

Oplos van 'n eenvoudige lineêre regressievergelyking

Op 'n klein hoeveelheid data kom 'n "selfgeskrewe" funksie na vore, wat die koëffisiënte vind deur die Cramer-metode te gebruik.

Nou kan jy aanbeweeg na ander maniere om die koëffisiënte te vind Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking.

gradiënt afkoms

Kom ons definieer eers wat 'n gradiënt is. Op 'n eenvoudige manier is die gradiënt 'n segment wat die rigting van maksimum groei van die funksie aandui. Na analogie van opdraande klim, waar die helling lyk, is daar die steilste klim na die top van die berg. Om die bergvoorbeeld te ontwikkel, onthou dat ons eintlik die steilste afdraande nodig het om die laagtepunt so vinnig as moontlik te bereik, dit wil sê die minimum - die plek waar die funksie nie toeneem nie en nie afneem nie. Op hierdie punt sal die afgeleide nul wees. Daarom het ons nie 'n gradiënt nodig nie, maar 'n anti-gradiënt. Om die antigradiënt te vind, moet jy net die gradiënt vermenigvuldig met -1 (minus een).

Laat ons aandag gee aan die feit dat 'n funksie verskeie minima kan hê, en nadat ons na een van hulle gedaal het volgens die algoritme wat hieronder voorgestel word, sal ons nie 'n ander minimum kan vind wat laer as die gevind een kan wees nie. Ontspan, ons is nie in gevaar nie! In ons geval het ons te doen met 'n enkele minimum, aangesien ons funksie Oplos van 'n eenvoudige lineêre regressievergelyking op die grafiek is 'n gewone parabool. En soos ons almal baie goed van 'n skoolwiskundekursus behoort te weet, het 'n parabool net een minimum.

Nadat ons uitgevind het hoekom ons 'n gradiënt nodig het, en ook dat die gradiënt 'n segment is, dit wil sê 'n vektor met gegewe koördinate, wat net dieselfde koëffisiënte is Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking ons kan gradiënt afkoms implementeer.

Voordat ek begin, stel ek voor om net 'n paar sinne oor die afkomsalgoritme te lees:

  • Ons bepaal pseudo-lukraak die koördinate van die koëffisiënte Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking. In ons voorbeeld sal ons koëffisiënte naby nul definieer. Dit is 'n algemene praktyk, maar elke geval kan sy eie praktyk hê.
  • Van koördinaat Oplos van 'n eenvoudige lineêre regressievergelyking trek die waarde van die gedeeltelike afgeleide van die 1ste orde by die punt af Oplos van 'n eenvoudige lineêre regressievergelyking. Dus, as die afgeleide positief is, neem die funksie toe. Daarom, deur die waarde van die afgeleide af te trek, sal ons in die teenoorgestelde rigting van groei beweeg, dit wil sê in die rigting van afkoms. As die afgeleide negatief is, dan is die funksie op hierdie punt besig om af te neem en die waarde van die afgeleide af te trek, beweeg ons na die daling.
  • Ons voer 'n soortgelyke operasie met die koördinaat uit Oplos van 'n eenvoudige lineêre regressievergelyking: trek die waarde van die gedeeltelike afgeleide by die punt af Oplos van 'n eenvoudige lineêre regressievergelyking.
  • Om nie oor die minimum te spring nie en nie in die diep ruimte weg te vlieg nie, is dit nodig om die stapgrootte in die rigting van afkoms te stel. Oor die algemeen kan 'n mens 'n hele artikel skryf oor hoe om die stap korrek in te stel en hoe om dit tydens afdaling te verander om die koste van berekeninge te verminder. Maar nou het ons 'n effens ander taak, en ons sal die stapgrootte bepaal deur die wetenskaplike metode van "poke" of, soos hulle in die gewone mense sê, empiries.
  • Sodra ons buite die gegewe koördinate is Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking trek die waardes van die afgeleides af, ons kry nuwe koördinate Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking. Ons neem die volgende stap (aftrekking), reeds vanaf die berekende koördinate. En so begin die siklus weer en weer, totdat die vereiste konvergensie bereik word.

Almal! Nou is ons gereed om te gaan soek na die diepste kloof van die Mariana-sloot. Laat ons begin.

Gradiënt-afkomskode

# напишем функцию градиентного спуска без использования библиотеки NumPy. 
# Функция на вход принимает диапазоны значений x,y, длину шага (по умолчанию=0,1), допустимую погрешность(tolerance)
def gradient_descent_usual(x_us,y_us,l=0.1,tolerance=0.000000000001):
    # сумма значений (все месяца)
    sx = sum(x_us)
    # сумма истинных ответов (выручка за весь период)
    sy = sum(y_us)
    # сумма произведения значений на истинные ответы
    list_xy = []
    [list_xy.append(x_us[i]*y_us[i]) for i in range(len(x_us))]
    sxy = sum(list_xy)
    # сумма квадратов значений
    list_x_sq = []
    [list_x_sq.append(x_us[i]**2) for i in range(len(x_us))]
    sx_sq = sum(list_x_sq)
    # количество значений
    num = len(x_us)
    # начальные значения коэффициентов, определенные псевдослучайным образом
    a = float(random.uniform(-0.5, 0.5))
    b = float(random.uniform(-0.5, 0.5))
    # создаем массив с ошибками, для старта используем значения 1 и 0
    # после завершения спуска стартовые значения удалим
    errors = [1,0]
    # запускаем цикл спуска
    # цикл работает до тех пор, пока отклонение последней ошибки суммы квадратов от предыдущей, не будет меньше tolerance
    while abs(errors[-1]-errors[-2]) > tolerance:
        a_step = a - l*(num*a + b*sx - sy)/num
        b_step = b - l*(a*sx + b*sx_sq - sxy)/num
        a = a_step
        b = b_step
        ab = [a,b]
        errors.append(errors_sq_Kramer_method(ab,x_us,y_us))
    return (ab),(errors[2:])

# запишем массив значений 
list_parametres_gradient_descence = gradient_descent_usual(x_us,y_us,l=0.1,tolerance=0.000000000001)


print ' 33[1m' + ' 33[4m' + "Значения коэффициентов a и b:" + ' 33[0m'
print 'a =', round(list_parametres_gradient_descence[0][0],3)
print 'b =', round(list_parametres_gradient_descence[0][1],3)
print


print ' 33[1m' + ' 33[4m' + "Сумма квадратов отклонений:" + ' 33[0m'
print round(list_parametres_gradient_descence[1][-1],3)
print



print ' 33[1m' + ' 33[4m' + "Количество итераций в градиентном спуске:" + ' 33[0m'
print len(list_parametres_gradient_descence[1])
print

Oplos van 'n eenvoudige lineêre regressievergelyking

Ons het tot onder in die Mariana-sloot geduik en daar het ons almal dieselfde waardes van die koëffisiënte gevind Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelykingwat eintlik te verwagte is.

Kom ons maak nog 'n duik, net hierdie keer sal die vulling van ons diepsee voertuig ander tegnologie wees, naamlik die biblioteek Numpy.

Gradient Descent Code (NumPy)

# перед тем определить функцию для градиентного спуска с использованием библиотеки NumPy, 
# напишем функцию определения суммы квадратов отклонений также с использованием NumPy
def error_square_numpy(ab,x_np,y_np):
    y_pred = np.dot(x_np,ab)
    error = y_pred - y_np
    return sum((error)**2)

# напишем функцию градиентного спуска с использованием библиотеки NumPy. 
# Функция на вход принимает диапазоны значений x,y, длину шага (по умолчанию=0,1), допустимую погрешность(tolerance)
def gradient_descent_numpy(x_np,y_np,l=0.1,tolerance=0.000000000001):
    # сумма значений (все месяца)
    sx = float(sum(x_np[:,1]))
    # сумма истинных ответов (выручка за весь период)
    sy = float(sum(y_np))
    # сумма произведения значений на истинные ответы
    sxy = x_np*y_np
    sxy = float(sum(sxy[:,1]))
    # сумма квадратов значений
    sx_sq = float(sum(x_np[:,1]**2))
    # количество значений
    num = float(x_np.shape[0])
    # начальные значения коэффициентов, определенные псевдослучайным образом
    a = float(random.uniform(-0.5, 0.5))
    b = float(random.uniform(-0.5, 0.5))
    # создаем массив с ошибками, для старта используем значения 1 и 0
    # после завершения спуска стартовые значения удалим
    errors = [1,0]
    # запускаем цикл спуска
    # цикл работает до тех пор, пока отклонение последней ошибки суммы квадратов от предыдущей, не будет меньше tolerance
    while abs(errors[-1]-errors[-2]) > tolerance:
        a_step = a - l*(num*a + b*sx - sy)/num
        b_step = b - l*(a*sx + b*sx_sq - sxy)/num
        a = a_step
        b = b_step
        ab = np.array([[a],[b]])
        errors.append(error_square_numpy(ab,x_np,y_np))
    return (ab),(errors[2:])

# запишем массив значений 
list_parametres_gradient_descence = gradient_descent_numpy(x_np,y_np,l=0.1,tolerance=0.000000000001)

print ' 33[1m' + ' 33[4m' + "Значения коэффициентов a и b:" + ' 33[0m'
print 'a =', round(list_parametres_gradient_descence[0][0],3)
print 'b =', round(list_parametres_gradient_descence[0][1],3)
print


print ' 33[1m' + ' 33[4m' + "Сумма квадратов отклонений:" + ' 33[0m'
print round(list_parametres_gradient_descence[1][-1],3)
print

print ' 33[1m' + ' 33[4m' + "Количество итераций в градиентном спуске:" + ' 33[0m'
print len(list_parametres_gradient_descence[1])
print

Oplos van 'n eenvoudige lineêre regressievergelyking
Koëffisiëntwaardes Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking is onveranderd.

Kom ons kyk hoe die fout tydens gradiëntdaling verander het, dit wil sê hoe die som van die kwadraatafwykings met elke stap verander het.

Kode vir somkwadraatafwykingplot

print 'График№4 "Сумма квадратов отклонений по-шагово"'
plt.plot(range(len(list_parametres_gradient_descence[1])), list_parametres_gradient_descence[1], color='red', lw=3)
plt.xlabel('Steps (Iteration)', size=16)
plt.ylabel('Sum of squared deviations', size=16)
plt.show()

Grafiek #4 "Som van kwadraatafwykings in gradiëntafkoms"

Oplos van 'n eenvoudige lineêre regressievergelyking

Op die grafiek sien ons dat die fout met elke stap afneem, en na 'n sekere aantal iterasies neem ons 'n byna horisontale lyn waar.

Laastens, kom ons evalueer die verskil in kode-uitvoeringstyd:

Kode vir tydsberekening van gradiënt afkoms berekening

print ' 33[1m' + ' 33[4m' + "Время выполнения градиентного спуска без использования библиотеки NumPy:" + ' 33[0m'
%timeit list_parametres_gradient_descence = gradient_descent_usual(x_us,y_us,l=0.1,tolerance=0.000000000001)
print '***************************************'
print

print ' 33[1m' + ' 33[4m' + "Время выполнения градиентного спуска с использованием библиотеки NumPy:" + ' 33[0m'
%timeit list_parametres_gradient_descence = gradient_descent_numpy(x_np,y_np,l=0.1,tolerance=0.000000000001)

Oplos van 'n eenvoudige lineêre regressievergelyking

Miskien doen ons iets verkeerd, maar weer 'n eenvoudige "selfgeskrewe" funksie wat nie die biblioteek gebruik nie Numpy voor die berekeningstyd van die funksie wat die biblioteek gebruik Numpy.

Maar ons staan ​​nie stil nie, maar beweeg na 'n ander opwindende manier om die eenvoudige lineêre regressievergelyking op te los. Ontmoet!

Stogastiese Gradiënt Afkoms

Om vinnig te verstaan ​​hoe stogastiese gradiënt-afkoms werk, is dit beter om die verskille van konvensionele gradiënt-afkoms te definieer. Ons, in die geval van gradiënt afkoms, in die vergelykings van afgeleides van Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking gebruik die som van die waardes van alle kenmerke en ware antwoorde beskikbaar in die steekproef (dit is die som van alle Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking). In stogastiese gradiënt-afkoms sal ons nie al die waardes in die steekproef gebruik nie, maar in plaas daarvan sal ons pseudo-lukraak die sogenaamde steekproefindeks kies en die waardes daarvan gebruik.

Byvoorbeeld, as die indeks gedefinieer word as nommer 3 (drie), dan neem ons die waardes Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking, dan vervang ons die waardes in die vergelykings van afgeleides en bepaal nuwe koördinate. Dan, nadat ons die koördinate bepaal het, bepaal ons weer die steekproefindeks op 'n pseudo-ewekansige wyse, vervang die waardes wat met die indeks ooreenstem in die parsiële differensiaalvergelykings, en bepaal die koördinate op 'n nuwe manier Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking ens. tot groen konvergensie. Met die eerste oogopslag kan dit lyk asof dit enigsins kan werk, maar dit werk. Dit is weliswaar opmerklik dat die fout nie met elke stap afneem nie, maar daar is beslis 'n neiging.

Wat is die voordele van stogastiese gradiënt-afkoms bo konvensionele gradiënt-afkoms? As ons steekproefgrootte baie groot is en in tienduisende waardes gemeet word, dan is dit baie makliker om byvoorbeeld 'n ewekansige duisend daarvan te verwerk as die hele steekproef. Dit is waar stogastiese gradiënt-afkoms inskop. In ons geval sal ons natuurlik nie ’n groot verskil agterkom nie.

Kom ons kyk na die kode.

Kode vir Stogastiese Gradiënt Afkoms

# определим функцию стох.град.шага
def stoch_grad_step_usual(vector_init, x_us, ind, y_us, l):
#     выбираем значение икс, которое соответствует случайному значению параметра ind 
# (см.ф-цию stoch_grad_descent_usual)
    x = x_us[ind]
#     рассчитывыаем значение y (выручку), которая соответствует выбранному значению x
    y_pred = vector_init[0] + vector_init[1]*x_us[ind]
#     вычисляем ошибку расчетной выручки относительно представленной в выборке
    error = y_pred - y_us[ind]
#     определяем первую координату градиента ab
    grad_a = error
#     определяем вторую координату ab
    grad_b = x_us[ind]*error
#     вычисляем новый вектор коэффициентов
    vector_new = [vector_init[0]-l*grad_a, vector_init[1]-l*grad_b]
    return vector_new


# определим функцию стох.град.спуска
def stoch_grad_descent_usual(x_us, y_us, l=0.1, steps = 800):
#     для самого начала работы функции зададим начальные значения коэффициентов
    vector_init = [float(random.uniform(-0.5, 0.5)), float(random.uniform(-0.5, 0.5))]
    errors = []
#     запустим цикл спуска
# цикл расчитан на определенное количество шагов (steps)
    for i in range(steps):
        ind = random.choice(range(len(x_us)))
        new_vector = stoch_grad_step_usual(vector_init, x_us, ind, y_us, l)
        vector_init = new_vector
        errors.append(errors_sq_Kramer_method(vector_init,x_us,y_us))
    return (vector_init),(errors)


# запишем массив значений 
list_parametres_stoch_gradient_descence = stoch_grad_descent_usual(x_us, y_us, l=0.1, steps = 800)

print ' 33[1m' + ' 33[4m' + "Значения коэффициентов a и b:" + ' 33[0m'
print 'a =', round(list_parametres_stoch_gradient_descence[0][0],3)
print 'b =', round(list_parametres_stoch_gradient_descence[0][1],3)
print


print ' 33[1m' + ' 33[4m' + "Сумма квадратов отклонений:" + ' 33[0m'
print round(list_parametres_stoch_gradient_descence[1][-1],3)
print

print ' 33[1m' + ' 33[4m' + "Количество итераций в стохастическом градиентном спуске:" + ' 33[0m'
print len(list_parametres_stoch_gradient_descence[1])

Oplos van 'n eenvoudige lineêre regressievergelyking

Ons kyk noukeurig na die koëffisiënte en vang onsself op die vraag "Hoe so?". Ons het ander waardes van die koëffisiënte gekry Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking. Miskien het stogastiese gradiënt-afkoms meer optimale parameters vir die vergelyking gevind? Ongelukkig nee. Dit is genoeg om na die som van kwadraatafwykings te kyk en te sien dat met nuwe waardes van die koëffisiënte, die fout groter is. Ons is nie haastig om te wanhoop nie. Kom ons bou 'n grafiek van foutverandering.

Kode vir die plot van die som van kwadraatafwykings in stogastiese gradiëntafkoms

print 'График №5 "Сумма квадратов отклонений по-шагово"'
plt.plot(range(len(list_parametres_stoch_gradient_descence[1])), list_parametres_stoch_gradient_descence[1], color='red', lw=2)
plt.xlabel('Steps (Iteration)', size=16)
plt.ylabel('Sum of squared deviations', size=16)
plt.show()

Grafiek #5 "Som van kwadraatafwykings in Stogastiese Gradiënt-afkoms"

Oplos van 'n eenvoudige lineêre regressievergelyking

Nadat ons na die skedule gekyk het, val alles in plek en nou sal ons alles regmaak.

So wat het gebeur? Die volgende het gebeur. Wanneer ons lukraak 'n maand kies, dan is dit vir die gekose maand wat ons algoritme poog om die fout in die berekening van inkomste te verminder. Dan kies ons nog 'n maand en herhaal die berekening, maar ons verminder die fout vir die tweede gekose maand. En laat ons nou onthou dat ons die eerste twee maande aansienlik afwyk van die lyn van die eenvoudige lineêre regressievergelyking. Dit beteken dat wanneer enige van hierdie twee maande gekies word, deur die fout van elkeen van hulle te verminder, ons algoritme die fout oor die hele steekproef ernstig verhoog. So wat om te doen? Die antwoord is eenvoudig: jy moet die trap van afkoms verminder. Inderdaad, deur die afkomstap te verminder, sal die fout ook ophou om op of af te "spring". Of eerder, die “spring”-fout sal nie ophou nie, maar dit sal dit nie so vinnig doen nie :) Kom ons kyk.

Kode om SGD met 'n kleiner stap te laat loop

# запустим функцию, уменьшив шаг в 100 раз и увеличив количество шагов соответсвующе 
list_parametres_stoch_gradient_descence = stoch_grad_descent_usual(x_us, y_us, l=0.001, steps = 80000)

print ' 33[1m' + ' 33[4m' + "Значения коэффициентов a и b:" + ' 33[0m'
print 'a =', round(list_parametres_stoch_gradient_descence[0][0],3)
print 'b =', round(list_parametres_stoch_gradient_descence[0][1],3)
print


print ' 33[1m' + ' 33[4m' + "Сумма квадратов отклонений:" + ' 33[0m'
print round(list_parametres_stoch_gradient_descence[1][-1],3)
print



print ' 33[1m' + ' 33[4m' + "Количество итераций в стохастическом градиентном спуске:" + ' 33[0m'
print len(list_parametres_stoch_gradient_descence[1])

print 'График №6 "Сумма квадратов отклонений по-шагово"'
plt.plot(range(len(list_parametres_stoch_gradient_descence[1])), list_parametres_stoch_gradient_descence[1], color='red', lw=2)
plt.xlabel('Steps (Iteration)', size=16)
plt.ylabel('Sum of squared deviations', size=16)
plt.show()

Oplos van 'n eenvoudige lineêre regressievergelyking

Grafiek #6 "Som van kwadraatafwykings vir stogastiese gradiënt afkoms (80 XNUMX stappe)"

Oplos van 'n eenvoudige lineêre regressievergelyking

Die kans het verbeter, maar is steeds nie ideaal nie. Hipoteties kan dit op hierdie manier reggestel word. Ons kies byvoorbeeld op die laaste 1000 iterasies die waardes van die koëffisiënte waarmee die minimum fout gemaak is. Dit is waar, hiervoor sal ons die waardes van die koëffisiënte self moet neerskryf. Ons sal dit nie doen nie, maar eerder aandag gee aan die skedule. Dit lyk glad en dit lyk asof die fout eweredig afneem. Eintlik is dit nie. Kom ons kyk na die eerste 1000 iterasies en vergelyk dit met die laastes.

Kode vir SGD-grafiek (eerste 1000 stappe)

print 'График №7 "Сумма квадратов отклонений по-шагово. Первые 1000 итераций"'
plt.plot(range(len(list_parametres_stoch_gradient_descence[1][:1000])), 
         list_parametres_stoch_gradient_descence[1][:1000], color='red', lw=2)
plt.xlabel('Steps (Iteration)', size=16)
plt.ylabel('Sum of squared deviations', size=16)
plt.show()

print 'График №7 "Сумма квадратов отклонений по-шагово. Последние 1000 итераций"'
plt.plot(range(len(list_parametres_stoch_gradient_descence[1][-1000:])), 
         list_parametres_stoch_gradient_descence[1][-1000:], color='red', lw=2)
plt.xlabel('Steps (Iteration)', size=16)
plt.ylabel('Sum of squared deviations', size=16)
plt.show()

Grafiek No. 7 "Som van kwadraatafwykings van SGD (eerste 1000 stappe)"

Oplos van 'n eenvoudige lineêre regressievergelyking

Grafiek #8 "Som van kwadraatafwykings van SGD (laaste 1000 stappe)"

Oplos van 'n eenvoudige lineêre regressievergelyking

Heel aan die begin van die afdraande neem ons 'n redelik eenvormige en skerp afname in die fout waar. By die laaste iterasies sien ons dat die fout om en om die waarde van 1,475 gaan en op sommige oomblikke selfs gelyk is aan hierdie optimale waarde, maar dan gaan dit steeds op ... Ek herhaal, jy kan die waardes van die koëffisiënte Oplos van 'n eenvoudige lineêre regressievergelyking и Oplos van 'n eenvoudige lineêre regressievergelyking, en kies dan diegene waarvoor die fout minimaal is. Ons het egter 'n groter probleem gehad: ons moes 80 duisend stappe neem (sien kode) om waardes naby aan optimaal te kry. En dit weerspreek reeds die idee om berekeningstyd te bespaar in stogastiese gradiënt-afkoms met betrekking tot gradiënt-afkoms. Wat kan reggestel en verbeter word? Dit is nie moeilik om te sien dat ons in die eerste iterasies geleidelik daal en daarom moet ons 'n groot stap in die eerste iterasies laat en die stap verminder soos ons vorentoe beweeg. Ons sal dit nie in hierdie artikel doen nie – dit het reeds gesloer. Die wat wil kan self dink hoe om dit te doen, dis nie moeilik nie 🙂

Kom ons voer nou stogastiese gradiënt-afkoms uit met behulp van die biblioteek Numpy (en laat ons nie struikel oor die rotse wat ons vroeër geïdentifiseer het nie)

Kode vir Stogastiese Gradiënt Afkoms (NumPy)

# для начала напишем функцию градиентного шага
def stoch_grad_step_numpy(vector_init, X, ind, y, l):
    x = X[ind]
    y_pred = np.dot(x,vector_init)
    err = y_pred - y[ind]
    grad_a = err
    grad_b = x[1]*err
    return vector_init - l*np.array([grad_a, grad_b])

# определим функцию стохастического градиентного спуска
def stoch_grad_descent_numpy(X, y, l=0.1, steps = 800):
    vector_init = np.array([[np.random.randint(X.shape[0])], [np.random.randint(X.shape[0])]])
    errors = []
    for i in range(steps):
        ind = np.random.randint(X.shape[0])
        new_vector = stoch_grad_step_numpy(vector_init, X, ind, y, l)
        vector_init = new_vector
        errors.append(error_square_numpy(vector_init,X,y))
    return (vector_init), (errors)

# запишем массив значений 
list_parametres_stoch_gradient_descence = stoch_grad_descent_numpy(x_np, y_np, l=0.001, steps = 80000)

print ' 33[1m' + ' 33[4m' + "Значения коэффициентов a и b:" + ' 33[0m'
print 'a =', round(list_parametres_stoch_gradient_descence[0][0],3)
print 'b =', round(list_parametres_stoch_gradient_descence[0][1],3)
print


print ' 33[1m' + ' 33[4m' + "Сумма квадратов отклонений:" + ' 33[0m'
print round(list_parametres_stoch_gradient_descence[1][-1],3)
print



print ' 33[1m' + ' 33[4m' + "Количество итераций в стохастическом градиентном спуске:" + ' 33[0m'
print len(list_parametres_stoch_gradient_descence[1])
print

Oplos van 'n eenvoudige lineêre regressievergelyking

Die waardes het geblyk amper dieselfde te wees as wanneer dit gedaal het sonder om te gebruik Numpy. Dit is egter logies.

Kom ons vind uit hoeveel tyd stogastiese gradiënt afdraandes ons geneem het.

Kode om SGD-berekeningstyd te bepaal (80k stappe)

print ' 33[1m' + ' 33[4m' +
"Время выполнения стохастического градиентного спуска без использования библиотеки NumPy:"
+ ' 33[0m'
%timeit list_parametres_stoch_gradient_descence = stoch_grad_descent_usual(x_us, y_us, l=0.001, steps = 80000)
print '***************************************'
print

print ' 33[1m' + ' 33[4m' +
"Время выполнения стохастического градиентного спуска с использованием библиотеки NumPy:"
+ ' 33[0m'
%timeit list_parametres_stoch_gradient_descence = stoch_grad_descent_numpy(x_np, y_np, l=0.001, steps = 80000)

Oplos van 'n eenvoudige lineêre regressievergelyking

Hoe verder die bos in, hoe donkerder die wolke: weereens wys die "selfgeskrewe" formule die beste resultaat. Dit alles dui daarop dat daar selfs meer subtiele maniere moet wees om die biblioteek te gebruik. Numpy, wat rekenaarbewerkings werklik versnel. In hierdie artikel sal ons nie oor hulle leer nie. Iets om op jou gemak oor na te dink :)

Ons som op

Voordat ek opsom, wil ek graag 'n vraag beantwoord wat heel waarskynlik by ons liewe leser ontstaan ​​het. Hoekom eintlik sulke “torings” met afdraandes, hoekom moet ons op en af ​​met die berg stap (meestal af) om die kosbare laagland te vind, as ons so 'n kragtige en eenvoudige toestel in ons hande het, in die vorm van 'n analitiese oplossing wat ons onmiddellik na die regte plek teleporteer?

Die antwoord op hierdie vraag lê op die oppervlak. Nou het ons 'n baie eenvoudige voorbeeld ontleed waarin die ware antwoord is Oplos van 'n eenvoudige lineêre regressievergelyking hang af van een kenmerk Oplos van 'n eenvoudige lineêre regressievergelyking. Jy sien dit nie gereeld in die lewe nie, so kom ons verbeel ons dat ons 2, 30, 50 of meer tekens het. Voeg hierby duisende, en selfs tienduisende waardes vir elke kenmerk. In hierdie geval kan die analitiese oplossing die toets druip en misluk. Op sy beurt sal gradiëntafkoms en sy variasies ons stadig maar seker nader aan die doelwit bring - die minimum van die funksie. En moenie bekommerd wees oor die spoed nie – ons sal waarskynlik steeds die maniere ontleed wat ons sal toelaat om die staplengte (dit is die spoed) in te stel en aan te pas.

En nou vir 'n kort opsomming.

Eerstens hoop ek dat die materiaal wat in die artikel aangebied word, beginner "datawetenskaplikes" sal help om te verstaan ​​hoe om eenvoudige (en nie net nie) lineêre regressievergelykings op te los.

Tweedens het ons na verskeie maniere gekyk om die vergelyking op te los. Nou, afhangende van die situasie, kan ons die een kies wat die beste geskik is vir die taak op hande.

Derdens het ons die krag van bykomende instellings gesien, naamlik die staplengte van gradiëntafkoms. Hierdie parameter moet nie verwaarloos word nie. Soos hierbo genoem, moet die staplengte tydens die afdraande verander word om die koste van die uitvoer van berekeninge te verminder.

Vierdens, in ons geval het "selfgeskrewe" funksies die beste tydresultaat van berekeninge getoon. Dit is waarskynlik te wyte aan nie die mees professionele gebruik van die biblioteek se vermoëns nie. Numpy. Maar hoe dit ook al sy, die gevolgtrekking stel homself soos volg voor. Aan die een kant is dit soms die moeite werd om gevestigde menings te bevraagteken, en aan die ander kant is dit nie altyd die moeite werd om alles te kompliseer nie - inteendeel, soms is 'n eenvoudiger manier om 'n probleem op te los meer effektief. En aangesien ons doel was om drie benaderings te ontleed om 'n eenvoudige lineêre regressievergelyking op te los, was die gebruik van "selfgeskrewe" funksies vir ons genoeg.

Letterkunde (of so iets)

1. Lineêre regressie

http://statistica.ru/theory/osnovy-lineynoy-regressii/

2. Kleinste vierkante metode

mathprofi.ru/method_naimenshih_kvadratov.html

3. Afgeleide

www.mathprofi.ru/chastnye_proizvodnye_primery.html

4. helling

mathprofi.ru/proizvodnaja_po_napravleniju_i_gradient.html

5. Gradiënt Afkoms

habr.com/en/post/471458

habr.com/en/post/307312

artemarakcheev.com//2017-12-31/linear_regression

6. NumPy-biblioteek

docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.linalg.solve.html

docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.linalg.pinv.html

pythonworld.com/numpy/2.html

Bron: will.com

Voeg 'n opmerking