සරල (යුගල) ප්රතිගාමී රේඛාවක ගණිතමය සමීකරණය තීරණය කිරීමට ක්රම කිහිපයක් ලිපිය සාකච්ඡා කරයි.
මෙහි සාකච්ඡා කෙරෙන සමීකරණය විසඳීමේ සියලු ක්රම පදනම් වන්නේ අඩුම වර්ග ක්රමය මතය. ක්රම පහත පරිදි දක්වන්නෙමු.
- විශ්ලේෂණාත්මක විසඳුම
- Gradient Descent
- ස්ටෝචස්ටික් අනුක්රමණ සම්භවය
සරල රේඛාවක සමීකරණය විසඳීමේ එක් එක් ක්රමය සඳහා, ලිපිය විවිධ කාර්යයන් සපයයි, ඒවා ප්රධාන වශයෙන් පුස්තකාලය භාවිතා නොකර ලියා ඇති ඒවාට බෙදා ඇත. numpy සහ ගණනය කිරීම් සඳහා භාවිතා කරන ඒවා numpy. දක්ෂ ලෙස භාවිතා කරන බව විශ්වාස කෙරේ numpy පරිගණක වියදම් අඩු කරනු ඇත.
ලිපියේ දක්වා ඇති සියලුම කේතයන් භාෂාවෙන් ලියා ඇත පයිතන් 2.7 භාවිතා කිරීම ජුපිටර් නෝට්බුක්. මූලාශ්ර කේතය සහ නියැදි දත්ත සහිත ගොනුව පළ කර ඇත
ලිපිය වඩාත් ඉලක්ක කර ඇත්තේ ආරම්භකයින් සහ දැනටමත් ක්රමයෙන් කෘතිම බුද්ධිය පිළිබඳ ඉතා පුළුල් අංශයක් - යන්ත්ර ඉගෙනීම ප්රගුණ කිරීමට පටන් ගෙන ඇති අය සඳහා ය.
ද්රව්යය නිදර්ශනය කිරීම සඳහා, අපි ඉතා සරල උදාහරණයක් භාවිතා කරමු.
උදාහරණ කොන්දේසි
යැපීම සංලක්ෂිත අගයන් පහක් අපට ඇත Y от X (වගුව අංක 1):
වගු අංක 1 "උදාහරණ කොන්දේසි"
අගයන් යැයි අපි උපකල්පනය කරමු වසරේ මාසය වන අතර, සහ - මේ මාසයේ ආදායම. වෙනත් වචන වලින් කිවහොත්, ආදායම වසරේ මාසය මත රඳා පවතී, සහ - ආදායම රඳා පවතින එකම ලකුණ.
උදාහරණය එසේ ය, වසරේ මාසය මත ආදායමේ කොන්දේසි සහිත යැපීම පිළිබඳ දෘෂ්ටි කෝණයෙන් සහ අගයන් සංඛ්යාවේ දෘෂ්ටි කෝණයෙන් - ඒවායින් ඉතා ස්වල්පයක් ඇත. කෙසේ වෙතත්, එවැනි සරල කිරීමක් මඟින් ඔවුන් පවසන පරිදි, සෑම විටම පහසුවෙන් නොව, ආරම්භකයින් උකහා ගන්නා ද්රව්ය පැහැදිලි කිරීමට හැකි වනු ඇත. තවද අංකවල සරල බව සැලකිය යුතු ශ්රම පිරිවැයකින් තොරව කඩදාසි මත උදාහරණය විසඳීමට කැමති අයට ඉඩ සලසයි.
ආකෘතියේ සරල (යුගල කළ) ප්රතිගාමී රේඛාවක ගණිතමය සමීකරණය මගින් උදාහරණයේ දී ඇති යැපීම හොඳින් ආසන්න කළ හැකි යැයි උපකල්පනය කරමු:
එහිදී ආදායම ලැබුණු මාසයයි, - මාසයට අනුරූප ආදායම, и ඇස්තමේන්තුගත රේඛාවේ ප්රතිගාමී සංගුණක වේ.
සංගුණකය බව සලකන්න බොහෝ විට ඇස්තමේන්තුගත රේඛාවේ බෑවුම හෝ අනුක්රමණය ලෙස හැඳින්වේ; ප්රමාණය නියෝජනය කරයි එය වෙනස් වන විට .
නිසැකවම, උදාහරණයේ අපගේ කාර්යය වන්නේ සමීකරණයේ එවැනි සංගුණක තෝරා ගැනීමයි и , සත්ය පිළිතුරු වලින් මසකට අපගේ ගණනය කළ ආදායම් අගයන්හි අපගමනය, i.e. නියැදියේ ඉදිරිපත් කර ඇති අගයන් අවම වනු ඇත.
අඩු හතරැස් ක්රමය
අවම වර්ග ක්රමයට අනුව, අපගමනය ගණනය කළ යුත්තේ එය වර්ග කිරීමෙනි. මෙම තාක්ෂණය මඟින් ප්රතිවිරුද්ධ සලකුණු තිබේ නම්, අපගමනය අන්යෝන්ය වශයෙන් අවලංගු කිරීම වළක්වා ගැනීමට ඔබට ඉඩ සලසයි. උදාහරණයක් ලෙස, එක් අවස්ථාවක නම්, අපගමනය වේ +5 (ප්ලස් පහ), සහ අනෙකෙහි -5 (අඩු පහක්), එවිට අපගමනයන්හි එකතුව එකිනෙක අවලංගු වන අතර අගය 0 (ශුන්ය) වේ. අපගමනය වර්ග කිරීම නොව, මාපාංකයේ ගුණය භාවිතා කළ හැකි අතර එවිට සියලු අපගමනයන් ධනාත්මක වන අතර සමුච්චය වනු ඇත. අපි මෙම කරුණ පිළිබඳව විස්තරාත්මකව වාසය නොකරමු, නමුත් ගණනය කිරීම් වල පහසුව සඳහා, අපගමනය වර්ග කිරීම සිරිතක් බව සරලව දක්වන්නෙමු.
සූත්රය පෙනෙන්නේ මෙයයි, අපි අවම වර්ග අපගමන එකතුව (දෝෂ) තීරණය කරමු:
එහිදී සත්ය පිළිතුරු ආසන්නයේ ශ්රිතයකි (එනම්, අප ගණනය කළ ආදායම),
සත්ය පිළිතුරු වේ (නියැදියේ සපයා ඇති ආදායම),
නියැදි දර්ශකය වේ (අපගමනය තීරණය කරනු ලබන මාසයේ අංකය)
අපි ශ්රිතය අවකලනය කරමු, අර්ධ අවකල සමීකරණ නිර්වචනය කරමු, සහ විශ්ලේෂණාත්මක විසඳුම වෙත යාමට සූදානම් වෙමු. නමුත් පළමුව, අවකලනය යනු කුමක්ද යන්න පිළිබඳ කෙටි විනෝද චාරිකාවක් ගෙන ව්යුත්පන්නයේ ජ්යාමිතික අර්ථය මතක තබා ගනිමු.
අවකලනය
අවකලනය යනු ශ්රිතයක ව්යුත්පන්නය සෙවීමේ ක්රියාවලියයි.
ව්යුත්පන්නය භාවිතා කරන්නේ කුමක් සඳහාද? ශ්රිතයක ව්යුත්පන්නය ශ්රිතයේ වෙනස් වීමේ වේගය සංලක්ෂිත කරන අතර එහි දිශාව අපට කියයි. දී ඇති ලක්ෂ්යයක ව්යුත්පන්නය ධනාත්මක නම්, ශ්රිතය වැඩි වේ, එසේ නොමැති නම්, ශ්රිතය අඩු වේ. තවද නිරපේක්ෂ ව්යුත්පන්නයේ අගය වැඩි වන තරමට ශ්රිත අගයන් වෙනස් වීමේ වේගය මෙන්ම ශ්රිත ප්රස්ථාරයේ බෑවුම වැඩි වේ.
උදාහරණයක් ලෙස, Cartesian ඛණ්ඩාංක පද්ධතියක කොන්දේසි යටතේ, M(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 '********************************************'
දෘශ්යකරණය
දැන්, අපි පළමුව, දත්ත පූරණය කළ පසු, දෙවනුව, පැටවීමේ නිවැරදි බව පරීක්ෂා කර අවසානයේ දත්ත ආකෘතිකරණය කළ පසු, අපි පළමු දෘශ්යකරණය සිදු කරන්නෙමු. මේ සඳහා බොහෝ විට භාවිතා කරන ක්රමය වේ යුගලය පුස්තකාල මුහුදු වෙරළ. අපගේ උදාහරණයේ සීමිත සංඛ්යා නිසා පුස්තකාලය භාවිතා කිරීමේ තේරුමක් නැත මුහුදු වෙරළ. අපි සාමාන්ය පුස්තකාලය භාවිතා කරන්නෙමු මැට්ප්ලොට්ලිබ් සහ නිකමට බලන්න විසිරිලා.
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)
කුඩා දත්ත ප්රමාණයක් සමඟින්, "ස්වයං-ලිඛිත" ශ්රිතයක් ඉදිරියට එයි, එය Cramer's ක්රමය භාවිතයෙන් සංගුණක සොයා ගනී.
දැන් ඔබට සංගුණක සොයා ගැනීමට වෙනත් ක්රම වෙත ගමන් කළ හැකිය и .
Gradient Descent
පළමුව, ශ්රේණිය යනු කුමක්දැයි නිර්වචනය කරමු. සරලව කිවහොත්, ශ්රේණිය යනු ශ්රිතයක උපරිම වර්ධන දිශාව පෙන්නුම් කරන කොටසකි. කන්දක් නැගීම හා සමානව, කඳු මුදුනට බෑවුම් සහිතම නැග්ම ඇති තැන ග්රේඩියන්ට් මුහුණත වේ. කන්ද සමඟ උදාහරණය වර්ධනය කරමින්, අපට මතකයි, ඇත්ත වශයෙන්ම අපට හැකි ඉක්මනින් පහත්බිමට ළඟා වීමට නම්, එනම් අවම වශයෙන් - ශ්රිතය වැඩි නොවන හෝ අඩු නොවන ස්ථානයට බෑවුම් සහිත බැසීමක් අවශ්ය බව. මෙම අවස්ථාවේදී ව්යුත්පන්නය ශුන්යයට සමාන වනු ඇත. එබැවින්, අපට අනුක්රමණයක් අවශ්ය නොවේ, නමුත් ප්රති-ග්රේඩියන්ට් එකක්. ප්රතිග්රේඩියන්ට් සොයා ගැනීමට ඔබට අවශ්ය වන්නේ අනුක්රමණය ගුණ කිරීම පමණි -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 "වර්ග අපගමන එකතුව SGD (පළමු පියවර 1000)"
ප්රස්තාර අංක 8 “වර්ග අපගමන එකතුව SGD (අවසන් පියවර 1000)”
බැසීමේ ආරම්භයේදීම, දෝෂයේ තරමක් ඒකාකාරී හා දැඩි අඩුවීමක් අපි නිරීක්ෂණය කරමු. අවසාන පුනරාවර්තන වලදී, දෝෂය 1,475 අගය වටා සහ වටේට යන බව අපට පෙනෙන අතර සමහර අවස්ථාවලදී මෙම ප්රශස්ත අගයට සමාන වේ, නමුත් පසුව එය තවමත් ඉහළ යයි ... මම නැවතත්, ඔබට අගයන් ලියා ගත හැකිය. සංගුණක и , ඉන්පසු දෝෂය අවම වන ඒවා තෝරන්න. කෙසේ වෙතත්, අපට වඩාත් බරපතල ගැටළුවක් තිබුණි: අගයන් ප්රශස්ත මට්ටමට සමීප වීමට අපට පියවර 80 ක් (කේතය බලන්න) ගැනීමට සිදු විය. තවද මෙය දැනටමත් අනුක්රමණයට සාපේක්ෂව ස්ටෝචස්ටික් අනුක්රමික සම්භවයක් සමඟ ගණනය කිරීමේ කාලය ඉතිරි කිරීමේ අදහසට පටහැනි වේ. නිවැරදි කර වැඩිදියුණු කළ හැක්කේ කුමක්ද? පළමු පුනරාවර්තන වලදී අපි විශ්වාසයෙන් පහළට යන බව සැලකිල්ලට ගැනීම අපහසු නැත, එබැවින්, අපි පළමු පුනරාවර්තනයන්හි විශාල පියවරක් තබා ඉදිරියට යන විට පියවර අඩු කළ යුතුය. අපි මෙම ලිපියෙන් මෙය නොකරනු ඇත - එය දැනටමත් දිගු වේ. කැමති අයට මෙය කරන්නේ කෙසේදැයි සිතා ගත හැකිය, එය අපහසු නැත :)
දැන් අපි පුස්තකාලය භාවිතයෙන් ස්ටෝචස්ටික් ග්රේඩියන්ට් බැසීමක් සිදු කරමු numpy (අපි කලින් හඳුනාගත් ගල් මත පැකිලෙන්නේ නැහැ)
Stochastic Gradient Descent සඳහා කේතය (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. රේඛීය පසුබෑම
2. අඩු කොටු ක්රමය
3. ව්යුත්පන්න
4. Gradient
5. අනුක්රමණ සම්භවය
6. NumPy පුස්තකාලය
මූලාශ්රය: www.habr.com