Risoluzione dell'equazione della regressione lineare semplice

L'articolo discute diversi modi per determinare l'equazione matematica di una semplice retta di regressione (accoppiata).

Tutti i metodi per risolvere l'equazione qui discussa si basano sul metodo dei minimi quadrati. Indichiamo i metodi come segue:

  • Soluzione analitica
  • Discesa gradiente
  • Discesa stocastica del gradiente

Per ogni metodo di risoluzione dell'equazione di una retta, l'articolo fornisce varie funzioni, che si dividono principalmente in quelle scritte senza utilizzare la libreria NumPy e quelli che usano per i calcoli NumPy. Si ritiene che l'uso abile NumPy ridurrΓ  i costi informatici.

Tutto il codice fornito nell'articolo Γ¨ scritto nella lingua python 2.7 con Notebook Jupyter. Il codice sorgente e il file con i dati di esempio vengono pubblicati su Github

L'articolo Γ¨ piΓΉ rivolto sia ai principianti che a coloro che hanno giΓ  iniziato gradualmente a padroneggiare lo studio di una sezione molto ampia dell'intelligenza artificiale: l'apprendimento automatico.

Per illustrare il materiale, utilizziamo un esempio molto semplice.

Condizioni di esempio

Abbiamo cinque valori che caratterizzano la dipendenza Y ΠΎΡ‚ X (Tabella n. 1):

Tabella n.1 β€œCondizioni di esempio”

Risoluzione dell'equazione della regressione lineare semplice

Assumeremo che i valori Risoluzione dell'equazione della regressione lineare semplice Γ¨ il mese dell'anno e Risoluzione dell'equazione della regressione lineare semplice - entrate di questo mese. In altre parole, le entrate dipendono dal mese dell'anno e Risoluzione dell'equazione della regressione lineare semplice - l'unico segno da cui dipendono le entrate.

L'esempio è così così, sia dal punto di vista della dipendenza condizionale delle entrate dal mese dell'anno, sia dal punto di vista del numero di valori: ce ne sono pochissimi. Tuttavia, tale semplificazione consentirà, come si suol dire, di spiegare, non sempre con facilità, il materiale assimilato dai principianti. E anche la semplicità dei numeri consentirà a chi lo desidera di risolvere l'esempio su carta senza notevoli costi di manodopera.

Supponiamo che la dipendenza fornita nell'esempio possa essere approssimata abbastanza bene dall'equazione matematica di una semplice retta di regressione (accoppiata) della forma:

Risoluzione dell'equazione della regressione lineare semplice

dove Risoluzione dell'equazione della regressione lineare semplice Γ¨ il mese in cui sono state ricevute le entrate, Risoluzione dell'equazione della regressione lineare semplice β€” entrate corrispondenti al mese, Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice sono i coefficienti di regressione della retta stimata.

Si noti che il coefficiente Risoluzione dell'equazione della regressione lineare semplice spesso chiamato pendenza o gradiente della linea stimata; rappresenta l'importo con cui il Risoluzione dell'equazione della regressione lineare semplice quando cambia Risoluzione dell'equazione della regressione lineare semplice.

Ovviamente, il nostro compito nell'esempio Γ¨ selezionare tali coefficienti nell'equazione Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice, a cui le deviazioni dei nostri valori di entrate calcolati per mese dalle risposte vere, ad es. i valori presentati nel campione saranno minimi.

Metodo dei minimi quadrati

Secondo il metodo dei minimi quadrati, la deviazione dovrebbe essere calcolata elevandola al quadrato. Questa tecnica consente di evitare la reciproca cancellazione delle deviazioni se hanno segni opposti. Ad esempio, se in un caso la deviazione è +5 (più cinque), e nell'altro -5 (meno cinque), la somma delle deviazioni si annullerà a vicenda e ammonterà a 0 (zero). È possibile non elevare al quadrato la deviazione, ma utilizzare la proprietà del modulo e quindi tutte le deviazioni saranno positive e si accumuleranno. Non ci soffermeremo su questo punto in dettaglio, ma indicheremo semplicemente che per comodità di calcolo è consuetudine elevare al quadrato la deviazione.

Ecco come appare la formula con la quale determineremo la somma minima delle deviazioni quadrate (errori):

Risoluzione dell'equazione della regressione lineare semplice

dove Risoluzione dell'equazione della regressione lineare semplice Γ¨ una funzione di approssimazione delle risposte vere (ovvero delle entrate che abbiamo calcolato),

Risoluzione dell'equazione della regressione lineare semplice sono le risposte vere (entrate fornite nel campione),

Risoluzione dell'equazione della regressione lineare semplice Γ¨ l'indice del campione (numero del mese in cui viene determinata la deviazione)

Differenziamo la funzione, definiamo le equazioni alle derivate parziali e prepariamoci a passare alla soluzione analitica. Ma prima facciamo una breve escursione su cos'Γ¨ la differenziazione e ricordiamo il significato geometrico della derivata.

Differenziazione

La derivazione Γ¨ l'operazione di trovare la derivata di una funzione.

A cosa serve il derivato? La derivata di una funzione caratterizza la velocitΓ  di variazione della funzione e ci dice la sua direzione. Se la derivata in un dato punto Γ¨ positiva la funzione aumenta, altrimenti diminuisce. E maggiore Γ¨ il valore della derivata assoluta, maggiore Γ¨ il tasso di variazione dei valori della funzione, nonchΓ© piΓΉ ripida la pendenza del grafico della funzione.

Ad esempio, nelle condizioni di un sistema di coordinate cartesiane, il valore della derivata nel punto M(0,0) Γ¨ uguale a + 25 significa che in un dato punto, quando il valore viene spostato Risoluzione dell'equazione della regressione lineare semplice a destra da un'unitΓ  convenzionale, valore Risoluzione dell'equazione della regressione lineare semplice aumenta di 25 unitΓ  convenzionali. Sul grafico sembra un aumento abbastanza marcato dei valori Risoluzione dell'equazione della regressione lineare semplice da un dato punto.

Un altro esempio. Il valore del derivato Γ¨ uguale all'0,1 ottobre significa che quando spostato Risoluzione dell'equazione della regressione lineare semplice per una unitΓ  convenzionale, valore Risoluzione dell'equazione della regressione lineare semplice diminuisce solo di 0,1 unitΓ  convenzionali. Allo stesso tempo, sul grafico della funzione, possiamo osservare una pendenza verso il basso appena percettibile. Facendo un'analogia con una montagna, Γ¨ come se stessimo discendendo molto lentamente un dolce pendio da una montagna, a differenza dell'esempio precedente, dove dovevamo scalare cime molto ripide :)

Quindi, dopo aver differenziato la funzione Risoluzione dell'equazione della regressione lineare semplice per probabilitΓ  Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice, definiamo equazioni alle derivate parziali del 1Β° ordine. Dopo aver determinato le equazioni, riceveremo un sistema di due equazioni, risolvendo il quale potremo selezionare tali valori dei coefficienti Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice, per il quale i valori delle derivate corrispondenti in determinati punti cambiano di una quantitΓ  molto, molto piccola, e nel caso di una soluzione analitica non cambiano affatto. In altre parole, la funzione di errore ai coefficienti trovati raggiungerΓ  il minimo, poichΓ© i valori delle derivate parziali in questi punti saranno pari a zero.

Quindi, secondo le regole della derivazione, l'equazione delle derivate parziali del 1Β° ordine rispetto al coefficiente Risoluzione dell'equazione della regressione lineare semplice assumerΓ  la forma:

Risoluzione dell'equazione della regressione lineare semplice

Equazione alle derivate parziali del 1Β° ordine rispetto a Risoluzione dell'equazione della regressione lineare semplice assumerΓ  la forma:

Risoluzione dell'equazione della regressione lineare semplice

Di conseguenza, abbiamo ricevuto un sistema di equazioni che ha una soluzione analitica abbastanza semplice:

inizio{equazione*}
iniziare{casi}
na + bsomma_limiti_{i=1}^nx_i β€” somma_limiti_{i=1}^ny_i = 0

somma_limiti_{i=1}^nx_i(a +b sommalimiti_{i=1}^nx_i β€” somma_limiti_{i=1}^ny_i) = 0
conclusione{casi}
fine{equazione*}

Prima di risolvere l'equazione precarichiamo, controlliamo che il caricamento sia corretto e formattiamo i dati.

Caricamento e formattazione dei dati

Da notare che poichΓ© per la soluzione analitica, e successivamente per la discesa del gradiente e stocastico, utilizzeremo il codice in due varianti: utilizzando la libreria NumPy e senza utilizzarlo, avremo bisogno di un'adeguata formattazione dei dati (vedi codice).

Codice di caricamento ed elaborazione dati

# ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ всС Π½ΡƒΠΆΠ½Ρ‹Π΅ Π½Π°ΠΌ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ
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 '********************************************'

Visualizzazione

Ora, dopo aver prima caricato i dati, poi verificato la correttezza del caricamento e infine formattato i dati, effettueremo la prima visualizzazione. Il metodo spesso utilizzato per questo Γ¨ trama a coppie Biblioteca Seaborn. Nel nostro esempio, a causa del numero limitato, non ha senso utilizzare la biblioteca Seaborn. Utilizzeremo la biblioteca normale matplotlib e basta guardare il grafico a dispersione.

Codice del grafico a dispersione

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()

Grafico n. 1 β€œDipendenza delle entrate dal mese dell'anno”

Risoluzione dell'equazione della regressione lineare semplice

Soluzione analitica

Usiamo gli strumenti piΓΉ comuni in python e risolvi il sistema di equazioni:

inizio{equazione*}
iniziare{casi}
na + bsomma_limiti_{i=1}^nx_i β€” somma_limiti_{i=1}^ny_i = 0

somma_limiti_{i=1}^nx_i(a +b sommalimiti_{i=1}^nx_i β€” somma_limiti_{i=1}^ny_i) = 0
conclusione{casi}
fine{equazione*}

Secondo la regola di Cramer troveremo il determinante generale, così come i determinanti di Risoluzione dell'equazione della regressione lineare semplice e Risoluzione dell'equazione della regressione lineare semplice, dopodiché, dividendo il determinante per Risoluzione dell'equazione della regressione lineare semplice al determinante generale: trova il coefficiente Risoluzione dell'equazione della regressione lineare semplice, allo stesso modo troviamo il coefficiente Risoluzione dell'equazione della regressione lineare semplice.

Codice della soluzione analitica

# ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ для расчСта коэффициСнтов 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)

Ecco cosa abbiamo ottenuto:

Risoluzione dell'equazione della regressione lineare semplice

Quindi, sono stati trovati i valori dei coefficienti, Γ¨ stata stabilita la somma delle deviazioni al quadrato. Disegniamo una linea retta sull'istogramma di dispersione in base ai coefficienti trovati.

Codice della linea di regressione

# ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ для формирования массива рассчСтных Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π²Ρ‹Ρ€ΡƒΡ‡ΠΊΠΈ
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()

Grafico n.2 β€œRisposte corrette e calcolate”

Risoluzione dell'equazione della regressione lineare semplice

Puoi guardare il grafico della deviazione per ogni mese. Nel nostro caso, non ne trarremo alcun valore pratico significativo, ma soddisferemo la nostra curiositΓ  su quanto bene la semplice equazione di regressione lineare caratterizzi la dipendenza delle entrate dal mese dell'anno.

Codice del grafico delle deviazioni

# ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ для формирования массива ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠΉ Π² ΠΏΡ€ΠΎΡ†Π΅Π½Ρ‚Π°Ρ…
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()

Grafico n. 3 β€œDeviazioni, %”

Risoluzione dell'equazione della regressione lineare semplice

Non perfetto, ma abbiamo completato il nostro compito.

Scriviamo una funzione che, per determinare i coefficienti Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice utilizza la libreria NumPy, piΓΉ precisamente, scriveremo due funzioni: una utilizzando una matrice pseudoinversa (sconsigliata nella pratica, poichΓ© il processo Γ¨ computazionalmente complesso e instabile), l'altra utilizzando un'equazione di matrice.

Codice della soluzione analitica (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

Confrontiamo il tempo impiegato per determinare i coefficienti Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice, secondo i 3 metodi presentati.

Codice per il calcolo del tempo di calcolo

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)

Risoluzione dell'equazione della regressione lineare semplice

Con una piccola quantitΓ  di dati, viene fuori una funzione β€œautoscritta”, che trova i coefficienti utilizzando il metodo di Cramer.

Ora puoi passare ad altri modi per trovare i coefficienti Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice.

Discesa gradiente

Innanzitutto, definiamo cos'è un gradiente. In poche parole, il gradiente è un segmento che indica la direzione di massima crescita di una funzione. Per analogia con la scalata di una montagna, dove le pareti in pendenza sono dove si trova la salita più ripida verso la cima della montagna. Sviluppando l'esempio con la montagna, ricordiamo che in realtà abbiamo bisogno della discesa più ripida per raggiungere il più velocemente possibile la pianura, cioè il minimo, il luogo dove la funzione non aumenta né diminuisce. A questo punto la derivata sarà pari a zero. Pertanto non abbiamo bisogno di un gradiente, ma di un antigradiente. Per trovare l'antigradiente devi solo moltiplicare il gradiente per -1 (meno uno).

Prestiamo attenzione al fatto che una funzione puΓ² avere diversi minimi, e scendendo in uno di essi utilizzando l'algoritmo proposto di seguito, non saremo in grado di trovare un altro minimo, che potrebbe essere inferiore a quello trovato. Rilassatevi, questa non Γ¨ una minaccia per noi! Nel nostro caso abbiamo a che fare con un unico minimo, essendo la nostra funzione Risoluzione dell'equazione della regressione lineare semplice sul grafico c'Γ¨ una parabola regolare. E come tutti dovremmo sapere molto bene dal nostro corso di matematica scolastica, una parabola ha un solo minimo.

Dopo aver scoperto perché avevamo bisogno di un gradiente e anche che il gradiente è un segmento, cioè un vettore con determinate coordinate, che sono esattamente gli stessi coefficienti Risoluzione dell'equazione della regressione lineare semplice и Risoluzione dell'equazione della regressione lineare semplice possiamo implementare la discesa del gradiente.

Prima di iniziare, suggerisco di leggere solo alcune frasi sull’algoritmo di discesa:

  • Determiniamo in modo pseudo-casuale le coordinate dei coefficienti Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice. Nel nostro esempio, determineremo coefficienti prossimi allo zero. Questa Γ¨ una pratica comune, ma ogni caso puΓ² avere la propria pratica.
  • Dalle coordinate Risoluzione dell'equazione della regressione lineare semplice sottrarre il valore della derivata parziale di 1Β° ordine nel punto Risoluzione dell'equazione della regressione lineare semplice. Quindi, se la derivata Γ¨ positiva, la funzione aumenta. Pertanto, sottraendo il valore del derivato, ci sposteremo nella direzione opposta alla crescita, cioΓ¨ nella direzione della discesa. Se la derivata Γ¨ negativa allora la funzione a questo punto diminuisce e sottraendo il valore della derivata ci muoviamo nella direzione di discesa.
  • Eseguiamo un'operazione simile con la coordinata Risoluzione dell'equazione della regressione lineare semplice: sottrarre il valore della derivata parziale nel punto Risoluzione dell'equazione della regressione lineare semplice.
  • Per non saltare oltre il minimo e volare nello spazio profondo, Γ¨ necessario impostare la dimensione del gradino nella direzione di discesa. In generale si potrebbe scrivere un articolo intero su come impostare correttamente il passo e su come modificarlo durante il processo di discesa in modo da ridurre i costi computazionali. Ma ora abbiamo davanti a noi un compito leggermente diverso e stabiliremo la dimensione del passo utilizzando il metodo scientifico del β€œpoke” o, come si dice nel linguaggio comune, empiricamente.
  • Una volta che siamo dalle coordinate indicate Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice sottraiamo i valori delle derivate, otteniamo nuove coordinate Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice. Facciamo il passo successivo (sottrazione), giΓ  dalle coordinate calcolate. E cosΓ¬ il ciclo ricomincia ancora e ancora, finchΓ© non viene raggiunta la convergenza richiesta.

Tutto! Ora siamo pronti per andare alla ricerca della gola piΓΉ profonda della Fossa delle Marianne. Iniziamo.

Codice per la discesa del gradiente

# напишСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Π³Ρ€Π°Π΄ΠΈΠ΅Π½Ρ‚Π½ΠΎΠ³ΠΎ спуска Π±Π΅Π· использования Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ 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

Risoluzione dell'equazione della regressione lineare semplice

Ci siamo tuffati fino al fondo della Fossa delle Marianne e lì abbiamo trovato tutti gli stessi valori di coefficiente Risoluzione dell'equazione della regressione lineare semplice и Risoluzione dell'equazione della regressione lineare semplice, che è esattamente quello che c'era da aspettarselo.

Facciamo un'altra immersione, solo che questa volta il nostro veicolo sottomarino sarΓ  riempito con altre tecnologie, vale a dire una biblioteca NumPy.

Codice per la discesa del gradiente (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

Risoluzione dell'equazione della regressione lineare semplice
Valori dei coefficienti Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice immutabile.

Diamo un'occhiata a come Γ¨ cambiato l'errore durante la discesa del gradiente, ovvero come Γ¨ cambiata la somma delle deviazioni al quadrato ad ogni passaggio.

Codice per tracciare somme di deviazioni quadrate

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()

Grafico n. 4 β€œSomma dei quadrati delle deviazioni durante la discesa del gradiente”

Risoluzione dell'equazione della regressione lineare semplice

Sul grafico vediamo che ad ogni passo l'errore diminuisce, e dopo un certo numero di iterazioni osserviamo una linea quasi orizzontale.

Infine, stimiamo la differenza nel tempo di esecuzione del codice:

Codice per determinare il tempo di calcolo della discesa del gradiente

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)

Risoluzione dell'equazione della regressione lineare semplice

Forse stiamo facendo qualcosa di sbagliato, ma anche in questo caso si tratta di una semplice funzione β€œscritta in casa” che non utilizza la libreria NumPy supera il tempo di calcolo di una funzione utilizzando la libreria NumPy.

Ma non stiamo fermi, ma ci stiamo muovendo verso lo studio di un altro entusiasmante modo per risolvere la semplice equazione di regressione lineare. Incontrare!

Discesa stocastica del gradiente

Per comprendere rapidamente il principio di funzionamento della discesa del gradiente stocastica, Γ¨ meglio determinarne le differenze rispetto alla discesa del gradiente ordinaria. Noi, nel caso della discesa del gradiente, nelle equazioni delle derivate di Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice utilizzato le somme dei valori di tutte le caratteristiche e le risposte vere disponibili nel campione (ovvero le somme di tutti Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice). Nella discesa del gradiente stocastico, non utilizzeremo tutti i valori presenti nel campione, ma selezioneremo invece in modo pseudo-casuale il cosiddetto indice del campione e utilizzeremo i suoi valori.

Ad esempio, se si determina che l'indice Γ¨ il numero 3 (tre), prendiamo i valori Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice, quindi sostituiamo i valori nelle equazioni derivate e determiniamo nuove coordinate. Quindi, dopo aver determinato le coordinate, determiniamo nuovamente in modo pseudo-casuale l'indice del campione, sostituiamo i valori corrispondenti all'indice nelle equazioni alle derivate parziali e determiniamo le coordinate in un modo nuovo Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice eccetera. finchΓ© la convergenza diventa verde. A prima vista potrebbe non sembrare che possa funzionare affatto, ma Γ¨ cosΓ¬. È vero che vale la pena notare che l’errore non diminuisce ad ogni passo, ma sicuramente c’è una tendenza.

Quali sono i vantaggi della discesa del gradiente stocastico rispetto a quella convenzionale? Se la dimensione del nostro campione Γ¨ molto ampia e misurata in decine di migliaia di valori, allora Γ¨ molto piΓΉ semplice elaborarne, ad esempio, un migliaio a caso, piuttosto che l’intero campione. È qui che entra in gioco la discesa stocastica del gradiente. Nel nostro caso, ovviamente, non noteremo molta differenza.

Diamo un'occhiata al codice.

Codice per la discesa del gradiente stocastico

# ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ стох.Π³Ρ€Π°Π΄.шага
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])

Risoluzione dell'equazione della regressione lineare semplice

Osserviamo attentamente i coefficienti e ci sorprendiamo a porci la domanda "Come puΓ² essere?" Abbiamo altri valori di coefficiente Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice. Forse la discesa del gradiente stocastico ha trovato parametri piΓΉ ottimali per l'equazione? Sfortunatamente no. Basta guardare la somma dei quadrati delle deviazioni e vedere che con nuovi valori dei coefficienti l'errore Γ¨ maggiore. Non abbiamo fretta di disperare. Costruiamo un grafico della modifica dell'errore.

Codice per tracciare la somma delle deviazioni quadrate nella discesa del gradiente stocastico

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()

Grafico n. 5 β€œSomma dei quadrati delle deviazioni durante la discesa del gradiente stocastico”

Risoluzione dell'equazione della regressione lineare semplice

Guardando il programma, tutto va a posto e ora sistemeremo tutto.

Allora, cos'Γ¨ successo? È successo quanto segue. Quando selezioniamo un mese in modo casuale, Γ¨ per il mese selezionato che il nostro algoritmo cerca di ridurre l'errore nel calcolo delle entrate. Quindi selezioniamo un altro mese e ripetiamo il calcolo, ma riduciamo l'errore per il secondo mese selezionato. Ora ricorda che i primi due mesi si discostano in modo significativo dalla linea della semplice equazione di regressione lineare. CiΓ² significa che quando viene selezionato uno qualsiasi di questi due mesi, riducendo l'errore di ciascuno di essi, il nostro algoritmo aumenta notevolmente l'errore per l'intero campione. Quindi che si fa? La risposta Γ¨ semplice: bisogna ridurre il gradino di discesa. Dopotutto, riducendo il passo di discesa, anche l'errore smetterΓ  di β€œsaltare” su e giΓΉ. O meglio, l'errore di β€œsalto” non si fermerΓ , ma non lo farΓ  cosΓ¬ velocemente :) Controlliamo.

Codice per eseguire SGD con incrementi piΓΉ piccoli

# запустим Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΠ² шаг Π² 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()

Risoluzione dell'equazione della regressione lineare semplice

Grafico n. 6 β€œSomma dei quadrati delle deviazioni durante la discesa del gradiente stocastico (80mila passi)”

Risoluzione dell'equazione della regressione lineare semplice

I coefficienti sono migliorati, ma non sono ancora ideali. Ipoteticamente, questo può essere corretto in questo modo. Selezioniamo, ad esempio, nelle ultime 1000 iterazioni i valori dei coefficienti con cui è stato commesso l'errore minimo. È vero, per questo dovremo annotare anche i valori dei coefficienti stessi. Non lo faremo, ma presteremo attenzione al programma. Sembra liscio e l'errore sembra diminuire in modo uniforme. In realtà, questo non è vero. Diamo un'occhiata alle prime 1000 iterazioni e confrontiamole con le ultime.

Codice per grafico SGD (primi 1000 passi)

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()

Grafico n. 7 β€œSomma dei quadrati delle deviazioni SGD (primi 1000 passi)”

Risoluzione dell'equazione della regressione lineare semplice

Grafico n. 8 β€œSomma dei quadrati delle deviazioni SGD (ultimi 1000 passi)”

Risoluzione dell'equazione della regressione lineare semplice

All'inizio della discesa osserviamo una diminuzione dell'errore abbastanza uniforme e marcata. Nelle ultime iterazioni vediamo che l'errore gira intorno al valore di 1,475 e in alcuni momenti arriva anche a questo valore ottimale, ma poi sale ancora... Ripeto, potete annotare i valori del coefficienti Risoluzione dell'equazione della regressione lineare semplice ΠΈ Risoluzione dell'equazione della regressione lineare semplice, quindi seleziona quelli per i quali l'errore Γ¨ minimo. Abbiamo perΓ² avuto un problema piΓΉ serio: abbiamo dovuto fare 80mila passi (vedi codice) per ottenere valori prossimi a quelli ottimali. E questo giΓ  contraddice l’idea di risparmiare tempo di calcolo con la discesa stocastica del gradiente rispetto alla discesa del gradiente. Cosa si puΓ² correggere e migliorare? Non Γ¨ difficile notare che nelle prime iterazioni stiamo scendendo con sicurezza e, quindi, dovremmo lasciare un ampio passo nelle prime iterazioni e ridurre il passo man mano che andiamo avanti. Non lo faremo in questo articolo: Γ¨ giΓ  troppo lungo. Chi lo desidera puΓ² pensare da solo a come farlo, non Γ¨ difficile :)

Ora eseguiamo la discesa del gradiente stocastico utilizzando la libreria NumPy (e non inciampiamo nelle pietre che abbiamo individuato prima)

Codice per la discesa del gradiente stocastico (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

Risoluzione dell'equazione della regressione lineare semplice

I valori si sono rivelati quasi gli stessi di quando si scendeva senza utilizzare NumPy. Tuttavia, questo Γ¨ logico.

Scopriamo quanto tempo ci hanno impiegato le discese a gradiente stocastico.

Codice per determinare il tempo di calcolo SGD (80mila passaggi)

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)

Risoluzione dell'equazione della regressione lineare semplice

PiΓΉ ci si addentra nella foresta, piΓΉ scure sono le nuvole: ancora una volta, la formula β€œautoscritta” mostra il risultato migliore. Tutto ciΓ² suggerisce che devono esserci modi ancora piΓΉ sottili per utilizzare la biblioteca NumPy, che velocizzano davvero le operazioni di calcolo. In questo articolo non ne parleremo. Ci sarΓ  qualcosa a cui pensare nel tuo tempo libero :)

Riassumiamo

Prima di riassumere, vorrei rispondere ad una domanda che molto probabilmente Γ¨ nata dal nostro caro lettore. PerchΓ©, infatti, tale β€œtortura” con le discese, perchΓ© dobbiamo camminare su e giΓΉ per la montagna (soprattutto giΓΉ) per trovare la preziosa pianura, se abbiamo tra le mani un dispositivo cosΓ¬ potente e semplice, nel forma di una soluzione analitica, che ci teletrasporta istantaneamente nel posto giusto?

La risposta a questa domanda si trova in superficie. Ora abbiamo esaminato un esempio molto semplice, in cui la risposta vera Γ¨ Risoluzione dell'equazione della regressione lineare semplice dipende da un segno Risoluzione dell'equazione della regressione lineare semplice. Non lo vedi spesso nella vita, quindi immaginiamo di avere 2, 30, 50 o piΓΉ segni. Aggiungiamo a questo migliaia, o anche decine di migliaia di valori per ciascun attributo. In questo caso, la soluzione analitica potrebbe non resistere al test e fallire. A sua volta, la discesa del gradiente e le sue variazioni ci avvicineranno lentamente ma inesorabilmente all'obiettivo: il minimo della funzione. E non preoccuparti della velocitΓ : probabilmente esamineremo i modi che ci consentiranno di impostare e regolare la lunghezza del passo (ovvero la velocitΓ ).

E ora il vero e proprio breve riassunto.

In primo luogo, spero che il materiale presentato nell'articolo aiuti i β€œdata scientist” principianti a capire come risolvere semplici (e non solo) equazioni di regressione lineare.

In secondo luogo, abbiamo esaminato diversi modi per risolvere l’equazione. Ora, a seconda della situazione, possiamo scegliere quello piΓΉ adatto a risolvere il problema.

In terzo luogo, abbiamo visto la potenza delle impostazioni aggiuntive, ovvero la lunghezza del gradino di discesa del gradiente. Questo parametro non puΓ² essere trascurato. Come notato sopra, per ridurre il costo dei calcoli, la lunghezza del passo dovrebbe essere modificata durante la discesa.

In quarto luogo, nel nostro caso, le funzioni β€œscritte in casa” hanno mostrato i migliori risultati temporali per i calcoli. CiΓ² Γ¨ probabilmente dovuto all'uso non proprio professionale delle capacitΓ  della biblioteca NumPy. Comunque sia, la seguente conclusione suggerisce da sola. Da un lato, a volte vale la pena mettere in discussione le opinioni consolidate e, dall'altro, non sempre vale la pena complicare tutto: al contrario, a volte un modo piΓΉ semplice per risolvere un problema Γ¨ piΓΉ efficace. E poichΓ© il nostro obiettivo era analizzare tre approcci per risolvere una semplice equazione di regressione lineare, l'uso di funzioni "autoprodotte" per noi era abbastanza.

Letteratura (o qualcosa del genere)

1. Regressione lineare

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

2. Metodo dei minimi quadrati

mathprofi.ru/metod_naimenshih_kvadratov.html

3. Derivato

www.mathprofi.ru/chastnye_proizvodnye_primery.html

4. gradiente

mathprofi.ru/proizvodnaja_po_napravleniju_i_gradient.html

5. Discesa del gradiente

habr.com/en/post/471458

habr.com/en/post/307312

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

6. Libreria NumPy

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.ru/numpy/2.html

Fonte: habr.com

Aggiungi un commento