From a33bc05e8d1822c80b39bf187b74b98961a42faf Mon Sep 17 00:00:00 2001 From: Poojan Smart <44301271+PoojanSmart@users.noreply.github.com> Date: Wed, 11 Oct 2023 19:50:03 +0530 Subject: [PATCH 01/11] Adds exponential moving average algorithm --- financial/exponential_moving_average.py | 67 +++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 financial/exponential_moving_average.py diff --git a/financial/exponential_moving_average.py b/financial/exponential_moving_average.py new file mode 100644 index 000000000000..5d602b923c4d --- /dev/null +++ b/financial/exponential_moving_average.py @@ -0,0 +1,67 @@ +""" + Calculates exponential moving average (EMA) on the series of numbers + Wikipedia Reference: https://en.wikipedia.org/wiki/Exponential_smoothing + Reference: https://www.investopedia.com/terms/e/ema.asp#toc-what-is-an-exponential-moving-average-ema + + Exponential moving average is used in financial field to analyze changes stock prices. + EMA is used in conjuction with Simple moving average (SMA), EMA reacts to the changes in + the value quicker than SMA, which is one of the advantages of using EMA. +""" + +import numpy as np + +def exponential_moving_average(series : list[float], window_size : int) -> list [float]: + ''' + :param series: Array of numbers (Time series data) + :param window_size: Window size for calculating average (window_size > 0) + :return: Resulting array of exponentially averaged numbers + + Formula: + + st = alpha * xt + (1 - alpha) * st_prev + alpha = 2/(1 + window_size) - smoothing factor + + Exponential moving average (EMA) is a rule of thumb technique for + smoothing time series data using the exponential window function. + ''' + + if (window_size <= 0): + raise ValueError("window_size must be > 0") + elif (window_size >= len(series)): + raise ValueError("window_size must be < length of series") + + # Resultent array + exp_averaged_arr : list[float] = [] + + # Calculating smoothing factor + alpha = 2 / (1 + window_size) + + # Exponential average at timestamp t + st = series[0] + + for t in range(len(series)): + if t <= window_size: + # Assigning simple moving average till the window_size for the first time + # is reached + st = (st + series[t]) * 0.5 + exp_averaged_arr.append(st) + else: + # Calculating exponential moving average based on current timestamp data + # point and previous exponential average value + st = (alpha * series[t]) + ((1 - alpha) * st) + exp_averaged_arr.append(st) + + return exp_averaged_arr + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + test_series = [2,5,3,8.2,6,9,10] + test_window_size = 3 + result = exponential_moving_average(test_series, test_window_size) + print("Test series: ", test_series) + print("Window size: ", test_window_size) + print("Result: ", result) + From acdc0a2fddff23a3149e3d04c72b5a5dccd6fbb0 Mon Sep 17 00:00:00 2001 From: Poojan Smart <44301271+PoojanSmart@users.noreply.github.com> Date: Wed, 11 Oct 2023 20:21:21 +0530 Subject: [PATCH 02/11] code clean up --- financial/exponential_moving_average.py | 45 +++++++++++++------------ 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/financial/exponential_moving_average.py b/financial/exponential_moving_average.py index 5d602b923c4d..1afb96e3b9c4 100644 --- a/financial/exponential_moving_average.py +++ b/financial/exponential_moving_average.py @@ -3,35 +3,38 @@ Wikipedia Reference: https://en.wikipedia.org/wiki/Exponential_smoothing Reference: https://www.investopedia.com/terms/e/ema.asp#toc-what-is-an-exponential-moving-average-ema - Exponential moving average is used in financial field to analyze changes stock prices. - EMA is used in conjuction with Simple moving average (SMA), EMA reacts to the changes in - the value quicker than SMA, which is one of the advantages of using EMA. + Exponential moving average is used in finance to analyze changes stock prices. + EMA is used in conjuction with Simple moving average (SMA), EMA reacts to the + changes inthe value quicker than SMA, which is one of the advantages of using EMA. """ -import numpy as np -def exponential_moving_average(series : list[float], window_size : int) -> list [float]: - ''' - :param series: Array of numbers (Time series data) - :param window_size: Window size for calculating average (window_size > 0) - :return: Resulting array of exponentially averaged numbers +def exponential_moving_average(series: list[float], window_size: int) -> list[float]: + """ + Returns the exponential moving average of the given array list + >>> exponential_moving_average([2, 5, 3, 8.2, 6, 9, 10], 3) + [2.0, 3.5, 3.25, 5.725, 5.8625, 7.43125, 8.715625] - Formula: + :param series: Array of numbers (Time series data) + :param window_size: Window size for calculating average (window_size > 0) + :return: Resulting array of exponentially averaged numbers - st = alpha * xt + (1 - alpha) * st_prev - alpha = 2/(1 + window_size) - smoothing factor + Formula: - Exponential moving average (EMA) is a rule of thumb technique for - smoothing time series data using the exponential window function. - ''' + st = alpha * xt + (1 - alpha) * st_prev + alpha = 2/(1 + window_size) - smoothing factor - if (window_size <= 0): + Exponential moving average (EMA) is a rule of thumb technique for + smoothing time series data using the exponential window function. + """ + + if window_size <= 0: raise ValueError("window_size must be > 0") - elif (window_size >= len(series)): + elif window_size >= len(series): raise ValueError("window_size must be < length of series") # Resultent array - exp_averaged_arr : list[float] = [] + exp_averaged_arr: list[float] = [] # Calculating smoothing factor alpha = 2 / (1 + window_size) @@ -50,18 +53,18 @@ def exponential_moving_average(series : list[float], window_size : int) -> list # point and previous exponential average value st = (alpha * series[t]) + ((1 - alpha) * st) exp_averaged_arr.append(st) - + return exp_averaged_arr + if __name__ == "__main__": import doctest doctest.testmod() - test_series = [2,5,3,8.2,6,9,10] + test_series = [2, 5, 3, 8.2, 6, 9, 10] test_window_size = 3 result = exponential_moving_average(test_series, test_window_size) print("Test series: ", test_series) print("Window size: ", test_window_size) print("Result: ", result) - From 1ce781fef3a68d017b1a4f0dbc1c5188169c0a8c Mon Sep 17 00:00:00 2001 From: Poojan Smart <44301271+PoojanSmart@users.noreply.github.com> Date: Wed, 11 Oct 2023 20:26:10 +0530 Subject: [PATCH 03/11] spell correction --- financial/exponential_moving_average.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/financial/exponential_moving_average.py b/financial/exponential_moving_average.py index 1afb96e3b9c4..7d903ee48937 100644 --- a/financial/exponential_moving_average.py +++ b/financial/exponential_moving_average.py @@ -4,8 +4,8 @@ Reference: https://www.investopedia.com/terms/e/ema.asp#toc-what-is-an-exponential-moving-average-ema Exponential moving average is used in finance to analyze changes stock prices. - EMA is used in conjuction with Simple moving average (SMA), EMA reacts to the - changes inthe value quicker than SMA, which is one of the advantages of using EMA. + EMA is used in conjunction with Simple moving average (SMA), EMA reacts to the + changes in the value quicker than SMA, which is one of the advantages of using EMA. """ From 7b09aeb1566cf12291ee9fa1c29a2a964b39a6ef Mon Sep 17 00:00:00 2001 From: Poojan Smart <44301271+PoojanSmart@users.noreply.github.com> Date: Thu, 12 Oct 2023 12:12:58 +0530 Subject: [PATCH 04/11] Modifies I/O types of function --- financial/exponential_moving_average.py | 45 ++++++++++++++----------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/financial/exponential_moving_average.py b/financial/exponential_moving_average.py index 7d903ee48937..2014639fc150 100644 --- a/financial/exponential_moving_average.py +++ b/financial/exponential_moving_average.py @@ -8,16 +8,21 @@ changes in the value quicker than SMA, which is one of the advantages of using EMA. """ +from collections.abc import Iterator -def exponential_moving_average(series: list[float], window_size: int) -> list[float]: + +def exponential_moving_average( + series_generator: Iterator[float], window_size: int +) -> Iterator[float]: """ - Returns the exponential moving average of the given array list - >>> exponential_moving_average([2, 5, 3, 8.2, 6, 9, 10], 3) + Returns the generator which generates exponential moving average of the given + series generator + >>> list(exponential_moving_average((ele for ele in [2, 5, 3, 8.2, 6, 9, 10]), 3)) [2.0, 3.5, 3.25, 5.725, 5.8625, 7.43125, 8.715625] - :param series: Array of numbers (Time series data) + :param series_generator: Generator which generates numbers :param window_size: Window size for calculating average (window_size > 0) - :return: Resulting array of exponentially averaged numbers + :return: Returns generator of which returns exponentially averaged numbers Formula: @@ -30,31 +35,27 @@ def exponential_moving_average(series: list[float], window_size: int) -> list[fl if window_size <= 0: raise ValueError("window_size must be > 0") - elif window_size >= len(series): - raise ValueError("window_size must be < length of series") - - # Resultent array - exp_averaged_arr: list[float] = [] # Calculating smoothing factor alpha = 2 / (1 + window_size) + # Defining timestamp t + t = 0 + # Exponential average at timestamp t - st = series[0] + st = None - for t in range(len(series)): + for xt in series_generator: if t <= window_size: # Assigning simple moving average till the window_size for the first time # is reached - st = (st + series[t]) * 0.5 - exp_averaged_arr.append(st) + st = float(xt) if st is None else (st + xt) * 0.5 else: # Calculating exponential moving average based on current timestamp data # point and previous exponential average value - st = (alpha * series[t]) + ((1 - alpha) * st) - exp_averaged_arr.append(st) - - return exp_averaged_arr + st = (alpha * xt) + ((1 - alpha) * st) + t += 1 + yield st if __name__ == "__main__": @@ -62,9 +63,13 @@ def exponential_moving_average(series: list[float], window_size: int) -> list[fl doctest.testmod() + def test_gen_func(arr: list[float]): + yield from arr + test_series = [2, 5, 3, 8.2, 6, 9, 10] + test_generator = test_gen_func(test_series) test_window_size = 3 - result = exponential_moving_average(test_series, test_window_size) + result = exponential_moving_average(test_generator, test_window_size) print("Test series: ", test_series) print("Window size: ", test_window_size) - print("Result: ", result) + print("Result: ", list(result)) From 040379f72fe0fb84b966281a0534d141ed045a43 Mon Sep 17 00:00:00 2001 From: Poojan Smart <44301271+PoojanSmart@users.noreply.github.com> Date: Thu, 12 Oct 2023 12:18:45 +0530 Subject: [PATCH 05/11] Replaces generator function --- financial/exponential_moving_average.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/financial/exponential_moving_average.py b/financial/exponential_moving_average.py index 2014639fc150..506dc607b64f 100644 --- a/financial/exponential_moving_average.py +++ b/financial/exponential_moving_average.py @@ -63,11 +63,8 @@ def exponential_moving_average( doctest.testmod() - def test_gen_func(arr: list[float]): - yield from arr - test_series = [2, 5, 3, 8.2, 6, 9, 10] - test_generator = test_gen_func(test_series) + test_generator = (ele for ele in test_series) test_window_size = 3 result = exponential_moving_average(test_generator, test_window_size) print("Test series: ", test_series) From 6edf6e5395202ef4830057c4712cb97391340ec8 Mon Sep 17 00:00:00 2001 From: Poojan Smart <44301271+PoojanSmart@users.noreply.github.com> Date: Thu, 12 Oct 2023 12:36:07 +0530 Subject: [PATCH 06/11] Resolved mypy type error --- financial/exponential_moving_average.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/financial/exponential_moving_average.py b/financial/exponential_moving_average.py index 506dc607b64f..104ddc10252d 100644 --- a/financial/exponential_moving_average.py +++ b/financial/exponential_moving_average.py @@ -43,13 +43,13 @@ def exponential_moving_average( t = 0 # Exponential average at timestamp t - st = None + st = 0.0 for xt in series_generator: if t <= window_size: # Assigning simple moving average till the window_size for the first time # is reached - st = float(xt) if st is None else (st + xt) * 0.5 + st = float(xt) if t == 0 else (st + xt) * 0.5 else: # Calculating exponential moving average based on current timestamp data # point and previous exponential average value From 68c4bb87d24081238a2a7c5ddc942f8a35243cb8 Mon Sep 17 00:00:00 2001 From: Poojan Smart <44301271+PoojanSmart@users.noreply.github.com> Date: Thu, 12 Oct 2023 17:28:50 +0530 Subject: [PATCH 07/11] readibility of code and documentation --- financial/exponential_moving_average.py | 47 ++++++++++++++++--------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/financial/exponential_moving_average.py b/financial/exponential_moving_average.py index 104ddc10252d..91c46687ca51 100644 --- a/financial/exponential_moving_average.py +++ b/financial/exponential_moving_average.py @@ -1,7 +1,8 @@ """ - Calculates exponential moving average (EMA) on the series of numbers + Calculate the exponential moving average (EMA) on the series of numbers. Wikipedia Reference: https://en.wikipedia.org/wiki/Exponential_smoothing - Reference: https://www.investopedia.com/terms/e/ema.asp#toc-what-is-an-exponential-moving-average-ema + https://www.investopedia.com/terms/e/ema.asp#toc-what-is-an-exponential + -moving-average-ema Exponential moving average is used in finance to analyze changes stock prices. EMA is used in conjunction with Simple moving average (SMA), EMA reacts to the @@ -12,22 +13,27 @@ def exponential_moving_average( - series_generator: Iterator[float], window_size: int + series: Iterator[float], window_size: int ) -> Iterator[float]: """ Returns the generator which generates exponential moving average of the given - series generator - >>> list(exponential_moving_average((ele for ele in [2, 5, 3, 8.2, 6, 9, 10]), 3)) + series + >>> list(exponential_moving_average(iter([2, 5, 3, 8.2, 6, 9, 10]), 3)) [2.0, 3.5, 3.25, 5.725, 5.8625, 7.43125, 8.715625] - :param series_generator: Generator which generates numbers + :param series: Generator which generates numbers :param window_size: Window size for calculating average (window_size > 0) :return: Returns generator of which returns exponentially averaged numbers Formula: st = alpha * xt + (1 - alpha) * st_prev - alpha = 2/(1 + window_size) - smoothing factor + + Where, + st : Exponential moving average at timestamp t + xt : Datapoint in series at timestamp t + st_prev : Exponential moving average at timestamp t-1 + alpha : 2/(1 + window_size) - smoothing factor Exponential moving average (EMA) is a rule of thumb technique for smoothing time series data using the exponential window function. @@ -40,22 +46,28 @@ def exponential_moving_average( alpha = 2 / (1 + window_size) # Defining timestamp t - t = 0 + timestamp = 0 # Exponential average at timestamp t - st = 0.0 + exponential_average = 0.0 - for xt in series_generator: - if t <= window_size: + for datapoint in series: + if timestamp <= window_size: # Assigning simple moving average till the window_size for the first time # is reached - st = float(xt) if t == 0 else (st + xt) * 0.5 + exponential_average = ( + float(datapoint) + if timestamp == 0 + else (exponential_average + datapoint) * 0.5 + ) else: # Calculating exponential moving average based on current timestamp data # point and previous exponential average value - st = (alpha * xt) + ((1 - alpha) * st) - t += 1 - yield st + exponential_average = (alpha * datapoint) + ( + (1 - alpha) * exponential_average + ) + timestamp += 1 + yield exponential_average if __name__ == "__main__": @@ -64,9 +76,10 @@ def exponential_moving_average( doctest.testmod() test_series = [2, 5, 3, 8.2, 6, 9, 10] - test_generator = (ele for ele in test_series) test_window_size = 3 - result = exponential_moving_average(test_generator, test_window_size) + result = exponential_moving_average( + series=iter(test_series), window_size=test_window_size + ) print("Test series: ", test_series) print("Window size: ", test_window_size) print("Result: ", list(result)) From ce8ecce5000d78d6b6f44f457309e98705e0ece8 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 12 Oct 2023 15:51:18 +0200 Subject: [PATCH 08/11] Update exponential_moving_average.py --- financial/exponential_moving_average.py | 58 ++++++++++--------------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/financial/exponential_moving_average.py b/financial/exponential_moving_average.py index 91c46687ca51..0b6cea3b4c91 100644 --- a/financial/exponential_moving_average.py +++ b/financial/exponential_moving_average.py @@ -1,5 +1,5 @@ """ - Calculate the exponential moving average (EMA) on the series of numbers. + Calculate the exponential moving average (EMA) on the series of stock prices. Wikipedia Reference: https://en.wikipedia.org/wiki/Exponential_smoothing https://www.investopedia.com/terms/e/ema.asp#toc-what-is-an-exponential -moving-average-ema @@ -13,17 +13,17 @@ def exponential_moving_average( - series: Iterator[float], window_size: int + stock_prices: Iterator[float], window_size: int ) -> Iterator[float]: """ - Returns the generator which generates exponential moving average of the given - series - >>> list(exponential_moving_average(iter([2, 5, 3, 8.2, 6, 9, 10]), 3)) - [2.0, 3.5, 3.25, 5.725, 5.8625, 7.43125, 8.715625] + Yields exponential moving averages of the given stock prices. + >>> tuple(exponential_moving_average(iter([2, 5, 3, 8.2, 6, 9, 10]), 3)) + (2, 3.5, 3.25, 5.725, 5.8625, 7.43125, 8.715625) - :param series: Generator which generates numbers - :param window_size: Window size for calculating average (window_size > 0) - :return: Returns generator of which returns exponentially averaged numbers + :param stock_prices: A stream of stock prices + :param window_size: The number of stock prices that will trigger a new calculation + of the exponential average (window_size > 0) + :return: Yields a sequence of exponential moving averages Formula: @@ -31,12 +31,12 @@ def exponential_moving_average( Where, st : Exponential moving average at timestamp t - xt : Datapoint in series at timestamp t + xt : stock price in from the stock prices at timestamp t st_prev : Exponential moving average at timestamp t-1 alpha : 2/(1 + window_size) - smoothing factor Exponential moving average (EMA) is a rule of thumb technique for - smoothing time series data using the exponential window function. + smoothing time series data using an exponential window function. """ if window_size <= 0: @@ -45,29 +45,19 @@ def exponential_moving_average( # Calculating smoothing factor alpha = 2 / (1 + window_size) - # Defining timestamp t - timestamp = 0 - # Exponential average at timestamp t - exponential_average = 0.0 + moving_average = 0.0 - for datapoint in series: - if timestamp <= window_size: + for i, stock_price in enumerate(stock_prices): + if i <= window_size: # Assigning simple moving average till the window_size for the first time # is reached - exponential_average = ( - float(datapoint) - if timestamp == 0 - else (exponential_average + datapoint) * 0.5 - ) + moving_average = (moving_average + stock_price) * 0.5 if i else stock_price else: # Calculating exponential moving average based on current timestamp data # point and previous exponential average value - exponential_average = (alpha * datapoint) + ( - (1 - alpha) * exponential_average - ) - timestamp += 1 - yield exponential_average + moving_average = (alpha * stock_price) + ((1 - alpha) * moving_average) + yield moving_average if __name__ == "__main__": @@ -75,11 +65,9 @@ def exponential_moving_average( doctest.testmod() - test_series = [2, 5, 3, 8.2, 6, 9, 10] - test_window_size = 3 - result = exponential_moving_average( - series=iter(test_series), window_size=test_window_size - ) - print("Test series: ", test_series) - print("Window size: ", test_window_size) - print("Result: ", list(result)) + stock_prices = [2.0, 5, 3, 8.2, 6, 9, 10] + window_size = 3 + result = tuple(exponential_moving_average(iter(stock_prices), window_size)) + print(f"{stock_prices = }") + print(f"{window_size = }") + print(f"{result = }") From 1ea82fab31f2f4ee50268361e86610b99139a12a Mon Sep 17 00:00:00 2001 From: Poojan Smart <44301271+PoojanSmart@users.noreply.github.com> Date: Tue, 17 Oct 2023 08:22:34 +0530 Subject: [PATCH 09/11] Adds hinge loss function --- machine_learning/loss_functions/hinge_loss.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 machine_learning/loss_functions/hinge_loss.py diff --git a/machine_learning/loss_functions/hinge_loss.py b/machine_learning/loss_functions/hinge_loss.py new file mode 100644 index 000000000000..5028bb5a4628 --- /dev/null +++ b/machine_learning/loss_functions/hinge_loss.py @@ -0,0 +1,55 @@ +""" +Hinge Loss + +Description: +Compute the Hinge loss used for training SVM (Support Vector Machine). + +Formula: +loss = max(0, 1 - true * pred) + +Reference: https://en.wikipedia.org/wiki/Hinge_loss + +Author: Poojan Smart +Email: smrtpoojan@gmail.com +""" + +import numpy as np + + +def hinge_loss(y_true: np.ndarray, pred: np.ndarray) -> float: + """ + Calculate the hinge loss for y_true and pred for binary classification. + + Args: + y_true: Array of actual values (ground truth) encoded as -1 and 1. + pred: Array of predicted values. + + Returns: + Hinge loss + + Examples: + >>> y_true = np.array([-1, 1, 1, -1, 1]) + >>> pred = np.array([-4, -0.3, 0.7, 5, 10]) + >>> hinge_loss(y_true, pred) + 1.52 + >>> y_true = np.array([-1, 1, 1, -1, 1, 1]) + >>> pred = np.array([-4, -0.3, 0.7, 5, 10]) + >>> hinge_loss(y_true, pred) + Traceback (most recent call last): + ... + ValueError: Length of predicted and actual array must be same. + """ + + if len(y_true) != len(pred): + raise ValueError("Length of predicted and actual array must be same.") + + intermidiate_result = 1.0 - (y_true * pred) + intermidiate_result[intermidiate_result < 0] = 0 + loss = np.mean(intermidiate_result) + return loss + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From c24a3da86ffab2bc61e09c7087d1773af7ff32b4 Mon Sep 17 00:00:00 2001 From: Poojan Smart <44301271+PoojanSmart@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:00:31 +0530 Subject: [PATCH 10/11] suggested doc and refactoring changes --- machine_learning/loss_functions/hinge_loss.py | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/machine_learning/loss_functions/hinge_loss.py b/machine_learning/loss_functions/hinge_loss.py index 5028bb5a4628..327d842eec13 100644 --- a/machine_learning/loss_functions/hinge_loss.py +++ b/machine_learning/loss_functions/hinge_loss.py @@ -16,16 +16,16 @@ import numpy as np -def hinge_loss(y_true: np.ndarray, pred: np.ndarray) -> float: +def hinge_loss(y_true: np.ndarray, y_pred: np.ndarray) -> float: """ - Calculate the hinge loss for y_true and pred for binary classification. + Calculate the mean hinge loss for y_true and y_pred for binary classification. Args: y_true: Array of actual values (ground truth) encoded as -1 and 1. - pred: Array of predicted values. + y_pred: Array of predicted values. Returns: - Hinge loss + The hinge loss between y_true and y_pred. Examples: >>> y_true = np.array([-1, 1, 1, -1, 1]) @@ -38,15 +38,24 @@ def hinge_loss(y_true: np.ndarray, pred: np.ndarray) -> float: Traceback (most recent call last): ... ValueError: Length of predicted and actual array must be same. + >>> y_true = np.array([-1, 1, 10, -1, 1]) + >>> pred = np.array([-4, -0.3, 0.7, 5, 10]) + >>> hinge_loss(y_true, pred) + Traceback (most recent call last): + ... + ValueError: y_true can have values -1 or 1 only. """ - if len(y_true) != len(pred): + if len(y_true) != len(y_pred): raise ValueError("Length of predicted and actual array must be same.") - intermidiate_result = 1.0 - (y_true * pred) - intermidiate_result[intermidiate_result < 0] = 0 - loss = np.mean(intermidiate_result) - return loss + # Raise value error when y_true (encoded labels) have any other values + # than -1 and 1 + if np.array_equal(np.sort(np.unique(y_true)), np.array([-1, 1])) is False: + raise ValueError("y_true can have values -1 or 1 only.") + + hinge_losses = np.maximum(0, 1.0 - (y_true * y_pred)) + return np.mean(hinge_losses) if __name__ == "__main__": From 0fb72743b8bdeae49eafc346bcaedd0c546b6872 Mon Sep 17 00:00:00 2001 From: Poojan Smart <44301271+PoojanSmart@users.noreply.github.com> Date: Wed, 18 Oct 2023 07:31:43 +0530 Subject: [PATCH 11/11] refactoring --- machine_learning/loss_functions/hinge_loss.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machine_learning/loss_functions/hinge_loss.py b/machine_learning/loss_functions/hinge_loss.py index 327d842eec13..5480a8cd62ee 100644 --- a/machine_learning/loss_functions/hinge_loss.py +++ b/machine_learning/loss_functions/hinge_loss.py @@ -51,7 +51,7 @@ def hinge_loss(y_true: np.ndarray, y_pred: np.ndarray) -> float: # Raise value error when y_true (encoded labels) have any other values # than -1 and 1 - if np.array_equal(np.sort(np.unique(y_true)), np.array([-1, 1])) is False: + if np.any((y_true != -1) & (y_true != 1)): raise ValueError("y_true can have values -1 or 1 only.") hinge_losses = np.maximum(0, 1.0 - (y_true * y_pred))