From a434a1a64754f33ad1711c21b8a0eef1b62cf1d1 Mon Sep 17 00:00:00 2001 From: Gerhardsa0 Date: Tue, 7 Nov 2023 21:22:27 +0100 Subject: [PATCH] added a structre and a first test run for my example for rnn, so I add RNN Layer and a Model class, which holds a List of layers. There are things for an Layer Interface. will structure and check it more tomorrow --- src/safeds/ml/nn/__init__.py | 4 ++ src/safeds/ml/nn/_model.py | 40 +++++++++++++++++++ src/safeds/ml/nn/_rnn_layer.py | 29 ++++++++++++++ .../test_timeseries_creation.py | 27 ++++--------- 4 files changed, 81 insertions(+), 19 deletions(-) create mode 100644 src/safeds/ml/nn/__init__.py create mode 100644 src/safeds/ml/nn/_model.py create mode 100644 src/safeds/ml/nn/_rnn_layer.py diff --git a/src/safeds/ml/nn/__init__.py b/src/safeds/ml/nn/__init__.py new file mode 100644 index 000000000..ef2001628 --- /dev/null +++ b/src/safeds/ml/nn/__init__.py @@ -0,0 +1,4 @@ +"""Layers for neural networks tasks.""" + +from ._rnn_layer import RNN_Layer +from ._model import Model \ No newline at end of file diff --git a/src/safeds/ml/nn/_model.py b/src/safeds/ml/nn/_model.py new file mode 100644 index 000000000..15a9cd1e5 --- /dev/null +++ b/src/safeds/ml/nn/_model.py @@ -0,0 +1,40 @@ +import pandas as pd +import numpy as np +import torch +import torch.nn as nn +from torch.utils.data import DataLoader +from safeds.ml.nn import RNN_Layer +from safeds.data.tabular.containers import Column, Table, TaggedTable, TimeSeries +from safeds.exceptions import ColumnSizeError, DuplicateColumnNameError + +class Model(): + def __init__(self, layers : list): + self._model = PyTorchModel(layers) + + + def from_layers(self, layers: list): + pass + + #this is just a demo function + def model_forward(self, data : DataLoader): + for batch in iter(data): + inputs, labels = batch + inputs = inputs.to(torch.float32) + self._model(inputs) + + + def train(self,x): + pass + +class PyTorchModel(nn.Module): + def __init__(self, LayerListe :list[RNN_Layer]): + super(PyTorchModel, self).__init__() + self.layerliste = [] + for layer in LayerListe: + self.layerliste.append(layer._create_pytorch_layer()) + + def forward(self, x): + out = x + for layer in self.layerliste: + out = layer(out) + return out diff --git a/src/safeds/ml/nn/_rnn_layer.py b/src/safeds/ml/nn/_rnn_layer.py new file mode 100644 index 000000000..5b0cabeef --- /dev/null +++ b/src/safeds/ml/nn/_rnn_layer.py @@ -0,0 +1,29 @@ +import pandas as pd +import numpy as np +import torch +import torch.nn as nn +from torch.utils.data import DataLoader +from safeds.data.tabular.containers import Column, Table, TaggedTable, TimeSeries +from safeds.exceptions import ColumnSizeError, DuplicateColumnNameError + + +class RNN_Layer(): + def __init__(self, input_dim, output_dim)-> None: + self._input_dim = input_dim + self._output_dim = output_dim + + + def _create_pytorch_layer(self): + return LSTMLayer(self._input_dim, self._output_dim) + + + +#definiere LSTM Layer in PyTorch +class LSTMLayer(nn.Module): + def __init__(self, input_dim, output_dim): + super(LSTMLayer, self).__init__() + self.lstm = nn.LSTM(input_dim, output_dim, batch_first = True) + + def forward(self, x): + lstm_out, _ = self.lstm(x) + return lstm_out \ No newline at end of file diff --git a/tests/safeds/data/tabular/containers/_table/_timeseries_table/test_timeseries_creation.py b/tests/safeds/data/tabular/containers/_table/_timeseries_table/test_timeseries_creation.py index 067708650..04b929af5 100644 --- a/tests/safeds/data/tabular/containers/_table/_timeseries_table/test_timeseries_creation.py +++ b/tests/safeds/data/tabular/containers/_table/_timeseries_table/test_timeseries_creation.py @@ -6,24 +6,13 @@ from torch.utils.data import DataLoader from safeds.data.tabular.containers import Column, Table, TaggedTable, TimeSeries from safeds.exceptions import ColumnSizeError, DuplicateColumnNameError +from safeds.ml.nn import RNN_Layer, Model -#definiere LSTM Model in PyTorch -class LSTMModel(nn.Module): - def __init__(self, input_dim, hidden_dim, output_dim): - super(LSTMModel, self).__init__() - self.hidden_dim = hidden_dim - self.lstm = nn.LSTM(input_dim, hidden_dim, batch_first = True) - self.fc = nn.Linear(hidden_dim, output_dim) - - def forward(self, x): - lstm_out, _ = self.lstm(x) - out = self.fc(lstm_out) - return out - def test_create_timeseries() -> None: + table = Table(data={"f1": [1, 2, 3, 4, 6, 7], "target": [7,2, 3, 1, 3, 7], "f2": [4,7, 5, 5, 5, 7]}) ts = TimeSeries(data={"f1": [1, 2, 3, 4, 6, 7], "target": [7,2, 3, 1, 3, 7], "f2": [4,7, 5, 5, 5, 7]}, target_name="target", @@ -33,20 +22,20 @@ def test_create_timeseries() -> None: feature_names=["f1", "f2", "target"]) + # ein Modell erstellen ist in safeDS noch nicht definiert darum low level in PyTorch # 2 ist hier die number der feature Columns input_dim = ts._window_size * len(ts._feature_names) hidden_dim = 1 output_dim = ts._forecast_horizon - model = LSTMModel(input_dim, hidden_dim, output_dim) + layer1 = RNN_Layer(input_dim, hidden_dim) + layer2 = RNN_Layer(hidden_dim, output_dim) + model = Model([layer1, layer2]) #damit der Datensatz low level laden kann hier into_Dataloader - loader = ts.into_DataLoader() + model.model_forward(ts.into_DataLoader()) + - for batch in iter(loader): - inputs, labels = batch - inputs = inputs.to(torch.float32) - model(inputs) #wenn durchläuft wurde korrekt Table in Dataloader geladen