This commit is contained in:
2024-06-07 10:29:56 +02:00
parent 3e9bcb87e9
commit 17a7ea9435
3 changed files with 56 additions and 14 deletions

4
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"python.analysis.typeCheckingMode": "off",
"python.analysis.autoImportCompletions": true
}

View File

@@ -41,7 +41,7 @@ def frogs() -> tuple[int, MLAlgorithm]:
ds = Dataset(CLASSIFICATION + "frogs.csv", "Species", TargetType.MultiClassification) ds = Dataset(CLASSIFICATION + "frogs.csv", "Species", TargetType.MultiClassification)
ds.remove(["Family", "Genus", "RecordID"]) ds.remove(["Family", "Genus", "RecordID"])
ds.factorize(["Species"]) ds.factorize(["Species"])
return (1000, MultiLayerPerceptron(ds, learning_rate=0.08)) return (1000, MultiLayerPerceptron(ds, [4, 3]))
@@ -59,5 +59,5 @@ def learn_dataset(function:Callable[..., tuple[int, MLAlgorithm]], epochs:int=10
return ml return ml
if __name__ == "__main__": if __name__ == "__main__":
ml = learn_dataset(electrical_grid) ml = learn_dataset(frogs)
print(ml.accuracy(ml.testset)) print(ml.accuracy(ml.testset))

View File

@@ -43,7 +43,7 @@ class LinearRegression(GradientDescent):
return self.theta.dot(x.T) return self.theta.dot(x.T)
def _loss(self, x:np.ndarray, y:np.ndarray, m:int) -> float: def _loss(self, x:np.ndarray, y:np.ndarray, m:int) -> float:
diff = (x.dot(self.theta) - y) diff = (self._h0(x) - y)
return 1/(2*m) * np.sum(diff ** 2) return 1/(2*m) * np.sum(diff ** 2)
class LogisticRegression(GradientDescent): class LogisticRegression(GradientDescent):
@@ -56,19 +56,57 @@ class LogisticRegression(GradientDescent):
return 1/m * np.sum(diff) return 1/m * np.sum(diff)
class MultiLayerPerceptron(MLAlgorithm): class MultiLayerPerceptron(MLAlgorithm):
neurons: list[np.ndarray] layers: list[np.ndarray]
calculated: list[np.ndarray]
def __init__(self, dataset:Dataset, layers:list[int]=[4,3]) -> None: def __init__(self, dataset:Dataset, layers:list[int]) -> None:
super().__init__(dataset) super().__init__(dataset)
input = self.learnset.x.shape[1]
output = self.learnset.y.shape[1]
if type(layers) is not list[int]:
layers = [4, 3, output]
else: layers.append(output)
self.layers = []
self.calculated = []
for next in layers:
current = np.random.rand(input, next)
self.layers.append(current)
input = next + 1 # bias
def _h0(self, x:np.ndarray) -> np.ndarray: def _h0(self, x:np.ndarray) -> np.ndarray:
pass input = x
def learning_step(self) -> float: for i, layer in enumerate(self.layers):
pass if i != 0:
def predict_loss(self, dataset:np.ndarray) -> float: ones = np.ones(shape=(input.shape[0], 1))
pass input = np.hstack([input, ones])
def get_parameters(self): input = input.dot(layer)
pass input = input * (input > 0) # activation function ReLU
def set_parameters(self, parameters): self.calculated[i] = input # saving previous result
pass return self.soft_max(input)
def soft_max(self, input:np.ndarray) -> np.ndarray:
input = np.exp(input)
total_sum = np.sum(input, axis=1)
input = input.T / total_sum
return input.T
def learning_step(self) -> float:
raise NotImplemented
def predict_loss(self, dataset:Data) -> float:
diff = self._h0(dataset.x) - dataset.y
return 1/(2*dataset.size) * np.sum(diff ** 2)
def get_parameters(self):
parameters = []
for x in self.layers:
parameters.append(x.copy())
return parameters
def set_parameters(self, parameters):
self.layers = parameters