commit 265beea3b0962857190bc9d6a5d4063041b1fe32 Author: Gabriele Gilardi Date: Wed Jun 10 16:54:22 2020 +0900 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c173c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,153 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# static files generated from Django application using `collectstatic` +media +static + +# Visual Studio Code +.vscode/ + +# Matlab directory +Code_MatLab/ + +# Docs directory +Docs/ +data/ diff --git a/Code_Python/filters.py b/Code_Python/filters.py new file mode 100644 index 0000000..74373b6 --- /dev/null +++ b/Code_Python/filters.py @@ -0,0 +1,168 @@ +""" +Class for filter/smooth data. + +Copyright (c) 2020 Gabriele Gilardi + + +ToDo: +- generalize to multidimensional input arrays +- use NaN or input values for points not filtered? +- plot filtered data +- add plot filter + +""" + +import sys +import numpy as np + + +def Generalized(X, b, a): + """ + Applies a generic filter + + Inputs: + X Data to filter + b Transfer response coefficients (numerator) + a Transfer response coefficients (denominator) + + Outputs: + Y Filtered data + idx Index first element in Y actually filtered + + Elements from 0 to (idx-1) are set equal to NaN. + """ + # Initialize + nel_X = len(X) + nel_b = len(b) + nel_a = len(a) + idx = np.amax([0, nel_b-1, nel_a-1]) + Y = X.copy() + + # Apply filter + for i in range(idx, nel_X): + tmp = 0.0 + + # Contribution from [b] (numerator) + for j in range(nel_b): + tmp = tmp + b[j] * X[i-j] + + # Contribution from [a] (denominator) + for j in range(1, nel_a): + tmp = tmp - a[j] * Y[i-j] + + # Filtered value + Y[i] = tmp / a[0] + + # Set elements from 0 to (idx-1) equal to NaN + Y[0:idx] = np.nan + + return Y, idx + + +class Filter: + + def __init__(self, X): + """ + """ + self.X = np.asarray(X) + self.nel = len(X) + self.idx = 0 + + def SMA(self, N=10): + """ + Simple Moving Average + N = order/smoothing factor + """ + b = np.ones(float(N)) / float(N) + a = np.array([1.0]) + Y, self.idx = Generalized(self.X, b, a) + return Y + + def EMA(self, N=10): + """ + Exponential Moving Average + N = order/smoothing factor + The damping term is determined as equivalent to a N-SMA + """ + alpha = 2.0 / (float(N) + 1.0) + b = np.array([alpha]) + a = np.array([1.0, alpha-1.0]) + Y, self.idx = Generalized(self.X, b, a) + return Y + + def InstTrend(self, alpha=0.5): + """ + Instantaneous Trendline (2nd order, IIR, low pass, Ehlers) + alpha = damping term + """ + b = np.array([(alpha-alpha**2/4.0), (alpha**2/2.0), + -(alpha-3.0*alpha**2/4.0)]) + a = np.array([1.0, -2.0*(1.0-alpha), (1.0-alpha)**2]) + Y, self.idx = Generalized(self.X, b, a) + return Y + + def PassBand(self, P=5, delta=0.3): + """ + Pass Band + P = cut-off period (50% power loss, -3 dB) + delta = band centered in P and in percent + (Example: 0.3 => 30% of P => 0.3*P, if P = 10 => 0.3*10 = 3) + """ + beta = np.cos(2.0 * pi / float(P)) + gamma = np.cos(2.0*pi*(2.0*delta)/float(P)) + alpha = 1.0 / gamma - np.sqrt(1.0 / gamma ** 2 - 1.0) + b = np.array([(1.0-alpha)/2.0, 0.0, -(1.0-alpha)/2.0]) + a = np.array([1.0, -beta*(1.0+alpha), alpha]) + Y, self.idx = Generalized(self.X, b, a) + return Y + + def StopBand(self, P=5, delta=0.3): + """ + Stop Band + P = cut-off period (50% power loss, -3 dB) + delta = band centered in P and in percent + (Example: 0.3 => 30% of P => 0.3*P, if P = 10 => 0.3*10 = 3) + """ + beta = cos(2.0*pi/float(P)) + gamma = cos(2.0*pi*(2.0*delta)/float(P)) + alpha = 1.0/gamma - sqrt(1.0/gamma**2 - 1.0) + b = np.array([(1.0+alpha)/2.0, -2.0*beta*(1.0+alpha)/2.0, + (1.0+alpha)/2.0]) + a = np.array([1.0, -beta*(1.0+alpha), alpha]) + Y, self.idx = Generalized(self.X, b, a) + return Y + + def GaussLow(self, P=2, N=1): + """ + Gauss Low (low pass, IIR, N-th order, must be P > 1) + P = cut-off period (50% power loss, -3 dB) + N = times the filter is called (order) + """ + P = np.array([2, P], dtype=int).max() # or error? warning? + A = 2.0**(1.0/float(N)) - 1.0 + B = 4.0*sin(pi/float(P))**2.0 + C = 2.0*(cos(2.0*pi/float(P)) - 1.0) + delta = sqrt(B**2.0 - 4.0*A*C) + alpha = (-B + delta)/(2.0*A) + b = np.array([alpha]) + a = np.array([1.0, -(1.0-alpha)]) + Y = np.copy(self.X) + for i in range(N): + Y, self.idx = Generalized(Y, b, a) + return Y + + def ZEMA1(self, N=10, K=1.0, Vn=5): + """ + Zero lag Exponential Moving Average (type 1) + N = order/smoothing factor + K = coefficient/gain + Vn = look back bar for the momentum + The damping term is determined as equivalent to a N-SMA + """ + alpha = 2.0 / (float(N) + 1.0) + b = np.zeros(Vn+1) + b[0] = alpha * (1.0 + K) + b[-1] = - alpha * K + a = np.array([1.0, -(1.0-alpha)]) + Y, self.idx = Generalized(self.X, b, a) + return Y diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5e534f0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Gabriele Gilardi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..947f996 --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# Feed-Forward Neural Network (FFNN) for Regression Problems + +## Reference + +- Mathematical background: ["Neural Networks and Deep Learning"](http://neuralnetworksanddeeplearning.com/index.html). + +- Datasets: [UCI Machine Learning Repository](https://archive.ics.uci.edu/ml/datasets.php). + +## Characteristics + +- The code has been written and tested in Python 3.7.7. +- Usage: *python test.py example*. + +## Parameters + +`example` Name of the example to run (wine, stock, wifi, pulsar.) + +`problem` Defines the type of problem. Equal to C specifies logistic regression, anything else specifies linear regression. The default value is `None`. + +## Examples + +There are four examples in *test.py*: wine, stock, wifi, pulsar. Since GDO is used, `use_grad` is set to `True`. For all examples `init_weights` is also set to `True`. + +### Single-label linear regression examples: wine + +```python +data_file = 'wine_dataset.csv' +n_features = 11 +hidden_layers = [20] +split_factor = 0.7 +L2 = 0.0 +epochs = 50000 +alpha = 0.2 +d_alpha = 1.0 +tolX = 1.e-7 +tolF = 1.e-7 +``` + +Original dataset: . + +The dataset has 11 features, 1 label, 4898 samples, 261 variables, and a layout of [11, 20, 1]. + +Correlation predicted/actual values: 0.708 (training), 0.601 (test). + +Exit on `epochs` with `tolX` = 2.0e-4 and `tolF` = 1.1e-7.