<jupyter_start><jupyter_text>Cost FunctionWe need a function that will minimize the parameters over our dataset. One common function that is often used is mean squared error, which measure the difference between the estimator (the dataset) and the estimated value (the prediction). It looks like this:![title](images/cost_function.png)<jupyter_code>def derivative(X, y, theta):
    m = X.shape[0]
    '''
    Функція для обчислення похідних штрафної функції J по thetha.
    
    Параметри:
    X - тренувальний датасет. 0 - колонка з одиниць, далі - реальні риси
    y - точні значення передбачуваної величини
    thetha - вектор параметрів регресії
    
    Результат:
    Вектор похідних d_thetha
    '''
    ######################
    d_thetha = np.dot(hypothesis(X, theta) - y, X)/m 
    ######################
    return d_thetha
def gradient_descent(X, y, theta, alpha, num_iters, print_J = True):
    '''
    Функція, що реалізує градієнтний спуск для метода лінійної регресії.
    
    Параметри:
    X - тренувальний датасет. 0 - колонка з одиниць, далі - реальні риси
    y - точні значення передбачуваної величини
    thetha - вектор початкових параметрів регресії
    alpha - швидкість навчання
    num_iters - кількість ітерацій
    print_J - виведення штрафної функції на екран після кожної ітерації
    
    Результат:
    theta - оптимальні значення параметрів регресії
    J_history - масив історичних значень штрафної функції після кожної ітерації
    '''
    m = X.shape[0]
    J_history = []
    J = cost_function(X, y, theta)
    if print_J == True:
        print(J)
    J_history.append(J)
    for i in range(num_iters):
        ######################
        # Використати написані вище функції
        delta = derivative(X, y, theta) 
        theta = theta - alpha*delta
        J = cost_function(X, y, theta) 
        ######################
        if print_J == True:
            print(J)
        J_history.append(J)
    return theta, J_history
def plot_J(X, y):
    '''
    Функція для виведення графіків штрафної функції для різних значень параметрів на вхідних даних
    
    Параметри:
    X - тренувальний датасет. 0 - колонка з одиниць, далі - реальні риси
    y - точні значення передбачуваної величини
    '''
    theta_0 = np.linspace(-10, 10, 100)
    theta_1 = np.linspace(-1, 4, 100)
    
    J_vals = np.zeros((len(theta_0), len(theta_1)))
    for i, t0 in enumerate(theta_0):
        for j, t1 in enumerate(theta_1):
            theta = np.array([t0, t1])
            J_vals[i, j] = cost_function(X, y, theta)
    
    J_vals = J_vals.T
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    ax.plot_surface(theta_0, theta_1, J_vals, color='b')
    plt.xlabel('theta_0')
    plt.ylabel('theta_1')
    plt.title('Surface plot of the cost function')
    plt.show()
    plt.contour(theta_0, theta_1, J_vals, np.logspace(-2, 3, 20))
    plt.xlabel('theta_0')
    plt.ylabel('theta_1')
    plt.title('Contour plot of the cost function')
    plt.show()<jupyter_output><empty_output><jupyter_text>Основний код програми Отримання датасетів та видрук їх параметрів.<jupyter_code>X, y = load_datasets('burrito.csv')
dataForDraw = pd.read_csv('burrito.csv')
print('Dataset: X={}, y={}'.format(X.shape, y.shape))
dataForDraw.head()<jupyter_output><empty_output><jupyter_text>Візуалізуємо дані за допомогою пакету Seaborn<jupyter_code>dataForDraw = pd.DataFrame(dataForDraw, columns=['A', 'B'])

with sns.axes_style('white'):
    sns.jointplot("A", "B", data=dataForDraw, kind='hex')<jupyter_output><empty_output><jupyter_text>Розбиття датасету на частини:<jupyter_code>X_train, X_test, y_train, y_test = split_datasets(X, y, 0.2)
print('Training set: X={}, y={}'.format(X_train.shape, y_train.shape))
print('Test set: X={}, y={}'.format(X_test.shape, y_test.shape))<jupyter_output>Training set: X=(77,), y=(77,)
Test set: X=(20,), y=(20,)<jupyter_text>Відображення тренувальних і тестових даних на графіку (для 1 змінної)<jupyter_code>plot_data(X_train, X_test, y_train, y_test)<jupyter_output><empty_output><jupyter_text>Підготовка тренувальних даних (додавання 0-колонки з одиницями). Ініціалізація параметрів регресії (0, 0):<jupyter_code>X_train_norm, mean, std = normalize(X_train)
X = prepare_X(X_train_norm)
theta = np.array([0, 0])<jupyter_output><empty_output><jupyter_text>Для спрощення записів аліас для вектора передбачуваних значень<jupyter_code>y = y_train[:]<jupyter_output><empty_output><jupyter_text>У випадку використання ВСІХ даних для тренування (test_size=0.0), штрафна функція має повернути величину близьку до 32.072.<jupyter_code>print('X: {}'.format(X.shape))
print('y: {}'.format(y.shape))
print(cost_function(X, y, theta))<jupyter_output>X: (77, 2)
y: (77,)
34.9528636410156<jupyter_text>Налаштування гіперпараметрів регресії: швидкості навчання та кількості ітерацій.<jupyter_code>alpha = 0.01
num_iters = 1500<jupyter_output><empty_output><jupyter_text>Запуск градієнтного спуску та видрук знайдених оптимальних значень на екран. У випадку використання всіх даних для тренування, результати будуть близькі до Theta 0: -3.63; Theta 1: 1.17<jupyter_code>new_theta, Js = gradient_descent(X, y, theta, alpha, num_iters, False)
print('Theta 0: {}; Theta 1: {}'.format(new_theta[0], new_theta[1]))<jupyter_output>Theta 0: 5.942826885709893; Theta 1: 4.946063220493804<jupyter_text>Відображення штрафної функції як функції від thetha0, thetha1.<jupyter_code>plot_J(X, y)<jupyter_output><empty_output><jupyter_text>Відображення знайденої апроксимації разом із тренувальними даними.<jupyter_code>x = np.arange(3, 25, 0.1)
h = new_theta[0] + new_theta[1]*(x-mean)/std

plt.plot(x, h)
plt.scatter(X_train, y_train, marker='*', c='green')

plt.show()<jupyter_output><empty_output><jupyter_text>Оцінка похибки апроксимації на тестових даних (test_size має бути більше 0.0 та менше 1.0).<jupyter_code>####################
# Нормалізувати тестовий датасет, використовуючи mean, std з тренувального
####################
X_test_norm = (X_test - mean)/std
X_test_proc = prepare_X(X_test_norm)
y_test_pred = hypothesis(X_test_proc, new_theta)
rel_diff = np.abs(np.divide(y_test - y_test_pred, y_test)) * 100

res = pd.DataFrame({'X' : X_test, 'y_actual' : y_test, 'y_pred' : y_test_pred, 'err' : rel_diff})
print(res)
print(cost_function(X_test_proc, y_test, new_theta))<jupyter_output>X  y_actual     y_pred          err
36   8.0959    4.1164   5.840224    41.876979
1    5.5277    9.1302   2.651648    70.957397
51   5.3077    1.8396   2.378504    29.294647
48  11.7000    8.0043  10.314933    28.867397
9    5.0546    3.8166   2.064265    45.913501
60   8.8254    5.1694   6.745943    30.497592
71   7.3345    4.0259   4.894900    21.585227
56   6.2742    2.4756   3.578473    44.549717
95  13.3940    9.0551  12.418137    37.139700
41   6.8825    3.9115   4.333714    10.794176
34   8.2111    6.5426   5.983252     8.549326
78  10.2740    6.7526   8.544467    26.535963
10   5.7107    3.2522   2.878853    11.479819
73   7.2259    3.3411   4.760066    42.470029
88   5.5204    0.1520   2.642584  1638.542304
44   7.8247    6.7318   5.503513    18.246045
31   6.5894    5.9966   3.969813    33.798941
6    7.4764    4.3483   5.071077    16.622062
24   5.5649    3.0825   2.697834    12.479035
64  18.9590   17.0540  19.327422    13.330729
2.3230872289006483
{'fraction_non_alphanumeric': 0.12744695414099932, 'fraction_numerical': 0.09787816563997262, 'mean_word_length': 3.816084377059987, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '69694', 'license': 'MIT', 'n_tokens_mistral': 3398, 'n_tokens_neox': 3360, 'n_words': 644, 'path': 'Linear Regression/Linear Regression - Task.ipynb', 'repo_name': 'YaroslavChelentano/ML_LNU_PMP31_HOMEWORKS', 'size': '7305'}