├── .Rbuildignore ├── CHANGES.md ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── R ├── LVQs_helper_functions.R ├── NNClasses.R └── RcppExports.R ├── README.md ├── inst └── CITATION ├── man ├── Autoencoder.Rd ├── BP-class.Rd ├── LVQs-class.Rd ├── LVQs_recall.Rd ├── LVQs_train.Rd ├── LVQu.Rd ├── MAM-class.Rd ├── NN-R-components.Rd ├── NN-class.Rd ├── NN-components.Rd └── nnlib2Rcpp.Rd ├── nnlib2Rcpp.Rproj ├── paper ├── paper.bib └── paper.md ├── src ├── RcppExports.cpp ├── Rcpp_Autoencoder.cpp ├── Rcpp_BP_supervised_module.cpp ├── Rcpp_LVQ_supervised_module.cpp ├── Rcpp_LVQ_unsupervised.cpp ├── Rcpp_MAM_supervised_module.cpp ├── Rcpp_NN_module.cpp ├── Rcpp_R_aux_control.h ├── Rcpp_R_connection_matrix.h ├── Rcpp_R_layer.h ├── Rcpp_aux_control_R.h ├── additional_parts.h ├── additional_parts_other.h ├── additional_parts_softmax.h ├── aux_control.cpp ├── aux_control.h ├── component.cpp ├── component.h ├── connection.cpp ├── connection.h ├── connection_matrix.cpp ├── connection_matrix.h ├── connection_set.h ├── layer.h ├── layer2D.h ├── nn.cpp ├── nn.h ├── nn_bp.cpp ├── nn_bp.h ├── nn_lvq.cpp ├── nn_lvq.h ├── nn_mam.h ├── nnlib2.h ├── nnlib2_dllist.h ├── nnlib2_error.cpp ├── nnlib2_error.h ├── nnlib2_memory.cpp ├── nnlib2_memory.h ├── nnlib2_misc.cpp ├── nnlib2_misc.h ├── nnlib2_string.cpp ├── nnlib2_string.h ├── nnlib2_vector.h ├── pe.cpp ├── pe.h └── spare_parts.h ├── support └── manual.pdf └── vignettes ├── intro.bib ├── intro.ltx ├── nClassDiagram.png ├── nLVQs.png ├── nNNAutoenc.png └── nNNMEX.png /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^.*\.md$ 4 | ^doc$ 5 | ^Meta$ 6 | ^paper 7 | ^support 8 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | Changes to nnlib2Rcpp version 0.1.1 (from 0.1.0) 2 | - removed redundant unused files. 3 | - minor documentation fixes (Rcpp missing entries added), passes devtools::check() with no related warnings. 4 | - since LVQ has two variations (supervised and unsupervised), it was mentioned in comments that the names may be misleading or confusing. So the LVQ related R functions and modules are renamed as follows: 5 | ‘LVQs’ for supervised LVQ function (was ‘LVQ’ in v.0.1.0) 6 | ‘LVQs_NN’ for supervised LVQ module (was ‘LVQ_NN’ in v.0.1.0) 7 | ‘LVQu’ for unsupervised LVQ function (was ‘SOM’ in v.0.1.0) 8 | - minor documentation improvements. 9 | - pdf documentation removed, but can be built by running the following R command: devtools::build_manual() 10 | 11 | --- 12 | 13 | Changes to nnlib2Rcpp version 0.1.2 (from 0.1.1) 14 | - (checked with R 3.6.3 and RTools35.) 15 | - (checked with R 4.0.0 and RTools40 (produces 1 extra NOTE). 16 | - removed redundant BP functions. All BP functionality is now implemented in BP module class (safer and more convenient for supervised methods). 17 | - removed redundant Supervised-LVQ functions. All Supervised-LVQ functionality is now implemented in LVQs module class (safer and more convenient for supervised methods). Unsupervised-LVQ is still implemented as a function (LVQu). 18 | - removed MAM functions. All MAM functionality is now implemented in MAM module class (safer and more convenient for supervised methods). 19 | - Minor changes in nnlib2 (now uses nnlib2 v.0.1.5). 20 | - Fixed LICENCE file (was incompatible with CRAN). 21 | 22 | --- 23 | 24 | Changes to nnlib2Rcpp version 0.1.3 (from 0.1.2) 25 | - includes nnlib2 v.0.1.7. 26 | 27 | --- 28 | 29 | Changes to nnlib2Rcpp version 0.1.4 (from 0.1.3) 30 | - (checked on Linux Mint 19.3 with R 3.6.3) 31 | - (checked with R 4.0.0 and RTools40 (produces 1 extra NOTE). 32 | - includes nnlib2 v.0.2.0. 33 | - added module "NN" which allows creation and control of custom NN from R using predefined components. It also provides fixed method for adding user-defined NN components which can be used in the module. 34 | 35 | --- 36 | 37 | Changes to nnlib2Rcpp version 0.1.5 (from 0.1.4). 38 | - added some methods to module "NN" (get_weight_at, set_weight_at). 39 | - added some methods to module "NN" (set_misc_values_at). 40 | 41 | --- 42 | 43 | Changes to nnlib2Rcpp version 0.1.6 (from 0.1.5) 44 | - added method to module "NN" (recall_dataset) to decode/map/retrieve output for entire input dataset. 45 | - added method to module "NN" (encode_dataset_unsupervised) for faster unsupervised training. 46 | - added method to module "NN" (encode_datasets_supervised) for faster supervised training. 47 | - includes nnlib2 v.0.2.4 48 | - added method to module "NN" (get_output_at). 49 | - added method to module "NN" (set_output_at). 50 | - added package vignette. 51 | - other minor changes. 52 | 53 | --- 54 | 55 | Changes to nnlib2Rcpp version 0.1.7 (from 0.1.6) 56 | - minor changes (only affect source). 57 | 58 | --- 59 | 60 | Changes to nnlib2Rcpp version 0.1.8 (from 0.1.7) 61 | - minor documentation changes. 62 | - other minor changes. 63 | 64 | --- 65 | 66 | Changes to nnlib2Rcpp version 0.1.9 (from 0.1.8) 67 | - documentation changes (clarify hidden_layer_size). 68 | - added show() to modules NN,MAM,LVQs and BP (to handle R's print generic function). 69 | - other minor changes. 70 | 71 | --- 72 | 73 | Changes to nnlib2Rcpp version 0.1.10 (from 0.1.9) 74 | - NN method add_layer now accepts additional optional parameter (double) to be used by specific layer implementations (for example, BP layers interpret it is as the learning rate). More optional parameters may be added in future versions. 75 | - NN methods add_connection_set, connect_layers_at and fully_connect_layers_at now accept additional optional parameter (double) to be used by specific connection set implementations (for example, BP connection sets interpret it is as the learning rate). More optional parameters may be added in future versions. 76 | - includes nnlib2 v.0.2.6 (added functionality to directly get/set biases in layer processing elements (PE)). 77 | - changes in NN module to support get/set biases (added functions: set_biases_at, set_bias_at, get_biases_at, get_bias_at). 78 | - numbers specifying PE and connections in NN module functions now start from 0 (was 1, changed to agree with those shown when NN is printed. This affects functions: get_weight_at, set_weight_at and remove_single_connection). 79 | - other minor changes. 80 | 81 | --- 82 | 83 | Changes to nnlib2Rcpp version 0.1.11 (from 0.1.10) 84 | - modified handling of errors and warnings. 85 | - added method to module "NN" (get_misc_values_at) 86 | - added method to module "NN" (get_topology_info, returns data.frame with NN topology information). 87 | - added "softmax", "bp-hidden-softmax" and "bp-output-softmax" layer types (see https://github.com/VNNikolaidis/nnlib2Rcpp/issues/14) 88 | - added documentation describing the names of available NN components (NN_component_names.Rd). 89 | - added method to module "NN" (set_input_at (same as input_at)). 90 | - other minor changes. 91 | - (Note: v.0.1.11 was not released to CRAN) 92 | 93 | --- 94 | 95 | Changes to nnlib2Rcpp version 0.2.0 (from 0.1.11) 96 | - split additional_parts.h to several files (for less clutter when users create their components). 97 | - small run time performance improvements (less checks in dllist operations). 98 | - (bug fix) added call to input_function() in pe move_input_to_output(). This allows pass_through_layer to receive input from connections (and not just directly via set_input). 99 | - enabled NN's get_input_at() method for layers (there are issues in the way this is currently implemented, see code for "preview_current_input" method of pe c++ class). 100 | - added "set_weights_at" method to module "NN". 101 | - added aux_control component for calling R functions from the NN (Rcpp_aux_control_R.h [edit: now Rcpp_R_aux_control.h]). 102 | - added methods to module "NN" ("add_R_forwarding", "add_R_pipelining", "add_R_ignoring" and "add_R_function"). These methods create NN components that can call an R function during NN processing (encoding or recalling data). 103 | - added options to Autoencoder function that allow to stop training when an acceptable error level has been reached. 104 | - added option to module "BP" (method "set_error_level") to stop training when an acceptable error level has been reached. 105 | - added to module "NN" methods "encode_all_fwd", "encode_all_bwd", "recall_all_fwd" and "recall_all_bwd". 106 | - other minor changes. 107 | 108 | --- 109 | 110 | Changes to nnlib2Rcpp version 0.2.1 (from 0.2.0) 111 | - (nnlib2) added class 'generic_connection_matrix', a matrix-based connection set that can be used to replace generic_connection_set (this is derived from connection_set, working draft, needs improvements, expect small run time performance gains). 112 | - (nnlib2) used generic_connection_matrix derived classes in BP and related neural nets. Note: Option #define BP_CONNECTIONS in 'nn_bp.cpp' selects whether bp_connection_set (based on 'generic_connection_set') or bp_connection_matrix (based on generic_connection_matrix) is to be used. 113 | - added example_connection_matrix (example that creates a matrix-based connection set to be used in NN module via its add_connection_set). 114 | - Rcpp_aux_control_R.h was renamed to Rcpp_R_aux_control.h. 115 | - modified "add_connection_set" method of module "NN" to also accept a list (R object) containing the parameters. This also allows for user-defined parameters to be passed when creating new connection sets. 116 | - modified "connect_layers_at" and "fully_connect_layers_at" methods of module "NN" to also accept a list (R object) containing the parameters for creating the new connection set. This also allows for user-defined parameters to be passed when creating new layers. 117 | - modified "add_layer" method of module "NN" to also accept a list (R object) containing the parameters. This also allows for user-defined parameters to be passed when creating new layers. 118 | - added 'R-connections' (C++ class 'R_connection_matrix'), a matrix-based connection_set type that calls R functions when encoding/recalling (file Rcpp_R_layer.h). 119 | - added 'R-layer' (C++ class 'R_layer') a layer type that calls R functions when encoding/recalling (file Rcpp_R_connection_matrix.h). 120 | - added support and documentation (file NN-R-components.Rd) about using 'R-layer' and 'R-connections' in 'NN' module. 121 | - other minor changes. 122 | 123 | --- 124 | 125 | Changes to nnlib2Rcpp version 0.2.2 (from 0.2.1) 126 | - minor corrections and changes in documentation. 127 | - added 'display_rate' parameter to Autoencoder function (controls or limits display of current error when training). 128 | - added 'mute' method to 'BP' module (enables/disables display of current error when training). 129 | 130 | --- 131 | 132 | Changes to nnlib2Rcpp version 0.2.3 (from 0.2.2) 133 | - minor change in documentation (nnlib2Rcpp.Rd, as suggested by Kurt Hornik) 134 | 135 | --- 136 | 137 | Changes to nnlib2Rcpp version 0.2.4 (from 0.2.3) 138 | - minor corrections in documentation (NN-R-components.Rd) 139 | - in documentation, file examples which employ the matrix multiplication operator (%*%), the percent symbol is replaced by backslash-percent so that these examples appear correctly in the help viewer. 140 | - in documentation, changed all files to eliminate "Unnecessary braces" notes when tools::checkRd() is used. 141 | 142 | --- 143 | 144 | Changes to nnlib2Rcpp version 0.2.5 (from 0.2.4) 145 | - added example in NN documentation (NN-class.Rd). 146 | - changes resulting from discussion in [this issue](https://github.com/VNNikolaidis/nnlib2Rcpp/issues/16): 147 | - added get_weights, set_weights methods to LVQs (allows access to codebook vectors). 148 | - added set_number_of_nodes_per_class method to LVQs (allows multiple output nodes (i.e codebook vectors) per class in the training data). 149 | - added get_number_of_nodes_per_class method to LVQs (returns number of output nodes that are used per class). 150 | - added get_number_of_rewards method to LVQs (counts number of times each output node was positively reinforced). 151 | - added setup method to LVQs (allows setting up an untrained supervised LVQ). 152 | - added enable_punishment, disable_punishment methods to LVQs (enable/disable negative reinforcement). 153 | - other minor changes. 154 | 155 | --- 156 | 157 | Changes to nnlib2Rcpp version 0.2.6 (from 0.2.5) 158 | - changes to LVQs (and related lvq_nn, lvq_connection_set classes) to make it more fit for use on real data: allow lvq_nn getting and setting limits for weight values, define training coefficients etc. 159 | - added related methods to LVQs (set_weight_limits, set_encoding_coefficients). 160 | - removed directive (usepackage[english]{babel}) from vignette file ('intro.ltx'). 161 | - added train_single method (encodes a single [data vector,class] pair). Used in combination with set_encoding_coefficients, allows allowing different training coefficients (reward, punish) per class (this may be useful in highly unbalanced class problems). 162 | - added option to LVQs recall (classify) data ignoring nodes that had less than a number of rewards received during encoding. 163 | - changed LVQs examples. 164 | - other minor changes. 165 | 166 | --- 167 | 168 | Changes to nnlib2Rcpp version 0.2.7 (from 0.2.6) 169 | - minor change to eliminate Valgrind issue (detected uninitialized value when a new LVQs is created). Fixed, does not affect functionality. 170 | 171 | --- 172 | 173 | Changes to nnlib2Rcpp version 0.2.8 (from 0.2.7) 174 | - minor change in documentation of LVQ, explaining why data should be in 0 to 1 range if random values in [0 1] are used for initial weights. 175 | - added (due to recent supervised LVQ popularity) two LVQs wrapper functions to simplify using LVQs (functions LVQs_train, LVQs_recall). 176 | 177 | --- 178 | 179 | Changes to nnlib2Rcpp version 0.2.9 (from 0.2.8) 180 | - minor changes in documentation of supervised LVQ (LVQs) helper functions. 181 | - support importing a set of codebook vectors in LVQs_train function (to continue training from previous LVQs_train invocations, use custom initial weights etc). 182 | 183 | --- 184 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: nnlib2Rcpp 2 | Type: Package 3 | Title: A Tool for Creating Custom Neural Networks in C++ and using Them in R 4 | Version: 0.2.9 5 | Author: Vasilis Nikolaidis [aut, cph, cre] () 6 | Maintainer: Vasilis Nikolaidis 7 | Description: Contains a module to define neural networks from custom components and versions of Autoencoder, BP, LVQ, MAM NN. 8 | LinkingTo: Rcpp 9 | Imports: Rcpp , methods, graphics, utils, class 10 | License: MIT + file LICENSE 11 | Authors@R: person(given = "Vasilis", family = "Nikolaidis", email = "v.nikolaidis@uop.gr", role = c("aut", "cph", "cre"), comment = c(ORCID = "0000-0003-1471-8788")) 12 | URL: https://github.com/VNNikolaidis/nnlib2Rcpp 13 | BugReports: https://github.com/VNNikolaidis/nnlib2Rcpp/issues 14 | Encoding: UTF-8 15 | Suggests: R.rsp 16 | VignetteBuilder: R.rsp 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2020 2 | COPYRIGHT HOLDER: Vasilis N. Nikolaidis 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This code is under MIT licence. 2 | 3 | Copyright (c) 2020 Vasilis N. Nikolaidis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | exportPattern("^[[:alpha:]]+") 2 | useDynLib(nnlib2Rcpp) 3 | importFrom(Rcpp, sourceCpp) 4 | importFrom(methods, new) 5 | importFrom("graphics", "points") 6 | importFrom("utils", "capture.output") 7 | importFrom("class", "knn") 8 | -------------------------------------------------------------------------------- /R/NNClasses.R: -------------------------------------------------------------------------------- 1 | BP <- Rcpp::setRcppClass("BP") 2 | LVQs <- Rcpp::setRcppClass("LVQs") 3 | MAM <- Rcpp::setRcppClass("MAM") 4 | NN <- Rcpp::setRcppClass("NN") 5 | -------------------------------------------------------------------------------- /R/RcppExports.R: -------------------------------------------------------------------------------- 1 | # Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | Autoencoder <- function(data_in, desired_new_dimension, number_of_training_epochs, learning_rate, num_hidden_layers = 1L, hidden_layer_size = 5L, show_nn = FALSE, error_type = "MAE", acceptable_error_level = 0, display_rate = 1000L) { 5 | .Call('_nnlib2Rcpp_Autoencoder', PACKAGE = 'nnlib2Rcpp', data_in, desired_new_dimension, number_of_training_epochs, learning_rate, num_hidden_layers, hidden_layer_size, show_nn, error_type, acceptable_error_level, display_rate) 6 | } 7 | 8 | LVQu <- function(data, max_number_of_desired_clusters, number_of_training_epochs, neighborhood_size = 1L, show_nn = FALSE) { 9 | .Call('_nnlib2Rcpp_LVQu', PACKAGE = 'nnlib2Rcpp', data, max_number_of_desired_clusters, number_of_training_epochs, neighborhood_size, show_nn) 10 | } 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nnlib2Rcpp 2 | An R package providing access to Neural Networks created using nnlib2. 3 | 4 | --- 5 | 6 | A tool for creating custom neural networks in C++ and using them in R. The Artificial Neural Networks (ANN), also called Artificial Neural Systems (ANS) or simply Neural Networks (NN) are created using the 'nnlib2' C++ library. 7 | 8 | Currently also includes predefined versions of BP, Autoencoder, MAM, LVQ (supervised and unsupervised). 9 | 10 | All NNs are created using 'nnlib2' (a C++ library of classes for implementing NNs) and interfaced with R via RCpp. 11 | 12 | The package also provides the NN R module (Class "NN") which allows creation and control of custom NNs configurations and topologies from R. These NNs consist of components (predefined or user-defined) usually defined via 'nnlib2'. To add new user-defined NN components (layers, nodes, connections, sets of connections etc) to the package see the "NN" component documentation (type ?NN in R). Note: defining components via 'nnlib2' requires some familiarity with C++. 13 | 14 | --- 15 | 16 | To install: 17 | 18 | (a) From CRAN Repository (recommended): The CRAN (stable) version of this package can be installed the usual way, i.e. by invoking the following R command: 19 | 20 | install.packages("nnlib2Rcpp") 21 | 22 | (b) From GitHub: To add the GitHub (latest) version of this package to your R installation, use the following R commands: 23 | 24 | library(devtools) 25 | install_github("VNNikolaidis/nnlib2Rcpp") 26 | 27 | (c) From r-universe: To add the package (corresponding to the latest GitHub release version) to your R installation, use the following R command: 28 | 29 | install.packages('nnlib2Rcpp', repos = 'https://vnnikolaidis.r-universe.dev') 30 | 31 | Once installed, for package help (including documentation and examples for each function or class provided by nnlib2Rcpp) use the following R command: 32 | 33 | help(package='nnlib2Rcpp') 34 | 35 | while the package vignette (containing information on adding custom components) can be viewed using the following R command: 36 | 37 | vignette("intro", package='nnlib2Rcpp') 38 | 39 | The package vignette is also available in PDF format here: 40 | 41 | https://github.com/VNNikolaidis/nnlib2Rcpp/blob/master/support/manual.pdf 42 | 43 | A reference manual in PDF format (for the last version in CRAN) can be found here: 44 | 45 | https://cran.r-project.org/web/packages/nnlib2Rcpp/nnlib2Rcpp.pdf 46 | 47 | --- 48 | 49 | For information on citing this package use the following R command: 50 | 51 | citation("nnlib2Rcpp") 52 | 53 | --- 54 | 55 | For copyright information see LICENSE.md file or DESCRIPTION+LICENSE files (as imposed by package format for CRAN submissions). 56 | 57 | --- 58 | 59 | The ‘nnlib2’ library used (and included) in this package is a collection of C++ base classes and templates for creating NNs. This library is also available as a standalone project, in GitHub repository (https://github.com/VNNikolaidis/nnlib2). For a (simplified) class-diagram of significant nnlib2 classes and templates see: https://github.com/VNNikolaidis/nnlib2/blob/master/misc/diagram%20of%20main%20classes.png 60 | 61 | For implementing new NN components and models in nnlib2 that can be used in nnlib2Rcpp, see also: 62 | 63 | https://r-posts.com/creating-custom-neural-networks-with-nnlib2rcpp/ ( permalink: https://wp.me/p8rgs6-sh ) 64 | 65 | Instructions on using 'nnlib2' and 'nnlib2Rcpp' can also be found in the package vingette, also available in PDF format here: 66 | 67 | https://github.com/VNNikolaidis/nnlib2Rcpp/blob/master/support/manual.pdf 68 | 69 | Link to related paper in the Journal of Open Source Software: 70 | 71 | [![DOI](https://joss.theoj.org/papers/10.21105/joss.02876/status.svg)](https://doi.org/10.21105/joss.02876) 72 | 73 | --- 74 | 75 | Future goals for this project (iF AND WHEN time permits) include: 76 | 77 | - implement additional neural network components and models using 'nnlib2' classes and templates (and thus new neural network components compatible with "NN" module in nnlib2Rcpp). 78 | - create a library of 'classic' neural network components and models. 79 | - add parallelism to ‘nnlib2’ component base classes (possibly via OpenMP, CUDA etc.). 80 | - replace custom data structures in 'nnlib2' with STL containers. 81 | - add support for package 'nn2poly' (https://arxiv.org/pdf/2406.01588) 82 | to the package. 83 | - other performance enhancements. 84 | 85 | Let us know if interested to contribute. 86 | 87 | --- 88 | 89 | We invite anyone to contribute to this software and/or provide feedback, suggestions, report issues or problems. 90 | 91 | To contact us, please use the issues option in GitHub or email (vnnikolaidis AT gmail.com). 92 | 93 | --- 94 | 95 | [![](https://cranlogs.r-pkg.org/badges/nnlib2Rcpp)](https://cran.r-project.org/package=nnlib2Rcpp) 96 | [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4780957.svg)](https://doi.org/10.5281/zenodo.4780957) 97 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | bibentry( 2 | bibtype = "Article", 3 | title = "The nnlib2 library and nnlib2Rcpp R package for implementing neural networks", 4 | author = as.person("Vasilios N. Nikolaidis [aut]"), 5 | journal = "Journal of Open Source Software", 6 | volume = "6", 7 | number = "61", 8 | pages = "2876", 9 | year = "2021", 10 | publisher = "The Open Journal", 11 | doi = "10.21105/joss.02876", 12 | ) 13 | 14 | textVersion = "Nikolaidis, V. N., (2021). The nnlib2 library and nnlib2Rcpp R package for implementing neural networks. Journal of Open Source Software, 6(61), 2876, https://doi.org/10.21105/joss.02876" 15 | -------------------------------------------------------------------------------- /man/Autoencoder.Rd: -------------------------------------------------------------------------------- 1 | \name{Autoencoder} 2 | \alias{Autoencoder} 3 | %- Also NEED an '\alias' for EACH other topic documented here. 4 | \title{ 5 | Autoencoder NN 6 | } 7 | \description{ 8 | A neural network for autoencoding data, projects data to a new set of variables. 9 | } 10 | \usage{ 11 | Autoencoder( 12 | data_in, 13 | desired_new_dimension, 14 | number_of_training_epochs, 15 | learning_rate, 16 | num_hidden_layers = 1L, 17 | hidden_layer_size = 5L, 18 | show_nn = FALSE, 19 | error_type = "MAE", 20 | acceptable_error_level = 0, 21 | display_rate = 1000) 22 | } 23 | %- maybe also 'usage' for other objects documented here. 24 | \arguments{ 25 | \item{data_in}{ 26 | data to be autoencoded, a numeric matrix, (2d, cases in rows, variables in columns). It is recommended to be in [0 1] range. 27 | } 28 | \item{desired_new_dimension}{ 29 | number of new variables to be produced. This is effectively the size (length) of the special hidden layer that outputs the new variable values, thus the dimension of the output vector space. 30 | } 31 | \item{number_of_training_epochs}{ 32 | number of training epochs, aka presentations of all training data to ANN during training. 33 | } 34 | \item{learning_rate}{ 35 | the learning rate parameter of the Back-Propagation (BP) NN. 36 | } 37 | \item{num_hidden_layers}{ 38 | number of hidden layers on each side of the special layer. 39 | } 40 | \item{hidden_layer_size}{number of nodes (processing elements or PEs) in each of the hidden layers. In this implementation of Autoencoder all hidden layers are of the same length (defined here), except for the special hidden layer (whose size is defined by \code{desired_new_dimension} above).} 41 | 42 | \item{show_nn}{boolean, option to display the (trained) ANN internal structure.} 43 | 44 | \item{error_type}{string, error to display and possibly use to stop training (must be 'MSE' or 'MAE').} 45 | 46 | \item{acceptable_error_level}{stops training when error is below this level.} 47 | 48 | \item{display_rate}{number of epochs that pass before current error level is displayed (0 = never display current error).} 49 | } 50 | 51 | \value{ 52 | Returns a numeric matrix containing the projected data. 53 | } 54 | \references{ 55 | Nikolaidis V.N., Makris I.A, Stavroyiannis S, "ANS-based preprocessing of company performance indicators." Global Business and Economics Review 15.1 (2013): 49-58. 56 | } 57 | \author{ 58 | Vasilis N. Nikolaidis 59 | } 60 | \note{ 61 | This Autoencoder NN employs a \code{\link{BP}}-type NN to perform a data pre-processing step baring similarities to PCA since it too can be used for dimensionality reduction (Kramer 1991)(DeMers and Cottrell 1993)(Hinton and Salakhutdinov 2006). Unlike PCA, an autoencoding NN can also expand the feature-space dimensions (as feature expansion methods do). The NN maps input vectors to themselves via a special hidden layer (the coding layer, usually of different size than the input vector length) from which the new data vectors are produced. Note: 62 | The internal BP PEs in computing layers apply the logistic sigmoid threshold function, and their output is in [0 1] range. It is recommended to use this range in your data as well. More for this particular autoencoder implementation can be found in (Nikolaidis, Makris, and Stavroyiannis 2013). The method is not deterministic and the mappings may be non-linear, depending on the NN topology. 63 | 64 | (This function uses Rcpp to employ 'bpu_autoencoder_nn' class in nnlib2.) 65 | } 66 | 67 | %% ~Make other sections like Warning with \section{Warning }{....} ~ 68 | \seealso{\code{\link{BP}}.} 69 | \examples{ 70 | iris_s <- as.matrix(scale(iris[1:4])) 71 | output_dim <- 2 72 | epochs <- 100 73 | learning_rate <- 0.73 74 | num_hidden_layers <-2 75 | hidden_layer_size <- 5 76 | 77 | out_data <- Autoencoder( iris_s, output_dim, 78 | epochs, learning_rate, 79 | num_hidden_layers, hidden_layer_size, FALSE) 80 | 81 | plot( out_data,pch=21, 82 | bg=c("red","green3","blue")[unclass(iris$Species)], 83 | main="Randomly autoencoded Iris data") 84 | } 85 | % Add one or more standard keywords, see file 'KEYWORDS' in the 86 | % R documentation directory. 87 | \keyword{ neural }% use one of RShowDoc("KEYWORDS") 88 | -------------------------------------------------------------------------------- /man/BP-class.Rd: -------------------------------------------------------------------------------- 1 | \name{BP-class} 2 | \Rdversion{1.1} 3 | \docType{class} 4 | \alias{BP-class} 5 | \alias{BP} 6 | \alias{Rcpp_BP} 7 | \alias{Rcpp_BP-class} 8 | 9 | \title{Class \code{"BP"}} 10 | \description{ 11 | Supervised Back-Propagation (BP) NN module, for encoding input-output mappings. 12 | } 13 | \section{Extends}{ 14 | Class \code{"\linkS4class{RcppClass}"}, directly. 15 | 16 | All reference classes extend and inherit methods from \code{"\linkS4class{envRefClass}"}. 17 | 18 | } 19 | \references{ 20 | Simpson, P. K. (1991). Artificial neural systems: Foundations, paradigms, applications, and implementations. New York: Pergamon Press. 21 | } 22 | \author{ 23 | Vasilis N. Nikolaidis 24 | } 25 | \note{ 26 | This R module maintains an internal Back-Propagation (BP) multilayer perceptron NN (described in Simpson (1991) as the vanilla back-propagation algorithm), which can be used to store input-output vector pairs. Since the nodes (PEs) in computing layers of this BP implementation apply the logistic sigmoid threshold function, their output is in [0 1] range (and so should the desired output vector values). 27 | 28 | (This object uses Rcpp to employ 'bp_nn' class in nnlib2.)} 29 | 30 | %% ~Make other sections like Warning with \section{Warning }{....} ~ 31 | 32 | \seealso{\code{\link{Autoencoder}}.} 33 | 34 | \examples{ 35 | # create some data... 36 | iris_s <- as.matrix(scale(iris[1:4])) 37 | 38 | # use a randomly picked subset of (scaled) iris data for training. 39 | training_cases <- sample(1:nrow(iris_s), nrow(iris_s)/2,replace=FALSE) 40 | train_set <- iris_s[training_cases,] 41 | train_class_ids <- as.integer(iris$Species[training_cases]) 42 | train_num_cases <- nrow(train_set) 43 | train_num_variables <- ncol(train_set) 44 | train_num_classes <- max(train_class_ids) 45 | 46 | # create output dataset to be used for training. 47 | # Here we encode class as 0s and 1s (one-hot encoding). 48 | 49 | train_set_data_out <- matrix( 50 | data = 0, 51 | nrow = train_num_cases, 52 | ncol = train_num_classes) 53 | 54 | # now for each case, assign a 1 to the column corresponding to its class, 0 otherwise 55 | # (note: there are better R ways to do this in R) 56 | for(r in 1:train_num_cases) train_set_data_out[r,train_class_ids[r]]=1 57 | 58 | # done with data, let's use BP... 59 | bp<-new("BP") 60 | 61 | bp$encode(train_set,train_set_data_out,0.8,10000,2,4) 62 | 63 | # let's test by recalling the original training set... 64 | bp_output <- bp$recall(train_set) 65 | 66 | cat("- Using this demo's encoding, recalled class is:\n") 67 | print(apply(bp_output,1,which.max)) 68 | cat("- BP success in recalling correct class is: ", 69 | sum(apply(bp_output,1,which.max)==train_class_ids)," out of ", 70 | train_num_cases, "\n") 71 | 72 | # Let's see how well it recalls the entire Iris set: 73 | bp_output <- bp$recall(iris_s) 74 | 75 | # show output 76 | cat("\n- Recalling entire Iris set returns:\n") 77 | print(bp_output) 78 | cat("- Using this demo's encoding, original class is:\n") 79 | print(as.integer(iris$Species)) 80 | cat("- Using this demo's encoding, recalled class is:\n") 81 | bp_classification <- apply(bp_output,1,which.max) 82 | print(bp_classification) 83 | cat("- BP success in recalling correct class is: ", 84 | sum(apply(bp_output,1,which.max)==as.integer(iris$Species)), 85 | "out of ", nrow(iris_s), "\n") 86 | plot(iris_s, pch=bp_classification, main="Iris classified by a partialy trained BP (module)") 87 | } 88 | \keyword{classes} 89 | \section{Fields}{ 90 | \describe{ 91 | \item{\code{.CppObject}:}{Object of class \code{C++Object} ~~ } 92 | \item{\code{.CppClassDef}:}{Object of class \code{activeBindingFunction} ~~ } 93 | \item{\code{.CppGenerator}:}{Object of class \code{activeBindingFunction} ~~ } 94 | } 95 | } 96 | \section{Methods}{ 97 | \describe{ 98 | 99 | \item{\code{encode( data_in, data_out, learning_rate, training_epochs, hidden_layers, hidden_layer_size )}:}{ Setup a new BP NN and encode input-output data pairs. Parameters are: 100 | \itemize{ 101 | \item\code{data_in}: numeric matrix, containing input vectors as rows. . It is recommended that these values are in 0 to 1 range. 102 | \item\code{data_out}: numeric matrix, containing corresponding (desired) output vectors. It is recommended that these values are in 0 to 1 range. 103 | \item\code{learning_rate}: a number (preferably greater than 0 and less than 1) used in training. 104 | \item\code{training_epochs}: number of training epochs, aka single presentation iterations of all training data pairs to the NN during training. 105 | \item\code{hidden_layers}: number of hidden layers to be created between input and output layers. 106 | \item\code{hidden_layer_size}: number of nodes (processing elements or PEs) in each of the hidden layers (all hidden layers are of the same length in this implementation of BP). 107 | } 108 | Note: to encode additional input-output vector pairs in an existing BP, use \code{train_single} or \code{train_multiple} methods (see below). 109 | } 110 | 111 | \item{\code{recall(data_in)}:}{ Get output for a dataset (numeric matrix \code{data_in}) from the (trained) BP NN. } 112 | 113 | \item{\code{setup(input_dim, output_dim, learning_rate, hidden_layers, hidden_layer_size)}:}{ Setup the BP NN so it can be trained and used. Note: this is not needed if using \code{encode}. Parameters are: 114 | \itemize{ 115 | \item\code{input_dim}: integer length of input vectors. 116 | \item\code{output_dim}: integer length of output vectors. 117 | \item\code{learning_rate}: a number (preferably greater than 0 and less than 1) used in training. 118 | \item\code{hidden_layers}: number of hidden layers to be created between input and output layers. 119 | \item\code{hidden_layer_size}: number of nodes (processing elements or PEs) in each of the hidden layers (all hidden layers are of the same length in this implementation of BP). 120 | } 121 | } 122 | 123 | \item{\code{train_single (data_in, data_out)}:}{ Encode an input-output vector pair in the BP NN. Only performs a single training iteration (multiple may be required for proper encoding). Vector sizes should be compatible to the current NN (as resulted from the \code{encode} or \code{setup} methods). Returns error level indicator value.} 124 | 125 | \item{\code{train_multiple (data_in, data_out, training_epochs)}:}{ Encode multiple input-output vector pairs stored in corresponding datasets. Performs multiple iterations in epochs (see \code{encode}). Vector sizes should be compatible to the current NN (as resulted from the \code{encode} or \code{setup} methods). Returns error level indicator value.} 126 | 127 | 128 | \item{\code{set_error_level(error_type, acceptable_error_level)}:}{ Set options that stop training when an acceptable error level has been reached (when a subsequent \code{encode} or \code{train_multiple} is performed). Parameters are: 129 | \itemize{ 130 | \item\code{error_type}: string, error type to display and use to stop training (must be 'MSE' or 'MAE'). 131 | \item\code{acceptable_error_level}: training stops when error is below this level. 132 | } 133 | } 134 | 135 | \item{\code{mute(on)}:}{ Disable output of current error level when training (if parameter \code{on} is TRUE). } 136 | 137 | \item{\code{print()}:}{ Print NN structure. } 138 | 139 | \item{\code{show()}:}{ Print NN structure. } 140 | 141 | \item{\code{load(filename)}:}{ Retrieve the NN from specified file. } 142 | 143 | \item{\code{save(filename)}:}{ Save the NN to specified file. } 144 | } 145 | 146 | The following methods are inherited (from the corresponding class): 147 | objectPointer ("RcppClass"), initialize ("RcppClass"), show ("RcppClass") 148 | } 149 | -------------------------------------------------------------------------------- /man/LVQs_recall.Rd: -------------------------------------------------------------------------------- 1 | \name{LVQs_recall} 2 | \alias{LVQs_recall} 3 | %- Also NEED an '\alias' for EACH other topic documented here. 4 | \title{ 5 | LVQs Helper Function: Classify Data Using Supervised LVQ Code-Book Vectors 6 | } 7 | \description{ 8 | This function simplifies using a Supervised Learning Vector Quantizer Neural Network on data (as compared to using the \code{\link{LVQs}} module directly). It employs the codebook vector information returned by \code{\link{LVQs_train}} to assign data to classes. 9 | } 10 | \usage{ 11 | LVQs_recall(codebook_info, 12 | data, 13 | k = 1, 14 | recall_rewards_limit = 1, 15 | verbose = FALSE, 16 | ...) 17 | } 18 | %- maybe also 'usage' for other objects documented here. 19 | \arguments{ 20 | \item{codebook_info}{ 21 | LVQ codebook vector information (as returned by \code{\link{LVQs_train}}). 22 | } 23 | \item{data}{ 24 | data to be classified, numeric matrix (2d, cases in rows, variables in columns). 25 | } 26 | \item{k}{ 27 | number of neighbours (codebook vectors) considered. See \code{help("knn",package = class)}. 28 | } 29 | 30 | \item{recall_rewards_limit}{ 31 | do not use codebook vectors that were rewarded less that this limit during training. 32 | } 33 | \item{verbose}{ 34 | show extra information and plots. 35 | } 36 | \item{\dots}{ 37 | additional parameters for k-Nearest Neighbour Classification function (\code{class::knn}), see \code{help("knn",package = class)}. 38 | } 39 | } 40 | \details{ 41 | This is a k-Nearest Neighbor Classifier (employs \code{class::knn}), customized for LVQs codebook vectors and related information returned by \code{\link{LVQs_train}} function. 42 | } 43 | \value{ 44 | Factor of classifications ids for \code{data} (as returned by function \code{class::knn}, see \code{help("knn",package = class)}). 45 | } 46 | \references{ 47 | Simpson, P. K. (1991). Artificial neural systems: Foundations, paradigms, applications, and implementations. New York: Pergamon Press. p.88. 48 | 49 | Venables, W. N. & Ripley, B. D. (2002) Modern Applied Statistics with S. 50 | Fourth Edition. Springer, New York. ISBN 0-387-95457-0 51 | } 52 | \author{ 53 | Vasilis N. Nikolaidis 54 | } 55 | \seealso{ 56 | \code{\link{LVQs_train}}, \code{\link{LVQs}}. 57 | } 58 | \examples{ 59 | # start with the well-know iris dataset: 60 | 61 | DATA <- iris[,1:4] 62 | CLASS <- as.factor(iris$Species) 63 | 64 | # Randomly split the data into training and testing sets: 65 | 66 | indices <- sample(1:nrow(DATA), size = .5 * nrow(DATA)) 67 | 68 | train_data <- DATA[indices, ] 69 | train_class <- CLASS[indices] 70 | 71 | test_data <- DATA[-indices, ] 72 | test_class <- CLASS[-indices] 73 | 74 | # train LVQ using train data and class: 75 | 76 | cv <- LVQs_train(train_data, 77 | train_class, 78 | number_of_output_nodes_per_class = 4) 79 | 80 | # recall (classify) test data: 81 | 82 | cl <- LVQs_recall(cv, test_data) 83 | 84 | # Compare known and returned test data classifications: 85 | 86 | print(table(test_class, cl)) 87 | } 88 | 89 | -------------------------------------------------------------------------------- /man/LVQs_train.Rd: -------------------------------------------------------------------------------- 1 | \name{LVQs_train} 2 | \alias{LVQs_train} 3 | 4 | \title{ 5 | LVQs Helper Function: Train a Supervised LVQ 6 | } 7 | \description{ 8 | This function simplifies using a Supervised Learning Vector Quantizer Neural Network on data (as compared to using the \code{\link{LVQs}} module directly). It trains a supervised Learning Vector Quantizer Neural Network (\code{\link{LVQs}}). Once the NN is trained, the function returns a matrix containing codebook vectors and related information. This matrix can then be used by \code{\link{LVQs_recall}} to classify data. 9 | } 10 | \usage{ 11 | LVQs_train( train_data, 12 | train_class, 13 | iterations = 1000, 14 | number_of_output_nodes_per_class = 1, 15 | reward_coef = +0.2, 16 | punish_coef = -0.2, 17 | training_order = "reorder_once", 18 | initialization_method = "sample", 19 | recall_train_data = FALSE, 20 | initial_codebook_vectors = NULL 21 | ) 22 | } 23 | 24 | \arguments{ 25 | \item{train_data}{ 26 | training data, numeric matrix (2d, cases in rows, variables in columns). 27 | } 28 | \item{train_class}{ 29 | vector of integers or factor containing the desired class id for each training data case (row). Expected ids start from 1. Number of classes is assumed to be equal to the maximum class id found here. 30 | } 31 | \item{iterations}{ 32 | integer, number of training epochs, i.e. number of times the entire training data set will be presented to the NN during training. Maximum allowed is 10000. 33 | } 34 | \item{number_of_output_nodes_per_class}{ 35 | integer, number of output nodes (and thus codebook vectors) to be used per class. A single value is expected, all classes are assigned this (same) number of output nodes. 36 | } 37 | \item{reward_coef}{ 38 | coefficient used when a output node (and thus codebook vector) is rewarded (has been correctly selected when a training data vector is encoded) and is adjusted closer to the data. For more, see \code{set_encoding_coefficients} method of \code{\link{LVQs}} 39 | } 40 | \item{punish_coef}{ 41 | coefficient used when a output node (and thus codebook vector) is punished (has been incorrectly selected when a training data vector is encoded) and is adjusted away from the data. For more, see \code{set_encoding_coefficients} method of \code{\link{LVQs}} 42 | } 43 | \item{training_order}{ 44 | order by which the data set vectors will be presented to LVQs for encoding during each training iteration (epoch). Options are: \code{'original'} (vectors are presented in the order in which they are stored, i.e. first row to last), \code{'reorder_once'} (vectors are randomly reordered once, then presented in this same order in all iterations), and \code{'reorder'} (vectors are randomly reordered before each iteration). 45 | } 46 | 47 | \item{initialization_method}{ 48 | defines how the connections weights (codebook vectors) will be initialized. Options are: \code{'0to1'} (random values in [0 1] range, note: internal training data will also be scaled to the same range), \code{'means'} codebook vectors will be the corresponding class's mean vector), \code{'first'} (the first data vector(s) of each class will be used as initial codebook vector(s), randomly re-selected if not enough are available), \code{'sample'} (randomly selected data vectors of each class will be used as initial codebook vectors, with replacement if not enough are available), and \code{'user-defined'} (weights specified in parameter \code{initial_codebook_vectors} are used to initialize the LVQ). 49 | } 50 | 51 | \item{recall_train_data}{ 52 | once training completes, recall the training data and show accuracy and confusion matrix. 53 | } 54 | 55 | \item{initial_codebook_vectors}{ 56 | a matrix of codebook vectors to be used as initial weight values when \code{initialization_method} parameter is set to \code{'user-defined'} (see above). Must have the same number of columns as \code{train_data} and sufficient codebook vectors (rows) to initialize all connections (i.e. number of classes found in \code{train_class} * \code{number_of_output_nodes_per_class}). Note: the matrix returned by a previous invocation of \code{LVQs_train} can be used here, excluding its last two columns (those named \code{'Rewards'} and \code{'Class'}). 57 | } 58 | } 59 | 60 | \details{ 61 | This is a wrapper function which internally employs an instance of the \code{\link{LVQs}} module. For more details, see \code{\link{LVQs}}. 62 | } 63 | \value{ 64 | A numeric matrix containing the codebook vector coordinates, the number of times each vector was rewarded during encoding (second from last column named \code{'Rewards'}, ) and the class it corresponds to (last column, named \code{'Class'}). This matrix can be used by \code{\link{LVQs_recall}} function to classify other data. 65 | } 66 | \references{ 67 | Simpson, P. K. (1991). Artificial neural systems: Foundations, paradigms, applications, and implementations. New York: Pergamon Press. p.88. 68 | } 69 | \author{ 70 | Vasilis N. Nikolaidis 71 | } 72 | \seealso{ 73 | \code{\link{LVQs_recall}}, \code{\link{LVQs}}. 74 | } 75 | \examples{ 76 | # start with the well-know iris dataset: 77 | 78 | DATA <- iris[,1:4] 79 | CLASS <- as.factor(iris$Species) 80 | 81 | # Randomly split the data into training and testing sets: 82 | 83 | indices <- sample(1:nrow(DATA), size = .5 * nrow(DATA)) 84 | 85 | train_data <- DATA[indices, ] 86 | train_class <- CLASS[indices] 87 | 88 | test_data <- DATA[-indices, ] 89 | test_class <- CLASS[-indices] 90 | 91 | # train LVQ using train data and class: 92 | 93 | cvi <- LVQs_train(train_data, 94 | train_class, 95 | number_of_output_nodes_per_class = 4) 96 | 97 | # recall (classify) test data: 98 | 99 | cl <- LVQs_recall(cvi, test_data) 100 | 101 | # Compare known and returned test data classifications: 102 | 103 | print(table(test_class, cl)) 104 | } 105 | 106 | -------------------------------------------------------------------------------- /man/LVQu.Rd: -------------------------------------------------------------------------------- 1 | \name{LVQu} 2 | \alias{LVQu} 3 | \alias{SOM} 4 | 5 | %- Also NEED an '\alias' for EACH other topic documented here. 6 | \title{ 7 | Unsupervised LVQ 8 | } 9 | \description{ 10 | Unsupervised (clustering) Learning Vector Quantization (LVQ) NN. 11 | } 12 | \usage{ 13 | LVQu( 14 | data, 15 | max_number_of_desired_clusters, 16 | number_of_training_epochs, 17 | neighborhood_size, 18 | show_nn ) 19 | } 20 | %- maybe also 'usage' for other objects documented here. 21 | \arguments{ 22 | \item{data}{ 23 | data to be clustered, a numeric matrix, (2d, cases in rows, variables in columns). By default, initial weights are set to random values in [0 1], so data should also be in 0 to 1 range. 24 | } 25 | \item{max_number_of_desired_clusters}{ 26 | clusters to be produced (at most) 27 | } 28 | \item{number_of_training_epochs}{ 29 | number of training epochs, aka presentations of all training data to ANN during training. 30 | } 31 | \item{neighborhood_size}{ 32 | integer >=1, specifies affected neighbor output nodes during training. if 1 (Single Winner) the ANN is somewhat similar to k-means. 33 | } 34 | \item{show_nn}{ 35 | boolean, option to display the (trained) ANN internal structure. 36 | } 37 | } 38 | \value{ 39 | Returns a vector of integers containing a cluster id for each data case (row). 40 | } 41 | \references{ 42 | Kohonen, T (1988). Self-Organization and Associative Memory, Springer-Verlag.; Simpson, P. K. (1991). Artificial neural systems: Foundations, paradigms, applications, and implementations. New York: Pergamon Press. 43 | 44 | Philippidis, TP & Nikolaidis, VN & Kolaxis, JG. (1999). Unsupervised pattern recognition techniques for the prediction of composite failure. Journal of acoustic emission. 17. 69-81. 45 | } 46 | \author{ 47 | Vasilis N. Nikolaidis 48 | } 49 | \note{ 50 | Function LVQu employs an unsupervised LVQ for clustering data (Kohonen 1988). This LVQ variant is described as Unsupervised Learning LVQ in Simpson (1991) and is a simplified 1-D version of Self-Organizing-Map (SOM). Its parameter \code{neighborhood_size} controls the encoding mode (where \code{neighborhood_size}=1 is Single-Winner Unsupervised encoding, similar to k-means, while an odd valued \code{neighborhood_size} > 1 means Multiple-Winner Unsupervised encoding mode). Initial weights are random (uniform distribution) in 0 to 1 range. As these weights represent cluster center coordinates (the class reference vector), it is important that input data is also scaled to this range. 51 | 52 | (This function uses Rcpp to employ 'som_nn' class in nnlib2.) 53 | } 54 | \seealso{ 55 | \code{\link{LVQs}} (supervised LVQ module), 56 | } 57 | \examples{ 58 | # LVQ expects data in 0 to 1 range, so scale... 59 | iris_s<-as.matrix(iris[1:4]) 60 | c_min<-apply(iris_s,2,FUN = "min") 61 | c_max<-apply(iris_s,2,FUN = "max") 62 | c_rng<-c_max-c_min 63 | iris_s<-sweep(iris_s,2,FUN="-",c_min) 64 | iris_s<-sweep(iris_s,2,FUN="/",c_rng) 65 | 66 | cluster_ids<-LVQu(iris_s,5,100) 67 | plot(iris_s, pch=cluster_ids, main="LVQ-clustered Iris data") 68 | } 69 | % Add one or more standard keywords, see file 'KEYWORDS' in the 70 | % R documentation directory. 71 | \keyword{ classif }% use one of RShowDoc("KEYWORDS") 72 | \keyword{ neural }% __ONLY ONE__ keyword per line 73 | -------------------------------------------------------------------------------- /man/MAM-class.Rd: -------------------------------------------------------------------------------- 1 | \name{MAM-class} 2 | \Rdversion{1.1} 3 | \docType{class} 4 | \alias{MAM-class} 5 | \alias{MAM} 6 | \alias{Rcpp_MAM} 7 | \alias{Rcpp_MAM-class} 8 | 9 | \title{Class \code{"MAM"}} 10 | \description{ 11 | A single Matrix Associative Memory (MAM) implemented as a (supervised) NN. 12 | } 13 | \section{Extends}{ 14 | Class \code{"\linkS4class{RcppClass}"}, directly. 15 | 16 | All reference classes extend and inherit methods from \code{"\linkS4class{envRefClass}"}. 17 | } 18 | \references{ 19 | Pao Y (1989). Adaptive Pattern Recognition and Neural Networks. Reading, MA (US); Addison-Wesley Publishing Co., Inc. 20 | } 21 | \author{ 22 | Vasilis N. Nikolaidis 23 | } 24 | \note{ 25 | The NN in this module uses supervised training to store input-output vector pairs. 26 | 27 | (This function uses Rcpp to employ 'mam_nn' class in nnlib2.) 28 | } 29 | 30 | %% ~Make other sections like Warning with \section{Warning }{....} ~ 31 | 32 | \seealso{\code{\link{BP},\link{LVQs}}.} 33 | 34 | \examples{ 35 | iris_s <- as.matrix(scale(iris[1:4])) 36 | class_ids <- as.integer(iris$Species) 37 | num_classes <- max(class_ids) 38 | 39 | # create output dataset to be used for training, Here we encode class as -1s and 1s 40 | iris_data_out <- matrix( data = -1, nrow = nrow(iris_s), ncol = num_classes) 41 | 42 | # now for each case, assign a 1 to the column corresponding to its class 43 | for(r in 1:nrow(iris_data_out)) iris_data_out[r,class_ids[r]]=1 44 | 45 | # Finally apply MAM: 46 | # Encode train pairs in MAM and then get output dataset by recalling the test data. 47 | 48 | mam <- new("MAM") 49 | 50 | mam$encode(iris_s,iris_data_out) 51 | 52 | # test the encoding by recalling the original input data... 53 | mam_data_out <- mam$recall(iris_s) 54 | 55 | # find which MAM output has the largest value and use this as the final cluster tag. 56 | mam_recalled_cluster_ids = apply(mam_data_out,1,which.max) 57 | 58 | plot(iris_s, pch=mam_recalled_cluster_ids, main="MAM recalled Iris data classes") 59 | 60 | cat("MAM recalled these IDs:\n") 61 | print(mam_recalled_cluster_ids) 62 | } 63 | \keyword{classes} 64 | \section{Fields}{ 65 | \describe{ 66 | \item{\code{.CppObject}:}{Object of class \code{C++Object} ~~ } 67 | \item{\code{.CppClassDef}:}{Object of class \code{activeBindingFunction} ~~ } 68 | \item{\code{.CppGenerator}:}{Object of class \code{activeBindingFunction} ~~ } 69 | } 70 | } 71 | \section{Methods}{ 72 | \describe{ 73 | 74 | \item{\code{encode( data_in, data_out )}:}{ Setup a new MAM NN and encode input-output data pairs. Parameters are: 75 | \itemize{ 76 | \item\code{data_in}: numeric matrix, input data to be encoded in MAM, a numeric matrix (2d, of n rows). Each row will be paired to the corresponding data_out row, forming an input-output vector pair. 77 | \item\code{data_out}: numeric matrix, output data to be encoded in MAM, a numeric matrix (2d, also of n rows). Each row will be paired to the corresponding data_in row, forming an input-output vector pair. 78 | } 79 | Note: to encode additional input-output vector pairs in an existing MAM, use \code{train_single} method (see below). 80 | } 81 | 82 | \item{\code{recall(data)}:}{ Get output for a dataset (numeric matrix \code{data}) from the (trained) MAM NN. } 83 | 84 | \item{\code{train_single (data_in, data_out)}:}{ Encode an input-output vector pair in the MAM NN. Vector sizes should be compatible to the current NN (as resulted from the \code{encode} method).} 85 | 86 | \item{\code{print()}:}{ print NN structure. } 87 | 88 | \item{\code{show()}:}{ print NN structure. } 89 | 90 | \item{\code{load(filename)}:}{ retrieve the NN from specified file. } 91 | 92 | \item{\code{save(filename)}:}{ save the NN to specified file. } 93 | } 94 | 95 | The following methods are inherited (from the corresponding class): 96 | objectPointer ("RcppClass"), initialize ("RcppClass"), show ("RcppClass") 97 | } 98 | -------------------------------------------------------------------------------- /man/NN-components.Rd: -------------------------------------------------------------------------------- 1 | \name{NN_component_names} 2 | \alias{NN_component_names} 3 | 4 | \title{Names of available NN components} 5 | 6 | \description{A quick summary of names that can be used for adding NN components in a \code{\link{NN}} module. These names are available in the current package version. More components can be defined by the user or may be added in future versions.} 7 | 8 | \section{Current names for layers:}{ 9 | Layer names currently available include: 10 | \itemize{ 11 | \item\code{generic}: a layer of generic Processing Elements (PEs). 12 | \item\code{generic_d}: same as above. 13 | \item\code{pe}: same as above. 14 | \item\code{pass-through}: a layer with PEs that simply pass input to output. 15 | \item\code{which-max}: a layer with PEs that return the index of one of their inputs whose value is maximum. 16 | \item\code{MAM}: a layer with PEs for Matrix-Associative-Memory NNs (see vignette). 17 | \item\code{LVQ-input}: LVQ input layer (see vignette). 18 | \item\code{LVQ-output}: LVQ output layer (see vignette). 19 | \item\code{BP-hidden}: Back-Propagation hidden layer (see vignette). 20 | \item\code{BP-output}: Back-Propagation output layer (see vignette). 21 | \item\code{R-layer}: A layer whose encode and recall (map) functionality is defined in R (see \link{NN_R_components}). 22 | } 23 | Additional (user-defined) layers currently available include: 24 | \itemize{ 25 | \item\code{JustAdd10}: a layer where PEs output the sum of their inputs plus 10 (created for use as example in vingnette). 26 | \item\code{perceptron}: a classic perceptron layer (created for use as example in \href{https://www.r-bloggers.com/2020/07/creating-custom-neural-networks-with-nnlib2rcpp/}{in this post}). 27 | \item\code{MEX}: a layer created for use as example in vingnette. 28 | \item\code{example_layer_0}: a layer created to be used as a simple code example for users creating custom layers. 29 | \item\code{example_layer_1}: as above. 30 | \item\code{example_layer_2}: as above. 31 | \item\code{BP-hidden-softmax}: Back-Propagation hidden layer that performs softmax on its output (when recalling). 32 | \item\code{BP-output-softmax}: Back-Propagation output layer that performs softmax on its output (when recalling). 33 | \item\code{softmax}: a layer that (during recall) sums its inputs and outputs the softmax values. 34 | \item\code{R-connections}: A set of connections whose encode and recall (map) functionality is defined in R (see \link{NN_R_components}). 35 | } 36 | } 37 | 38 | \section{Current names for sets of connections:}{ 39 | Names for connection sets that are currently available include: 40 | \itemize{ 41 | \item\code{generic}: a set of generic connections. 42 | \item\code{pass-through}: connections that pass data through with no modification. 43 | \item\code{wpass-through}: connections that pass data multiplied by weight. 44 | \item\code{MAM}: connections for Matrix-Associative-Memory NNs (see vignette). 45 | \item\code{LVQ}: connections for LVQ NNs (see vignette). 46 | \item\code{BP}: connections for Back-Propagation (see vignette). 47 | } 48 | Additional (user-defined) connection sets currently available include: 49 | \itemize{ 50 | \item\code{perceptron}: connections for perceptron (created for use as example in \href{https://www.r-bloggers.com/2020/07/creating-custom-neural-networks-with-nnlib2rcpp/}{in this post}). 51 | \item\code{MEX}: a connection set created for use as example in vingnette. 52 | \item\code{example_connection_set_0}: a connection set created to be used as a simple code example for users creating custom types of connection sets. 53 | \item\code{example_connection_set_1}: as above. 54 | \item\code{example_connection_set_2}: as above. 55 | } 56 | } 57 | 58 | \author{ 59 | Vasilis N. Nikolaidis 60 | } 61 | 62 | \note{ 63 | These are component names that can be currently used to add components to a NN using the methods provided by \code{\link{NN}} module. Such methods include \code{add_layer}, \code{add_connection_set}, \code{connect_layers_at}, \code{fully_connect_layers_at} etc. Some of these components may be experimental or created for use in examples and may change or be removed in future versions, while other components may be added. 64 | 65 | More information on expanding the library with new, user-defined types of NN components (nodes, layers, connections etc) and models, can be found in the package's vignette as well as the related \href{https://github.com/VNNikolaidis/nnlib2Rcpp}{repository on Github}). A quick example can also be found \href{https://www.r-bloggers.com/2020/07/creating-custom-neural-networks-with-nnlib2rcpp/}{in this post}. Please consider submitting any useful components you create, to enrich future versions of the package. 66 | } 67 | 68 | \seealso{\code{\link{NN}}, \link{NN_R_components}.} 69 | 70 | 71 | -------------------------------------------------------------------------------- /man/nnlib2Rcpp.Rd: -------------------------------------------------------------------------------- 1 | \name{nnlib2Rcpp-package} 2 | \Rdversion{1.1} 3 | \docType{package} 4 | \alias{nnlib2Rcpp} 5 | \alias{nnlib2Rcpp-package} 6 | 7 | \title{A collection of Neural Networks and tools to create custom models} 8 | \description{ 9 | This package provides a module (NN module) to define and control neural networks containing predefined or custom components (layers, sets of connnections etc.). These components may have been derived from nnlib2 NN components (written in C++) or defined using R. 10 | 11 | It also contains a small collection of ready-to-use Neural Networks (NN), i.e. versions of Autoencoder, Back-Propagation, Learning Vector Quantization and Matrix Associative Memory NN. More information and examples for each of the above can be found in its documentation (see below). 12 | } 13 | 14 | \section{Ready-to-use Neural Networks:}{ 15 | \itemize{ 16 | \item Plain Back-Propagation (BP-supervised) (\code{\link{BP}}) 17 | \item Learning Vector Quantization (LVQ-supervised) (\code{\link{LVQs}}) 18 | \item Learning Vector Quantization (LVQ-unsupervised) (\code{\link{LVQu}}) 19 | \item Matrix Associative Memory (MAM-supervised) (\code{\link{MAM}}) 20 | \item Autoencoder (unsupervised) (\code{\link{Autoencoder}}) 21 | }} 22 | 23 | \section{Custom Neural Networks:}{ 24 | \itemize{ 25 | \item NN module (\code{\link{NN}}) 26 | }} 27 | 28 | \references{ 29 | \itemize{ 30 | \item 31 | Nikolaidis, V. N., (2021). The nnlib2 library and nnlib2Rcpp R package for implementing neural networks. Journal of Open Source Software, 6(61), 2876, \doi{10.21105/joss.02876}. 32 | } 33 | 34 | References for the ready-to-use NN models (can also be found in related documentation): 35 | \itemize{ 36 | \item 37 | Kohonen, T (1988). Self-Organization and Associative Memory, Springer-Verlag.; Simpson, P. K. (1991). Artificial neural systems: Foundations, paradigms, applications, and implementations. New York: Pergamon Press. 38 | 39 | \item 40 | Pao Y (1989). Adaptive Pattern Recognition and Neural Networks. Reading, MA (US); Addison-Wesley Publishing Co., Inc. 41 | 42 | \item 43 | Simpson, P. K. (1991). Artificial neural systems: Foundations, paradigms, applications, and implementations. New York: Pergamon Press. 44 | 45 | \item 46 | Philippidis, TP & Nikolaidis, VN & Kolaxis, JG. (1999). Unsupervised pattern recognition techniques for the prediction of composite failure. Journal of acoustic emission. 17. 69-81. 47 | 48 | \item 49 | Nikolaidis V.N., Makris I.A, Stavroyiannis S, "ANS-based preprocessing of company performance indicators." Global Business and Economics Review 15.1 (2013): 49-58, \doi{10.1504/GBER.2013.050667}. 50 | } 51 | } 52 | 53 | \seealso{ 54 | More information and examples on using the package can be found in the following vignette: 55 | 56 | \code{vignette("manual", package='nnlib2Rcpp')} 57 | 58 | Related links: 59 | \itemize{ 60 | \item \url{https://github.com/VNNikolaidis/nnlib2Rcpp} 61 | \item Package manual in PDF format at \url{https://github.com/VNNikolaidis/nnlib2Rcpp/blob/master/support/manual.pdf}) 62 | \item Report bugs, issues and suggestions at \url{https://github.com/VNNikolaidis/nnlib2Rcpp/issues} 63 | } 64 | 65 | } 66 | \author{ 67 | Author/Maintainer: 68 | \itemize{ 69 | \item Vasilis Nikolaidis \email{vnnikolaidis@gmail.com} 70 | } 71 | 72 | Contributors: 73 | \itemize{ 74 | \item Arfon Smith [contributor] 75 | \item Dirk Eddelbuettel [contributor] 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /nnlib2Rcpp.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: No 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: No 9 | NumSpacesForTab: 4 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | -------------------------------------------------------------------------------- /paper/paper.bib: -------------------------------------------------------------------------------- 1 | @inproceedings{abadi2016tensorflow, 2 | title={Tensorflow: A system for large-scale machine learning}, 3 | author={M. Abadi and P.Barham and J.Chen and Z.Chen and A.Davis and J.Dean and M.Devin and S.Ghemawat and G.Irving and M.Isard and others}, 4 | booktitle={12th $\{$USENIX$\}$ Symposium on Operating Systems Design and Implementation ($\{$OSDI$\}$ 16)}, 5 | pages={265--283}, 6 | year={2016} 7 | } 8 | 9 | @inproceedings{torch, 10 | title = {Torch7: A Matlab-like Environment for Machine Learning}, 11 | author = {R. Collobert and K. Kavukcuoglu and C. Farabet}, 12 | booktitle = {BigLearn, NIPS Workshop}, 13 | year = {2011} 14 | } 15 | 16 | @misc{keras1, 17 | title={Keras}, 18 | author={Chollet, Fran\c{c}ois and others}, 19 | year={2015}, 20 | howpublished={\url{https://keras.io}} 21 | } 22 | 23 | @incollection{PyTorch1, 24 | title = {PyTorch: An Imperative Style, High-Performance Deep Learning Library}, 25 | author = {Paszke, Adam and Gross, Sam and others}, 26 | booktitle = {Advances in Neural Information Processing Systems 32}, 27 | editor = {H. Wallach and H. Larochelle and A. Beygelzimer and F. d\textquotesingle Alch\'{e}-Buc and E. Fox and R. Garnett}, 28 | pages = {8024--8035}, 29 | year = {2019}, 30 | publisher = {Curran Associates, Inc.}, 31 | } 32 | 33 | @Manual{h2o_platform, 34 | title = {H2O: Scalable Machine Learning Platform}, 35 | author = {H2O.ai}, 36 | year = {2020}, 37 | note = {version 3.30.0.6}, 38 | url = {https://github.com/h2oai/h2o-3}, 39 | } 40 | 41 | @Inbook{Zell1994, 42 | author="Zell, Andreas 43 | and Mache, Niels 44 | and H{\"u}bner, Ralf 45 | and Mamier, G{\"u}nter 46 | and Vogt, Michael 47 | and Schmalzl, Michael 48 | and Herrmann, Kai-Uwe", 49 | editor="Skrzypek, Josef", 50 | title="SNNS (Stuttgart Neural Network Simulator)", 51 | bookTitle="Neural Network Simulation Environments", 52 | year="1994", 53 | publisher="Springer US", 54 | address="Boston, MA", 55 | pages="165--186", 56 | isbn="978-1-4615-2736-7", 57 | doi="10.1007/978-1-4615-2736-7_9", 58 | url="https://doi.org/10.1007/978-1-4615-2736-7_9" 59 | } 60 | 61 | @article{FANN, 62 | author = {Nissen, Steffen}, 63 | year = {2003}, 64 | month = {12}, 65 | pages = {}, 66 | title = {Implementation of a Fast Artificial Neural Network library (FANN)}, 67 | url = {https://github.com/libfann/fann} 68 | } 69 | 70 | @misc{chollet2017kerasR, 71 | title={R Interface to Keras}, 72 | author={Chollet, Fran\c{c}ois and Allaire, JJ and others}, 73 | year={2017}, 74 | publisher={GitHub}, 75 | howpublished={\url{https://github.com/rstudio/keras}}, 76 | } 77 | 78 | @Manual{RLanguage, 79 | title = {R: A Language and Environment for Statistical Computing}, 80 | author = {{R Core Team}}, 81 | organization = {R Foundation for Statistical Computing}, 82 | address = {Vienna, Austria}, 83 | year = {2020}, 84 | url = {https://www.R-project.org/}, 85 | } 86 | 87 | @misc{CRANtorch, 88 | title = {Package ‘torch’}, 89 | author = {D. Falbel and J. Luraschi and others}, 90 | year = {2020}, 91 | note = {R package}, 92 | journal = {​CRAN repository}, 93 | url = {https://CRAN.R-project.org/package=torch}, 94 | } 95 | 96 | @misc{CRANrTorch, 97 | title = {Package ‘rTorch’}, 98 | author = {A. Reyes}, 99 | year = {2020}, 100 | note = {R package}, 101 | journal = {​CRAN repository}, 102 | url = {https://CRAN.R-project.org/package=rTorch}, 103 | } 104 | 105 | @Manual{CRANh2o, 106 | title = {h2o: R Interface for the 'H2O' Scalable Machine Learning Platform}, 107 | author = {E. LeDell and others}, 108 | year = {2020}, 109 | note = {R package}, 110 | url = {https://CRAN.R-project.org/package=h2o}, 111 | } 112 | 113 | @Article{CRANRSNNS, 114 | title = {Neural Networks in {R} Using the Stuttgart Neural Network Simulator: {RSNNS}}, 115 | author = {Christoph Bergmeir and Jos\'e M. Ben\'itez}, 116 | journal = {Journal of Statistical Software}, 117 | year = {2012}, 118 | volume = {46}, 119 | number = {7}, 120 | pages = {1--26}, 121 | url = {http://www.jstatsoft.org/v46/i07/}, 122 | } 123 | 124 | @Book{CRANnnet, 125 | title = {Modern Applied Statistics with S}, 126 | author = {W. N. Venables and B. D. Ripley}, 127 | publisher = {Springer}, 128 | edition = {Fourth}, 129 | address = {New York}, 130 | year = {2002}, 131 | note = {ISBN 0-387-95457-0}, 132 | url = {http://www.stats.ox.ac.uk/pub/MASS4}, 133 | } 134 | 135 | @Manual{CRANdeepnet, 136 | title = {deepnet: deep learning toolkit in R}, 137 | author = {Xiao Rong}, 138 | year = {2014}, 139 | note = {R package version 0.2}, 140 | url = {https://CRAN.R-project.org/package=deepnet}, 141 | } 142 | 143 | @Manual{CRANdeepNN, 144 | title = {deepNN: Deep Learning}, 145 | author = {Benjamin Taylor}, 146 | year = {2020}, 147 | note = {R package version 1.0}, 148 | url = {https://CRAN.R-project.org/package=deepNN}, 149 | } 150 | 151 | @Manual{CRANRcppDL, 152 | title = {RcppDL: Deep Learning Methods via Rcpp}, 153 | author = {Qiang Kou and Yusuke Sugomori}, 154 | year = {2014}, 155 | note = {R package version 0.0.5}, 156 | url = {https://CRAN.R-project.org/package=RcppDL}, 157 | } 158 | 159 | @book{SimpsonANS, 160 | author = {Simpson, Patrick K.}, 161 | title = {Artificial Neural Systems: Foundations, Paradigms, Applications, and Implementations}, 162 | year = {1991}, 163 | isbn = {0071053557}, 164 | publisher = {McGraw-Hill, Inc.}, 165 | address = {USA} 166 | } 167 | 168 | @book{McCord91, 169 | author = {McCord-Nelson, Marilyn and Illingworth, W. T.}, 170 | title = {A Practical Guide to Neural Nets}, 171 | year = {1991}, 172 | isbn = {0201523760}, 173 | publisher = {Addison-Wesley Longman Publishing Co., Inc.}, 174 | address = {USA} 175 | } 176 | 177 | @book{pao1989adaptive, 178 | title={Adaptive Pattern Recognition and Neural Networks}, 179 | author={Pao, Yohhan}, 180 | year={1989}, 181 | publisher={Reading, MA (US); Addison-Wesley Publishing Co., Inc.} 182 | } 183 | 184 | @book{TheoPR, 185 | author = {Theodoridis, Sergios and Koutroumbas, Konstantinos}, 186 | title = {Pattern Recognition, Fourth Edition}, 187 | year = {2008}, 188 | isbn = {1597492728}, 189 | publisher = {Academic Press, Inc.}, 190 | address = {USA}, 191 | edition = {4th} 192 | } 193 | 194 | @article{philippidis1999unsupervised, 195 | title={Unsupervised Pattern Recognition Techniques for the Prediction of Composite Failure}, 196 | author={Philippidis, TP and Nikolaidis, VN and Kolaxis, JG}, 197 | journal={Journal of Acoustic Emission}, 198 | volume={17}, 199 | number={1-2}, 200 | pages={69--81}, 201 | year={1999} 202 | } 203 | 204 | @phdthesis{Nikolaidis199Phd, 205 | title = {Non-Destructive Inspection (NDI) Techniques for Composite Materials using Unconventional Pattern Regognition Methods (in Greek)}, 206 | school = {University of Patras}, 207 | author = {Vasilios Nikolaidis}, 208 | year = {1999}, 209 | url = {https://www.didaktorika.gr/eadd/handle/10442/11158?locale=en} 210 | } 211 | 212 | @article{nikolaidis2013ans, 213 | title={ANS-based Preprocessing of Company Performance Indicators}, 214 | author={Nikolaidis, Vasilios N and Makris, Ilias A and Stavroyiannis, Stavros}, 215 | journal={Global Business and Economics Review}, 216 | volume={15}, 217 | number={1}, 218 | pages={49--58}, 219 | year={2013}, 220 | doi={10.1504/gber.2013.050667}, 221 | publisher={Inderscience Publishers Ltd} 222 | } 223 | 224 | @misc{nnlib2RcppCRAN, 225 | title = {Package ‘nnlib2Rcpp’}, 226 | author = {Vasilis Nikolaidis}, 227 | year = {2020}, 228 | note = {R package}, 229 | journal = {​CRAN repository}, 230 | url = {https://CRAN.R-project.org/package=nnlib2Rcpp}, 231 | } 232 | 233 | @misc{nnlib2RcppGitHub, 234 | title = {‘nnlib2Rcpp’}, 235 | author = {Vasilis Nikolaidis}, 236 | year = {2020}, 237 | note = {R package}, 238 | journal = {​GitHub repository}, 239 | url = {https://github.com/VNNikolaidis/nnlib2Rcpp}, 240 | } 241 | 242 | @Manual{Rcpp1, 243 | title = {Rcpp: Seamless R and C++ Integration}, 244 | author = {Dirk Eddelbuettel and Romain Francois and JJ Allaire and Kevin Ushey and Qiang Kou and Nathan Russell and Douglas Bates and John Chambers}, 245 | year = {2020}, 246 | note = {R package version 1.0.4}, 247 | url = {https://CRAN.R-project.org/package=Rcpp}, 248 | } 249 | -------------------------------------------------------------------------------- /paper/paper.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'The nnlib2 library and nnlib2Rcpp R package for implementing neural networks' 3 | tags: 4 | - neural networks 5 | - R 6 | - Cpp 7 | authors: 8 | - name: Vasilis N Nikolaidis 9 | orcid: 0000-0003-1471-8788 10 | affiliation: 1 11 | affiliations: 12 | - name: University of Peloponnese 13 | index: 1 14 | date: 15 September 2020 15 | bibliography: paper.bib 16 | --- 17 | 18 | # Summary 19 | 20 | Artificial Neural Networks (ANN or NN) are computing models used in various data-driven applications. Such systems typically consist of a large number of processing elements (or nodes), usually organized in layers, which exchange data via weighted connections. An ever-increasing number of different neural network models have been proposed and used. Among the several factors differentiating each model are the network topology, the processing and training methods in nodes and connections, and the sequences utilized for transferring data to, within and from the model etc. The software presented here is a C++ library of classes and templates for implementing neural network components and models and an R package that allows users to instantiate and use such components from the R programming language. 21 | 22 | # Statement of need 23 | 24 | A significant number of capable, flexible, high performance tools for NN are available today, including frameworks such as `Tensorflow` [@abadi2016tensorflow] and `Torch` [@torch], and related high level APIs including `Keras` [@keras1] and `PyTorch` [@PyTorch1]. Ready-to-use NN models are also provided by various machine learning platforms such as `H2O` [@h2o_platform] or libraries, `SNNS` [@Zell1994] and `FANN` [@FANN]. Ready to use NNs are available in a large number of software packages (`WEKA`, `SPSS`, `Matlab`, `NeuroSolutions`, `Noesis` and many others). The R language [@RLanguage], widely used for data analysis, includes package `nnet` [@CRANnnet] in its standard packages, while a significant number of NN-related extension packages can be found in CRAN and other repositories. These include interfaces and bindings to aforementioned tools (`keras` [@chollet2017kerasR], `torch` [@CRANtorch], `rTorch` [@CRANrTorch], `h2o ` [@CRANh2o], `RSNNS` [@CRANRSNNS]), as well as several other NN-specific packages that provide ready-to-use NN models (`deepnet` [@CRANdeepnet], `deepNN` [@CRANdeepNN], RcppDL [@CRANRcppDL] etc.). 25 | 26 | The `nnlib2` library adds another tool for NN experimentation and implementation. It is a collection of C++ base classes and class-templates for defining NN parts, components and entire models. It contains base classes (and related functionality) for each part of a NN (processing nodes, connections, layers, groups of connections etc.) and for NN models that contain such parts. The library does not focus (in its current state) on high-performance computing but on being a versatile basis on which new NN parts and models can be defined with consistent, readable, maintainable and reusable code. Although the software does contain some ready-to-use NN models and their related reusable NN parts (currently for versions of Back-propagation, autoencoder, Learning Vector Quantization and Matrix Associative Memory), its main purpose is to aid the creation of new custom NN parts and the experimentation with them in arbitrary NN models and configurations. Overall the library (and related R package): 27 | 28 | 1. Allows the implementation of NN parts and models from reusable components that follow a common interface thus can easily be modified, combined with each other etc, making them suitable for educational or experimentation purposes. 29 | 2. Provides a basis for implementation of different NN parts and models, including classic NNs. 30 | 3. Is versatile enough for experimentation with new, custom components, configurations and models. 31 | 4. Has no dependencies with other software; to build or employ the `nnlib2` parts and models only a standard C++ compiler is required, and the produced models are standalone, lightweight, highly portable and can be embedded in any C++ application. 32 | 5. Allows for the exact same NN parts (processing nodes, connections, layers, groups of connections etc.) defined using `nnlib2` to be employed, combined, manipulated and monitored in R, via package `nnlib2Rcpp` which includes the entire `nnlib2` library and also provides supporting R functions and modules for this purpose. Thus, new NN components can be developed entirely using R-related tools (such as Rtools and RStudio), and then be used in R or transferred to a pure C++ application if needed. 33 | 34 | # Discussion 35 | 36 | As implied earlier, the `nnlib2` library may appeal to NN students and experimenters who seek a basis for implementing various NN models in C++ and take advantage of the versatility and direct control of the model that this approach allows. Furthermore, the library lets new NN definitions be written in code that is comparatively simple and self-explanatory; most of the provided base classes and templates correspond to typical NN components (processing nodes, layers of nodes, connections, sets of connections between layers, entire neural networks etc.) and closely follow the conceptual model often found in related bibliography such as [@SimpsonANS;@McCord91;@pao1989adaptive;@TheoPR] and elsewhere. Typical component functionality and features are provided in these base definitions, while diverse, model-specific components are to be implemented in custom sub-classes. By following a common interface, components (or even entire NN models) can be reused in other models. Finally, the library presents a high degree of target and compiler independence, with early versions used in various solutions targeting different operating systems, mainly for research purposes, for example in [@philippidis1999unsupervised;@Nikolaidis199Phd;@nikolaidis2013ans]. 37 | 38 | To take advantage of the R ecosystem, improve its usability and widen its audience, the `nnlib2` library has also been integrated into an R package (a process supported by `Rcpp` [@Rcpp1]). The package, named `nnlib2Rcpp` (available on CRAN [@nnlib2RcppCRAN] and GitHub [@nnlib2RcppGitHub]) includes the entire `nnlib2` code as well as an additional R class (class NN) with methods that allow users to instantiate the `nnlib2` NN components they define, combine them in custom NN configurations and generally control, monitor and employ them from R. Finally, the package provides a small collection of predefined NN components and complete ready-to-use NN models (for versions of Back Propagation, autoencoder, supervised/unsupervised Learning Vector Quantization and Matrix Associative Memory neural networks). 39 | 40 | # References 41 | -------------------------------------------------------------------------------- /src/RcppExports.cpp: -------------------------------------------------------------------------------- 1 | // Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | #include 5 | 6 | using namespace Rcpp; 7 | 8 | #ifdef RCPP_USE_GLOBAL_ROSTREAM 9 | Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get(); 10 | Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); 11 | #endif 12 | 13 | // Autoencoder 14 | NumericMatrix Autoencoder(NumericMatrix data_in, int desired_new_dimension, int number_of_training_epochs, double learning_rate, int num_hidden_layers, int hidden_layer_size, bool show_nn, std::string error_type, double acceptable_error_level, int display_rate); 15 | RcppExport SEXP _nnlib2Rcpp_Autoencoder(SEXP data_inSEXP, SEXP desired_new_dimensionSEXP, SEXP number_of_training_epochsSEXP, SEXP learning_rateSEXP, SEXP num_hidden_layersSEXP, SEXP hidden_layer_sizeSEXP, SEXP show_nnSEXP, SEXP error_typeSEXP, SEXP acceptable_error_levelSEXP, SEXP display_rateSEXP) { 16 | BEGIN_RCPP 17 | Rcpp::RObject rcpp_result_gen; 18 | Rcpp::RNGScope rcpp_rngScope_gen; 19 | Rcpp::traits::input_parameter< NumericMatrix >::type data_in(data_inSEXP); 20 | Rcpp::traits::input_parameter< int >::type desired_new_dimension(desired_new_dimensionSEXP); 21 | Rcpp::traits::input_parameter< int >::type number_of_training_epochs(number_of_training_epochsSEXP); 22 | Rcpp::traits::input_parameter< double >::type learning_rate(learning_rateSEXP); 23 | Rcpp::traits::input_parameter< int >::type num_hidden_layers(num_hidden_layersSEXP); 24 | Rcpp::traits::input_parameter< int >::type hidden_layer_size(hidden_layer_sizeSEXP); 25 | Rcpp::traits::input_parameter< bool >::type show_nn(show_nnSEXP); 26 | Rcpp::traits::input_parameter< std::string >::type error_type(error_typeSEXP); 27 | Rcpp::traits::input_parameter< double >::type acceptable_error_level(acceptable_error_levelSEXP); 28 | Rcpp::traits::input_parameter< int >::type display_rate(display_rateSEXP); 29 | rcpp_result_gen = Rcpp::wrap(Autoencoder(data_in, desired_new_dimension, number_of_training_epochs, learning_rate, num_hidden_layers, hidden_layer_size, show_nn, error_type, acceptable_error_level, display_rate)); 30 | return rcpp_result_gen; 31 | END_RCPP 32 | } 33 | // LVQu 34 | IntegerVector LVQu(NumericMatrix data, int max_number_of_desired_clusters, int number_of_training_epochs, int neighborhood_size, bool show_nn); 35 | RcppExport SEXP _nnlib2Rcpp_LVQu(SEXP dataSEXP, SEXP max_number_of_desired_clustersSEXP, SEXP number_of_training_epochsSEXP, SEXP neighborhood_sizeSEXP, SEXP show_nnSEXP) { 36 | BEGIN_RCPP 37 | Rcpp::RObject rcpp_result_gen; 38 | Rcpp::RNGScope rcpp_rngScope_gen; 39 | Rcpp::traits::input_parameter< NumericMatrix >::type data(dataSEXP); 40 | Rcpp::traits::input_parameter< int >::type max_number_of_desired_clusters(max_number_of_desired_clustersSEXP); 41 | Rcpp::traits::input_parameter< int >::type number_of_training_epochs(number_of_training_epochsSEXP); 42 | Rcpp::traits::input_parameter< int >::type neighborhood_size(neighborhood_sizeSEXP); 43 | Rcpp::traits::input_parameter< bool >::type show_nn(show_nnSEXP); 44 | rcpp_result_gen = Rcpp::wrap(LVQu(data, max_number_of_desired_clusters, number_of_training_epochs, neighborhood_size, show_nn)); 45 | return rcpp_result_gen; 46 | END_RCPP 47 | } 48 | 49 | RcppExport SEXP _rcpp_module_boot_class_BP(); 50 | RcppExport SEXP _rcpp_module_boot_class_LVQs(); 51 | RcppExport SEXP _rcpp_module_boot_class_MAM(); 52 | RcppExport SEXP _rcpp_module_boot_class_NN(); 53 | 54 | static const R_CallMethodDef CallEntries[] = { 55 | {"_nnlib2Rcpp_Autoencoder", (DL_FUNC) &_nnlib2Rcpp_Autoencoder, 10}, 56 | {"_nnlib2Rcpp_LVQu", (DL_FUNC) &_nnlib2Rcpp_LVQu, 5}, 57 | {"_rcpp_module_boot_class_BP", (DL_FUNC) &_rcpp_module_boot_class_BP, 0}, 58 | {"_rcpp_module_boot_class_LVQs", (DL_FUNC) &_rcpp_module_boot_class_LVQs, 0}, 59 | {"_rcpp_module_boot_class_MAM", (DL_FUNC) &_rcpp_module_boot_class_MAM, 0}, 60 | {"_rcpp_module_boot_class_NN", (DL_FUNC) &_rcpp_module_boot_class_NN, 0}, 61 | {NULL, NULL, 0} 62 | }; 63 | 64 | RcppExport void R_init_nnlib2Rcpp(DllInfo *dll) { 65 | R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); 66 | R_useDynamicSymbols(dll, FALSE); 67 | } 68 | -------------------------------------------------------------------------------- /src/Rcpp_Autoencoder.cpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // (C)2019 Vasilis.N.Nikolaidis All rights reserved. 3 | // ----------------------------------------------------------- 4 | // Rcpp glue code for Autoencoder NN (bpu_autoencoder_nn, supervised) 5 | // ----------------------------------------------------------- 6 | 7 | #include "nnlib2.h" 8 | 9 | #ifdef NNLIB2_FOR_RCPP 10 | using namespace Rcpp; 11 | 12 | //-------------------------------------------------------------------------------- 13 | 14 | #include "nn_bp.h" 15 | 16 | using namespace nnlib2; 17 | using namespace nnlib2::bp; 18 | 19 | //-------------------------------------------------------------------------------- 20 | 21 | // [[Rcpp::export]] 22 | NumericMatrix Autoencoder ( 23 | NumericMatrix data_in, 24 | int desired_new_dimension, 25 | int number_of_training_epochs, // (each presents all data) 26 | double learning_rate, 27 | int num_hidden_layers = 1, // number of hidden layers on each side of special layer 28 | int hidden_layer_size = 5, // number of nodes in each hidden layer 29 | bool show_nn = false, 30 | std::string error_type = "MAE", 31 | double acceptable_error_level = 0, 32 | int display_rate = 1000 33 | ) 34 | { 35 | TEXTOUT << "acceptable error level = " << acceptable_error_level << "\n"; 36 | 37 | int input_dimension = data_in.cols(); 38 | int num_training_cases = data_in.rows(); 39 | 40 | NumericMatrix data_out; 41 | 42 | if (input_dimension <= 0) return data_out; 43 | if (num_training_cases <= 0) return data_out; 44 | 45 | data_out=NumericMatrix(num_training_cases,desired_new_dimension); 46 | 47 | bpu_autoencoder_nn ae; 48 | if( ae.no_error()) ae.setup(input_dimension, learning_rate, num_hidden_layers, hidden_layer_size, desired_new_dimension); 49 | if(NOT ae.no_error()) return(data_out); 50 | 51 | if((error_type!="MAE") AND 52 | (error_type!="MSE")) 53 | { 54 | error_type="MAE"; 55 | warning("Unsupported error type (must be 'MAE' or 'MSE'). Using and displaying Mean Absolute Error (MAE)"); 56 | } 57 | 58 | if(error_type=="MSE") 59 | { 60 | ae.m_use_squared_error = true; 61 | } 62 | else 63 | { 64 | ae.m_use_squared_error = false; 65 | } 66 | 67 | if(acceptable_error_level<0) acceptable_error_level=0; 68 | if(display_rate<0) display_rate=1000; 69 | 70 | TEXTOUT << "Max number of epochs = " << number_of_training_epochs << "\n"; 71 | DATA error_level = 0; 72 | 73 | for(int i=0;(i0) 86 | if(i%display_rate==0) 87 | { 88 | checkUserInterrupt(); // (RCpp function to check if user pressed cancel) 89 | TEXTOUT << "Epoch = "<< i << " , error level = " << error_level << "\n"; 90 | } 91 | 92 | if(error_level<=acceptable_error_level) 93 | { 94 | TEXTOUT << "Epoch = "<< i << " , error level = " << error_level << "\n"; 95 | TEXTOUT << "Training reached acceptable error level ( "; 96 | TEXTOUT << error_type << " "; 97 | TEXTOUT << error_level << " <= " << acceptable_error_level << " )\n"; 98 | break; 99 | } 100 | } 101 | 102 | TEXTOUT << "Training ended , error level = " << error_level << "\n\n"; 103 | 104 | if(show_nn) 105 | { 106 | TEXTOUT << "------Network structure (BEGIN)--------\n"; 107 | ae.to_stream(TEXTOUT); 108 | TEXTOUT << "--------Network structure (END)--------\n"; 109 | } 110 | 111 | NumericVector v_out(desired_new_dimension); // buffer for output 112 | double * fp_out = REAL(v_out); // buffer for output (as double *) 113 | 114 | for(int r=0;r 15 | #include 16 | 17 | using namespace nnlib2; 18 | using namespace nnlib2::bp; 19 | 20 | //-------------------------------------------------------------------------------- 21 | // Note: below is BP implemented as a Module 22 | //-------------------------------------------------------------------------------- 23 | // R wrapper class: 24 | 25 | class BP 26 | { 27 | protected: 28 | 29 | bp_nn bp; 30 | 31 | double m_acceptable_error_level; 32 | std::string m_error_type; 33 | 34 | bool m_mute_training_output; 35 | 36 | public: 37 | 38 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 39 | 40 | BP() 41 | { 42 | TEXTOUT << "BP NN created, now encode data (or load NN from file).\n"; 43 | bp.reset(); 44 | set_error_level("MAE",0); 45 | m_mute_training_output = false; 46 | } 47 | 48 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 49 | // Setup BP and encode input-output datasets in the NN 50 | 51 | void encode(NumericMatrix data_in, 52 | NumericMatrix data_out, 53 | double learning_rate, 54 | int training_epochs, 55 | int hidden_layers, 56 | int hidden_layer_size) 57 | { 58 | int input_dim = data_in.cols(); 59 | int output_dim = data_out.cols(); 60 | 61 | if(setup(input_dim,output_dim,learning_rate,hidden_layers,hidden_layer_size)) 62 | train_multiple(data_in,data_out,training_epochs); 63 | } 64 | 65 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 66 | // Setup a new BP 67 | 68 | bool setup(int input_dim, int output_dim, double learning_rate, int hidden_layers, int hidden_layer_size) 69 | { 70 | if(!bp.setup(input_dim, output_dim, learning_rate, hidden_layers, hidden_layer_size)) 71 | { 72 | error(NN_INTEGR_ERR,"Cannot setup BP NN"); 73 | bp.reset(); 74 | return false; 75 | } 76 | return true; 77 | } 78 | 79 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 80 | // Encode multiple input-output vector pairs stored in corresponding datasets 81 | 82 | double train_multiple (NumericMatrix data_in, 83 | NumericMatrix data_out, 84 | int training_epochs) 85 | { 86 | if((data_in.rows()<=0) OR 87 | (data_in.rows()!=data_out.rows())) 88 | { 89 | error(NN_DATAST_ERR,"Cannot train BP with these datasets"); 90 | return DATA_MAX; 91 | } 92 | 93 | int num_training_cases=data_in.rows(); 94 | // encode all data input-output pairs 95 | DATA error_level = DATA_MAX; 96 | 97 | if(m_mute_training_output) TEXTOUT << "Training...\n"; 98 | 99 | for(int i=0;i( "BP" ) 270 | .constructor() 271 | //.constructor() 272 | .method( "encode", &BP::encode, "Setup BP and encode input-output datasets in the NN" ) 273 | .method( "train_multiple", &BP::train_single, "Encode multiple input-output vector pairs stored in corresponding datasets" ) 274 | .method( "train_single", &BP::train_single, "Encode a single input-output vector pair in current BP NN" ) 275 | .method( "setup", &BP::setup, "Setup the BP NN" ) 276 | .method( "recall", &BP::recall, "Get output for a dataset using BP NN" ) 277 | .method( "print", &BP::print, "Print BP NN details" ) 278 | .method( "show", &BP::show, "Print BP NN details" ) 279 | .method( "mute", &BP::mute, "Disable output of current error level during training" ) 280 | .method( "load", &BP::load_from_file, "Load BP" ) 281 | .method( "save", &BP::save_to_file, "Save BP" ) 282 | .method( "set_error_level" ,&BP::set_error_level, "Set parameters for acceptable error when training." ) 283 | 284 | ; 285 | } 286 | 287 | //-------------------------------------------------------------------------------- 288 | 289 | #endif // NNLIB2_FOR_RCPP 290 | -------------------------------------------------------------------------------- /src/Rcpp_LVQ_unsupervised.cpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // (C)2019 Vasilis.N.Nikolaidis All rights reserved. 3 | // ----------------------------------------------------------- 4 | // Rcpp glue code for Self-Organized Map NN (som_nn,unsupervised) 5 | // ----------------------------------------------------------- 6 | 7 | #include "nnlib2.h" 8 | 9 | #ifdef NNLIB2_FOR_RCPP 10 | using namespace Rcpp; 11 | 12 | //-------------------------------------------------------------------------------- 13 | 14 | #include "nnlib2_misc.h" // for which_max 15 | #include "nn_lvq.h" // for som_nn 16 | 17 | using namespace nnlib2; 18 | using namespace nnlib2::lvq; 19 | 20 | //-------------------------------------------------------------------------------- 21 | // Rcpp glue code for LVQ-unsupervised (som_nn) 22 | 23 | // [[Rcpp::export]] 24 | IntegerVector LVQu ( NumericMatrix data, 25 | int max_number_of_desired_clusters, 26 | int number_of_training_epochs, // (each presents all data) 27 | int neighborhood_size =1, // should be odd. 28 | bool show_nn = false ) 29 | { 30 | IntegerVector returned_cluster_ids = rep(-1,data.rows()); 31 | 32 | int input_data_dim = data.cols(); 33 | int output_dim = max_number_of_desired_clusters; 34 | 35 | som_nn som(neighborhood_size); // A Self-Organizing-Map NN 36 | 37 | if(som.no_error()) som.setup(input_data_dim,output_dim); 38 | if(NOT som.no_error()) return returned_cluster_ids; 39 | 40 | // encode all data 41 | 42 | for(int i=0;i 15 | #include 16 | 17 | using namespace nnlib2; 18 | using namespace nnlib2::mam; 19 | 20 | //-------------------------------------------------------------------------------- 21 | // Note: below is MAM implemented as a Module 22 | //-------------------------------------------------------------------------------- 23 | // R wrapper class: 24 | 25 | class MAM 26 | { 27 | protected: 28 | 29 | mam_nn mam; 30 | 31 | public: 32 | 33 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 34 | 35 | MAM() 36 | { 37 | TEXTOUT << "MAM created, now encode data (or load NN from file).\n"; 38 | mam.reset(); 39 | } 40 | 41 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 42 | 43 | void encode(NumericMatrix data_in, 44 | NumericMatrix data_out) 45 | { 46 | int num_train_items = data_in.rows(); 47 | if (num_train_items != data_out.rows()) 48 | { 49 | TEXTOUT << "Cannot train, input and output datasets do not have matching number of rows.\n"; 50 | return; 51 | } 52 | 53 | // setup the MAM NN... 54 | 55 | mam.setup(data_in.cols(),data_out.cols()); 56 | 57 | // ... and encode data: 58 | 59 | if(mam.is_ready()) 60 | for(int r=0;r( "MAM" ) 166 | .constructor() 167 | //.constructor() 168 | .method( "encode", &MAM::encode, "Encode input and corresponding output" ) 169 | .method( "train_single",&MAM::train_single, "Encode a single input-output vector pair in current MAM NN" ) 170 | .method( "recall", &MAM::recall, "Get output for a dataset using MAM NN" ) 171 | .method( "print", &MAM::print, "Print MAM NN details" ) 172 | .method( "show", &MAM::show, "Print MAM NN details" ) 173 | .method( "load", &MAM::load_from_file,"Load MAM" ) 174 | .method( "save", &MAM::save_to_file, "Save MAM" ) 175 | ; 176 | } 177 | 178 | //-------------------------------------------------------------------------------- 179 | 180 | #endif // NNLIB2_FOR_RCPP 181 | -------------------------------------------------------------------------------- /src/Rcpp_R_layer.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // (C)2020 Vasilis.N.Nikolaidis All rights reserved. 3 | // ----------------------------------------------------------- 4 | // layer component for NN module (nnlib2Rcpp) 5 | // ----------------------------------------------------------- 6 | 7 | #include "nnlib2.h" 8 | 9 | #ifdef NNLIB2_FOR_RCPP 10 | 11 | #ifndef RCPP_NN_R_LAYER 12 | #define RCPP_NN_R_LAYER 13 | 14 | #include "layer.h" 15 | 16 | using namespace nnlib2; 17 | 18 | //-------------------------------------------------------------------------------- 19 | 20 | class R_layer : public pe_layer 21 | { 22 | protected: 23 | 24 | string m_R_function_encode; // the R function to be called 25 | string m_R_function_recall; // the R function to be called 26 | 27 | private: 28 | 29 | bool collect_data_for_R_call(NumericVector REF input, 30 | NumericMatrix REF input_q, 31 | NumericVector REF bias, 32 | NumericVector REF misc, 33 | NumericVector REF output); 34 | 35 | public: 36 | 37 | R_layer(string name, 38 | int size, 39 | string encode_FUN = "" , 40 | string recall_FUN = ""); 41 | 42 | void encode (); 43 | void recall (); 44 | }; 45 | 46 | //-------------------------------------------------------------------------------- 47 | 48 | R_layer::R_layer(string name, 49 | int size, 50 | string encode_FUN, 51 | string recall_FUN) 52 | :pe_layer(name,size) 53 | { 54 | m_R_function_encode = encode_FUN; 55 | m_R_function_recall = recall_FUN; 56 | m_name = m_name + "(" + encode_FUN + "," + recall_FUN + ")"; 57 | } 58 | 59 | 60 | //-------------------------------------------------------------------------------- 61 | 62 | bool R_layer::collect_data_for_R_call( NumericVector REF input, 63 | NumericMatrix REF input_q, 64 | NumericVector REF bias, 65 | NumericVector REF misc, 66 | NumericVector REF output) 67 | { 68 | if(size()<=0) return false; 69 | 70 | // collect the current value in PE input registers... 71 | input = NumericVector(size()); 72 | double * fp_v_input = REAL(input); 73 | for (int i = 0; i < size(); i++) fp_v_input[i] = pes[i].input; 74 | 75 | // determine how many values are waiting to be input via received_values... 76 | int maxw = 0; 77 | for (int i = 0; i < size(); i++) 78 | if(maxw < pes[i].number_of_received_input_values()) 79 | maxw = pes[i].number_of_received_input_values(); 80 | 81 | // ... and collect them 82 | 83 | if(maxw>0) 84 | { 85 | input_q = NumericMatrix(maxw,size()); 86 | for (int i = 0; i < size(); i++) 87 | for(int v = 0; v < pes[i].number_of_received_input_values(); v++) 88 | input_q(v,i) = pes[i].received_input_value(v); 89 | } 90 | 91 | 92 | // collect the current value in PE bias registers... 93 | bias = NumericVector(size()); 94 | double * fp_v_bias = REAL(bias); 95 | for (int i = 0; i < size(); i++) fp_v_bias[i] = pes[i].bias; 96 | 97 | // collect the current value in PE misc registers... 98 | misc = NumericVector(size()); 99 | double * fp_v_misc = REAL(misc); 100 | for (int i = 0; i < size(); i++) fp_v_misc[i] = pes[i].misc; 101 | 102 | // collect the current value in PE output registers... 103 | output = NumericVector(size()); 104 | double * fp_v_output = REAL(output); 105 | for (int i = 0; i < size(); i++) fp_v_output[i] = pes[i].output; 106 | 107 | return true; 108 | } 109 | 110 | //-------------------------------------------------------------------------------- 111 | 112 | void R_layer::encode() 113 | { 114 | if(m_R_function_encode!="") 115 | { 116 | NumericVector input; 117 | NumericMatrix input_q; 118 | NumericVector bias; 119 | NumericVector misc; 120 | NumericVector output; 121 | 122 | if(NOT collect_data_for_R_call(input,input_q,bias,misc,output)) 123 | { 124 | warning("Layer cannot encode, preparing R data failed"); 125 | return; 126 | } 127 | 128 | // Call the R function... 129 | 130 | Function f(m_R_function_encode); 131 | 132 | List ret_vals = f( Named("INPUT")=input, 133 | Named("INPUT_Q")=input_q, 134 | Named("BIAS")=bias, 135 | Named("MISC")=misc, 136 | Named("OUTPUT")=output ); 137 | 138 | // Once finished, set local new_v_destin_in values as the destination input 139 | 140 | if(ret_vals.length()<=0) 141 | { 142 | // warning("No data was returned from "+m_R_function_encode); 143 | return; 144 | } 145 | 146 | if(ret_vals.containsElementNamed("INPUT")) {warning("Note: Layer will not set INPUT to specific returned values during encode.");} 147 | if(ret_vals.containsElementNamed("INPUT_Q")) {warning("Note: Layer will not set INPUT_Q (PE received values) to specific returned values during encode.");} 148 | 149 | if(ret_vals.containsElementNamed("BIAS")) 150 | { 151 | bias = ret_vals["BIAS"]; 152 | if((bias.length()>0) AND (bias.length()!=size())) 153 | { 154 | error(NN_INTEGR_ERR,"Length of returned BIAS values not equal to layer size"); 155 | return; 156 | } 157 | for (int i=0; i0) AND (misc.length()!=size())) 165 | { 166 | error(NN_INTEGR_ERR,"Length of returned MISC values not equal to layer size"); 167 | return; 168 | } 169 | for (int i=0; i0) AND (output.length()!=size())) 177 | { 178 | error(NN_INTEGR_ERR,"Length of returned OUTPUT not equal to layer size"); 179 | return; 180 | } 181 | for (int i=0; i example_pe_layer_1; 19 | 20 | class example_pe_layer_2: public Layer 21 | { 22 | public: 23 | example_pe_layer_2(string name, int size) : Layer(name,size) {}; 24 | }; 25 | 26 | //-------------------------------------------------------------------------------------------- 27 | // minimal examples of connection and connection_set definitions: 28 | //-------------------------------------------------------------------------------------------- 29 | 30 | class example_connection: public connection {}; 31 | 32 | typedef Connection_Set example_connection_set_1; 33 | 34 | class example_connection_set_2: public Connection_Set 35 | { 36 | public: 37 | example_connection_set_2(string name) : Connection_Set(name) {}; 38 | }; 39 | 40 | //-------------------------------------------------------------------------------------------- 41 | // minimal examples of matrix based (derived from generic_connection_matrix) definitions: 42 | //-------------------------------------------------------------------------------------------- 43 | 44 | class example_connection_matrix: public generic_connection_matrix 45 | { 46 | public: 47 | 48 | example_connection_matrix(string name):generic_connection_matrix(name,true){}; 49 | 50 | void encode () {}; // Just an example, does nothing 51 | void recall () {}; // Just an example, does nothing 52 | }; 53 | 54 | //------------------------------------------------------------------------------ 55 | #ifdef NNLIB2_FOR_RCPP // this part is currently used only in nnlib2Rcpp 56 | //------------------------------------------------------------------------------ 57 | // register new layer classes here: 58 | // given the name, it should return a pointer to a newly created layer 59 | //------------------------------------------------------------------------------ 60 | 61 | layer PTR generate_custom_layer(List parameters) 62 | { 63 | // extract incoming parameters from list: 64 | 65 | string name = parameters["name"]; 66 | int size = parameters["size"]; 67 | DATA optional_parameter = DATA_MIN; 68 | 69 | if(parameters.containsElementNamed("optional_parameter")) 70 | optional_parameter = parameters["optional_parameter"]; 71 | 72 | // create the new layer: 73 | 74 | if(name == "JustAdd10") return new JustAdd10_layer (name,size); 75 | if(name == "perceptron") return new perceptron_layer(name,size); 76 | if(name == "MEX") return new MEX_layer(name, size); 77 | 78 | if(name == "example_layer_0") return new Layer (name, size); 79 | if(name == "example_layer_1") return new example_pe_layer_1(name, size); 80 | if(name == "example_layer_2") return new example_pe_layer_2(name, size); 81 | 82 | if(name == "softmax") return new softmax_layer(name, size); 83 | 84 | if(name == "BP-hidden-softmax") 85 | { 86 | bp_comput_softmax_layer PTR pl = new bp_comput_softmax_layer; 87 | // depending on their specifics, some type of layers may have additional setup steps. For BP layers: 88 | pl->setup(name,size); 89 | pl->randomize_biases(-1,1); 90 | DATA bp_learnrate = 0.6; 91 | if(optional_parameter!=DATA_MIN) 92 | bp_learnrate = optional_parameter; 93 | pl->set_learning_rate(bp_learnrate); 94 | TEXTOUT << "(This " << name << " layer uses learning rate = " << bp_learnrate << ")\n"; 95 | return pl; 96 | } 97 | 98 | if(name == "BP-output-softmax") 99 | { 100 | bp_output_softmax_layer PTR pl = new bp_output_softmax_layer; 101 | // depending on their specifics, some type of layers may have additional setup steps. For BP layers: 102 | pl->setup(name,size); 103 | pl->randomize_biases(-1,1); 104 | DATA bp_learnrate = 0.6; 105 | if(optional_parameter!=DATA_MIN) 106 | bp_learnrate = optional_parameter; 107 | pl->set_learning_rate(bp_learnrate); 108 | TEXTOUT << "(This " << name << " layer uses learning rate = " << bp_learnrate << ")\n"; 109 | return pl; 110 | } 111 | 112 | return NULL; 113 | } 114 | 115 | //------------------------------------------------------------------------------ 116 | // register new connection_set classes here: 117 | // given the name, it should return a pointer to a newly created connection_set 118 | //------------------------------------------------------------------------------ 119 | 120 | connection_set PTR generate_custom_connection_set(List parameters) 121 | { 122 | string name = parameters["name"]; 123 | 124 | DATA optional_parameter = DATA_MIN; 125 | 126 | if(parameters.containsElementNamed("optional_parameter")) 127 | optional_parameter = parameters["optional_parameter"]; 128 | 129 | // examples of adding new connection set types: 130 | 131 | if(name == "perceptron") return new perceptron_connection_set(name); 132 | if(name == "MEX") return new MEX_connection_set(name); 133 | 134 | if(name == "example_connection_set_0") return new Connection_Set(name); 135 | if(name == "example_connection_set_1") return new example_connection_set_1(name); 136 | if(name == "example_connection_set_2") return new example_connection_set_2(name); 137 | 138 | if(name == "example_connection_matrix") return new example_connection_matrix(name); 139 | 140 | return NULL; 141 | } 142 | 143 | //------------------------------------------------------------------------------ 144 | #endif // NNLIB2_FOR_RCPP // end of part currently used only in nnlib2Rcpp 145 | //------------------------------------------------------------------------------ 146 | 147 | #endif // NNLIB2_ADDITIONAL_PARTS_H 148 | -------------------------------------------------------------------------------- /src/additional_parts_other.h: -------------------------------------------------------------------------------- 1 | #ifndef NNLIB2_ADDITIONAL_PARTS_OTHER_H 2 | #define NNLIB2_ADDITIONAL_PARTS_OTHER_H 3 | 4 | #include "nn.h" 5 | using namespace nnlib2; 6 | 7 | //-------------------------------------------------------------------------------------------- 8 | // example for manual.pdf (vignette) 9 | 10 | class MEX_connection: public connection 11 | { 12 | public: 13 | 14 | // model-specific behavior during mapping stage: 15 | 16 | void recall() 17 | { 18 | destin_pe().receive_input_value(pow( source_pe().output - weight() , 2) ); 19 | } 20 | 21 | // model-specific behavior during training stage: 22 | // in this example, only the current connection weight (i.e. weight()) 23 | // and incoming value from the source node (i.e. source_pe().output) are 24 | // used in a series of calculations that eventually change the 25 | // connection weight (see last line). 26 | 27 | void encode() 28 | { 29 | double x = source_pe().output - weight(); 30 | double s = .3; 31 | double m = weight(); 32 | double pi = 2*acos(0.0); 33 | double f = 1/(s*sqrt(2*pi)) * exp(-0.5*pow((x-m)/s,2)); 34 | double d = (f * x) / 2; 35 | weight() = weight() + d; 36 | } 37 | 38 | }; 39 | 40 | typedef Connection_Set < MEX_connection > MEX_connection_set; 41 | 42 | //-------------------------------------------------------------------------------------------- 43 | // example for manual.pdf (vignette) 44 | 45 | class MEX_pe : public pe 46 | { 47 | public: 48 | 49 | void recall() 50 | { 51 | pe::recall(); 52 | output = sqrt(output); 53 | } 54 | }; 55 | 56 | typedef Layer < MEX_pe > MEX_layer; 57 | 58 | //-------------------------------------------------------------------------------------------- 59 | // example (for RBloggers blog post): Perceptron components 60 | // see: https://www.r-bloggers.com/2020/07/creating-custom-neural-networks-with-nnlib2rcpp/ 61 | 62 | // Perceptron nodes: 63 | class perceptron_pe : public pe 64 | { 65 | public: 66 | DATA threshold_function(DATA value) 67 | { 68 | if(value>0) return 1; 69 | return 0; 70 | } 71 | }; 72 | 73 | // Percepton layer: 74 | typedef Layer < perceptron_pe > perceptron_layer; 75 | 76 | // Perceptron connections: 77 | // Note: 78 | // At the example in the post the destination PE inputs were also used to store 79 | // the desired output (iris class). This is mentioned in the post, but was chosen 80 | // for simplicity and compatibility with the nnlib2Rcpp version then available at CRAN. 81 | // 82 | // This version searches for the desired output in the 'misc' register of the 83 | // destination PEs, thus is more correct: the desired value is not an actual PE input. 84 | // To use this while following the post's example, 'use set_misc_values_at' 85 | // instead of 'set_input_at'. I.e. In the post's example code 86 | // replace: 87 | // p$input_at(3,desired_data_out[c,]) 88 | // with: 89 | // p$set_misc_values_at(3,desired_data_out[c,]) 90 | 91 | class perceptron_connection: public connection 92 | { 93 | public: 94 | 95 | // multiply incoming (from source node) value by weight and send it to destination node. 96 | void recall() 97 | { 98 | destin_pe().receive_input_value( weight() * source_pe().output ); 99 | } 100 | 101 | // for simplicity, learning rate is fixed to 0.3. Desired output in 'misc' (was 'input'): 102 | void encode() 103 | { 104 | weight() = weight() + 0.3 * (destin_pe().misc - destin_pe().output) * source_pe().output; 105 | } 106 | }; 107 | 108 | // Perceptron group of connections 109 | typedef Connection_Set< perceptron_connection > perceptron_connection_set; 110 | 111 | //-------------------------------------------------------------------------------------------- 112 | // example: a (useless) pe that just adds 10 to the sum of its inputs when recalling data 113 | 114 | class JustAdd10_pe : public pe 115 | { 116 | public: 117 | void recall() { pe::recall(); output = output + 10; } 118 | }; 119 | 120 | typedef Layer < JustAdd10_pe > JustAdd10_layer; 121 | 122 | //-------------------------------------------------------------------------------------------- 123 | 124 | #endif // NNLIB2_ADDITIONAL_PARTS_OTHER_H 125 | -------------------------------------------------------------------------------- /src/additional_parts_softmax.h: -------------------------------------------------------------------------------- 1 | #ifndef NNLIB2_ADDITIONAL_PARTS_SOFTMAX_H 2 | #define NNLIB2_ADDITIONAL_PARTS_SOFTMAX_H 3 | 4 | #include "nn.h" 5 | using namespace nnlib2; 6 | 7 | //-------------------------------------------------------------------------------------------- 8 | // a layer that performs softmax when recalling data. 9 | // it contains generic "dumb" pes, so most processing is done in layer code 10 | // Note: 11 | // when encoding it simply passes input to output. 12 | // when recalling it outputs the components of the softmax vector of input values. 13 | 14 | class softmax_layer: public pe_layer 15 | { 16 | public: 17 | 18 | softmax_layer(string name, int size):pe_layer(name,size){} 19 | 20 | void recall() 21 | { 22 | if(no_error()) 23 | { 24 | DATA denom=0; 25 | for(int i=0;i0, but just to be sure 33 | warning("Sum is zero, cannot compute softmax."); 34 | else 35 | for(int i=0;i