sw-mlp 1.0.0__tar.gz

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.
sw_mlp-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 swangarch and contributer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
sw_mlp-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,439 @@
1
+ Metadata-Version: 2.4
2
+ Name: sw-mlp
3
+ Version: 1.0.0
4
+ Summary: A multilayer perceptron implemented with Numpy.
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Dist: matplotlib>=3.11.2
8
+ Requires-Dist: numpy>=2.5.4
9
+ Requires-Dist: pandas==2.2.3
10
+ Requires-Python: >=3.12, <3.13
11
+ Description-Content-Type: text/markdown
12
+
13
+ # Multilayer Perceptron
14
+
15
+ Multilayer perceptron (MLP) is a simple neural network (NN), can solve both regression and classification tasks. The project provides a reusable and modular implementation.
16
+
17
+ [[Demo Video]](https://www.youtube.com/watch?v=YRcl1f--tcw)
18
+
19
+ ## Requirements
20
+
21
+ The project is built from scratch with Python, with only Numpy, Pandas, Matplotlib,
22
+ without high-level ML libraries.
23
+
24
+ Use Python **3.12** and **uv** to manage the environment and dependencies.
25
+ Install uv before continuing. Run the following commands from the project root:
26
+
27
+ ```bash
28
+ git clone https://github.com/swangarch/multilayer_perceptron
29
+ cd multilayer_perceptron
30
+
31
+ # Create .venv and install the locked dependencies and the project
32
+ uv sync --locked
33
+
34
+ # Alternatively, use the Makefile (runs uv sync)
35
+ make setup
36
+ ```
37
+
38
+ Commands below use `uv run`, so activating the virtual environment is not required.
39
+ To activate it manually on macOS/Linux, use `source .venv/bin/activate`.
40
+
41
+
42
+ ## Usage
43
+
44
+ Run these commands from the project root. Makefile targets use `uv run -m mlp`.
45
+
46
+ ```bash
47
+ uv run -m mlp --help
48
+ ```
49
+
50
+ ### For example dataset classification
51
+
52
+ ```bash
53
+ # To split the dataset
54
+ make split
55
+
56
+ # To train with training configuration file and training dataset
57
+ make train
58
+
59
+ # To test with test dataset
60
+ make test
61
+ ```
62
+
63
+ Breast cancer diagnosis dataset, a binary classification based on 30 features of a cell.
64
+
65
+ ### MNIST handwrite digits classification (0–9)
66
+
67
+ ```bash
68
+ # To split, train and test the dataset
69
+ make digit
70
+ ```
71
+
72
+ For the handwritten digit classification task (0–9), the model achieved 97.19% test accuracy using 33,000 training samples of 28 × 28 images in the optimal configuration.
73
+
74
+ For the handwritten character recognition task with 94 categories, the model reached 91% accuracy based on 175,000 of 28 × 28 images training samples.
75
+
76
+ ### For random generated 1d data regression
77
+
78
+ ```bash
79
+ # To train and test generated data, with relu activation
80
+ make regre-relu
81
+
82
+ # To train and test generated data, with sigmoid activation
83
+ make regre-sigmoid
84
+ ```
85
+
86
+ ## Packaging
87
+
88
+ Build the wheel and source distribution with uv:
89
+
90
+ ```bash
91
+ uv build
92
+
93
+ # Alternatively
94
+ make build
95
+ ```
96
+
97
+ The output files are written to `dist/`:
98
+
99
+ - `sw_mlp-1.0.0-py3-none-any.whl`
100
+ - `sw_mlp-1.0.0.tar.gz`
101
+
102
+ To install the wheel into a Python 3.12 virtual environment:
103
+
104
+ ```bash
105
+ uv venv --python 3.12
106
+ uv pip install dist/sw_mlp-1.0.0-py3-none-any.whl
107
+
108
+ # macOS/Linux: run the installed package
109
+ .venv/bin/python -m mlp --help
110
+ ```
111
+
112
+ The wheel contains the Python package. Example configurations and datasets in the
113
+ repository's `config/` and `data/` directories must be distributed separately.
114
+ Pass their paths when running the installed package. The split command writes to
115
+ `data/train.csv` and `data/test.csv`, so the working directory must contain a
116
+ `data/` directory.
117
+
118
+ ## Features
119
+
120
+ - Training methods → supports **Stochastic Gradient Descent (SGD)** and **mini-batch training**.
121
+
122
+ - **Visualization** → includes real-time animations to track the learning process.
123
+
124
+ - **Configurable** architecture → adjustable network shape, activation functions, initialization methods, max iterations, learning rate, batch size, etc via a configuration file.
125
+
126
+ - Data handling → data loading and preprocessing.
127
+
128
+ - Support multiple activation functions: **ReLU, Sigmoid, Softmax, Leaky ReLU**
129
+
130
+ - Support multiple loss functions:
131
+ - **Categorical Cross Entropy (CCE)** with automatic one-hot encoding for categorical labels
132
+ - **Binary Cross Entropy (BCE)**
133
+ - **Mean Squared Error (MSE)**
134
+
135
+ - Support **Fine-tuning**: continue training from saved weights for further optimization
136
+
137
+ ## Methodology
138
+
139
+ ![Demo](visualization/diagram/mlp.jpg)
140
+
141
+ A **Multilayer Perceptron** is a basic artificial neural network that learns to map input data to the correct output by adjusting internal parameters called weights and biases. It is composed of multiple layers of artificial neurons, where each neuron performs a simple computation — combining inputs, multiplying weights, adding a bias, and passing the result through an activation function to introduce non-linearity. Then using back propagation and gradient descent to find ideal weights and biases.
142
+
143
+ ### Learning Process
144
+ The learning process consists of three main stages:
145
+
146
+ - **Feedforward** — compute predictions by passing data through all layers.
147
+ - **Back propagation** — calculate gradients of the loss with respect to the weights, using chain rule.
148
+ - **Gradient Descent** — update weights and biases to minimize the loss over time.
149
+
150
+ Through **repeated iterations** of these steps, the MLP gradually improves its predictions and learns to generalize from the training data.
151
+
152
+ ### Feedfoward
153
+ ![Demo](visualization/diagram/feedforward.jpg)
154
+
155
+ In the feedforward step, the input data passes through several layers of neurons. Each neuron performs a weighted sum of its inputs, adds a bias, and then applies an activation function such as ReLU, Sigmoid, or Softmax.
156
+
157
+ When neurons are grouped into a layer, their computations can be efficiently expressed using **matrix multiplication**. This allows the model to process many neurons at once, using vectorized operations in **NumPy**. Each layer's output becomes the input to the next layer, forming a feedforward chain that passes information through the network.
158
+
159
+ $$Z=WX+b$$
160
+
161
+ $$A=f(Z)$$
162
+
163
+ The final layer produces the output — either a value (for regression) or class probabilities (for classification).
164
+
165
+ ### Back probagation
166
+ ![Demo](visualization/diagram/back_probagation.jpg)
167
+
168
+ In backpropagation, the model calculates how far its predictions are from the correct answers using a loss function (like MSE or Cross-Entropy). Then, it computes the gradient of this loss to each weight and bias using the **chain rule**. This process tells the model which direction each weight and bias should move to reduce the overall error.
169
+
170
+ For the output layer, the gradient simplification is elegant:
171
+
172
+ **MSE Regression**: The output layer typically uses no activation function (linear output). The gradient of the loss with respect to the output is:
173
+
174
+ $$\frac{\partial L}{\partial \hat{y}} = \hat{y} - y$$
175
+
176
+ **Cross-Entropy Classification**: The output layer uses Softmax (multi-class) or Sigmoid (binary) activation. Remarkably, when combined with Cross-Entropy loss, the gradient simplifies to the same form:
177
+
178
+ $$\frac{\partial L}{\partial z} = \hat{y} - y$$
179
+
180
+
181
+
182
+ If you're interested in the details, this [**article**](https://shivammehta25.github.io/posts/deriving-categorical-cross-entropy-and-softmax/) by Shivam Mehta explains in depth how this simplification was derived. This mathematical convenience makes backpropagation efficient for both regression and classification tasks.
183
+
184
+
185
+
186
+ ### Gradient descent
187
+ ![Demo](visualization/diagram/gradient_descent.jpg)
188
+
189
+ Gradient descent is the optimization process that updates the weights and biases. It moves the weights and biases in the direction that reduces the loss the most, step by step.
190
+
191
+ $$
192
+ W := W - 𝜂 \frac{\partial J}{\partial W}
193
+ $$
194
+
195
+ $$
196
+ b := b - 𝜂 \frac{\partial J}{\partial b}
197
+ $$
198
+
199
+ The learning rate controls how big each step is — too high can make learning unstable, too low can make it too slow.
200
+
201
+ There are two main modes implemented in this project:
202
+
203
+ **Stochastic Gradient Descent (SGD)**: updates weights for each training sample, when batch size is set to 1.
204
+
205
+ **Mini-batch Gradient Descent**: updates weights after a small batch of samples, balancing speed and stability.
206
+
207
+ ### Non linear classification
208
+
209
+ ![Demo](visualization/diagram/classification.jpg)
210
+
211
+ This diagram shows how an MLP can separate data that is not linearly separable — for instance, when data points form circular or spiral patterns.
212
+ With multiple layers and non-linear activations, the network learns complex boundaries that a simple linear model cannot.
213
+
214
+ ## Programs
215
+
216
+ In addition to the provided Makefile, the following section explains the usage in detail and describes how you can customize the training process to fit your specific needs.
217
+
218
+ ### Configuration
219
+
220
+
221
+ An json config file to pass network structure and training configuration is required.
222
+
223
+ ```
224
+ {
225
+ "shape": [784, 64, 32, 10],
226
+ // Network shape, number of neurons in each layer
227
+
228
+ "activation_funcs": ["relu", "relu", "softmax"],
229
+ // Activation functions for each layer
230
+
231
+ "weights_init": ["he", "he", "xavier"],
232
+ // Layer weights initialization methods, e.g. he / xavier / zero
233
+
234
+ "loss": "CategoricalCrossEntropy",
235
+ // Loss function, supporting MeanSquareError and CrossEntropy
236
+
237
+ "max_epoch": 1000,
238
+ // Maximum number of training epochs
239
+
240
+ "learning_rate": 0.01,
241
+ // Learning rate for gradient descent
242
+
243
+ "batch_size": 50,
244
+ // Batch size for mini-batch training, 1 for SGD
245
+
246
+ "classification": true,
247
+ // Whether to calculate accuracy (true for classification tasks)
248
+
249
+ "animation": "none",
250
+ // To show training animation, recommended only for 1D data
251
+
252
+ "train_ratio": 0.8,
253
+ // Ratio to split dataset into training and validation
254
+
255
+ "threshold": false,
256
+ // Threshold for early stopping, false means disabled
257
+
258
+ "index": false
259
+ // Whether the input CSV file contains an index column
260
+ }
261
+ ```
262
+ ### Train and predict
263
+ We recommand you to use --help option before the first usage.
264
+ ```
265
+ Usage:
266
+
267
+ uv run -m mlp <option> <config.json> <data.csv> [params.json]
268
+
269
+ Options:
270
+
271
+ -s: Split dataset into (train.csv) and (test.csv), no params required
272
+
273
+ -t: Train dataset, if params.json is provided, it performs fine tuning.
274
+
275
+ -p: Test on a test dataset, if params.json is provided, it performs prediction based on trained model.
276
+
277
+ --help: Show help messages.
278
+
279
+ -More features to come.
280
+
281
+ Note:
282
+
283
+ There is built in dataset generated by script, use --gen-data1d to replace dataset
284
+ ```
285
+
286
+ The program will:
287
+
288
+ - Defines the network structure (layers, activation functions).
289
+
290
+ - Trains using backpropagation and gradient descent.
291
+
292
+ - Visualize loss and prediction:
293
+
294
+ - By default, regression task will visualize the loss, and the data distribution for first dimension.
295
+
296
+ - In addition, classification task will add an accuracy plot.
297
+
298
+
299
+ ### Demo
300
+ The example graph on both classification and regression.
301
+
302
+ ![Demo](visualization/nn/demo.png)
303
+
304
+
305
+ ### Datasets
306
+
307
+ Datasets are provided in this repository, one example corresponding to breast cancer diagnosis classification.
308
+ It contains 32 columns, where the diagnosis column is the label to predict. The label can take two values:
309
+
310
+ M → Malignant (cancerous)
311
+
312
+ B → Benign (non-cancerous)
313
+
314
+ The remaining 30 numerical features describe various characteristics of a cell nucleus extracted with fine-needle aspiration (FNA), such as radius, texture, perimeter, area, and smoothness. These measurements are widely used for early breast cancer detection.
315
+
316
+ ### To split data:
317
+
318
+ It is split into two parts: one for training and validation one for testing.
319
+
320
+ ```bash
321
+ uv run -m mlp -s config/data.json data/data.csv
322
+ ```
323
+
324
+ The objective is to classify whether a tumor is malignant or benign based on the given features.
325
+
326
+ ### To train
327
+ ```bash
328
+ # Train a new model
329
+ uv run -m mlp -t config/data.json data/train.csv
330
+
331
+ # Fine-tune an existing model
332
+ uv run -m mlp -t config/data.json data/train.csv params.json
333
+ ```
334
+ After training, the params.json will be saved, which contain weights, biases and network structure.
335
+ If params.json is provided, the program will perform fine tuning.
336
+
337
+ ### To test
338
+ ```bash
339
+ uv run -m mlp -p config/data.json data/test.csv params.json
340
+ ```
341
+
342
+ The loss function is selected explicitly by the `loss` field in the configuration.
343
+ Use `BinaryCrossEntropy` with a sigmoid output for binary classification,
344
+ `CategoricalCrossEntropy` with a softmax output for multi-class classification,
345
+ or `MeanSquareError` with a linear output (`"none"`) for regression.
346
+ The output activation alone does not select the loss function.
347
+
348
+ The program will make prediction, an accuracy will be calculated and prediction will be saved in predictions.json.
349
+
350
+ ### Other datasets and configurations provided
351
+ - 0-9.csv _____ 0-9.json => 0 to 9 hand wirte digits recognition with softmax and CCE loss
352
+ - --gen-data1d _____ regre-relu.json => 1d random generated data with RELU activation and MSE loss
353
+ - --gen-data1d _____ regre-sigmoid.json => 1d random generated data with Sigmoid activation and MSE loss
354
+
355
+ ### Class
356
+
357
+ Below is a simple example of using the `MultiLayerPerceptron` class to train a regression model.
358
+
359
+ ```python
360
+ from mlp.neural_network import MultiLayerPerceptron, relu
361
+ from mlp.data_process import generate_data_rand
362
+
363
+ def main():
364
+ try:
365
+ # Define network structure: input → 64 → 32 → output
366
+ net_shape = (1, 64, 32, 1)
367
+ activation_funcs = (relu, relu, None) # last layer is linear (regression)
368
+ weights_init = ("he", "he", "he") # Define the weights initialization methods
369
+
370
+ # Initialize neural network
371
+ nn = MultiLayerPerceptron(net_shape, activation_funcs, weights_init)
372
+
373
+ # Generate training data
374
+ inputs, truths = generate_data_rand(142, 500, 0.02)
375
+ test_inputs, test_truths = generate_data_rand(123, 50, 0.02)
376
+ nn.train(inputs, truths, 10000, 0.005, batch_size=20, animation="plot")
377
+
378
+ # Test with new data
379
+ nn.test(test_inputs, test_truths)
380
+
381
+ # Save graphs
382
+ nn.save_plots()
383
+
384
+ except Exception as e:
385
+ print("Error:", e)
386
+
387
+
388
+ if __name__ == "__main__":
389
+ main()
390
+ ```
391
+
392
+ ### Generalization
393
+
394
+ The figure shows that multilayer perceptron is capable of learning non-linear patterns from different datasets and can generalize beyond the training data, making them applicable to a wide range of tasks.
395
+
396
+ ![Regression demo](visualization/nn/prediction.jpg)
397
+ ---
398
+
399
+ ### Hyperparameter Tuning: Batch Size
400
+
401
+ **Batch size** is a key hyperparameter that influences both training speed and model performance. To study its effect, I kept all other parameters constant and varied only the batch size, trained the model on the MNIST dataset. In this experiment, I used **CuPy** to replace **NumPy** in order to leverage GPU acceleration and improve computational efficiency during training.
402
+
403
+ ```json
404
+ {
405
+ "shape": [784, 392, 128, 64, 32, 10],
406
+ "activation_funcs": ["relu", "relu", "relu", "relu", "softmax"],
407
+ "weights_init": ["he", "he", "he", "he", "xavier"],
408
+ "loss": "CategoricalCrossEntropy"
409
+ }
410
+ ```
411
+
412
+ | Batch Size | Time (s) | Accuracy | Loss |
413
+ |:-----------:|:--------:|:--------:|:-----:|
414
+ | 1 | 2040 | 0.9814 | 0.1580 |
415
+ | 10 | 180 | 0.9769 | 0.1197 |
416
+ | 50 | 45 | 0.9719 | 0.1371 |
417
+ | 100 | 31 | 0.9676 | 0.1153 |
418
+ | 200 | 25 | 0.9593 | 0.1362 |
419
+ | 500 | 22 | 0.9414 | 0.1937 |
420
+ | 1000 | 21 | 0.9414 | 0.1937 |
421
+
422
+ #### Analysis
423
+
424
+ - **Training Time**: As batch size increases, training time decreases dramatically, reflecting better computational efficiency.
425
+
426
+ - **Accuracy**: Accuracy drops noticeably when batch size exceeds 200, indicating that very large batches may reduce generalization capability.
427
+ The drop in accuracy for large batches can sometimes be reduced by slightly increasing the learning rate.
428
+
429
+ - **Loss**: Smaller batches tend to achieve lower loss values, suggesting better fine-grained learning at the cost of longer training time.
430
+
431
+ #### Conclusion
432
+
433
+ In this experiment, batch sizes between 50 and 100 provide the best balance between training efficiency and model performance.
434
+ Smaller batches has higher accuracy but are slower, while larger batches are faster but may sacrifice precision.
435
+
436
+ ---
437
+
438
+ ## License
439
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.