Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Макалада жөнөкөй (жупташкан) регрессия сызыгынын математикалык теңдемесин аныктоонун бир нече жолдору каралат.

Бул жерде талкууланган теңдемени чечүүнүн бардык ыкмалары эң кичине квадраттар ыкмасына негизделген. Методдорду төмөнкүдөй белгилейли:

  • Аналитикалык чечим
  • Градиенттин түшүүсү
  • Стохастикалык градиенттин түшүүсү

Түз сызыктын теңдемесин чечүүнүн ар бир ыкмасы үчүн макалада ар кандай функциялар каралган, алар негизинен китепкананы колдонбостон жазылгандарга бөлүнөт. numpy жана эсептөөлөр үчүн колдонгондор numpy. Бул билгичтик менен пайдалануу деп эсептелет numpy эсептөө чыгымдарын азайтат.

Макалада берилген бардык код тилде жазылган питон 2.7 менен Jupyter дептери. Булак коду жана үлгү маалыматтары бар файл жайгаштырылат Github

Макала жаңыдан баштагандарга да, жасалма интеллекттин өтө кеңири бөлүмүн - машина үйрөнүүнү акырындык менен үйрөнө баштагандарга да багытталган.

Материалды түшүндүрүү үчүн биз абдан жөнөкөй мисалды колдонобуз.

Мисал шарттары

Бизде көз карандылыкты мүнөздөгөн беш баалуулук бар Y от X (No1 таблица):

Таблица №1 «Мисал шарттары»

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Биз баалуулуктар деп ойлойбуз Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу жылдын айы болуп саналат, жана Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу - ушул айдагы киреше. Башкача айтканда, киреше жылдын айына жараша болот, жана Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу - киреше көз каранды болгон жалгыз белги.

Мисалы, кирешенин жылдын айына шарттуу көз карандылыгы жагынан да, баалуулуктардын саны боюнча да - алардын саны өтө аз. Бирок, мындай жөнөкөйлөштүрүү, алар айткандай, башталгычтар өздөштүргөн материалды ар дайым оңой эмес, түшүндүрүүгө мүмкүндүк берет. Жана ошондой эле сандардын жөнөкөйлүгү олуттуу эмгек чыгымдары жок эле кагаз жүзүндө мисал чечүүнү каалагандарга мүмкүндүк берет.

Мисалда берилген көз карандылыкты форманын жөнөкөй (жупташкан) регрессия сызыгынын математикалык теңдемеси менен абдан жакшы жакындатууга болот деп ойлойлу:

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

кайда Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу киреше алынган ай, Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу - айга тиешелүү кирешелер; Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу бааланган линиянын регрессия коэффициенттери болуп саналат.

Коэффициент экенин белгилей кетүү керек Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу көбүнчө болжолдуу сызыктын эңкейиши же градиенти деп аталат; болгон сумманы билдирет Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу ал өзгөргөндө Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу.

Албетте, биздин мисалдагы милдетибиз теңдемеде ушундай коэффициенттерди тандоо Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу, анда биздин эсептелген кирешелердин ай боюнча туура жооптордон четтөөлөрү, б.а. үлгүдө берилген баалуулуктар минималдуу болот.

Эң кичине квадрат ыкмасы

Эң кичине квадраттар ыкмасына ылайык, четтөөнү квадраттоо жолу менен эсептөө керек. Бул ыкма карама-каршы белгилери бар болсо, четтөөлөрдү өз ара жокко чыгаруудан качууга мүмкүндүк берет. Мисалы, бир учурда, четтөө болуп саналат +5 (плюс беш), жана башка -5 (минус беш), анда четтөөлөрдүн суммасы бири-бирин жокко чыгарат жана 0 (нөл) түзөт. Четтөөнүн квадратын эмес, модулдун касиетин колдонсо болот, ошондо бардык четтөөлөр оң болуп, топтолот. Биз бул пунктка майда-чүйдөсүнө чейин токтолбойбуз, бирок жөн гана эсептөөлөрдүн ыңгайлуулугу үчүн четтөөнүн квадратын алуу салтка айланганын көрсөтөбүз.

Биз квадраттык четтөөлөрдүн (каталардын) эң аз суммасын аныктай турган формула мына ушундай болот:

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

кайда Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу чыныгы жооптордун жакындоо функциясы (башкача айтканда, биз эсептеген киреше),

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу туура жооптор (үлгүдө берилген киреше),

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу үлгү индекси болуп саналат (четтөө аныкталган айдын саны)

Функцияны дифференциалдап, жарым-жартылай дифференциалдык теңдемелерди аныктап, аналитикалык чечимге өтүүгө даяр бололу. Бирок адегенде дифференциация деген эмне жөнүндө кыскача экскурсия жасап, туундунун геометриялык маанисин эстеп көрөлү.

Дифференциация

Дифференциалдоо – функциянын туундусун табуу операциясы.

Туунду эмне үчүн колдонулат? Функциянын туундусу функциянын өзгөрүү ылдамдыгын мүнөздөйт жана анын багытын айтат. Эгерде берилген чекиттеги туунду оң болсо, анда функция өсөт, антпесе функция төмөндөйт. Ал эми абсолюттук туундунун мааниси канчалык чоң болсо, функциянын маанилеринин өзгөрүү ылдамдыгы ошончолук жогору, ошондой эле функциянын графигинин эңкейиши да ошончолук жогору болот.

Мисалы, декарттык координаттар системасынын шартында М(0,0) чекитиндеги туундунун мааниси 25 + мааниси жылдырылып, берилген чекитте дегенди билдирет Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу шарттуу бирдик, маани боюнча оңго Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу 25 шарттуу бирдикке көбөйөт. Графикте бул баалуулуктардын кескин көтөрүлүшү сыяктуу көрүнөт Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу берилген чекиттен.

Башка мисал. Туунду маани бирдей -0,1 которгондо дегенди билдирет Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу бир шарттуу бирдикке, мааниге Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу 0,1 шарттуу бирдикке гана азаят. Ошол эле учурда, функциянын графигинде биз анча байкалбаган ылдый эңкейишти байкай алабыз. Тоо менен салыштыруу, биз мурунку мисалдан айырмаланып, тоодон акырындык менен ылдый түшүп бара жаткандайбыз, ал жерде абдан тик чокуларга чыгууга туура келген :)

Ошентип, функцияны дифференциялоодон кийин Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу ыктымалдыгы боюнча Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу, 1-даражадагы жарым-жартылай дифференциалдык теңдемелерди аныктайбыз. Теңдемелерди аныктагандан кийин, биз эки теңдеменин тутумун алабыз, аны чечүү менен биз коэффициенттердин ушундай маанилерин тандай алабыз. Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу, анда берилген чекиттердеги тиешелүү туундулардын маанилери өтө, өтө аз өлчөмдө өзгөрөт, ал эми аналитикалык чечимде такыр өзгөрбөйт. Башкача айтканда, табылган коэффициенттердеги ката функциясы минимумга жетет, анткени бул чекиттердеги жарым-жартылай туундулардын маанилери нөлгө барабар болот.

Ошентип, дифференциялоонун эрежелерине ылайык, коэффициентке карата 1-даражадагы жарым-жартылай туунду теңдеме Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу формада болот:

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

карата 1-даражадагы жарым-жартылай туунду теңдеме Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу формада болот:

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Натыйжада, биз абдан жөнөкөй аналитикалык чечими бар теңдемелердин системасын алдык:

башталышы{теңдеме*}
башталышы{иштер}
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
аягы{иштер}
аягы{теңдеме*}

Теңдемени чечүүдөн мурун, алдын ала жүктөйбүз, жүктөөнүн туура экенин текшерип, маалыматтарды форматтайлы.

Маалыматтарды жүктөө жана форматтоо

Белгилей кетчү нерсе, аналитикалык чечим үчүн, андан кийин градиенттик жана стохастикалык градиенттик түшүү үчүн биз кодду эки вариантта колдонобуз: китепкананы колдонуу numpy жана аны колдонбостон, анда бизге тиешелүү маалыматтарды форматтоо керек болот (кодду караңыз).

Маалыматтарды жүктөө жана иштетүү коду

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

Визуализация

Эми, биринчиден, маалыматтарды жүктөгөндөн кийин, экинчиден, жүктөөнүн тууралыгын текшерип, акырында маалыматтарды форматтагандан кийин, биз биринчи визуализацияны жүргүзөбүз. Бул үчүн көбүнчө колдонулган ыкма жуп сюжет китепкана деңиз туулган. Биздин мисалда саны чектелүү болгондуктан китепкананы колдонуунун эч кандай пайдасы жок деңиз туулган. Биз кадимки китепкананы колдонобуз matplotlib жана жөн гана чачыранды карап.

Scatterplot коду

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

№1 диаграмма «Кирешелер жылдын айына көз карандылыгы»

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Аналитикалык чечим

Келгиле, эң кеңири таралган куралдарды колдонолу код жана теңдемелер системасын чечиңиз:

башталышы{теңдеме*}
башталышы{иштер}
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
аягы{иштер}
аягы{теңдеме*}

Крамердин эрежеси боюнча аркылуу жалпы аныктагычты, ошондой эле аныктоочуларды табабыз Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу жана тарабынан Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу, андан кийин аныктагычты бөлүү Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу жалпы аныктоочуга - коэффициентти табыңыз Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу, ошентип биз коэффициентти табабыз Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу.

Аналитикалык чечим коду

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

Бул жерде бизде эмне бар:

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Ошентип, коэффициенттердин маанилери табылды, квадраттык четтөөлөрдүн суммасы аныкталды. Табылган коэффициенттерге ылайык чачыратуу гистограммасына түз сызык салалы.

Регрессия сызык коду

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

№2 диаграмма «Туура жана эсептелген жооптор»

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Ар бир ай үчүн четтөө графигин карай аласыз. Биздин учурда, биз андан эч кандай олуттуу практикалык мааниге ээ болбойбуз, бирок биз жөнөкөй сызыктуу регрессиялык теңдеме кирешенин жылдын айына көз карандылыгын канчалык деңгээлде жакшы мүнөздөй турганына болгон кызыгуубузду канааттандырабыз.

Четтөө диаграммасынын коду

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

Диаграмма № 3 «Четтөөлөр, %»

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Кемчиликсиз эмес, бирок биз тапшырмабызды аткардык.

Коэффициенттерди аныктоо үчүн функцияны жазалы Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу китепкананы колдонот numpy, тагыраак айтканда, биз эки функцияны жазабыз: бири псевдоинверс матрицаны (практикада сунуш кылынбайт, анткени процесс эсептөө татаал жана туруксуз болгондуктан), экинчиси матрицалык теңдеменин жардамы менен.

Аналитикалык чечим коду (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

Коэффициенттерди аныктоого кеткен убакытты салыштырып көрөлү Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу, берилген 3 ыкмага ылайык.

Эсептөө убактысын эсептөө үчүн код

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)

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Бир аз сандагы маалыматтар менен алдыда "өз алдынча жазылган" функция чыгат, ал Крамердин ыкмасы менен коэффициенттерди табат.

Эми коэффициенттерди табуунун башка жолдоруна өтсөңүз болот Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу.

Градиенттин түшүүсү

Биринчиден, градиент деген эмне экенин аныктап алалы. Жөнөкөй сөз менен айтканда, градиент функциянын максималдуу өсүү багытын көрсөткөн сегмент. Тоого чыгууга окшошуп, градиент беттери тоонун чокусуна эң тик чыккан жер. Тоо менен мисалды иштеп чыгуу, биз, чынында, мүмкүн болушунча тезирээк түздүккө жетүү үчүн эң тик түшүү керек экенин эстейбиз, башкача айтканда, минимум - функция көбөйбөгөн же азайбаган жер. Бул учурда туунду нөлгө барабар болот. Демек, бизге градиент эмес, антиградиент керек. Антиградиентти табуу үчүн градиентти көбөйтүш керек -1 (минус бир).

Функциянын бир нече минимумдары болушу мүмкүн экенине көңүл буралы жана төмөндө сунуш кылынган алгоритм боюнча алардын бирине түшкөндөн кийин, табылгандан төмөн болушу мүмкүн болгон башка минимум таба албайбыз. Эс алалы, бул бизге коркунуч эмес! Биздин учурда биз бир минимум менен алектенебиз, анткени биздин функциябыз Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу графикте кадимки парабола. Биздин мектептеги математика курсунан баарыбыз жакшы билишибиз керек, параболанын бир гана минимум бар.

Бизге градиент эмне үчүн керек экенин, ошондой эле градиент сегмент экенин, б.а. координаталары так бирдей болгон вектор экенин билгенден кийин. Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу градиенттүү түшүүнү ишке ашыра алабыз.

Баштоодон мурун, мен түшүү алгоритми жөнүндө бир нече сүйлөмдөрдү окууну сунуштайм:

  • Коэффициенттердин координаталарын псевдококустук түрдө аныктайбыз Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу. Биздин мисалда биз нөлгө жакын коэффициенттерди аныктайбыз. Бул кеңири таралган практика, бирок ар бир иштин өзүнүн практикасы болушу мүмкүн.
  • Координатадан Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу чекиттеги 1-даражадагы жарым-жартылай туундунун маанисин алып салуу Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу. Демек, эгерде туунду оң болсо, анда функция көбөйөт. Демек, туундунун маанисин алып салуу менен биз өсүштүн тескери багытында, башкача айтканда, төмөндөө багытында жылабыз. Эгерде туунду терс болсо, анда бул учурда функция азаят жана туундунун маанисин алып салуу менен биз төмөндөө багытында жылабыз.
  • Ушундай эле операцияны координат менен аткарабыз Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу: чекиттеги жарым-жартылай туундунун маанисин алып салуу Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу.
  • Минималдуудан секирип, терең космоско учуп кетпеш үчүн кадамдын өлчөмүн түшүү багытында коюу керек. Жалпысынан алганда, эсептөө чыгымдарын азайтуу үчүн кадамды кантип туура коюу керектиги жана түшүү процессинде аны кантип өзгөртүү керектиги жөнүндө толук макала жазсаңыз болот. Бирок азыр биздин алдыбызда бир аз башкача милдет турат жана биз кадамдын өлчөмүн илимий “поке” ыкмасы менен же, алар айткандай, эмпирикалык түрдө белгилейбиз.
  • Берилген координаттардан чыккандан кийин Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу туундулардын маанилерин алып салуу, биз жаңы координаттарды алабыз Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу. Эсептелген координаттардан кийинки кадамды (кемитүү) жасайбыз. Ошентип, цикл талап кылынган конвергенцияга жеткенге чейин кайра-кайра башталат.

Баары! Эми биз Мариана траншеясынын эң терең капчыгайын издөөгө даярбыз. Келиңиз баштайлы.

Градиенттин түшүү коду

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

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Биз Мариана чуңкурунун түбүнө чейин чөктүк жана ал жерден бирдей коэффициенттин маанисин таптык Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу, бул так күтүлгөн нерсе.

Келгиле, дагы бир сүңгүп көрөлү, бул жолу гана биздин терең деңиздеги унаабыз башка технологияларга, тактап айтканда китепканага толот. numpy.

Градиенттин түшүү коду (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

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу
Коэффициенттин маанилери Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу өзгөрүлгүс.

Келгиле, градиенттин түшүүсү учурунда ката кандайча өзгөргөнүн, башкача айтканда, ар бир кадам сайын квадраттык четтөөлөрдүн суммасы кандай өзгөргөнүн карап көрөлү.

Квадраттык четтөөлөрдүн суммасын графикке салуу үчүн код

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

График №4 «Градиенттин түшүүдөгү квадраттык четтөөлөрдүн суммасы»

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Графикте биз ар бир кадам сайын ката азайып, белгилүү бир сандагы кайталоодон кийин дээрлик горизонталдуу сызыкты байкайбыз.

Акыр-аягы, келгиле, кодду аткаруу убакытындагы айырманы баалайлы:

Градиенттин түшүү убактысын эсептөө үчүн код

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)

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Балким, биз туура эмес кылып жаткандырбыз, бирок бул китепкананы колдонбогон жөнөкөй "үйдө жазылган" функция. numpy китепкананы колдонуу менен функциянын эсептөө убактысынан ашып кетет numpy.

Бирок биз бир орунда турбайбыз, бирок жөнөкөй сызыктуу регрессия теңдемесин чечүүнүн дагы бир кызыктуу жолун изилдөөгө карай бара жатабыз. Жолугушуу!

Стохастикалык градиенттин түшүүсү

Стохастикалык градиенттик түшүүнүн иштөө принцибин тез түшүнүү үчүн анын кадимки градиенттүү түшүүдөн айырмасын аныктаган жакшы. Биз, градиенттик ылдыйда, туундуларынын теңдемелеринде Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу үлгүдөгү бардык мүмкүнчүлүктөрдүн жана чыныгы жооптордун маанилеринин суммасын колдонгон (б.а. бардыгынын суммасы Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу). Стохастикалык градиент ылдыйда биз үлгүдөгү бардык баалуулуктарды колдонбойбуз, анын ордуна псевдо-кокустук деп аталган үлгү индексин тандап, анын маанилерин колдонобуз.

Мисалы, индекс 3 (үч) деп аныкталса, анда биз маанилерди алабыз Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу, анда биз баалуулуктарды туунду теңдемелерге алмаштырып, жаңы координаттарды аныктайбыз. Андан кийин, координаттарды аныктап, биз кайрадан псевдо-кокустуктан тандап индексти аныктайбыз, индекске туура келген маанилерди жарым-жартылай дифференциалдык теңдемелерге алмаштырабыз жана координаталарды жаңы ыкма менен аныктайбыз. Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу жана башкалар. конвергенция жашылга айланганга чейин. Бир караганда, бул такыр иштебей тургандай сезилиши мүмкүн, бирок ошондой болот. Ырас, ката кадам сайын азайбайт, бирок, албетте, тенденция бар.

Стохастикалык градиенттин кадимки градиентке караганда кандай артыкчылыктары бар? Эгерде биздин үлгүнүн көлөмү абдан чоң болсо жана он миңдеген маанилер менен ченелет, анда бүт тандоого караганда, айталы, алардын кокус миңин иштетүү алда канча оңой. Бул жерде стохастикалык градиенттин түшүүсү пайда болот. Биздин учурда, албетте, биз көп айырмачылыкты байкабайбыз.

Келгиле, кодду карап көрөлү.

Стохастикалык градиенттин түшүү коду

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

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Коэффициенттерди кылдаттык менен карап, «Бул кантип болушу мүмкүн?» деген суроону кармайбыз. Бизде башка коэффиценттердин мааниси бар Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу. Балким, стохастикалык градиенттин түшүүсү теңдеменин оптималдуу параметрлерин тапкандыр? Тилекке каршы жок. Квадраттык четтөөлөрдүн суммасын карап көрүү жана коэффициенттердин жаңы маанилери менен ката чоңураак экенин көрүү жетиштүү. Биз үмүтсүздүккө шашылбайбыз. Келгиле, катаны өзгөртүү графигин түзөлү.

Стохастикалык градиент ылдыйда квадраттык четтөөлөрдүн суммасынын графиктерин түзүү үчүн код

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

График №5 «Стохастикалык градиенттин түшүүсүнүн квадраттык четтөөлөрүнүн суммасы»

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Графикти карасак баары өз ордуна келип, азыр баарын оңдойбуз.

Анда эмне болду? Төмөнкү окуя болду. Бир айды кокусунан тандап алганыбызда, биздин алгоритм кирешени эсептөөдөгү катаны азайтууга аракет кылат. Андан кийин дагы бир айды тандап, эсепти кайталайбыз, бирок экинчи тандалган ай үчүн катаны азайтабыз. Эми эсиңизде болсун, алгачкы эки ай жөнөкөй сызыктуу регрессия теңдемесинин сызыгынан кыйла четтеп кетет. Бул эки айдын кайсынысы болбосун тандалганда, алардын ар биринин катасын азайтуу менен, биздин алгоритм бардык үлгүдөгү катаны олуттуу түрдө жогорулатат дегенди билдирет. Анда эмне кылуу керек? Жооп жөнөкөй: түшүү кадамын азайтуу керек. Анткени, түшүү кадамын азайтуу менен, ката да өйдө-ылдый "секирүүнү" токтотот. Тескерисинче, "секирүү" катасы токтобойт, бирок аны ушунчалык тез жасабайт :) Келгиле, текшерип көрөлү.

SGDди кичине кадамдар менен иштетүү үчүн код

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

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

График №6 «Стохастикалык градиенттин түшүүдөгү квадраттык четтөөлөрдүн суммасы (80 миң кадам)»

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Коэффициенттер жакшырды, бирок дагы эле идеалдуу эмес. Гипотетикалык жактан, муну ушундай жол менен оңдоого болот. Биз, мисалы, акыркы 1000 итерацияда минималдуу ката кетирилген коэффициенттердин маанилерин тандайбыз. Ырас, бул үчүн биз коэффициенттердин маанилерин да жазып алышыбыз керек. Биз муну кылбайбыз, тескерисинче графикке көңүл бурабыз. Бул жылмакай көрүнөт жана ката бир калыпта азаят окшойт. Чындыгында, бул туура эмес. Келгиле, биринчи 1000 итерацияны карап көрөлү жана аларды акыркысы менен салыштыралы.

SGD диаграммасынын коду (биринчи 1000 кадам)

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

График №7 «СГДнын квадраттык четтөөлөрүнүн суммасы (биринчи 1000 кадам)»

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

График №8 «СГДнын квадраттык четтөөлөрүнүн суммасы (акыркы 1000 кадам)»

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Түшүүнүн эң башында биз катачылыктын бир калыпта жана кескин төмөндөшүн байкайбыз. Акыркы итерацияларда ката 1,475 маанисин айланып, айланып баратканын көрүп жатабыз жана кээ бир учурларда бул оптималдуу мааниге барабар болот, бирок андан кийин ал дагы эле көтөрүлөт... Кайталап айтам, сиз XNUMXтин маанилерин жазсаңыз болот. коэффициенттер Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу и Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу, анан катасы аз болгондорду тандаңыз. Бирок, бизде олуттуу көйгөй бар болчу: оптималдууга жакын маанилерди алуу үчүн 80 миң кадамды жасоого туура келди (кодду караңыз). Бул градиент ылдыйга салыштырмалуу стохастикалык градиенттик түшүү менен эсептөө убактысын үнөмдөө идеясына карама-каршы келет. Эмнени оңдоого жана жакшыртууга болот? Биринчи итерацияларда биз ишеним менен ылдыйлап баратканыбызды байкап калуу кыйын эмес, демек, биринчи итерацияларда чоң кадам таштап, алга карай кадамды азайтышыбыз керек. Бул макалада биз муну кылбайбыз - бул өтө узун. Каалоочулар муну кантип жасаш керек экенин өздөрү ойлонсо болот, бул кыйын эмес :)

Эми китепкананы колдонуу менен стохастикалык градиенттин түшүүсүн жасайлы numpy (жана биз мурда аныктаган таштарга чалынбайлы)

Стохастикалык градиенттин түшүү коду (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

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Маанилер колдонбостон түшкөндө дээрлик бирдей болуп чыкты numpy. Бирок, бул логикалуу.

Келгиле, стохастикалык градиенттин түшүүсү бизди канча убакытка алып кеткенин билели.

SGD эсептөө убактысын аныктоо үчүн код (80 миң кадам)

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)

Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу

Токойго канчалык алыс болсо, булуттар ошончолук караңгылайт: дагы эле «өзү жазылган» формула эң жакшы натыйжаны көрсөтөт. Мунун баары китепкананы колдонуунун мындан да кылдат жолдору болушу керек экенин көрсөтүп турат numpy, бул чынында эле эсептөө операцияларын тездетет. Бул макалада биз алар жөнүндө биле албайбыз. Бош убактыңызда ойлоно турган нерсе болот :)

кошуу

Жыйынтыктоодон мурун, мен урматтуу окурманыбыздан келип чыккан суроого жооп бергим келет. Эмне үчүн, чындыгында, мындай «кыйноолор» ылдыйда, эмне үчүн биздин колубузда ушундай күчтүү жана жөнөкөй аппарат болсо, биз тоону (көбүнчө ылдый) басып өтүшүбүз керек. Бизди ошол замат туура жерге телепортациялаган аналитикалык чечимдин формасы?

Бул суроонун жообу бетинде. Эми биз абдан жөнөкөй мисалды карап чыктык, анда чыныгы жооп бар Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу бир белгиге көз каранды Жөнөкөй сызыктуу регрессия теңдемесин чыгаруу. Жашоодо муну көп байкабайсың, андыктан бизде 2, 30, 50 же андан көп белги бар деп элестетип көрөлү. Келгиле, ар бир атрибут үчүн миңдеген, ал тургай он миңдеген баалуулуктарды кошолу. Бул учурда, аналитикалык чечим сыноого туруштук бере албай, ийгиликсиз болушу мүмкүн. Өз кезегинде, градиенттин түшүүсү жана анын вариациялары акырындык менен, бирок сөзсүз түрдө бизди максатка - функциянын минимумуна жакындатат. Жана ылдамдык жөнүндө кабатыр болбоңуз - биз кадамдын узундугун (б.а. ылдамдыкты) орнотууга жана жөнгө салууга мүмкүндүк берүүчү жолдорду карап чыгабыз.

Ал эми азыр иш жүзүндө кыскача корутунду.

Биринчиден, макалада берилген материал жөнөкөй (жана гана эмес) сызыктуу регрессия теңдемелерин кантип чечүүнү түшүнүүдө "маалымат таануучуларга" жардам берет деп үмүттөнөм.

Экинчиден, теңдемени чечүүнүн бир нече жолдорун карап чыктык. Эми кырдаалга жараша маселени чечүүгө эң ылайыктуусун тандап алсак болот.

Үчүнчүдөн, биз кошумча орнотуулардын күчүн көрдүк, атап айтканда градиенттин түшүү кадамынын узундугу. Бул параметрди этибарга албай коюуга болбойт. Жогоруда белгиленгендей, эсептөөлөргө кеткен чыгымды азайтуу үчүн түшүү учурунда кадамдын узундугун өзгөртүү керек.

Төртүнчүдөн, биздин учурда, "үй-жазылган" функциялары эсептөөлөр үчүн мыкты убакыт натыйжаларын көрсөттү. Бул китепкананын мүмкүнчүлүктөрүн эң профессионалдуу пайдаланбагандыктан улам болсо керек numpy. Бирок, кандай болсо да, төмөнкү тыянак өзүн көрсөтүп турат. Бир жагынан, кээде калыптанып калган ой-пикирлерге шек келтируу керек, ал эми экинчи жагынан, ар дайым эле бардыгын татаалдаштыра бербейт - тескерисинче, кээде көйгөйдү чечүүнүн жөнөкөй жолу натыйжалуураак болот. Ал эми биздин максат жөнөкөй сызыктуу регрессия теңдемесин чечүү үчүн үч ыкманы талдоо болгондуктан, биз үчүн "өзүн-өзү жазылган" функцияларды колдонуу жетиштүү болду.

Адабият (же ушуга окшогон нерсе)

1. Сызыктуу регрессия

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

2. Эң кичине квадраттар ыкмасы

mathprofi.ru/metod_naimenshih_kvadratov.html

3. Туунду

www.mathprofi.ru/chastnye_proizvodnye_primery.html

4. Градиент

mathprofi.ru/proizvodnaja_po_napravleniju_i_gradient.html

5. Градиенттин түшүүсү

habr.com/en/post/471458

habr.com/en/post/307312

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

6. 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

Source: www.habr.com

Комментарий кошуу