सरल रेखीय प्रतिगमन के समीकरण को हल करना

लेख एक सरल (युग्मित) प्रतिगमन रेखा के गणितीय समीकरण को निर्धारित करने के कई तरीकों पर चर्चा करता है।

यहां चर्चा किए गए समीकरण को हल करने की सभी विधियां न्यूनतम वर्ग विधि पर आधारित हैं। आइए विधियों को इस प्रकार निरूपित करें:

  • विश्लेषणात्मक समाधान
  • ढतला हुआ वंश
  • स्टोकेस्टिक ग्रेडिएंट डिसेंट

एक सीधी रेखा के समीकरण को हल करने की प्रत्येक विधि के लिए, लेख विभिन्न फ़ंक्शन प्रदान करता है, जिन्हें मुख्य रूप से उन कार्यों में विभाजित किया गया है जो लाइब्रेरी का उपयोग किए बिना लिखे गए हैं Numpy और जिनका उपयोग गणना के लिए किया जाता है Numpy. ऐसा माना जाता है कि कुशल प्रयोग Numpy कंप्यूटिंग लागत कम हो जाएगी.

लेख में दिए गए सभी कोड भाषा में लिखे गए हैं अजगर २ साथ जुपीटर नोटबुक. नमूना डेटा के साथ स्रोत कोड और फ़ाइल पोस्ट की गई है Github

यह लेख शुरुआती और उन दोनों के लिए अधिक लक्षित है, जिन्होंने धीरे-धीरे कृत्रिम बुद्धिमत्ता - मशीन लर्निंग के एक बहुत व्यापक खंड के अध्ययन में महारत हासिल करना शुरू कर दिया है।

सामग्री को स्पष्ट करने के लिए, हम एक बहुत ही सरल उदाहरण का उपयोग करते हैं।

उदाहरण स्थितियाँ

हमारे पास पाँच मूल्य हैं जो निर्भरता की विशेषता बताते हैं Y से X (तालिका क्रमांक 1):

तालिका संख्या 1 "उदाहरण शर्तें"

सरल रेखीय प्रतिगमन के समीकरण को हल करना

हम मान लेंगे कि मान सरल रेखीय प्रतिगमन के समीकरण को हल करना वर्ष का महीना है, और सरल रेखीय प्रतिगमन के समीकरण को हल करना - इस महीने राजस्व। दूसरे शब्दों में, राजस्व वर्ष के महीने पर निर्भर करता है, और सरल रेखीय प्रतिगमन के समीकरण को हल करना - एकमात्र संकेत जिस पर राजस्व निर्भर करता है।

उदाहरण ऐसा है, वर्ष के महीने पर राजस्व की सशर्त निर्भरता के दृष्टिकोण से और मूल्यों की संख्या के दृष्टिकोण से - उनमें से बहुत कम हैं। हालाँकि, इस तरह के सरलीकरण से, जैसा कि वे कहते हैं, उस सामग्री को समझाना संभव हो जाएगा, जिसे शुरुआती लोग सीख लेते हैं, हमेशा आसानी से नहीं। और संख्याओं की सरलता उन लोगों को भी अनुमति देगी जो महत्वपूर्ण श्रम लागत के बिना कागज पर उदाहरण हल करना चाहते हैं।

आइए मान लें कि उदाहरण में दी गई निर्भरता को फॉर्म की एक सरल (युग्मित) प्रतिगमन रेखा के गणितीय समीकरण द्वारा काफी अच्छी तरह से अनुमानित किया जा सकता है:

सरल रेखीय प्रतिगमन के समीकरण को हल करना

जहां सरल रेखीय प्रतिगमन के समीकरण को हल करना वह महीना है जिसमें राजस्व प्राप्त हुआ था, सरल रेखीय प्रतिगमन के समीकरण को हल करना - महीने के अनुरूप राजस्व, सरल रेखीय प्रतिगमन के समीकरण को हल करना и सरल रेखीय प्रतिगमन के समीकरण को हल करना अनुमानित रेखा के प्रतिगमन गुणांक हैं।

ध्यान दें कि गुणांक सरल रेखीय प्रतिगमन के समीकरण को हल करना अक्सर अनुमानित रेखा का ढलान या ढाल कहा जाता है; उस राशि का प्रतिनिधित्व करता है जिसके द्वारा सरल रेखीय प्रतिगमन के समीकरण को हल करना जब यह बदलता है सरल रेखीय प्रतिगमन के समीकरण को हल करना.

जाहिर है, उदाहरण में हमारा कार्य समीकरण में ऐसे गुणांकों का चयन करना है सरल रेखीय प्रतिगमन के समीकरण को हल करना и सरल रेखीय प्रतिगमन के समीकरण को हल करना, जिस पर सही उत्तरों से महीने के हिसाब से हमारे परिकलित राजस्व मूल्यों का विचलन होता है, अर्थात। नमूने में प्रस्तुत मान न्यूनतम होंगे।

कम से कम वर्ग विधि

न्यूनतम वर्ग विधि के अनुसार विचलन की गणना वर्ग करके करनी चाहिए। यह तकनीक आपको विपरीत संकेत होने पर विचलनों को पारस्परिक रूप से रद्द करने से बचने की अनुमति देती है। उदाहरण के लिए, यदि एक मामले में, विचलन है +5 (प्लस पांच), और दूसरे में -5 (शून्य पांच), तो विचलनों का योग एक दूसरे को रद्द कर देगा और 0 (शून्य) हो जाएगा। विचलन को वर्गित करना संभव नहीं है, लेकिन मापांक की संपत्ति का उपयोग करना संभव है और फिर सभी विचलन सकारात्मक होंगे और जमा हो जाएंगे। हम इस बिंदु पर विस्तार से ध्यान नहीं देंगे, लेकिन केवल यह संकेत देंगे कि गणना की सुविधा के लिए, विचलन को वर्गित करने की प्रथा है।

यह वह सूत्र है जो इस प्रकार दिखता है जिसके साथ हम वर्ग विचलन (त्रुटियों) का न्यूनतम योग निर्धारित करेंगे:

सरल रेखीय प्रतिगमन के समीकरण को हल करना

जहां सरल रेखीय प्रतिगमन के समीकरण को हल करना सही उत्तरों के सन्निकटन का एक कार्य है (अर्थात, वह राजस्व जिसकी हमने गणना की है),

सरल रेखीय प्रतिगमन के समीकरण को हल करना सही उत्तर हैं (नमूने में दिया गया राजस्व),

सरल रेखीय प्रतिगमन के समीकरण को हल करना नमूना सूचकांक है (उस महीने की संख्या जिसमें विचलन निर्धारित किया गया है)

आइए फ़ंक्शन को अलग करें, आंशिक अंतर समीकरणों को परिभाषित करें, और विश्लेषणात्मक समाधान पर आगे बढ़ने के लिए तैयार रहें। लेकिन पहले, आइए एक संक्षिप्त भ्रमण करें कि विभेदन क्या है और व्युत्पन्न के ज्यामितीय अर्थ को याद रखें।

भेदभाव

विभेदन किसी फ़ंक्शन का व्युत्पन्न खोजने की प्रक्रिया है।

व्युत्पन्न का उपयोग किसके लिए किया जाता है? किसी फ़ंक्शन का व्युत्पन्न फ़ंक्शन के परिवर्तन की दर को दर्शाता है और हमें इसकी दिशा बताता है। यदि किसी दिए गए बिंदु पर व्युत्पन्न सकारात्मक है, तो फ़ंक्शन बढ़ता है; अन्यथा, फ़ंक्शन घट जाता है। और निरपेक्ष व्युत्पन्न का मूल्य जितना अधिक होगा, फ़ंक्शन मानों के परिवर्तन की दर उतनी ही अधिक होगी, साथ ही फ़ंक्शन ग्राफ़ का ढलान भी उतना ही अधिक होगा।

उदाहरण के लिए, कार्टेशियन समन्वय प्रणाली की शर्तों के तहत, बिंदु M(0,0) पर व्युत्पन्न का मान बराबर है +25 इसका मतलब है कि किसी दिए गए बिंदु पर, जब मान स्थानांतरित हो जाता है सरल रेखीय प्रतिगमन के समीकरण को हल करना एक पारंपरिक इकाई, मान द्वारा दाईं ओर सरल रेखीय प्रतिगमन के समीकरण को हल करना 25 पारंपरिक इकाइयों की वृद्धि। ग्राफ़ पर यह मूल्यों में काफी तेज़ वृद्धि जैसा दिखता है सरल रेखीय प्रतिगमन के समीकरण को हल करना किसी दिए गए बिंदु से.

एक और उदाहरण। व्युत्पन्न मूल्य बराबर है -0,1 इसका मतलब है कि विस्थापित होने पर सरल रेखीय प्रतिगमन के समीकरण को हल करना प्रति एक पारंपरिक इकाई, मूल्य सरल रेखीय प्रतिगमन के समीकरण को हल करना केवल 0,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 और बस स्कैटरप्लॉट को देखें।

स्कैटरप्लॉट कोड

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 (शून्य से एक कम)।

आइए इस तथ्य पर ध्यान दें कि एक फ़ंक्शन में कई मिनीमा हो सकते हैं, और नीचे प्रस्तावित एल्गोरिदम का उपयोग करके उनमें से एक में उतरने पर, हम एक और न्यूनतम नहीं ढूंढ पाएंगे, जो पाए गए न्यूनतम से कम हो सकता है। आइए आराम करें, यह हमारे लिए कोई खतरा नहीं है! हमारे मामले में हम अपने कार्य के बाद से एक न्यूनतम के साथ काम कर रहे हैं सरल रेखीय प्रतिगमन के समीकरण को हल करना ग्राफ़ पर एक नियमित परवलय है। और जैसा कि हम सभी को अपने स्कूल के गणित पाठ्यक्रम से अच्छी तरह से पता होना चाहिए, एक परवलय में केवल एक न्यूनतम होता है।

जब हमें पता चला कि हमें ग्रेडिएंट की आवश्यकता क्यों है, और यह भी कि ग्रेडिएंट एक खंड है, यानी, दिए गए निर्देशांक वाला एक वेक्टर, जो बिल्कुल समान गुणांक हैं सरल रेखीय प्रतिगमन के समीकरण को हल करना и सरल रेखीय प्रतिगमन के समीकरण को हल करना हम ग्रेडिएंट डिसेंट लागू कर सकते हैं।

शुरू करने से पहले, मैं डिसेंट एल्गोरिदम के बारे में बस कुछ वाक्य पढ़ने का सुझाव देता हूं:

  • हम गुणांकों के निर्देशांक छद्म-यादृच्छिक तरीके से निर्धारित करते हैं सरल रेखीय प्रतिगमन के समीकरण को हल करना и सरल रेखीय प्रतिगमन के समीकरण को हल करना. हमारे उदाहरण में, हम शून्य के निकट गुणांक निर्धारित करेंगे। यह एक सामान्य प्रथा है, लेकिन प्रत्येक मामले की अपनी प्रथा हो सकती है।
  • समन्वय से सरल रेखीय प्रतिगमन के समीकरण को हल करना बिंदु पर प्रथम क्रम के आंशिक व्युत्पन्न का मान घटाएँ सरल रेखीय प्रतिगमन के समीकरण को हल करना. इसलिए, यदि व्युत्पन्न सकारात्मक है, तो फ़ंक्शन बढ़ जाता है। इसलिए, व्युत्पन्न के मूल्य को घटाकर, हम विकास की विपरीत दिशा में, यानी वंश की दिशा में आगे बढ़ेंगे। यदि व्युत्पन्न ऋणात्मक है, तो इस बिंदु पर कार्य कम हो जाता है और व्युत्पन्न का मान घटाकर हम अवरोह की दिशा में आगे बढ़ते हैं।
  • हम समन्वय के साथ एक समान ऑपरेशन करते हैं सरल रेखीय प्रतिगमन के समीकरण को हल करना: बिंदु पर आंशिक व्युत्पन्न का मान घटाएं सरल रेखीय प्रतिगमन के समीकरण को हल करना.
  • न्यूनतम से अधिक न कूदने और गहरे अंतरिक्ष में उड़ने से बचने के लिए, चरण का आकार वंश की दिशा में निर्धारित करना आवश्यक है। सामान्य तौर पर, आप कम्प्यूटेशनल लागत को कम करने के लिए चरण को सही तरीके से कैसे सेट करें और डिसेंट प्रक्रिया के दौरान इसे कैसे बदलें, इसके बारे में एक पूरा लेख लिख सकते हैं। लेकिन अब हमारे सामने थोड़ा अलग कार्य है, और हम "पोक" की वैज्ञानिक पद्धति का उपयोग करके या, जैसा कि वे आम बोलचाल में कहते हैं, अनुभवजन्य रूप से चरण आकार स्थापित करेंगे।
  • एक बार हम दिए गए निर्देशांक से हैं सरल रेखीय प्रतिगमन के समीकरण को हल करना и सरल रेखीय प्रतिगमन के समीकरण को हल करना डेरिवेटिव के मान घटाएं, हमें नए निर्देशांक मिलते हैं सरल रेखीय प्रतिगमन के समीकरण को हल करना и सरल रेखीय प्रतिगमन के समीकरण को हल करना. हम अगला कदम (घटाव) लेते हैं, पहले से ही परिकलित निर्देशांक से। और इसलिए यह चक्र बार-बार शुरू होता है, जब तक कि आवश्यक अभिसरण प्राप्त नहीं हो जाता।

सभी! अब हम मारियाना ट्रेंच की सबसे गहरी घाटी की तलाश में जाने के लिए तैयार हैं। आएँ शुरू करें।

ग्रेडिएंट डिसेंट के लिए कोड

# напишем функцию градиентного спуска без использования библиотеки 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 "स्टोकेस्टिक ग्रेडिएंट डिसेंट के दौरान वर्ग विचलन का योग"

सरल रेखीय प्रतिगमन के समीकरण को हल करना

शेड्यूल को देखते हुए, सब कुछ ठीक हो जाता है और अब हम सब कुछ ठीक कर देंगे।

तो क्या हुआ? निम्नलिखित हुआ. जब हम बेतरतीब ढंग से एक महीने का चयन करते हैं, तो यह चयनित महीने के लिए होता है कि हमारा एल्गोरिदम राजस्व की गणना में त्रुटि को कम करना चाहता है। फिर हम एक और महीना चुनते हैं और गणना दोहराते हैं, लेकिन हम दूसरे चयनित महीने के लिए त्रुटि कम कर देते हैं। अब याद रखें कि पहले दो महीने सरल रेखीय प्रतिगमन समीकरण की रेखा से महत्वपूर्ण रूप से विचलित होते हैं। इसका मतलब यह है कि जब इन दो महीनों में से किसी एक को चुना जाता है, तो उनमें से प्रत्येक की त्रुटि को कम करके, हमारा एल्गोरिदम पूरे नमूने के लिए त्रुटि को गंभीरता से बढ़ाता है। इसलिए क्या करना है? उत्तर सरल है: आपको अवतरण चरण को कम करने की आवश्यकता है। आख़िरकार, अवतरण चरण को कम करने से, त्रुटि भी ऊपर और नीचे "कूदना" बंद कर देगी। या यूँ कहें कि, "कूदने" की त्रुटि बंद नहीं होगी, लेकिन यह इतनी जल्दी ऐसा नहीं करेगी :) आइए जाँच करें।

छोटी वृद्धि के साथ एसजीडी चलाने के लिए कोड

# запустим функцию, уменьшив шаг в 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 पुनरावृत्तियों को देखें और उनकी तुलना अंतिम से करें।

एसजीडी चार्ट के लिए कोड (पहले 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 (और आइए उन पत्थरों पर ठोकर न खाएँ जिन्हें हमने पहले पहचाना था)

स्टोकेस्टिक ग्रेडिएंट डिसेंट के लिए कोड (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. हालाँकि, यह तर्कसंगत है.

आइए जानें कि स्टोकेस्टिक ग्रेडिएंट अवरोहण में हमें कितना समय लगा।

एसजीडी गणना समय निर्धारित करने के लिए कोड (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. न्यूमपी लाइब्रेरी

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

स्रोत: www.habr.com

एक टिप्पणी जोड़ें