PyDLLib 1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. DLL/Data/Metrics.py +626 -0
  2. DLL/Data/Preprocessing.py +384 -0
  3. DLL/Data/_DataReader.py +55 -0
  4. DLL/Data/__init__.py +1 -0
  5. DLL/DeepLearning/Callbacks/_BackUp.py +71 -0
  6. DLL/DeepLearning/Callbacks/_BaseCallback.py +43 -0
  7. DLL/DeepLearning/Callbacks/_EarlyStopping.py +102 -0
  8. DLL/DeepLearning/Callbacks/_ReduceLROnPlateau.py +90 -0
  9. DLL/DeepLearning/Callbacks/__init__.py +4 -0
  10. DLL/DeepLearning/Initialisers/_Initialiser.py +24 -0
  11. DLL/DeepLearning/Initialisers/_Kaiming_He.py +55 -0
  12. DLL/DeepLearning/Initialisers/_Xavier_Glorot.py +39 -0
  13. DLL/DeepLearning/Initialisers/__init__.py +2 -0
  14. DLL/DeepLearning/Layers/Activations/_Activation.py +23 -0
  15. DLL/DeepLearning/Layers/Activations/_ReLU.py +51 -0
  16. DLL/DeepLearning/Layers/Activations/_Sigmoid.py +51 -0
  17. DLL/DeepLearning/Layers/Activations/_SoftMax.py +83 -0
  18. DLL/DeepLearning/Layers/Activations/_Tanh.py +47 -0
  19. DLL/DeepLearning/Layers/Activations/__init__.py +4 -0
  20. DLL/DeepLearning/Layers/Regularisation/_BaseRegularisation.py +12 -0
  21. DLL/DeepLearning/Layers/Regularisation/_BatchNormalisation.py +106 -0
  22. DLL/DeepLearning/Layers/Regularisation/_Dropout.py +79 -0
  23. DLL/DeepLearning/Layers/Regularisation/_GroupNormalisation.py +112 -0
  24. DLL/DeepLearning/Layers/Regularisation/_InstanceNormalisation.py +50 -0
  25. DLL/DeepLearning/Layers/Regularisation/_LayerNormalisation.py +37 -0
  26. DLL/DeepLearning/Layers/Regularisation/__init__.py +5 -0
  27. DLL/DeepLearning/Layers/_Add.py +109 -0
  28. DLL/DeepLearning/Layers/_Attention.py +161 -0
  29. DLL/DeepLearning/Layers/_BaseLayer.py +87 -0
  30. DLL/DeepLearning/Layers/_Bidirectional.py +113 -0
  31. DLL/DeepLearning/Layers/_Conv2D.py +133 -0
  32. DLL/DeepLearning/Layers/_Dense.py +109 -0
  33. DLL/DeepLearning/Layers/_DenseKAN.py +184 -0
  34. DLL/DeepLearning/Layers/_Flatten.py +55 -0
  35. DLL/DeepLearning/Layers/_Identity.py +50 -0
  36. DLL/DeepLearning/Layers/_Input.py +11 -0
  37. DLL/DeepLearning/Layers/_LSTM.py +261 -0
  38. DLL/DeepLearning/Layers/_LayerList.py +98 -0
  39. DLL/DeepLearning/Layers/_MaxPooling2D.py +101 -0
  40. DLL/DeepLearning/Layers/_RNN.py +185 -0
  41. DLL/DeepLearning/Layers/_Reshape.py +52 -0
  42. DLL/DeepLearning/Layers/__init__.py +14 -0
  43. DLL/DeepLearning/Losses/_BCE.py +96 -0
  44. DLL/DeepLearning/Losses/_BaseLoss.py +18 -0
  45. DLL/DeepLearning/Losses/_CCE.py +87 -0
  46. DLL/DeepLearning/Losses/_Exponential.py +101 -0
  47. DLL/DeepLearning/Losses/_Huber.py +104 -0
  48. DLL/DeepLearning/Losses/_MAE.py +85 -0
  49. DLL/DeepLearning/Losses/_MSE.py +86 -0
  50. DLL/DeepLearning/Losses/__init__.py +6 -0
  51. DLL/DeepLearning/Model.py +265 -0
  52. DLL/DeepLearning/Optimisers/_ADADELTA.py +53 -0
  53. DLL/DeepLearning/Optimisers/_ADAGRAD.py +51 -0
  54. DLL/DeepLearning/Optimisers/_ADAM.py +65 -0
  55. DLL/DeepLearning/Optimisers/_BaseOptimiser.py +20 -0
  56. DLL/DeepLearning/Optimisers/_LBFGS.py +120 -0
  57. DLL/DeepLearning/Optimisers/_RMSPROP.py +62 -0
  58. DLL/DeepLearning/Optimisers/_SGD.py +44 -0
  59. DLL/DeepLearning/Optimisers/__init__.py +6 -0
  60. DLL/DeepLearning/__init__.py +0 -0
  61. DLL/Exceptions/_Exceptions.py +19 -0
  62. DLL/Exceptions/__init__.py +2 -0
  63. DLL/MachineLearning/SupervisedLearning/Calibration/_CalibratedClassifier.py +88 -0
  64. DLL/MachineLearning/SupervisedLearning/Calibration/_IsotonicRegression.py +114 -0
  65. DLL/MachineLearning/SupervisedLearning/Calibration/__init__.py +2 -0
  66. DLL/MachineLearning/SupervisedLearning/GaussianProcesses/_GaussianProcessRegressor.py +190 -0
  67. DLL/MachineLearning/SupervisedLearning/GaussianProcesses/__init__.py +1 -0
  68. DLL/MachineLearning/SupervisedLearning/Kernels.py +851 -0
  69. DLL/MachineLearning/SupervisedLearning/LinearModels/TimeSeries.py +147 -0
  70. DLL/MachineLearning/SupervisedLearning/LinearModels/_Elasticnet.py +161 -0
  71. DLL/MachineLearning/SupervisedLearning/LinearModels/_LassoRegression.py +157 -0
  72. DLL/MachineLearning/SupervisedLearning/LinearModels/_LinearRegression.py +81 -0
  73. DLL/MachineLearning/SupervisedLearning/LinearModels/_LogisticRegression.py +182 -0
  74. DLL/MachineLearning/SupervisedLearning/LinearModels/_RANSAC.py +97 -0
  75. DLL/MachineLearning/SupervisedLearning/LinearModels/_RidgeRegression.py +78 -0
  76. DLL/MachineLearning/SupervisedLearning/LinearModels/__init__.py +6 -0
  77. DLL/MachineLearning/SupervisedLearning/NaiveBayes/_BernoulliNaiveBayes.py +115 -0
  78. DLL/MachineLearning/SupervisedLearning/NaiveBayes/_GaussianNaiveBayes.py +111 -0
  79. DLL/MachineLearning/SupervisedLearning/NaiveBayes/_MultinomialNaiveBayes.py +115 -0
  80. DLL/MachineLearning/SupervisedLearning/NaiveBayes/__init__.py +3 -0
  81. DLL/MachineLearning/SupervisedLearning/Neighbors/_KNearestNeighborsClassifier.py +115 -0
  82. DLL/MachineLearning/SupervisedLearning/Neighbors/_KNearestNeighborsRegressor.py +90 -0
  83. DLL/MachineLearning/SupervisedLearning/Neighbors/__init__.py +2 -0
  84. DLL/MachineLearning/SupervisedLearning/SupportVectorMachines/_SVC.py +293 -0
  85. DLL/MachineLearning/SupervisedLearning/SupportVectorMachines/_SVR.py +100 -0
  86. DLL/MachineLearning/SupervisedLearning/SupportVectorMachines/__init__.py +2 -0
  87. DLL/MachineLearning/SupervisedLearning/Trees/_AdaBoostClassifier.py +179 -0
  88. DLL/MachineLearning/SupervisedLearning/Trees/_AdaBoostRegressor.py +141 -0
  89. DLL/MachineLearning/SupervisedLearning/Trees/_DecisionTree.py +219 -0
  90. DLL/MachineLearning/SupervisedLearning/Trees/_GradientBoostingClassifier.py +207 -0
  91. DLL/MachineLearning/SupervisedLearning/Trees/_GradientBoostingRegressor.py +122 -0
  92. DLL/MachineLearning/SupervisedLearning/Trees/_LGBMClassifier.py +288 -0
  93. DLL/MachineLearning/SupervisedLearning/Trees/_LGBMRegressor.py +168 -0
  94. DLL/MachineLearning/SupervisedLearning/Trees/_LGBMTree.py +199 -0
  95. DLL/MachineLearning/SupervisedLearning/Trees/_RandomForest.py +96 -0
  96. DLL/MachineLearning/SupervisedLearning/Trees/_RegressionForest.py +75 -0
  97. DLL/MachineLearning/SupervisedLearning/Trees/_RegressionTree.py +148 -0
  98. DLL/MachineLearning/SupervisedLearning/Trees/_XGBoostClassifier.py +239 -0
  99. DLL/MachineLearning/SupervisedLearning/Trees/_XGBoostRegressor.py +131 -0
  100. DLL/MachineLearning/SupervisedLearning/Trees/_XGBoostTree.py +105 -0
  101. DLL/MachineLearning/SupervisedLearning/Trees/__init__.py +12 -0
  102. DLL/MachineLearning/SupervisedLearning/__init__.py +0 -0
  103. DLL/MachineLearning/UnsupervisedLearning/Clustering/_DBScan.py +87 -0
  104. DLL/MachineLearning/UnsupervisedLearning/Clustering/_GaussianMixtureModels.py +121 -0
  105. DLL/MachineLearning/UnsupervisedLearning/Clustering/_KMeans.py +120 -0
  106. DLL/MachineLearning/UnsupervisedLearning/Clustering/_SpectralClustering.py +105 -0
  107. DLL/MachineLearning/UnsupervisedLearning/Clustering/__init__.py +4 -0
  108. DLL/MachineLearning/UnsupervisedLearning/DimensionalityReduction/_LDA.py +118 -0
  109. DLL/MachineLearning/UnsupervisedLearning/DimensionalityReduction/_PCA.py +101 -0
  110. DLL/MachineLearning/UnsupervisedLearning/DimensionalityReduction/_QDA.py +69 -0
  111. DLL/MachineLearning/UnsupervisedLearning/DimensionalityReduction/_RobustPCA.py +143 -0
  112. DLL/MachineLearning/UnsupervisedLearning/DimensionalityReduction/_TSNE.py +151 -0
  113. DLL/MachineLearning/UnsupervisedLearning/DimensionalityReduction/_UMAP.py +176 -0
  114. DLL/MachineLearning/UnsupervisedLearning/DimensionalityReduction/__init__.py +6 -0
  115. DLL/MachineLearning/UnsupervisedLearning/OutlierDetection/_IsolationForest.py +175 -0
  116. DLL/MachineLearning/UnsupervisedLearning/OutlierDetection/__init__.py +1 -0
  117. DLL/MachineLearning/UnsupervisedLearning/__init__.py +0 -0
  118. DLL/MachineLearning/__init__.py +0 -0
  119. DLL/__init__.py +0 -0
  120. pydllib-1.0.dist-info/METADATA +104 -0
  121. pydllib-1.0.dist-info/RECORD +124 -0
  122. pydllib-1.0.dist-info/WHEEL +5 -0
  123. pydllib-1.0.dist-info/licenses/LICENSE +21 -0
  124. pydllib-1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,52 @@
1
+ import torch
2
+
3
+ from ._BaseLayer import BaseLayer
4
+
5
+
6
+ class Reshape(BaseLayer):
7
+ """
8
+ The reshape layer.
9
+
10
+ Args:
11
+ output_shape (int): The output_shape of the model not containing the batch_size dimension. Must be a positive integer or a tuple.
12
+ """
13
+ def __init__(self, output_shape, **kwargs):
14
+ output_shape = (output_shape,) if isinstance(output_shape, int) else output_shape
15
+
16
+ super().__init__(output_shape, **kwargs)
17
+ self.name = "Reshape"
18
+
19
+ def forward(self, input, **kwargs):
20
+ """
21
+ Reshapes the input into the output_shape.
22
+
23
+ Args:
24
+ input (torch.Tensor of shape (n_samples, *layer.input_shape)): The input to the layer. Must be a torch.Tensor of the spesified shape given by layer.input_shape.
25
+
26
+ Returns:
27
+ torch.Tensor of shape (n_samples, *layer.output_shape): The output tensor after reshaping the input tensor.
28
+ """
29
+ if not isinstance(input, torch.Tensor):
30
+ raise TypeError("input must be a torch.Tensor.")
31
+ if input.shape[1:] != self.input_shape:
32
+ raise ValueError(f"input is not the same shape as the spesified input_shape ({input.shape[1:], self.input_shape}).")
33
+
34
+ self.input = input
35
+ return input.reshape(input.shape[0], *self.output_shape)
36
+
37
+ def backward(self, dCdy, **kwargs):
38
+ """
39
+ Reshapes the gradient to the original shape.
40
+
41
+ Args:
42
+ dCdy (torch.Tensor of shape (n_samples, *layer.output_shape): The gradient given by the next layer.
43
+
44
+ Returns:
45
+ torch.Tensor of shape (n_samples, *layer.input_shape): The reshaped gradient after backpropagation through the layer.
46
+ """
47
+ if not isinstance(dCdy, torch.Tensor):
48
+ raise TypeError("dCdy must be a torch.Tensor.")
49
+ if dCdy.shape[1:] != self.output_shape:
50
+ raise ValueError(f"dCdy is not the same shape as the spesified output_shape ({dCdy.shape[1:], self.output_shape}).")
51
+
52
+ return dCdy.reshape(*self.input.shape)
@@ -0,0 +1,14 @@
1
+ from ._Conv2D import Conv2D
2
+ from ._Dense import Dense
3
+ from ._Flatten import Flatten
4
+ from ._Input import Input
5
+ from ._LSTM import LSTM
6
+ from ._MaxPooling2D import MaxPooling2D
7
+ from ._Reshape import Reshape
8
+ from ._RNN import RNN
9
+ from ._Bidirectional import Bidirectional
10
+ from ._Identity import Identity
11
+ from ._Add import Add
12
+ from ._LayerList import LayerList
13
+ from ._Attention import MultiHeadAttention
14
+ from ._DenseKAN import DenseKAN
@@ -0,0 +1,96 @@
1
+ import torch
2
+
3
+ from ._BaseLoss import BaseLoss
4
+
5
+
6
+ class BCE(BaseLoss):
7
+ """
8
+ The binary cross entropy loss. Used in binary classification. Identical to categorical cross entropy with 2 classes.
9
+
10
+ Args:
11
+ reduction (str, optional): The reduction method. Must be one of "mean" or "sum". Defaults to "mean".
12
+ """
13
+ def __init__(self, reduction="mean"):
14
+ if reduction not in ["mean", "sum"]:
15
+ raise ValueError('reduction must be in ["mean", "sum"].')
16
+
17
+ self.reduction = reduction
18
+
19
+ def loss(self, prediction, true_output):
20
+ """
21
+ Calculates the binary categorical cross entropy with the equations:
22
+
23
+ .. math::
24
+
25
+ \\begin{align*}
26
+ l_i &= y_i\\cdot\\text{ln}(f(x_i)) + (1 - y_i)\\cdot\\text{ln}(1 - f(x_i)),\\\\
27
+ L_{sum} &= \\sum_{i=1}^n l_i \\text{ or } L_{mean} = \\frac{1}{n}\\sum_{i=1}^n l_i,
28
+ \\end{align*}
29
+
30
+ where :math:`f(x_i)` is the predicted value and :math:`y_i` is the true value.
31
+
32
+ Args:
33
+ prediction (torch.Tensor): A tensor of predicted values in range [0, 1]. Must be the same shape as the true_output.
34
+ true_output (torch.Tensor): A tensor of true values labeled with 0 or 1. Must be the same shape as the prediction.
35
+
36
+ Returns:
37
+ torch.Tensor: A tensor containing a single value with the loss.
38
+ """
39
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
40
+ raise TypeError("prediction and true_output must be torch tensors.")
41
+ if prediction.shape != true_output.shape:
42
+ raise ValueError("prediction and true_output must have the same shape.")
43
+
44
+ if self.reduction == "mean":
45
+ return -torch.mean(true_output * torch.log(prediction + 1e-10) + (1 - true_output) * torch.log(1 - prediction + 1e-10))
46
+ return -torch.sum(true_output * torch.log(prediction + 1e-10) + (1 - true_output) * torch.log(1 - prediction + 1e-10))
47
+
48
+ def gradient(self, prediction, true_output):
49
+ """
50
+ Calculates the gradient of the binary categorical cross entropy.
51
+
52
+ Args:
53
+ prediction (torch.Tensor): A tensor of predicted values in range [0, 1]. Must be the same shape as the true_output.
54
+ true_output (torch.Tensor): A tensor of true values labeled with 0 or 1. Must be the same shape as the prediction.
55
+
56
+ Returns:
57
+ torch.Tensor: A tensor of the same shape as the inputs containing the gradients.
58
+ """
59
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
60
+ raise TypeError("prediction and true_output must be torch tensors.")
61
+ if prediction.shape != true_output.shape:
62
+ raise ValueError("prediction and true_output must have the same shape.")
63
+ if set(torch.unique(true_output).numpy()) != {0, 1}:
64
+ raise ValueError("The classes must be labelled 0 and 1.")
65
+
66
+ if self.reduction == "mean":
67
+ return (prediction - true_output) / ((prediction * (1 - prediction) + 1e-10) * prediction.shape[0])
68
+ return (prediction - true_output) / (prediction * (1 - prediction) + 1e-10)
69
+
70
+ def hessian(self, prediction, true_output):
71
+ """
72
+ Calculates the diagonal of the hessian matrix of the binary categorical cross entropy.
73
+
74
+ Args:
75
+ prediction (torch.Tensor): A tensor of predicted values in range [0, 1]. Must be the same shape as the true_output.
76
+ true_output (torch.Tensor): A tensor of true values labeled with 0 or 1. Must be the same shape as the prediction.
77
+
78
+ Returns:
79
+ torch.Tensor: A tensor of the same shape as the inputs containing the diagonal of the hessian matrix.
80
+ """
81
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
82
+ raise TypeError("prediction and true_output must be torch tensors.")
83
+ if prediction.shape != true_output.shape:
84
+ raise ValueError("prediction and true_output must have the same shape.")
85
+ if set(torch.unique(true_output).numpy()) != {0, 1}:
86
+ raise ValueError("The classes must be labelled 0 and 1.")
87
+
88
+ first_term = 1 / ((1 - prediction) * prediction + 1e-10)
89
+ second_term = (true_output - prediction) / ((1 - prediction) * prediction ** 2 + 1e-10)
90
+ third_term = (prediction - true_output) / ((1 - prediction) ** 2 * prediction + 1e-10)
91
+ hess = first_term + second_term + third_term
92
+
93
+ if self.reduction == "mean":
94
+ return hess / prediction.shape[0]
95
+ return hess
96
+
@@ -0,0 +1,18 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class BaseLoss(ABC):
5
+ """
6
+ :meta private:
7
+ """
8
+ @abstractmethod
9
+ def loss(self, prediction, true_output):
10
+ pass
11
+
12
+ @abstractmethod
13
+ def gradient(self, prediction, true_output):
14
+ pass
15
+
16
+ @abstractmethod
17
+ def hessian(self, prediction, true_output):
18
+ pass
@@ -0,0 +1,87 @@
1
+ import torch
2
+
3
+ from ._BaseLoss import BaseLoss
4
+
5
+
6
+ class CCE(BaseLoss):
7
+ """
8
+ The categorical cross entropy loss. Used in multi-class classification.
9
+
10
+ Args:
11
+ reduction (str, optional): The reduction method. Must be one of "mean" or "sum". Defaults to "mean".
12
+ """
13
+ def __init__(self, reduction="mean"):
14
+ if reduction not in ["mean", "sum"]:
15
+ raise ValueError('reduction must be in ["mean", "sum"].')
16
+
17
+ self.reduction = reduction
18
+
19
+ def loss(self, prediction, true_output):
20
+ """
21
+ Calculates the categorical categorical cross entropy with the equations:
22
+
23
+ .. math::
24
+
25
+ \\begin{align*}
26
+ l_i &= y_i\\cdot\\text{ln}(f(x_i)),\\\\
27
+ L_{sum} &= \\sum_{i=1}^n l_i \\text{ or } L_{mean} = \\frac{1}{n}\\sum_{i=1}^n l_i,
28
+ \\end{align*}
29
+
30
+ where :math:`f(x_i)` is the predicted value and :math:`y_i` is the true value.
31
+
32
+ Args:
33
+ prediction (torch.Tensor): A tensor of predicted values as a probability distribution. Must be the same shape as the true_output.
34
+ true_output (torch.Tensor): A one-hot encoded tensor of true values. Must be the same shape as the prediction.
35
+
36
+ Returns:
37
+ torch.Tensor: A tensor containing a single value with the loss.
38
+ """
39
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
40
+ raise TypeError("prediction and true_output must be torch tensors.")
41
+ if prediction.shape != true_output.shape:
42
+ raise ValueError("prediction and true_output must have the same shape.")
43
+
44
+ if self.reduction == "mean":
45
+ return -torch.mean(torch.sum(true_output * torch.log(prediction + 1e-5), dim=1))
46
+ return -torch.sum(true_output * torch.log(prediction + 1e-5))
47
+
48
+ def gradient(self, prediction, true_output):
49
+ """
50
+ Calculates the gradient of the categorical categorical cross entropy.
51
+
52
+ Args:
53
+ prediction (torch.Tensor): A tensor of predicted values as a probability distribution. Must be the same shape as the true_output.
54
+ true_output (torch.Tensor): A one-hot encoded tensor of true values. Must be the same shape as the prediction.
55
+
56
+ Returns:
57
+ torch.Tensor: A tensor of the same shape as the inputs containing the gradients.
58
+ """
59
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
60
+ raise TypeError("prediction and true_output must be torch tensors.")
61
+ if prediction.shape != true_output.shape:
62
+ raise ValueError("prediction and true_output must have the same shape.")
63
+
64
+ if self.reduction == "mean":
65
+ return -true_output / ((prediction + 1e-5) * prediction.shape[0])
66
+ return -true_output / (prediction + 1e-5)
67
+
68
+ def hessian(self, prediction, true_output):
69
+ """
70
+ Calculates the diagonal of the hessian matrix of the categorical cross entropy loss.
71
+
72
+ Args:
73
+ prediction (torch.Tensor): A tensor of predicted values in range [0, 1]. Must be the same shape as the true_output.
74
+ true_output (torch.Tensor): A tensor of true values labeled with 0 or 1. Must be the same shape as the prediction.
75
+
76
+ Returns:
77
+ torch.Tensor: A tensor of the same shape as the inputs containing the diagonal of the hessian matrix.
78
+ """
79
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
80
+ raise TypeError("prediction and true_output must be torch tensors.")
81
+ if prediction.shape != true_output.shape:
82
+ raise ValueError("prediction and true_output must have the same shape.")
83
+
84
+ grad = true_output / (prediction ** 2 + 1e-5)
85
+ if self.reduction == "mean":
86
+ return grad / prediction.shape[0]
87
+ return grad
@@ -0,0 +1,101 @@
1
+ import torch
2
+
3
+ from ._BaseLoss import BaseLoss
4
+
5
+
6
+ class Exponential(BaseLoss):
7
+ """
8
+ The exponential loss. Used for binary classification.
9
+
10
+ Args:
11
+ reduction (str, optional): The reduction method. Must be one of "mean" or "sum". Defaults to "mean".
12
+ """
13
+ def __init__(self, reduction="mean"):
14
+ if reduction not in ["mean", "sum"]:
15
+ raise ValueError('reduction must be in ["mean", "sum"].')
16
+
17
+ self.reduction = reduction
18
+
19
+ def loss(self, prediction, true_output):
20
+ """
21
+ Calculates the exponential loss with the equations:
22
+
23
+ .. math::
24
+
25
+ \\begin{align*}
26
+ l_i &= y_i\\cdot e^{-f(x_i)} + (1 - y_i)\\cdot e^{f(x_i)},\\\\
27
+ L_{sum} &= \\sum_{i=1}^n l_i \\text{ or } L_{mean} = \\frac{1}{n}\\sum_{i=1}^n l_i,
28
+ \\end{align*}
29
+
30
+ where :math:`f(x_i)` is the predicted value and :math:`y_i` is the true value.
31
+
32
+ Args:
33
+ prediction (torch.Tensor): A tensor of predicted values as a probability distribution. Must be the same shape as the true_output.
34
+ true_output (torch.Tensor): A one-hot encoded tensor of true values. Must be the same shape as the prediction.
35
+
36
+ Returns:
37
+ torch.Tensor: A tensor containing a single value with the loss.
38
+ """
39
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
40
+ raise TypeError("prediction and true_output must be torch tensors.")
41
+ if prediction.shape != true_output.shape:
42
+ raise ValueError("prediction and true_output must have the same shape.")
43
+ if set(torch.unique(true_output).numpy()) != {0, 1}:
44
+ raise ValueError("The classes must be labelled 0 and 1.")
45
+
46
+ prediction = 2 * prediction - 1
47
+ true_output = 2 * true_output - 1
48
+ loss = torch.exp(-prediction * true_output)
49
+ if self.reduction == "mean":
50
+ return loss.mean()
51
+ return loss.sum()
52
+
53
+ def gradient(self, prediction, true_output):
54
+ """
55
+ Calculates the gradient of the exponential loss.
56
+
57
+ Args:
58
+ prediction (torch.Tensor): A tensor of predicted values in range [0, 1]. Must be the same shape as the true_output.
59
+ true_output (torch.Tensor): A tensor of true values labeled with 0 or 1. Must be the same shape as the prediction.
60
+
61
+ Returns:
62
+ torch.Tensor: A tensor of the same shape as the inputs containing the gradients.
63
+ """
64
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
65
+ raise TypeError("prediction and true_output must be torch tensors.")
66
+ if prediction.shape != true_output.shape:
67
+ raise ValueError("prediction and true_output must have the same shape.")
68
+ if set(torch.unique(true_output).numpy()) != {0, 1}:
69
+ raise ValueError("The classes must be labelled 0 and 1.")
70
+
71
+ prediction = 2 * prediction - 1
72
+ true_output = 2 * true_output - 1
73
+ grad = -2 * true_output * torch.exp(-prediction * true_output)
74
+ if self.reduction == "mean":
75
+ return grad / prediction.shape[0]
76
+ return grad
77
+
78
+ def hessian(self, prediction, true_output):
79
+ """
80
+ Calculates the diagonal of the hessian matrix of the exponential loss.
81
+
82
+ Args:
83
+ prediction (torch.Tensor): A tensor of predicted values in range [0, 1]. Must be the same shape as the true_output.
84
+ true_output (torch.Tensor): A tensor of true values labeled with 0 or 1. Must be the same shape as the prediction.
85
+
86
+ Returns:
87
+ torch.Tensor: A tensor of the same shape as the inputs containing the diagonal of the hessian matrix.
88
+ """
89
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
90
+ raise TypeError("prediction and true_output must be torch tensors.")
91
+ if prediction.shape != true_output.shape:
92
+ raise ValueError("prediction and true_output must have the same shape.")
93
+ if set(torch.unique(true_output).numpy()) != {0, 1}:
94
+ raise ValueError("The classes must be labelled 0 and 1.")
95
+
96
+ prediction = 2 * prediction - 1
97
+ true_output = 2 * true_output - 1
98
+ grad = 4 * true_output ** 2 * torch.exp(-prediction * true_output)
99
+ if self.reduction == "mean":
100
+ return grad / prediction.shape[0]
101
+ return grad
@@ -0,0 +1,104 @@
1
+ import torch
2
+
3
+ from ._BaseLoss import BaseLoss
4
+
5
+
6
+ class Huber(BaseLoss):
7
+ """
8
+ The huber loss. Used for regression. Is a combination of squared error and absolute error.
9
+
10
+ Args:
11
+ delta (int | float, optional): The radius around the true value that uses the squared error. If the difference is larger than delta, the absolute error is used. Must be a positive real number. Defaults to 1.
12
+ reduction (str, optional): The reduction method. Must be one of "mean" or "sum".
13
+ """
14
+ def __init__(self, delta=1.0, reduction="mean"):
15
+ if not isinstance(delta, int | float) or delta <= 0:
16
+ raise ValueError("delta must be a positive real number.")
17
+ if reduction not in ["mean", "sum"]:
18
+ raise ValueError('reduction must be in ["mean", "sum"].')
19
+
20
+ self.delta = delta
21
+ self.reduction = reduction
22
+
23
+ def loss(self, prediction, true_output):
24
+ """
25
+ Calculates the huber loss with the equations:
26
+
27
+ .. math::
28
+
29
+ \\begin{align*}
30
+ l_i &= \\begin{cases}
31
+ \\frac{1}{2}(y_i - f(x_i))^2 & \\text{if } |y_i - f(x_i)| \\leq \\delta,\\\\
32
+ \\delta|y_i - f(x_i)| - \\frac{1}{2}\\delta^2 & \\text{otherwise},
33
+ \end{cases}\\\\
34
+ L_{sum} &= \\sum_{i=1}^n l_i \\text{ or } L_{mean} = \\frac{1}{n}\\sum_{i=1}^n l_i,
35
+ \\end{align*}
36
+
37
+ where :math:`f(x_i)` is the predicted value and :math:`y_i` is the true value.
38
+
39
+ Args:
40
+ prediction (torch.Tensor): A tensor of predicted values. Must be the same shape as the true_output.
41
+ true_output (torch.Tensor): A tensor of true values. Must be the same shape as the prediction.
42
+
43
+ Returns:
44
+ torch.Tensor: A tensor containing a single value with the loss.
45
+ """
46
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
47
+ raise TypeError("prediction and true_output must be torch tensors.")
48
+ if prediction.shape != true_output.shape:
49
+ raise ValueError("prediction and true_output must have the same shape.")
50
+
51
+ error = prediction - true_output
52
+ abs_error = torch.abs(error)
53
+ quadratic = 0.5 * error ** 2
54
+ linear = self.delta * (abs_error - 0.5 * self.delta)
55
+ if self.reduction == "mean":
56
+ return torch.where(abs_error <= self.delta, quadratic, linear).mean()
57
+ return torch.where(abs_error <= self.delta, quadratic, linear).sum()
58
+
59
+ def gradient(self, prediction, true_output):
60
+ """
61
+ Calculates the gradient of the huber loss.
62
+
63
+ Args:
64
+ prediction (torch.Tensor): A tensor of predicted values. Must be the same shape as the true_output.
65
+ true_output (torch.Tensor): A tensor of true values. Must be the same shape as the prediction.
66
+
67
+ Returns:
68
+ torch.Tensor: A tensor of the same shape as the inputs containing the gradients.
69
+ """
70
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
71
+ raise TypeError("prediction and true_output must be torch tensors.")
72
+ if prediction.shape != true_output.shape:
73
+ raise ValueError("prediction and true_output must have the same shape.")
74
+
75
+ error = prediction - true_output
76
+ abs_error = torch.abs(error)
77
+ quadratic_grad = error
78
+ linear_grad = self.delta * torch.sign(error)
79
+ if self.reduction == "mean":
80
+ return torch.where(abs_error <= self.delta, quadratic_grad, linear_grad) / prediction.shape[0]
81
+ return torch.where(abs_error <= self.delta, quadratic_grad, linear_grad)
82
+
83
+ def hessian(self, prediction, true_output):
84
+ """
85
+ Calculates the diagonal of the hessian matrix of the huber loss.
86
+
87
+ Args:
88
+ prediction (torch.Tensor): A tensor of predicted values. Must be the same shape as the true_output.
89
+ true_output (torch.Tensor): A tensor of true values. Must be the same shape as the prediction.
90
+
91
+ Returns:
92
+ torch.Tensor: A tensor of the same shape as the inputs containing the diagonal of the hessian matrix.
93
+ """
94
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
95
+ raise TypeError("prediction and true_output must be torch tensors.")
96
+ if prediction.shape != true_output.shape:
97
+ raise ValueError("prediction and true_output must have the same shape.")
98
+
99
+ abs_error = torch.abs(prediction - true_output)
100
+ quadratic_grad = torch.full((len(true_output),), 1)
101
+ linear_grad = torch.full((len(true_output),), 0)
102
+ if self.reduction == "mean":
103
+ return torch.where(abs_error <= self.delta, quadratic_grad, linear_grad) / prediction.shape[0]
104
+ return torch.where(abs_error <= self.delta, quadratic_grad, linear_grad)
@@ -0,0 +1,85 @@
1
+ import torch
2
+
3
+ from ._BaseLoss import BaseLoss
4
+
5
+
6
+ class MAE(BaseLoss):
7
+ """
8
+ The absolute error loss. Used for regression.
9
+
10
+ Args:
11
+ reduction (str, optional): The reduction method. Must be one of "mean" or "sum".
12
+ """
13
+ def __init__(self, reduction="mean"):
14
+ if reduction not in ["mean", "sum"]:
15
+ raise ValueError('reduction must be in ["mean", "sum"].')
16
+
17
+ self.reduction = reduction
18
+
19
+ def loss(self, prediction, true_output):
20
+ """
21
+ Calculates the absolute error loss with the equations:
22
+
23
+ .. math::
24
+
25
+ \\begin{align*}
26
+ l_i &= |y_i - f(x_i)|,\\\\
27
+ L_{sum} &= \\sum_{i=1}^n l_i \\text{ or } L_{mean} = \\frac{1}{n}\\sum_{i=1}^n l_i,
28
+ \\end{align*}
29
+
30
+ where :math:`f(x_i)` is the predicted value and :math:`y_i` is the true value.
31
+
32
+ Args:
33
+ prediction (torch.Tensor): A tensor of predicted values. Must be the same shape as the true_output.
34
+ true_output (torch.Tensor): A tensor of true values. Must be the same shape as the prediction.
35
+
36
+ Returns:
37
+ torch.Tensor: A tensor containing a single value with the loss.
38
+ """
39
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
40
+ raise TypeError("prediction and true_output must be torch tensors.")
41
+ if prediction.shape != true_output.shape:
42
+ raise ValueError("prediction and true_output must have the same shape.")
43
+
44
+ if self.reduction == "mean":
45
+ return torch.abs(prediction - true_output).mean()
46
+ return torch.abs(prediction - true_output).sum()
47
+
48
+
49
+ def gradient(self, prediction, true_output):
50
+ """
51
+ Calculates the gradient of the absolute error loss.
52
+
53
+ Args:
54
+ prediction (torch.Tensor): A tensor of predicted values. Must be the same shape as the true_output.
55
+ true_output (torch.Tensor): A tensor of true values. Must be the same shape as the prediction.
56
+
57
+ Returns:
58
+ torch.Tensor: A tensor of the same shape as the inputs containing the gradients.
59
+ """
60
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
61
+ raise TypeError("prediction and true_output must be torch tensors.")
62
+ if prediction.shape != true_output.shape:
63
+ raise ValueError("prediction and true_output must have the same shape.")
64
+
65
+ if self.reduction == "mean":
66
+ return torch.sign(prediction - true_output) / prediction.shape[0]
67
+ return torch.sign(prediction - true_output)
68
+
69
+ def hessian(self, prediction, true_output):
70
+ """
71
+ Calculates the diagonal of the hessian matrix of the absolute error loss.
72
+
73
+ Args:
74
+ prediction (torch.Tensor): A tensor of predicted values. Must be the same shape as the true_output.
75
+ true_output (torch.Tensor): A tensor of true values. Must be the same shape as the prediction.
76
+
77
+ Returns:
78
+ torch.Tensor: A tensor of the same shape as the inputs containing the diagonal of the hessian matrix.
79
+ """
80
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
81
+ raise TypeError("prediction and true_output must be torch tensors.")
82
+ if prediction.shape != true_output.shape:
83
+ raise ValueError("prediction and true_output must have the same shape.")
84
+
85
+ return torch.full((len(true_output),), 0)
@@ -0,0 +1,86 @@
1
+ import torch
2
+
3
+ from ._BaseLoss import BaseLoss
4
+
5
+
6
+ class MSE(BaseLoss):
7
+ """
8
+ The squared error loss. Used for regression.
9
+
10
+ Args:
11
+ reduction (str, optional): The reduction method. Must be one of "mean" or "sum".
12
+ """
13
+ def __init__(self, reduction="mean"):
14
+ if reduction not in ["mean", "sum"]:
15
+ raise ValueError('reduction must be in ["mean", "sum"].')
16
+
17
+ self.reduction = reduction
18
+
19
+ def loss(self, prediction, true_output):
20
+ """
21
+ Calculates the squared error loss with the equations:
22
+
23
+ .. math::
24
+
25
+ \\begin{align*}
26
+ l_i &= (y_i - f(x_i))^2,\\\\
27
+ L_{sum} &= \\sum_{i=1}^n l_i \\text{ or } L_{mean} = \\frac{1}{n}\\sum_{i=1}^n l_i,
28
+ \\end{align*}
29
+
30
+ where :math:`f(x_i)` is the predicted value and :math:`y_i` is the true value.
31
+
32
+ Args:
33
+ prediction (torch.Tensor): A tensor of predicted values. Must be the same shape as the true_output.
34
+ true_output (torch.Tensor): A tensor of true values. Must be the same shape as the prediction.
35
+
36
+ Returns:
37
+ torch.Tensor: A tensor containing a single value with the loss.
38
+ """
39
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
40
+ raise TypeError("prediction and true_output must be torch tensors.")
41
+ if prediction.shape != true_output.shape:
42
+ raise ValueError("prediction and true_output must have the same shape.")
43
+
44
+ if self.reduction == "mean":
45
+ return torch.mean((prediction - true_output) ** 2)
46
+ return torch.sum((prediction - true_output) ** 2)
47
+
48
+ def gradient(self, prediction, true_output):
49
+ """
50
+ Calculates the gradient of the squared error loss.
51
+
52
+ Args:
53
+ prediction (torch.Tensor): A tensor of predicted values. Must be the same shape as the true_output.
54
+ true_output (torch.Tensor): A tensor of true values. Must be the same shape as the prediction.
55
+
56
+ Returns:
57
+ torch.Tensor: A tensor of the same shape as the inputs containing the gradients.
58
+ """
59
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
60
+ raise TypeError("prediction and true_output must be torch tensors.")
61
+ if prediction.shape != true_output.shape:
62
+ raise ValueError("prediction and true_output must have the same shape.")
63
+
64
+ if self.reduction == "mean":
65
+ return 2 * (prediction - true_output) / prediction.shape[0]
66
+ return 2 * (prediction - true_output)
67
+
68
+ def hessian(self, prediction, true_output):
69
+ """
70
+ Calculates the diagonal of the hessian matrix of the squared error loss.
71
+
72
+ Args:
73
+ prediction (torch.Tensor): A tensor of predicted values. Must be the same shape as the true_output.
74
+ true_output (torch.Tensor): A tensor of true values. Must be the same shape as the prediction.
75
+
76
+ Returns:
77
+ torch.Tensor: A tensor of the same shape as the inputs containing the diagonal of the hessian matrix.
78
+ """
79
+ if not isinstance(prediction, torch.Tensor) or not isinstance(true_output, torch.Tensor):
80
+ raise TypeError("prediction and true_output must be torch tensors.")
81
+ if prediction.shape != true_output.shape:
82
+ raise ValueError("prediction and true_output must have the same shape.")
83
+
84
+ if self.reduction == "mean":
85
+ return torch.full((len(true_output),), 2 / prediction.shape[0])
86
+ return torch.full((len(true_output),), 2)
@@ -0,0 +1,6 @@
1
+ from ._MSE import MSE
2
+ from ._MAE import MAE
3
+ from ._BCE import BCE
4
+ from ._CCE import CCE
5
+ from ._Huber import Huber
6
+ from ._Exponential import Exponential