myfirstnn 0.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.
myfirstnn/__init__.py ADDED
File without changes
myfirstnn/__main__.py ADDED
@@ -0,0 +1,10 @@
1
+ """
2
+ This file is called at the start of the package myfirstNN
3
+ Authors: Alessio Parolini
4
+ """
5
+
6
+ from myfirstnn.core import main
7
+
8
+ if __name__ == "__main__":
9
+
10
+ main()
@@ -0,0 +1,3 @@
1
+ from myfirstnn.core.start import *
2
+
3
+ __all__ = ["main"]
@@ -0,0 +1,21 @@
1
+ """
2
+ main.py
3
+ Authors: Alessio Parolini
4
+ Manage and starts all the functions from other sub-packages. Imported in __main__.py for starts the package.
5
+ """
6
+
7
+ __all__ = ["main"]
8
+
9
+ from myfirstnn.display import AutoNNApp
10
+
11
+
12
+ def main() -> None:
13
+
14
+ app = AutoNNApp()
15
+
16
+ app.run()
17
+
18
+
19
+ if __name__ == "__main__":
20
+
21
+ main()
@@ -0,0 +1,3 @@
1
+ from myfirstnn.display.app import *
2
+
3
+ __all__ = ["AutoNNApp"]
@@ -0,0 +1,21 @@
1
+ """
2
+ This file manage the user interaction with the software via CLI
3
+ Authors: Alessio Parolini
4
+ """
5
+
6
+ __all__ = ["AutoNNApp"]
7
+
8
+ from textual.app import App, ComposeResult
9
+
10
+ from .components import Titles, ModelConfig
11
+
12
+
13
+ class AutoNNApp(App):
14
+
15
+ CSS_PATH = "styles/app.tcss"
16
+
17
+ def compose(self) -> ComposeResult:
18
+
19
+ yield Titles()
20
+
21
+ yield ModelConfig()
@@ -0,0 +1,5 @@
1
+ from myfirstnn.display.components.headers import *
2
+
3
+ from myfirstnn.display.components.form import *
4
+
5
+ __all__ = ["Titles", "ModelConfig"]
@@ -0,0 +1,107 @@
1
+ """
2
+ form.py
3
+ Authors: Alessio Parolini
4
+ This file contains the class to make the user config his model
5
+ """
6
+
7
+ __all__ = ["ModelConfig"]
8
+
9
+ from textual.widgets import Label, Input, Button, RichLog
10
+
11
+ from textual.app import ComposeResult
12
+
13
+ from textual.containers import Container, Center
14
+
15
+ from textual import work
16
+
17
+ from myfirstnn.learning import model_learning as model_l
18
+
19
+ from myfirstnn.learning import random_io_tensors as rand_tens
20
+
21
+ from myfirstnn.neuraln import SimpleNN
22
+
23
+
24
+ class ModelConfig(Container):
25
+ """
26
+ This class manage the user inputs to start the training
27
+ """
28
+
29
+ def __init__(self, *children, **kwargs):
30
+
31
+ super().__init__(*children, **kwargs)
32
+
33
+ def compose(self) -> ComposeResult:
34
+
35
+ yield Label(
36
+ content="[bold]Write here your model name:[/]",
37
+ id="model-label",
38
+ classes="form-label",
39
+ )
40
+
41
+ yield Input(
42
+ placeholder="Your model name here...",
43
+ id="model-name",
44
+ type="text",
45
+ )
46
+
47
+ yield Label(
48
+ content="[bold]How much data you wanna use (type an integer)?[/] Remind: more data means more work for your CPU/GPU",
49
+ id="inputs-label",
50
+ classes="form-label",
51
+ )
52
+
53
+ yield Input(
54
+ placeholder="Enter the number of input do you wanna use...",
55
+ id="model-inputs",
56
+ type="integer",
57
+ restrict="^[0-9]+$",
58
+ )
59
+
60
+ with Center():
61
+
62
+ yield Button(
63
+ label="Start training!",
64
+ id="start-button",
65
+ variant="warning",
66
+ )
67
+
68
+ yield RichLog(markup=True, id="training-log")
69
+
70
+ # functions
71
+
72
+ def on_button_pressed(self, event: Button.Pressed) -> None:
73
+
74
+ if event.button.id == "start-button":
75
+
76
+ model_name = self.query_one("#model-name", Input).value or "UserModel"
77
+
78
+ model_inputs = self.query_one("#model-inputs", Input).value or 200
79
+
80
+ self.query_one("#start-button", Button).disabled = True
81
+
82
+ self.app.set_focus(self.query_one("#training-log"))
83
+
84
+ self.training_setup(model_name=model_name, model_inputs=int(model_inputs))
85
+
86
+ @work(thread=True, exclusive=True)
87
+ def training_setup(self, model_name: str, model_inputs: int):
88
+ """
89
+ Uses the resources form other sub-packages (learning and neuraln) to create a model and train it.
90
+ Everything runs on a separate thread
91
+ """
92
+
93
+ model = SimpleNN(name=model_name)
94
+
95
+ test_data = rand_tens(
96
+ n_input=model_inputs, n_range=2, y_function=lambda x: x**2
97
+ )
98
+
99
+ text_log = self.query_one(RichLog)
100
+
101
+ text_log.write("Starting the model log...")
102
+
103
+ model_l(model=model, data=test_data, epochs=10000, log_func=text_log.write)
104
+
105
+ self.app.call_from_thread(
106
+ lambda: setattr(self.query_one("#start-button", Button), "disabled", False)
107
+ )
@@ -0,0 +1,39 @@
1
+ """
2
+ tui.py
3
+ Authors: Alessio Parolini
4
+ This file contains the class for the app headers
5
+ """
6
+
7
+ __all__ = ["Titles"]
8
+
9
+ from textual.app import ComposeResult
10
+
11
+ from textual.widgets import Label
12
+
13
+ from textual.containers import Container, Center
14
+
15
+
16
+ class Titles(Container):
17
+
18
+ def compose(self) -> ComposeResult:
19
+
20
+ with Center():
21
+
22
+ yield Label(
23
+ content=r"""
24
+ ░██ ░███ ░██ ░███ ░██
25
+ ░██ ░████ ░██ ░████ ░██
26
+ ░██████ ░██ ░██ ░████████ ░███████ ░██░██ ░██ ░██░██ ░██
27
+ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██
28
+ ░███████ ░██ ░██ ░██ ░██ ░██ ░██ ░██░██ ░██ ░██░██
29
+ ░██ ░██ ░██ ░███ ░██ ░██ ░██ ░██ ░████ ░██ ░████
30
+ ░█████░██ ░█████░██ ░████ ░███████ ░██ ░███ ░██ ░███ """,
31
+ id="tui-title",
32
+ )
33
+
34
+ yield Label(
35
+ content="""An incredible tool to create [bold #ffffff]your own AI model[/] from [bold #ffffff]random datas[/]!.\n
36
+ For now, it can learn only how to calculate squares (x^2) of numbers.\n
37
+ [bold]Try to edit number of inputs[/] to see how the precision changes!""",
38
+ id="description",
39
+ )
@@ -0,0 +1,93 @@
1
+ /* Styles for the main TUI */
2
+
3
+ Screen {
4
+
5
+ /* for the main app*/
6
+
7
+ overflow-y: scroll;
8
+
9
+ }
10
+
11
+ #tui-title {
12
+
13
+ /* the title */
14
+
15
+ color: #ffcc00;
16
+
17
+ text-align: center;
18
+
19
+ }
20
+
21
+ #description {
22
+
23
+ /* the description */
24
+
25
+ color: #fffae6;
26
+
27
+ text-align: center;
28
+
29
+ margin-top: 2;
30
+
31
+ border: solid #fffae6;
32
+
33
+ padding: 1 2 1 2
34
+
35
+ }
36
+
37
+ #start-button {
38
+
39
+ /* the button to start the training*/
40
+
41
+ margin: 1 2 1 2;
42
+
43
+ align: center middle;
44
+
45
+ }
46
+
47
+ #training-log {
48
+
49
+ height: 10;
50
+
51
+ margin: 1 2 1 2;
52
+
53
+ border: solid #ffcc00;
54
+
55
+ }
56
+
57
+ .form-label {
58
+
59
+ /* for the labels in form.py */
60
+
61
+ padding: 1 2 1 2
62
+
63
+ }
64
+
65
+ Button {
66
+
67
+ /* for all the buttons generally */
68
+
69
+ margin: 0 5 0 5;
70
+
71
+ background: #ffcc00;
72
+
73
+ }
74
+
75
+ Titles {
76
+
77
+ /* for the TUI titles */
78
+
79
+ height: auto;
80
+
81
+ align: center middle;
82
+ }
83
+
84
+ ModelConfig {
85
+
86
+ /* for the form.py component */
87
+
88
+ margin: 2 2 2 2;
89
+
90
+ height: auto;
91
+
92
+ }
93
+
@@ -0,0 +1,3 @@
1
+ from myfirstnn.learning.training import *
2
+
3
+ __all__ = ["random_io_tensors", "model_learning"]
@@ -0,0 +1,98 @@
1
+ """
2
+ training.py
3
+ Authors: Alessio Parolini
4
+ Manage the training of the model
5
+ """
6
+
7
+ __all__ = ["random_io_tensors", "model_learning"]
8
+
9
+ import torch
10
+
11
+ from torch import nn
12
+
13
+ from torch import optim
14
+
15
+ from myfirstnn.neuraln import SimpleNN
16
+
17
+ from typing import Callable, Any
18
+
19
+
20
+ def random_io_tensors(
21
+ n_input: int,
22
+ n_range: int,
23
+ y_function: Callable[[torch.Tensor], torch.Tensor],
24
+ seed: int = 28,
25
+ ) -> tuple[torch.Tensor, torch.Tensor]:
26
+ """
27
+ Generates random numbers for the tests. They will be always the sames, but's better for training.
28
+ :param n_input: the number of the random generated numbers
29
+ :param n_range: the range (before and after zero) where the number are created in
30
+ :param y_function: the function (even a lambda) to calculate the expected output
31
+ :param seed: the manual seed, to generate every time the same numbers.
32
+ :return: 2 torch.Tensors with X and Y
33
+ """
34
+
35
+ torch.manual_seed(seed) # setting the manual seed
36
+
37
+ x = (
38
+ 2 * n_range * torch.rand(n_input, 1) - n_range
39
+ ) # creating the results and putting in a range from -2 to 2
40
+
41
+ y = (
42
+ y_function(x) + torch.randn(n_input, 1) * 0.001
43
+ ) # calculating the Y starting from X, using the given function and add a Gaussian noise
44
+
45
+ return x, y
46
+
47
+
48
+ def model_learning(
49
+ model: SimpleNN,
50
+ data: tuple[torch.Tensor, torch.Tensor],
51
+ epochs: int = 300,
52
+ log_func: Callable[..., Any] = print,
53
+ ):
54
+ """
55
+
56
+ :param model: the model to train
57
+ :param data: the tuple of data (input and output) to use for the training
58
+ :param epochs: the number of epochs the training lasts
59
+ :param log_func: the function to show the log (ex: RichLog to shows logs in the TUI)
60
+ :return:
61
+ """
62
+
63
+ error = nn.MSELoss() # initializing the error function
64
+
65
+ learning_optimizer = optim.Adam(
66
+ model.parameters(), lr=0.02
67
+ ) # initializing the optimizer (ADAM)
68
+
69
+ final_loss = 0
70
+
71
+ log_func(
72
+ f"Starting the training for [bold]{getattr(model, 'name')}[/]. It will last exactly [bold]{epochs} epochs[/]. "
73
+ )
74
+
75
+ for epoch in range(epochs):
76
+
77
+ learning_optimizer.zero_grad() # resets the model gradients
78
+
79
+ expected_out = model(data[0]) # get the model output
80
+
81
+ loss = error(
82
+ expected_out, data[1]
83
+ ) # calculate the error from the expected output
84
+
85
+ loss.backward() # update the gradients
86
+
87
+ learning_optimizer.step() # the optimizer updates the weights
88
+
89
+ if epoch % 10 == 0: # every 10 epochs gives a report
90
+
91
+ log_func(f"Epoch: {epoch} on {epochs} - Actual loss: {loss.item():.6f}")
92
+
93
+ final_loss = (
94
+ loss.item()
95
+ ) # updating every epoch for logic causes (if the loop doesn't start) the assignment doesn't happen and there's no error
96
+
97
+ log_func(f"""[italic]Training is done[/].\n
98
+ Final loss: [bold]{final_loss:.6f}[/]""")
@@ -0,0 +1,3 @@
1
+ from myfirstnn.neuraln.model import *
2
+
3
+ __all__ = ["SimpleNN"]
@@ -0,0 +1,55 @@
1
+ """
2
+ model.py
3
+ Author: Alessio Parolini
4
+ Contains the data about the Neural Network Model
5
+ """
6
+
7
+ __all__ = ["SimpleNN"]
8
+
9
+ import torch
10
+
11
+ from torch import nn
12
+
13
+
14
+ class SimpleNN(nn.Module):
15
+ """
16
+ This is the class to create the model to predict parables
17
+ It has got 3 layers:
18
+ 1 -> 22 -> 1.
19
+ Uses the ReLU
20
+ """
21
+
22
+ def __init__(self, name: str):
23
+
24
+ super().__init__()
25
+
26
+ self.relu = nn.ReLU()
27
+
28
+ self.name = name
29
+
30
+ self.layer1 = nn.Linear(in_features=1, out_features=22) # first layer
31
+
32
+ self.layer2 = nn.Linear(in_features=22, out_features=22) # hidden layer
33
+
34
+ self.layer3 = nn.Linear(in_features=22, out_features=1) # final layer
35
+
36
+ self.layers: list[nn.Linear] = [self.layer1, self.layer2, self.layer3]
37
+
38
+ def __str__(self) -> str:
39
+
40
+ return f"""Model name: {self.name}\n
41
+ Layers: {len(self.layers)}\n
42
+ Input: {getattr(self.layers[0], "in_features")}\n
43
+ Output: {getattr(self.layers[-1], "out_features")}\n"""
44
+
45
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
46
+
47
+ for layer in self.layers:
48
+
49
+ x = layer(x)
50
+
51
+ if layer is not self.layers[-1]:
52
+
53
+ x = self.relu(x)
54
+
55
+ return x
@@ -0,0 +1,55 @@
1
+ Metadata-Version: 2.4
2
+ Name: myfirstnn
3
+ Version: 0.1.0
4
+ Summary: A simple TUI tool to creates and train NN from random data
5
+ Author-email: Alessio Parolini <alepar.ap9@gmail.com>
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Operating System :: OS Independent
8
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
9
+ Classifier: Environment :: Console
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: textual>=8.2.8
13
+ Requires-Dist: torch>=2.14.1
14
+
15
+ # autoNN
16
+
17
+ A simple TUI tool to create and train NN on random datas, to **teach the model how to calculate squares (x^2)**
18
+
19
+ > [!NOTE]
20
+ > I built this project for consolidate my skills and my knowledge about AI and Deep Learning. I know isn't perfect, I
21
+ know isn't so useful, I know the README is a too short... but is a **part of a bigger goal I'm working on. Stay tuned,
22
+ I'm gonna develop it soon**!
23
+
24
+ ## Software Structure
25
+
26
+ The file has 4 packages:
27
+
28
+ + **display**: contains the module that handles the TUI with Textual. Also contains the sub-package **components** with
29
+ the different TUI components.
30
+
31
+ + **learning**: contains the module with the functions to train the model once is created.
32
+
33
+ + **neuraln**: contains the module with the class to create the model with his NN.
34
+
35
+ + **core**: starts and runs all the software. His called in __main__.py to start the whole package
36
+
37
+ ## How it works
38
+
39
+ When you start the software, the TUI runs in your terminal. When you set the name and the number of inputs, you can
40
+ press the button **"Start Training"** and let the magic starts! You'll see al the log of the training, with a live loss,
41
+ and ** you're gonna prove how an AI model training works!**
42
+
43
+ ## How to install
44
+
45
+ To install this software, I need to have installed on your machine Python 3.11
46
+
47
+ ## Credit
48
+
49
+ This project was built using the following amazing open-source libraries:
50
+
51
+ * **[PyTorch](https://pytorch.org)** - An open-source machine learning framework used for creating, structuring, and
52
+ training the neural network models.
53
+ * **[Textual](https://textualize.io)** - A Python framework, used to build the beautiful and interactive Terminal User
54
+ Interface (TUI).
55
+
@@ -0,0 +1,19 @@
1
+ myfirstnn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ myfirstnn/__main__.py,sha256=TcQlUl7fpQgW29WnmbkgODwhSjSkWAdbQ7F3ctmzZbw,175
3
+ myfirstnn/core/__init__.py,sha256=L2vT5QwIJj6Y0RF8U2KDy-3ErkX6dnZ5LK_CCdzJMRY,58
4
+ myfirstnn/core/start.py,sha256=XJIkcnJHU0TL9cIvn-9Y_MJ5cJovPRS4iOsJINBoL5A,334
5
+ myfirstnn/display/__init__.py,sha256=NEDcupevQaRSf3VwMEKn43w9a0Qo_8nE6YHIzvZ2giQ,64
6
+ myfirstnn/display/app.py,sha256=22QEkVYwAO2KKsn03PVh8GPtARNSFEagI9SyN8obTF4,385
7
+ myfirstnn/display/components/__init__.py,sha256=vAldwuw63hD7BPn0vAyQs95VFE-1dhESG18siCNvDiE,142
8
+ myfirstnn/display/components/form.py,sha256=-5J-Tyq3wwYAhb7pPQARMaJ7zO_c333KLA1xeOvZJ4U,3032
9
+ myfirstnn/display/components/headers.py,sha256=aO99LoIJ7WMt3MpzBvGkCNxBH8WXiwE-Lg_wfAXnyDQ,1782
10
+ myfirstnn/display/styles/app.tcss,sha256=yXAAHApgjYcqEjVFeimHYdRJNgdVB9XaApbjrmaTYIA,997
11
+ myfirstnn/learning/__init__.py,sha256=NJqUxYAngtzjyYrFSVjkGELOLTcNmzmoyPzn9L7QvE0,96
12
+ myfirstnn/learning/training.py,sha256=ow_oUd8kyHo4xj7HSU0VPOb1AcOtTOGGJlz_I9eb3-o,2995
13
+ myfirstnn/neuraln/__init__.py,sha256=41ymRkks5xfju4sqwWuglA37RTEzCAxkA0kYaTFg7Uw,65
14
+ myfirstnn/neuraln/model.py,sha256=ZJgw_Z-y3i_Nc_rrxpQWi9_rBKGbr4RowG-CGxaxaEQ,1293
15
+ myfirstnn-0.1.0.dist-info/METADATA,sha256=3lZ3DI4KFArbtKBNn5jF7pEga115STyfb_tpfCEFvTI,2227
16
+ myfirstnn-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
17
+ myfirstnn-0.1.0.dist-info/entry_points.txt,sha256=3IOrjR6P6Zh4h2cxckcOyk4j4ZidbCZbDNMm4U2kdso,54
18
+ myfirstnn-0.1.0.dist-info/top_level.txt,sha256=TqjeQpcOtbvdiYTwkDdVmGLAedbLCN2NU3UIpQeUYC4,10
19
+ myfirstnn-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ myfirstnn = myfirstnn.__main__:main
@@ -0,0 +1 @@
1
+ myfirstnn