- # --------------------------------------------------------------------------
- # ------------ Metody Systemowe i Decyzyjne w Informatyce ----------------
- # --------------------------------------------------------------------------
- # Zadanie 1: Regresja liniowa
- # autorzy: A. Gonczarek, J. Kaczmar, S. Zareba
- # 2017
- # --------------------------------------------------------------------------
- from _operator import inv
- from numpy.linalg import inv
- import numpy as np
- from utils import polynomial
- def mean_squared_error(x, y, w):
- '''
- :param x: ciag wejsciowy Nx1
- :param y: ciag wyjsciowy Nx1
- :param w: parametry modelu (M+1)x1
- :return: blad sredniokwadratowy pomiedzy wyjsciami y
- oraz wyjsciami uzyskanymi z wielowamiu o parametrach w dla wejsc x
- '''
- error = 0.0
- for i in range(x.size):
- error += (y[i]-polynomial(x[i], w))**2
- return float(error/x.size)
- def design_matrix(x_train, M):
- '''
- :param x_train: ciag treningowy Nx1
- :param M: stopien wielomianu 0,1,2,...
- :return: funkcja wylicza Design Matrix Nx(M+1) dla wielomianu rzedu M
- '''
- matrix = np.empty((x_train.size, (M+1)))
- for i in range(x_train.size):
- for j in range(M + 1):
- matrix[i, j] = x_train[i]**j
- return matrix
- def least_squares(x_train, y_train, M):
- '''
- :param x_train: ciag treningowy wejscia Nx1
- :param y_train: ciag treningowy wyjscia Nx1
- :param M: rzad wielomianu
- :return: funkcja zwraca krotke (w,err), gdzie w sa parametrami dopasowanego wielomianu, a err blad sredniokwadratowy
- dopasowania
- '''
- fi = design_matrix(x_train, M)
- w = inv((fi.transpose() @ fi)) @ fi.transpose() @ y_train
- return w, mean_squared_error(x_train, y_train, w)
- def regularized_least_squares(x_train, y_train, M, regularization_lambda):
- '''
- :param x_train: ciag treningowy wejscia Nx1
- :param y_train: ciag treningowy wyjscia Nx1
- :param M: rzad wielomianu
- :param regularization_lambda: parametr regularyzacji
- :return: funkcja zwraca krotke (w,err), gdzie w sa parametrami dopasowanego wielomianu zgodnie z kryterium z regularyzacja l2,
- a err blad sredniokwadratowy dopasowania
- '''
- fi = design_matrix(x_train, M)
- fi_matrix = (fi.transpose() @ fi)
- lambda_matrix = np.eye(fi_matrix.shape[0]) * regularization_lambda
- w = inv(fi_matrix + lambda_matrix) @ fi.transpose() @ y_train
- return w, mean_squared_error(x_train, y_train, w)
- def model_selection(x_train, y_train, x_val, y_val, M_values):
- '''
- :param x_train: ciag treningowy wejscia Nx1
- :param y_train: ciag treningowy wyjscia Nx1
- :param x_val: ciag walidacyjny wejscia Nx1
- :param y_val: ciag walidacyjny wyjscia Nx1
- :param M_values: tablica stopni wielomianu, ktore maja byc sprawdzone
- :return: funkcja zwraca krotke (w,train_err,val_err), gdzie w sa parametrami modelu, ktory najlepiej generalizuje dane,
- tj. daje najmniejszy blad na ciagu walidacyjnym, train_err i val_err to bledy na sredniokwadratowe na ciagach treningowym
- i walidacyjnym
- '''
- w_score = []
- w_error_score = []
- for i in M_values:
- w, train_err = least_squares(x_train, y_train, i)
- val_err = mean_squared_error(x_val, y_val, w)
- w_score.append((w, train_err, val_err))
- w_error_score.append(val_err)
- min_index = w_error_score.index(min(w_error_score))
- return w_score[min_index]
- def regularized_model_selection(x_train, y_train, x_val, y_val, M, lambda_values):
- '''
- :param x_train: ciag treningowy wejscia Nx1
- :param y_train: ciag treningowy wyjscia Nx1
- :param x_val: ciag walidacyjny wejscia Nx1
- :param y_val: ciag walidacyjny wyjscia Nx1
- :param M: stopien wielomianu
- :param lambda_values: lista ze wartosciami roznych parametrow regularyzacji
- :return: funkcja zwraca krotke (w,train_err,val_err,regularization_lambda), gdzie w sa parametrami modelu, ktory najlepiej generalizuje dane,
- tj. daje najmniejszy blad na ciagu walidacyjnym. Wielomian dopasowany jest wg kryterium z regularyzacja. train_err i val_err to
- bledy na sredniokwadratowe na ciagach treningowym i walidacyjnym. regularization_lambda to najlepsza wartosc parametru regularyzacji
- '''
- w_score = []
- w_error_score = []
- for i in range(len(lambda_values)):
- w, train_err = regularized_least_squares(x_train, y_train, M, lambda_values[i])
- val_err = mean_squared_error(x_val, y_val, w)
- w_score.append((w, train_err, val_err, lambda_values[i]))
- w_error_score.append(val_err)
- min_index = w_error_score.index(min(w_error_score))
- return w_score[min_index]