Basit doğrusal regresyon denklemini çözme

Makalede basit (eşleştirilmiş) bir regresyon çizgisinin matematiksel denklemini belirlemenin çeşitli yolları tartışılmaktadır.

Burada tartışılan denklemi çözmenin tüm yöntemleri en küçük kareler yöntemine dayanmaktadır. Yöntemleri şu şekilde belirtelim:

  • Analitik çözüm
  • Dereceli alçalma
  • Stokastik gradyan inişi

Düz bir çizgi denklemini çözmenin her yöntemi için makale, esas olarak kütüphaneyi kullanmadan yazılanlara bölünmüş çeşitli işlevler sağlar. Dizi ve hesaplamalar için kullananlar Dizi. Ustaca kullanıldığına inanılıyor Dizi bilgi işlem maliyetlerini azaltacaktır.

Makalede verilen tüm kodlar dilde yazılmıştır. python 2.7 ile Jupyter Not Defteri. Kaynak kodu ve örnek verileri içeren dosya şu adreste yayınlanmıştır: Github

Makale daha çok hem yeni başlayanlara hem de yapay zekanın çok geniş bir bölümü olan makine öğrenimi üzerine yavaş yavaş uzmanlaşmaya başlayanlara yöneliktir.

Malzemeyi açıklamak için çok basit bir örnek kullanıyoruz.

Örnek koşullar

Bağımlılığı karakterize eden beş değerimiz var Y itibaren X (Tablo No. 1):

Tablo No. 1 “Örnek koşullar”

Basit doğrusal regresyon denklemini çözme

Değerlerin olduğunu varsayacağız Basit doğrusal regresyon denklemini çözme yılın ayıdır ve Basit doğrusal regresyon denklemini çözme — bu ayki gelir. Başka bir deyişle, gelir yılın ayına bağlıdır ve Basit doğrusal regresyon denklemini çözme - gelirin bağlı olduğu tek işaret.

Örnek öyle, hem gelirin yılın ayına koşullu bağımlılığı açısından hem de değer sayısı açısından - bunlardan çok azı var. Bununla birlikte, böyle bir basitleştirme, dedikleri gibi, yeni başlayanların özümsediği materyali her zaman kolaylıkla olmasa da açıklamayı mümkün kılacaktır. Ayrıca sayıların basitliği, örneği kağıt üzerinde önemli işçilik maliyetleri olmadan çözmek isteyenlere olanak sağlayacaktır.

Örnekte verilen bağımlılığın, formun basit (eşleştirilmiş) regresyon çizgisinin matematiksel denklemiyle oldukça iyi bir şekilde tahmin edilebileceğini varsayalım:

Basit doğrusal regresyon denklemini çözme

nerede Basit doğrusal regresyon denklemini çözme gelirin alındığı aydır, Basit doğrusal regresyon denklemini çözme - aya karşılık gelen gelir, Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme tahmin edilen doğrunun regresyon katsayılarıdır.

Katsayıya dikkat edin Basit doğrusal regresyon denklemini çözme genellikle tahmini çizginin eğimi veya eğimi olarak adlandırılır; miktarı temsil eder Basit doğrusal regresyon denklemini çözme değiştiğinde Basit doğrusal regresyon denklemini çözme.

Açıkçası, örnekteki görevimiz denklemdeki bu tür katsayıları seçmektir. Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme, aylara göre hesaplanan gelir değerlerimizin gerçek cevaplardan sapmaları, yani. örnekte sunulan değerler minimum olacaktır.

en küçük kareler yöntemi

En küçük kareler yöntemine göre sapmanın karesi alınarak hesaplanması gerekir. Bu teknik, zıt işaretleri varsa sapmaların karşılıklı olarak iptal edilmesini önlemenizi sağlar. Örneğin, bir durumda sapma şu şekilde ise +5 (artı beş) ve diğerinde -5 (eksi beş), bu durumda sapmaların toplamı birbirini iptal edecek ve 0 (sıfır) olacaktır. Sapmanın karesini almak değil, modülün özelliğini kullanmak mümkündür; o zaman tüm sapmalar pozitif olacak ve birikecektir. Bu nokta üzerinde ayrıntılı olarak durmayacağız, ancak hesaplamaların kolaylığı için sapmanın karesinin alınmasının geleneksel olduğunu belirtmekle yetineceğiz.

Sapmaların (hataların) karelerinin en küçük toplamını belirleyeceğimiz formül şu şekilde görünür:

Basit doğrusal regresyon denklemini çözme

nerede Basit doğrusal regresyon denklemini çözme gerçek cevapların (yani hesapladığımız gelirin) yaklaşık değerinin bir fonksiyonudur,

Basit doğrusal regresyon denklemini çözme doğru yanıtlardır (örnekte sağlanan gelir),

Basit doğrusal regresyon denklemini çözme örnek indeksidir (sapmanın belirlendiği ayın numarası)

Fonksiyonun türevini alalım, kısmi diferansiyel denklemleri tanımlayalım ve analitik çözüme geçmeye hazır olalım. Ama önce türevin ne olduğuna dair kısa bir gezinti yapalım ve türevin geometrik anlamını hatırlayalım.

Farklılaşma

Türev alma, bir fonksiyonun türevini bulma işlemidir.

Türev ne için kullanılır? Bir fonksiyonun türevi, fonksiyonun değişim hızını karakterize eder ve bize yönünü söyler. Belirli bir noktadaki türev pozitifse fonksiyon artar; aksi takdirde fonksiyon azalır. Mutlak türevin değeri ne kadar büyük olursa, fonksiyon değerlerinin değişim hızı da o kadar yüksek olur ve fonksiyon grafiğinin eğimi de o kadar dik olur.

Örneğin, Kartezyen koordinat sistemi koşulları altında, M(0,0) noktasındaki türevin değeri şuna eşittir: + 25 belirli bir noktada değer kaydırıldığında anlamına gelir Basit doğrusal regresyon denklemini çözme geleneksel bir birim tarafından sağa doğru, değer Basit doğrusal regresyon denklemini çözme 25 konvansiyonel birim artar. Grafikte değerlerde oldukça dik bir artış görünüyor Basit doğrusal regresyon denklemini çözme belirli bir noktadan.

Başka bir örnek. Türev değeri eşittir -0,1 yerinden edildiğinde anlamına gelir Basit doğrusal regresyon denklemini çözme bir geleneksel birim başına değer Basit doğrusal regresyon denklemini çözme yalnızca 0,1 geleneksel birim azalır. Aynı zamanda fonksiyonun grafiğinde zar zor fark edilen bir aşağı doğru eğim gözlemleyebiliriz. Bir dağ benzetmesi yaparsak, bir önceki örnekten farklı olarak, çok dik zirvelere tırmanmak zorunda kaldığımız gibi, sanki bir dağdan çok yavaş bir eğimle iniyoruz :)

Yani fonksiyonun türevini aldıktan sonra Basit doğrusal regresyon denklemini çözme ihtimallere göre Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme1. mertebeden kısmi diferansiyel denklemleri tanımlıyoruz. Denklemleri belirledikten sonra, katsayıların bu değerlerini seçebileceğimiz çözerek iki denklemden oluşan bir sistem alacağız. Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözmekarşılık gelen türevlerin değerlerinin belirli noktalarda çok çok küçük bir miktarda değiştiği ve analitik bir çözüm durumunda hiç değişmediği. Yani bu noktalardaki kısmi türevlerin değerleri sıfıra eşit olacağından, bulunan katsayılardaki hata fonksiyonu minimuma ulaşacaktır.

Yani, türev alma kurallarına göre, katsayıya göre 1. dereceden kısmi türev denklemi Basit doğrusal regresyon denklemini çözme şu şekli alacaktır:

Basit doğrusal regresyon denklemini çözme

1. mertebeden kısmi türev denklemi Basit doğrusal regresyon denklemini çözme şu şekli alacaktır:

Basit doğrusal regresyon denklemini çözme

Sonuç olarak, oldukça basit bir analitik çözümü olan bir denklem sistemi elde ettik:

başlangıç{denklem*}
başlangıç{vakalar}
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
son {vakalar}
bitiş{denklem*}

Denklemi çözmeden önce ön yükleme yapalım, yüklemenin doğru olup olmadığını kontrol edelim ve verileri formatlayalım.

Verileri yükleme ve biçimlendirme

Analitik çözüm için ve ardından gradyan ve stokastik gradyan inişi için kodu iki varyasyonda kullanacağımız gerçeğinden dolayı not edilmelidir: kütüphaneyi kullanmak Dizi ve onu kullanmadan, uygun veri formatlamasına ihtiyacımız olacak (koda bakın).

Veri yükleme ve işleme kodu

# импортируем все нужные нам библиотеки
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 '********************************************'

Görüntüleme

Şimdi öncelikle verileri yükledikten, ikinci olarak yüklemenin doğruluğunu kontrol ettikten ve son olarak verileri formatladıktan sonra ilk görselleştirmeyi gerçekleştireceğiz. Bunun için sıklıkla kullanılan yöntem çift ​​grafiği Kütüphane deniz doğumu. Örneğimizde sayı sınırlı olduğundan kütüphaneyi kullanmanın bir anlamı yoktur. deniz doğumu. Normal kütüphaneyi kullanacağız matplotlib ve dağılım grafiğine bakın.

Dağılım grafiği kodu

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

Grafik No. 1 “Gelirin yılın ayına bağımlılığı”

Basit doğrusal regresyon denklemini çözme

Analitik çözüm

En yaygın araçları kullanalım piton ve denklem sistemini çözelim:

başlangıç{denklem*}
başlangıç{vakalar}
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
son {vakalar}
bitiş{denklem*}

Cramer kuralına göre genel belirleyiciyi ve belirleyicileri şu şekilde bulacağız: Basit doğrusal regresyon denklemini çözme ve Basit doğrusal regresyon denklemini çözme, bundan sonra determinantı şuna böleriz: Basit doğrusal regresyon denklemini çözme genel belirleyiciye - katsayıyı bulun Basit doğrusal regresyon denklemini çözme, benzer şekilde katsayıyı buluyoruz Basit doğrusal regresyon denklemini çözme.

Analitik çözüm kodu

# определим функцию для расчета коэффициентов 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)

İşte elimizde olanlar:

Basit doğrusal regresyon denklemini çözme

Böylece katsayıların değerleri bulunmuş, sapmaların kareleri toplamı bulunmuştur. Bulunan katsayılara göre saçılma histogramı üzerine düz bir çizgi çizelim.

Regresyon satırı kodu

# определим функцию для формирования массива рассчетных значений выручки
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()

Tablo No. 2 “Doğru ve hesaplanmış cevaplar”

Basit doğrusal regresyon denklemini çözme

Her ay için sapma grafiğine bakabilirsiniz. Bizim durumumuzda bundan önemli bir pratik değer elde etmeyeceğiz, ancak basit doğrusal regresyon denkleminin gelirin yılın ayına bağımlılığını ne kadar iyi karakterize ettiği konusundaki merakımızı gidereceğiz.

Sapma grafik kodu

# определим функцию для формирования массива отклонений в процентах
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()

Grafik No. 3 “Sapmalar, %”

Basit doğrusal regresyon denklemini çözme

Mükemmel değil ama görevimizi tamamladık.

Katsayıları belirleyen bir fonksiyon yazalım. Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme kütüphaneyi kullanır DiziDaha doğrusu, iki fonksiyon yazacağız: biri sözde ters matris kullanarak (işlem hesaplama açısından karmaşık ve kararsız olduğundan pratikte önerilmez), diğeri ise bir matris denklemi kullanarak.

Analitik Çözüm Kodu (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

Katsayıları belirlemek için harcanan zamanı karşılaştıralım Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme, sunulan 3 yönteme uygun olarak.

Hesaplama süresini hesaplamak için kod

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)

Basit doğrusal regresyon denklemini çözme

Az miktarda veriyle, Cramer yöntemini kullanarak katsayıları bulan “kendi kendine yazılan” bir fonksiyon ortaya çıkıyor.

Artık katsayıları bulmanın diğer yollarına geçebilirsiniz Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme.

Dereceli alçalma

Öncelikle degradenin ne olduğunu tanımlayalım. Basitçe söylemek gerekirse gradyan, bir fonksiyonun maksimum büyüme yönünü gösteren bir segmenttir. Bir dağa tırmanmaya benzer şekilde, eğim yüzleri, dağın tepesine doğru en dik tırmanışın olduğu yerdir. Örneği dağla geliştirerek, ovaya en hızlı şekilde ulaşabilmek için aslında en dik inişe, yani minimum, fonksiyonun artmadığı veya azalmadığı yere ihtiyacımız olduğunu hatırlıyoruz. Bu noktada türev sıfıra eşit olacaktır. Bu nedenle, bir degradeye değil, bir antigradiyente ihtiyacımız var. Antigradient'i bulmak için degradeyi şu şekilde çarpmanız yeterlidir: -1 (eksi bir).

Bir fonksiyonun birden fazla minimuma sahip olabileceğine ve aşağıda önerilen algoritmayı kullanarak bunlardan birine indiğimizde, bulunandan daha düşük olabilecek başka bir minimum bulamayacağımıza dikkat edelim. Rahat olalım, bu bizim için bir tehdit değil! Bizim durumumuzda tek bir minimumla uğraşıyoruz, çünkü fonksiyonumuz Basit doğrusal regresyon denklemini çözme Grafikte düzenli bir parabol var. Ve hepimizin okuldaki matematik dersinden çok iyi bildiği gibi, bir parabolün yalnızca bir minimumu vardır.

Neden bir degradeye ihtiyacımız olduğunu ve ayrıca degradenin bir parça olduğunu, yani katsayıları tam olarak aynı olan belirli koordinatlara sahip bir vektör olduğunu öğrendikten sonra Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme degrade inişini uygulayabiliriz.

Başlamadan önce iniş algoritması hakkında birkaç cümle okumanızı öneririm:

  • Katsayıların koordinatlarını sözde rastgele bir şekilde belirliyoruz Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme. Örneğimizde sıfıra yakın katsayılar tanımlayacağız. Bu yaygın bir uygulamadır ancak her vakanın kendine özgü uygulaması olabilir.
  • Koordinattan Basit doğrusal regresyon denklemini çözme noktasındaki 1. dereceden kısmi türevin değerini çıkarın Basit doğrusal regresyon denklemini çözme. Yani türev pozitifse fonksiyon artar. Dolayısıyla türevin değerini çıkararak büyümenin tersi yönde yani iniş yönünde hareket edeceğiz. Türev negatifse bu noktadaki fonksiyon azalır ve türevin değerini çıkararak iniş yönünde hareket ederiz.
  • Koordinatla benzer bir işlem gerçekleştiriyoruz Basit doğrusal regresyon denklemini çözme: noktadaki kısmi türevin değerini çıkarın Basit doğrusal regresyon denklemini çözme.
  • Minimumun üzerinden atlayıp derin uzaya uçmamak için adım boyutunu iniş yönünde ayarlamak gerekir. Genel olarak, hesaplama maliyetlerini azaltmak için adımın nasıl doğru şekilde ayarlanacağı ve iniş süreci sırasında nasıl değiştirileceği hakkında tam bir makale yazabilirsiniz. Ancak şimdi önümüzde biraz farklı bir görev var ve adım boyutunu bilimsel "dürtme" yöntemini kullanarak veya halk dilinde dedikleri gibi ampirik olarak belirleyeceğiz.
  • Verilen koordinatlardan geldiğimizde Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme türevlerin değerlerini çıkarırsak yeni koordinatlar elde ederiz Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme. Zaten hesaplanan koordinatlardan bir sonraki adımı (çıkarma) atıyoruz. Ve böylece döngü, gerekli yakınsama sağlanana kadar tekrar tekrar başlar.

Tüm! Artık Mariana Çukuru'nun en derin geçidini aramaya hazırız. Başlayalım.

Gradyan iniş kodu

# напишем функцию градиентного спуска без использования библиотеки 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

Basit doğrusal regresyon denklemini çözme

Mariana Çukuru'nun en dibine daldık ve orada aynı katsayı değerlerini bulduk Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme, tam da beklenmesi gereken şey buydu.

Bir dalış daha yapalım ama bu sefer derin deniz aracımız başka teknolojilerle, yani kütüphaneyle dolu olacak Dizi.

Degrade iniş kodu (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

Basit doğrusal regresyon denklemini çözme
Katsayı değerleri Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme değiştirilemez.

Gradyan inişi sırasında hatanın nasıl değiştiğine, yani her adımda sapmaların karelerinin toplamının nasıl değiştiğine bakalım.

Sapmaların karelerinin toplamının grafiğini çizme kodu

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

Grafik No. 4 “Degrade iniş sırasında sapmaların karelerinin toplamı”

Basit doğrusal regresyon denklemini çözme

Grafikte her adımda hatanın azaldığını ve belirli sayıda tekrardan sonra neredeyse yatay bir çizgi gözlemlediğimizi görüyoruz.

Son olarak kod yürütme süresindeki farkı tahmin edelim:

Gradyan iniş hesaplama süresini belirleyen kod

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)

Basit doğrusal regresyon denklemini çözme

Belki bir şeyleri yanlış yapıyoruz ama yine de bu kütüphaneyi kullanmayan basit bir "evde yazılan" fonksiyondur. Dizi kütüphaneyi kullanan bir fonksiyonun hesaplama süresini aşıyor Dizi.

Ancak hareketsiz kalmıyoruz ve basit doğrusal regresyon denklemini çözmenin heyecan verici başka bir yolunu araştırmaya doğru ilerliyoruz. Tanışmak!

Stokastik gradyan inişi

Stokastik gradyan inişinin çalışma prensibini hızlı bir şekilde anlamak için, sıradan gradyan inişinden farklarını belirlemek daha iyidir. Gradyan iniş durumunda, türevlerin denklemlerinde Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme Örnekte mevcut olan tüm özelliklerin ve doğru cevapların değerlerinin toplamları (yani tüm özelliklerin toplamları) kullanıldı. Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme). Stokastik gradyan inişinde, örnekte mevcut olan tüm değerleri kullanmayacağız, bunun yerine sözde rastgele olarak sözde örnek indeksi seçip değerlerini kullanacağız.

Örneğin indeksin 3 (üç) numara olduğu belirlendiyse değerleri alıyoruz Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözmesonra değerleri türev denklemlerinde yerine koyarız ve yeni koordinatlar belirleriz. Daha sonra, koordinatları belirledikten sonra, örnek indeksi yine rastgele belirleriz, indekse karşılık gelen değerleri kısmi diferansiyel denklemlerde değiştiririz ve koordinatları yeni bir şekilde belirleriz. Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme vesaire. yakınsama yeşile dönene kadar. İlk bakışta bu hiç işe yarayacakmış gibi görünmeyebilir ama işe yarıyor. Hatanın her adımda azalmadığını belirtmekte fayda var ama bir eğilim olduğu kesin.

Stokastik gradyan inişinin geleneksel olana göre avantajları nelerdir? Eğer örneklem büyüklüğümüz çok büyükse ve onbinlerce değerle ölçülüyorsa, o zaman örneğin rastgele bin tanesini işlemek tüm örneklem yerine çok daha kolaydır. Stokastik gradyan inişinin devreye girdiği yer burasıdır. Bizim durumumuzda elbette çok fazla bir fark görmeyeceğiz.

Hadi koda bakalım.

Stokastik gradyan iniş kodu

# определим функцию стох.град.шага
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])

Basit doğrusal regresyon denklemini çözme

Katsayılara dikkatlice bakıyoruz ve kendimizi “Bu nasıl olabilir?” sorusunu sorarken buluyoruz. Başka katsayı değerlerimiz de var Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözme. Belki stokastik gradyan inişi denklem için daha uygun parametreler bulmuştur? Ne yazık ki hayır. Sapmaların karelerinin toplamına bakmak ve katsayıların yeni değerlerinde hatanın daha büyük olduğunu görmek yeterlidir. Umutsuzluğa kapılmak için acelemiz yok. Hata değişiminin bir grafiğini oluşturalım.

Stokastik gradyan inişinde sapmaların karelerinin toplamını çizmeye yönelik kod

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

Grafik No. 5 “Stokastik gradyan inişi sırasında sapmaların karelerinin toplamı”

Basit doğrusal regresyon denklemini çözme

Programa baktığımızda her şey yerli yerine oturuyor ve şimdi her şeyi düzelteceğiz.

Peki ne oldu? Aşağıdakiler oldu. Rastgele bir ay seçtiğimizde, algoritmamız gelir hesaplamasındaki hatayı seçilen ay için azaltmaya çalışır. Daha sonra başka bir ay seçip hesaplamayı tekrarlıyoruz ancak seçilen ikinci ay için hatayı azaltıyoruz. Şimdi, ilk iki ayın basit doğrusal regresyon denkleminden önemli ölçüde saptığını unutmayın. Yani bu iki aydan herhangi biri seçildiğinde algoritmamız her birinin hatasını azaltarak tüm örneklem için hatayı ciddi oranda artırıyor. Peki ne yapmalı? Cevap basit: iniş adımını azaltmanız gerekiyor. Sonuçta, iniş adımını azaltarak hata, yukarı ve aşağı "zıplamayı" da durduracaktır. Daha doğrusu “atlama” hatası durmayacak ama o kadar çabuk da bitmeyecek :) Hadi kontrol edelim.

SGD'yi daha küçük artışlarla çalıştıracak kod

# запустим функцию, уменьшив шаг в 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()

Basit doğrusal regresyon denklemini çözme

Grafik No. 6 “Stokastik gradyan inişi sırasında sapmaların karelerinin toplamı (80 bin adım)”

Basit doğrusal regresyon denklemini çözme

Katsayılar iyileşti ancak hala ideal değil. Varsayımsal olarak bu durum bu şekilde düzeltilebilir. Örneğin son 1000 yinelemede minimum hatanın yapıldığı katsayıların değerlerini seçiyoruz. Doğru, bunun için katsayıların değerlerini de yazmamız gerekecek. Bunu yapmayacağız, bunun yerine programa dikkat edeceğiz. Pürüzsüz görünüyor ve hata eşit şekilde azalıyor gibi görünüyor. Aslında, bu doğru değil. İlk 1000 yinelemeye bakalım ve bunları sonuncuyla karşılaştıralım.

SGD grafiği kodu (ilk 1000 adım)

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

Grafik No. 7 “SGD sapmalarının karelerinin toplamı (ilk 1000 adım)”

Basit doğrusal regresyon denklemini çözme

Grafik No. 8 “SGD sapmalarının karelerinin toplamı (son 1000 adım)”

Basit doğrusal regresyon denklemini çözme

İnişin en başında hatada oldukça düzenli ve dik bir azalma gözlemliyoruz. Son iterasyonlarda hatanın 1,475 civarında dolaştığını ve hatta bazı anlarda bu optimal değere eşitlendiğini ancak sonrasında hala yukarıya çıktığını görüyoruz... Tekrar ediyorum, değerleri yazabilirsiniz. katsayılar Basit doğrusal regresyon denklemini çözme и Basit doğrusal regresyon denklemini çözmeve ardından hatanın en az olduğu olanları seçin. Ancak daha ciddi bir sorunumuz vardı: Optimuma yakın değerler elde etmek için 80 bin adım atmak zorunda kaldık (kodlara bakın). Ve bu zaten, gradyan inişine göre stokastik gradyan inişiyle hesaplama süresinden tasarruf etme fikriyle çelişiyor. Neler düzeltilebilir ve geliştirilebilir? İlk iterasyonlarda emin adımlarla aşağı indiğimizi ve bu nedenle ilk iterasyonlarda büyük bir adım bırakıp ilerledikçe adımı azaltmamız gerektiğini fark etmek zor değil. Bu makalede bunu yapmayacağız - zaten çok uzun. Dileyenler bunu nasıl yapacaklarını kendileri düşünsünler, hiç de zor değil :)

Şimdi kütüphaneyi kullanarak stokastik gradyan inişini gerçekleştirelim Dizi (ve daha önce tespit ettiğimiz taşlara takılmayalım)

Stokastik Gradyan İniş Kodu (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

Basit doğrusal regresyon denklemini çözme

Değerlerin, kullanmadan inerken olduğu gibi neredeyse aynı olduğu ortaya çıktı. Dizi. Ancak bu mantıklıdır.

Stokastik gradyan inişlerinin ne kadar sürdüğünü bulalım.

SGD hesaplama süresini belirleme kodu (80 bin adım)

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)

Basit doğrusal regresyon denklemini çözme

Ormanın derinliklerine doğru bulutlar daha koyu olur: yine "kendi yazdığı" formül en iyi sonucu gösterir. Bütün bunlar kütüphaneyi kullanmanın daha da incelikli yollarının olması gerektiğini gösteriyor Dizi, bu da hesaplama işlemlerini gerçekten hızlandırır. Bu yazıda bunları öğrenmeyeceğiz. Boş zamanınızda düşünecek bir şeyiniz olacak :)

Özetliyoruz

Özetlemeden önce sevgili okurumuzun aklına gelebilecek bir soruya cevap vermek istiyorum. Aslında, neden inişlerle bu kadar “işkence”, eğer elimizde bu kadar güçlü ve basit bir cihaz varsa, değerli ovayı bulmak için neden dağda (çoğunlukla aşağı) inip çıkmamız gerekiyor? Bizi anında Doğru yere ışınlayacak analitik bir çözüm biçimi mi?

Bu sorunun cevabı yüzeyde yatıyor. Şimdi, doğru cevabın verildiği çok basit bir örneğe baktık. Basit doğrusal regresyon denklemini çözme bir işarete bağlıdır Basit doğrusal regresyon denklemini çözme. Bunu hayatta çok sık görmüyorsunuz, o yüzden 2, 30, 50 veya daha fazla burcumuz olduğunu hayal edelim. Buna her özellik için binlerce hatta onbinlerce değer ekleyelim. Bu durumda analitik çözüm teste dayanamayabilir ve başarısız olabilir. Buna karşılık, gradyan inişi ve onun varyasyonları bizi yavaş ama emin adımlarla hedefe, yani fonksiyonun minimumuna yaklaştıracaktır. Ve hız konusunda endişelenmeyin; muhtemelen adım uzunluğunu (yani hızı) ayarlamamıza ve düzenlememize olanak tanıyacak yollara bakacağız.

Ve şimdi asıl kısa özet.

Öncelikle, makalede sunulan materyalin, yeni başlayan "veri bilimcilerinin" basit (ve sadece değil) doğrusal regresyon denklemlerinin nasıl çözüleceğini anlamalarına yardımcı olacağını umuyorum.

İkinci olarak denklemi çözmenin çeşitli yollarına baktık. Artık duruma göre sorunu çözmeye en uygun olanı seçebiliriz.

Üçüncüsü, ek ayarların gücünü, yani degrade iniş adımı uzunluğunu gördük. Bu parametre ihmal edilemez. Yukarıda belirtildiği gibi hesaplama maliyetini azaltmak için iniş sırasında adım uzunluğunun değiştirilmesi gerekir.

Dördüncüsü, bizim durumumuzda, hesaplamalar için en iyi zaman sonuçlarını "evde yazılan" işlevler gösterdi. Bunun nedeni muhtemelen kütüphanenin yeteneklerinin yeterince profesyonelce kullanılmamasıdır. Dizi. Ancak öyle de olsa, aşağıdaki sonuç kendini gösteriyor. Bir yandan bazen yerleşik fikirleri sorgulamaya değer, diğer yandan her zaman her şeyi karmaşıklaştırmaya değmez - tam tersine, bazen bir sorunu çözmenin daha basit bir yolu daha etkilidir. Amacımız basit bir doğrusal regresyon denklemini çözmeye yönelik üç yaklaşımı analiz etmek olduğundan, "kendi kendine yazılan" fonksiyonların kullanılması bizim için oldukça yeterliydi.

Edebiyat (veya buna benzer bir şey)

1. Doğrusal regresyon

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

2. En Küçük Kareler Yöntemi

mathprofi.ru/metod_naimenshih_kvadratov.html

3. Türev

www.mathprofi.ru/chastnye_proizvodnye_primery.html

4. Gradyan

mathprofi.ru/proizvodnaja_po_napravleniju_i_gradient.html

5. Gradyan iniş

habr.com/en/post/471458

habr.com/en/post/307312

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

6. NumPy kütüphanesi

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

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

pythonworld.ru/numpy/2.html

Kaynak: habr.com

Yorum ekle